From: Tuukka Lehtonen Date: Mon, 6 Apr 2020 12:43:28 +0000 (+0000) Subject: Merge "Fix error in inserting dual inline components" X-Git-Url: https://gerrit.simantics.org/r/gitweb?a=commitdiff_plain;h=85bbf68087838bf65da8c7998a3b781ed5fb9fbd;hp=a745e75910247c95f7a9a5f4cc0598e2ca0cf95e;p=simantics%2F3d.git Merge "Fix error in inserting dual inline components" --- diff --git a/org.simantics.g3d.vtk/src/org/simantics/g3d/vtk/common/AbstractVTKNodeMap.java b/org.simantics.g3d.vtk/src/org/simantics/g3d/vtk/common/AbstractVTKNodeMap.java index ba62ddbf..bc7c3552 100644 --- a/org.simantics.g3d.vtk/src/org/simantics/g3d/vtk/common/AbstractVTKNodeMap.java +++ b/org.simantics.g3d.vtk/src/org/simantics/g3d/vtk/common/AbstractVTKNodeMap.java @@ -372,12 +372,14 @@ public abstract class AbstractVTKNodeMap implements VT private boolean useFullSyncWithUndo = false; protected void update(ReadGraph graph) throws DatabaseException { - synchronized (syncMutex) { - if (DEBUG) System.out.println("Graph update start"); - - if (runUndo && useFullSyncWithUndo) { + if (DEBUG) System.out.println("Graph update start"); + + if (runUndo && useFullSyncWithUndo) { + synchronized (syncMutex) { reset(graph); - } else { + } + } else { + synchronized (syncMutex) { graphUpdates = true; for (DBObject domainObject : mapping.getDomainModified()) { @SuppressWarnings("unchecked") @@ -385,18 +387,24 @@ public abstract class AbstractVTKNodeMap implements VT if (rangeObject != null) graphModified.add(rangeObject); } - mapping.updateRange(graph); + + } + + mapping.updateRange(graph); + + synchronized (syncMutex) { graphModified.clear(); syncDeletes(); - clearDeletes(); - graphUpdates = false; - } - - if (mapping.isRangeModified() && !runUndo && !runRedo) - commit((String)null); + } - if (DEBUG) System.out.println("Graph update done"); + clearDeletes(); + graphUpdates = false; } + + if (mapping.isRangeModified() && !runUndo && !runRedo) + commit((String)null); + + if (DEBUG) System.out.println("Graph update done"); } @Override @@ -438,7 +446,6 @@ public abstract class AbstractVTKNodeMap implements VT * This code here synchronizes removed and added objects to collect deletable objects. (a deletable object is one which is removed but not added). * */ - @SuppressWarnings("unused") protected void syncDeletes() { deleteUC.clear(); for (Pair n : removed) { @@ -460,7 +467,6 @@ public abstract class AbstractVTKNodeMap implements VT /** * Clears deletable objects from mapping cache. */ - @SuppressWarnings("unused") protected void clearDeletes() { if (DEBUG && delete.size() > 0) System.out.println("Delete"); for (E n : delete) { diff --git a/org.simantics.plant3d/src/org/simantics/plant3d/actions/AddComponentAction.java b/org.simantics.plant3d/src/org/simantics/plant3d/actions/AddComponentAction.java index 8dcee926..dae8c629 100644 --- a/org.simantics.plant3d/src/org/simantics/plant3d/actions/AddComponentAction.java +++ b/org.simantics.plant3d/src/org/simantics/plant3d/actions/AddComponentAction.java @@ -76,13 +76,13 @@ public class AddComponentAction extends vtkSwtAction { allowed.add(PositionType.NEXT); } } else { - if (component.getNext() == null) { + if (component.getNext() == null || component.getControlPoint().isVariableLength()) { allowed.add(PositionType.NEXT); } - if (component.getPrevious() == null) { + if (component.getPrevious() == null || component.getControlPoint().isVariableLength()) { allowed.add(PositionType.PREVIOUS); } - if (component instanceof InlineComponent && !component.getControlPoint().isFixedLength()){ + if (component instanceof InlineComponent && component.getControlPoint().isVariableLength()){ allowed.add(PositionType.SPLIT); } } diff --git a/org.simantics.plant3d/src/org/simantics/plant3d/dialog/ComponentSelectionDialog.java b/org.simantics.plant3d/src/org/simantics/plant3d/dialog/ComponentSelectionDialog.java index da764775..df00bc39 100644 --- a/org.simantics.plant3d/src/org/simantics/plant3d/dialog/ComponentSelectionDialog.java +++ b/org.simantics.plant3d/src/org/simantics/plant3d/dialog/ComponentSelectionDialog.java @@ -134,6 +134,9 @@ public class ComponentSelectionDialog extends Dialog implements ISelectionChange dialogSettings = settings.getSection(DIALOG); if (dialogSettings == null) dialogSettings = settings.addNewSection(DIALOG); + + if (component.getNext() != null && component.getPrevious() != null) + insertPosition = PositionType.PREVIOUS; } public void setLengthFactor(double lengthFactor) { @@ -267,6 +270,10 @@ public class ComponentSelectionDialog extends Dialog implements ISelectionChange horizFillData.applyTo(buttonComposite); GridLayoutFactory.fillDefaults().numColumns(3).applyTo(buttonComposite); + startButton.setSelection(insertPosition == PositionType.PREVIOUS); + middleButton.setSelection(insertPosition == PositionType.SPLIT); + endButton.setSelection(insertPosition == PositionType.NEXT); + startButton.setEnabled(false); middleButton.setEnabled(false); endButton.setEnabled(false); @@ -290,7 +297,6 @@ public class ComponentSelectionDialog extends Dialog implements ISelectionChange updateInsertPosition(PositionType.NEXT); } }); - endButton.setSelection(true); label = new Label(composite, SWT.NONE); label.setText("Name"); @@ -428,9 +434,9 @@ public class ComponentSelectionDialog extends Dialog implements ISelectionChange private void updateInsertPosition(PositionType type) { if (insertPosition == type) return; - endButton.setSelection(type == PositionType.NEXT); - middleButton.setSelection(type == PositionType.SPLIT); startButton.setSelection(type == PositionType.PREVIOUS); + middleButton.setSelection(type == PositionType.SPLIT); + endButton.setSelection(type == PositionType.NEXT); insertPosition = type; } @@ -481,7 +487,15 @@ public class ComponentSelectionDialog extends Dialog implements ISelectionChange } else { lenghtAdjustable = ((selected.getType() == Type.INLINE) && (selected.isVariable() || selected.isModifiable())); - if (insertAdjustable) { + + if (component.getNext() != null && component.getPrevious() != null) { + // We are inserting to a fully connected variable length component + // only allow insertion within the component + startButton.setEnabled(false); + middleButton.setEnabled(false); + endButton.setEnabled(false); + updateInsertPosition(PositionType.PREVIOUS); + } else if (insertAdjustable) { switch (selected.getType()) { case END: startButton.setEnabled(false); @@ -566,7 +580,7 @@ public class ComponentSelectionDialog extends Dialog implements ISelectionChange rotationAngleText.setEnabled(true); if (angle == null) { ok = false; - if (msg == null) msg = "Please provide a rotation angle"; + if (msg == null) msg = "Please provide a turn angle"; } } else { // this should not happen, since end components should not have variable, or diff --git a/org.simantics.plant3d/src/org/simantics/plant3d/scenegraph/InlineComponent.java b/org.simantics.plant3d/src/org/simantics/plant3d/scenegraph/InlineComponent.java index ed4917df..966bb421 100644 --- a/org.simantics.plant3d/src/org/simantics/plant3d/scenegraph/InlineComponent.java +++ b/org.simantics.plant3d/src/org/simantics/plant3d/scenegraph/InlineComponent.java @@ -174,6 +174,8 @@ public class InlineComponent extends PipelineComponent { map.put("radius2", pipeRun2.getPipeDiameter() * 0.5); } if (controlPoint.isOffset() && !componentCalculatedOffset) { + if (getPipeRun() != null && getAlternativePipeRun() != null) + updateOffset(); map.put("offset", controlPoint.getOffset()); } } diff --git a/org.simantics.plant3d/src/org/simantics/plant3d/scenegraph/controlpoint/PipeControlPoint.java b/org.simantics.plant3d/src/org/simantics/plant3d/scenegraph/controlpoint/PipeControlPoint.java index 0c7e3b26..cd4f407b 100644 --- a/org.simantics.plant3d/src/org/simantics/plant3d/scenegraph/controlpoint/PipeControlPoint.java +++ b/org.simantics.plant3d/src/org/simantics/plant3d/scenegraph/controlpoint/PipeControlPoint.java @@ -462,7 +462,7 @@ public class PipeControlPoint extends G3DNode implements IP3DNode { } if (this.rotationAngle != null && Math.abs(this.rotationAngle-rotationAngle) < MathTools.NEAR_ZERO) return; - if (Objects.equals(rotationAngle, rotationAngle)) + if (Objects.equals(this.rotationAngle, rotationAngle)) return; this.rotationAngle = rotationAngle; firePropertyChanged("rotationAngle"); @@ -788,9 +788,15 @@ public class PipeControlPoint extends G3DNode implements IP3DNode { } /** - * Returns direction vector. + * Returns direction vector pointing towards an adjacent component for + * directed control points or turn control points with one open end. * - * For directed control points, always returns outwards pointing vector. + * Always returns an outwards pointing vector. + * + * For any other type of component, the return value is null. + * + * For turn components this only return a non-null value for the unconnected + * end of the component. * * @param direction * @return normalized vector, or null @@ -834,6 +840,7 @@ public class PipeControlPoint extends G3DNode implements IP3DNode { Vector3d offset = new Vector3d(); MathTools.rotate(q2, v, offset); MathTools.rotate(q, offset, dir); + dir.negate(); dir.normalize(); return dir; } @@ -852,107 +859,70 @@ public class PipeControlPoint extends G3DNode implements IP3DNode { */ public Vector3d getPathLegDirection(Direction direction) { if (direction == Direction.NEXT) { - if (next != null) { - PipeControlPoint pcp = this; - if (pcp.isDualInline()) { - pcp = pcp.getDualSub(); - } - Vector3d v = new Vector3d(); - v.sub(next.getWorldPosition(),pcp.getWorldPosition()); - if (v.lengthSquared() > MathTools.NEAR_ZERO) - v.normalize(); - else - return null; - return v; - } else { - if (previous == null) { - if (!isDirected()) - throw new RuntimeException("Cannot calculate path leg direction for unconnected control point " + this); - return getDirectedControlPointDirection(); + return getPathLegDirectionNext(); + } else { + return getPathLegDirectionPrevious(); + } + } - } else { - if (isVariableAngle() && !asFixedAngle()) - throw new RuntimeException("Cannot calculate path leg direction for unconnected variable angle control point " + this); - if (isInline()) { - PipeControlPoint pcp = this; - if (pcp.isDualSub()) { - pcp = pcp.getParentPoint(); - } - Vector3d v = new Vector3d(); - v.sub(pcp.getWorldPosition(),previous.getWorldPosition()); - if (v.lengthSquared() > MathTools.NEAR_ZERO) - v.normalize(); - else - return null; - return v; - } else if (isDirected()) { - return getDirectedControlPointDirection(); - } else if (isEnd()) { - Vector3d v = new Vector3d(); - v.sub(getWorldPosition(),previous.getWorldPosition()); - if (v.lengthSquared() > MathTools.NEAR_ZERO) - v.normalize(); - else - return null; - return v; - } else if (isTurn() && asFixedAngle() && !_getReversed()) { - return getDirection(Direction.NEXT); - } - throw new RuntimeException("Missing implementation " + this); - } - } + public Vector3d getPathLegDirectionPrevious() { + if (previous != null) { + PipeControlPoint pcp = this; + if (isDualSub()) + pcp = getParentPoint(); + Vector3d v = new Vector3d(); + v.sub(previous.getWorldPosition(),pcp.getWorldPosition()); + if (v.lengthSquared() > MathTools.NEAR_ZERO) + v.normalize(); + else + return null; + return v; + } else if (isDirected()) { + Vector3d v = getDirectedControlPointDirection(); + v.negate(); + return v; + } else if (next == null) { + throw new RuntimeException("Cannot calculate path leg direction for unconnected control point " + this); + } else if (isVariableAngle() && !asFixedAngle()) { + throw new RuntimeException("Cannot calculate path leg direction for unconnected variable angle control point " + this); + } else if (isInline() || isEnd()) { + Vector3d v = getPathLegDirectionNext(); + if (v != null) v.negate(); + return v; + } else if (isTurn() && asFixedAngle() && _getReversed()) { + return getDirection(Direction.PREVIOUS); } else { - if (previous != null) { - PipeControlPoint pcp = this; - if (isDualSub()) - pcp = getParentPoint(); - Vector3d v = new Vector3d(); - v.sub(previous.getWorldPosition(),pcp.getWorldPosition()); - if (v.lengthSquared() > MathTools.NEAR_ZERO) - v.normalize(); - else - return null; - return v; - } else { - if (next == null) { - if (!isDirected()) - throw new RuntimeException("Cannot calculate path leg direction for unconnected control point " + this); - Vector3d v = getDirectedControlPointDirection(); - v.negate(); - return v; - } else { - if (isVariableAngle() && !asFixedAngle()) - throw new RuntimeException("Cannot calculate path leg direction for unconnected variable angle control point " + this); - if (isInline()) { - PipeControlPoint pcp = this; - if (pcp.isDualInline()) { - pcp = pcp.getDualSub(); - } - Vector3d v = new Vector3d(); - v.sub(pcp.getWorldPosition(),next.getWorldPosition()); - if (v.lengthSquared() > MathTools.NEAR_ZERO) - v.normalize(); - else - return null; - return v; - } else if (isDirected()) { - Vector3d v = getDirectedControlPointDirection(); - v.negate(); - return v; - } else if (isEnd()) { - Vector3d v = new Vector3d(); - v.sub(getWorldPosition(),next.getWorldPosition()); - if (v.lengthSquared() > MathTools.NEAR_ZERO) - v.normalize(); - else - return null; - return v; - } else if (isTurn() && asFixedAngle() && _getReversed()) { - return getDirection(Direction.PREVIOUS); - } - throw new RuntimeException("Missing implementation " + this); - } + throw new RuntimeException("Missing implementation " + this); + } + } + + public Vector3d getPathLegDirectionNext() { + if (next != null) { + PipeControlPoint pcp = this; + if (pcp.isDualInline()) { + pcp = pcp.getDualSub(); } + Vector3d v = new Vector3d(); + v.sub(next.getWorldPosition(),pcp.getWorldPosition()); + if (v.lengthSquared() > MathTools.NEAR_ZERO) + v.normalize(); + else + return null; + return v; + } else if (isDirected()) { + return getDirectedControlPointDirection(); + } else if (previous == null) { + throw new RuntimeException("Cannot calculate path leg direction for unconnected control point " + this); + } else if (isVariableAngle() && !asFixedAngle()) { + throw new RuntimeException("Cannot calculate path leg direction for unconnected variable angle control point " + this); + } else if (isInline() || isEnd()) { + Vector3d v = getPathLegDirectionPrevious(); + if (v != null) v.negate(); + return v; + } else if (isTurn() && asFixedAngle() && !_getReversed()) { + return getDirection(Direction.NEXT); + } else { + throw new RuntimeException("Missing implementation " + this); } } @@ -1648,6 +1618,21 @@ public class PipeControlPoint extends G3DNode implements IP3DNode { updateSubPoint(); } + public void orientToDirection(Vector3d dir) { + Double angleO = getRotationAngle(); + double angle = 0.0; + if (angleO != null) + angle = angleO; + boolean reversed = _getReversed(); + Quat4d q = null; + if (dir != null) { + q = getControlPointOrientationQuat(dir, angle, reversed); + } else { + q = getControlPointOrientationQuat(angle, reversed); + } + setWorldOrientation(q); + } + @Override public String toString() { return getClass().getName() + "@" + Integer.toHexString(hashCode()); diff --git a/org.simantics.plant3d/src/org/simantics/plant3d/scenegraph/controlpoint/PipingRules.java b/org.simantics.plant3d/src/org/simantics/plant3d/scenegraph/controlpoint/PipingRules.java index 542534c3..e930b8d6 100644 --- a/org.simantics.plant3d/src/org/simantics/plant3d/scenegraph/controlpoint/PipingRules.java +++ b/org.simantics.plant3d/src/org/simantics/plant3d/scenegraph/controlpoint/PipingRules.java @@ -294,7 +294,7 @@ public class PipingRules { scp.setWorldPosition(pos); Vector3d dir = new Vector3d(); dir.sub(pcp2.getWorldPosition(), pcp1.getWorldPosition()); - updateControlPointOrientation(scp, dir); + scp.orientToDirection(dir); scp.setLength(length); validate(scp.getPipeRun()); return scp; @@ -381,10 +381,43 @@ public class PipingRules { } + /** + * Calculate offset based on a given fixed component direction. + * + * The desired component direction is provided as an input to this method, + * unlike the direction vector that is calculated by calculateOffset. + * + * The returned offset vector is always perpendicular to the given direction + * vector. + * + * @param startPoint Start point of leg + * @param endPoint End point of leg + * @param start Starting component of leg + * @param list Inline components between start and end + * @param end Ending component of leg + * @param dir Direction at which the offset is calculated + * @param offset A vector object to receive the offset vector values + * @return True if offsets are present + */ public static boolean calculateDirectedOffset(Vector3d startPoint, Vector3d endPoint, PipeControlPoint start, ArrayList list, PipeControlPoint end, Vector3d dir, Vector3d offset) { return calculateOffset(startPoint, endPoint, start, list, end, dir, offset, true); } + /** + * Calculate offset and direction vectors for a path leg so that the given chain + * of components starts and ends at the given coordinates + * + * The returned direction and offset vectors are perpendicular to each other. + * + * @param startPoint Start point of the leg + * @param endPoint End point of the leg + * @param start Starting component of the leg + * @param list Inline components between start and end + * @param end Ending component of the leg + * @param dir A vector object to receive the component direction vector + * @param offset A vector object to receive the offset vector + * @return True if offsets are present + */ public static boolean calculateOffset(Vector3d startPoint, Vector3d endPoint, PipeControlPoint start, ArrayList list, PipeControlPoint end, Vector3d dir, Vector3d offset) { return calculateOffset(startPoint, endPoint, start, list, end, dir, offset, false); } @@ -397,8 +430,11 @@ public class PipingRules { } else { Vector3d sp = new Vector3d(startPoint); Point3d ep = new Point3d(endPoint); - dir.set(ep); - dir.sub(sp); + if (!directed) { + dir.set(ep); + dir.sub(sp); + } + double l = dir.lengthSquared(); if (l > MathTools.NEAR_ZERO) dir.scale(1.0/Math.sqrt(l)); @@ -1080,15 +1116,19 @@ public class PipingRules { Point3d otherPosition = new Point3d(dcpStart ? u.endPoint : u.startPoint); if (u.hasOffsets) { - Vector3d dir = new Vector3d(), offset = new Vector3d(); + Vector3d dir = dcp.getDirection(dcpStart ? Direction.NEXT : Direction.PREVIOUS); + if (!dcpStart) + dir.negate(); + + Vector3d offset = new Vector3d(); calculateDirectedOffset(u.startPoint, u.endPoint, u.start, u.list, u.end, dir, offset); u.dir = dir; u.offset = offset; if (dcpStart) - otherPosition.add(offset); - else otherPosition.sub(offset); + else + otherPosition.add(offset); } double mu[] = new double[2]; @@ -1236,7 +1276,7 @@ public class PipingRules { Point3d position1 = new Point3d(u.startPoint); Point3d position2 = new Point3d(u.endPoint); - Vector3d dir = new Vector3d(), offset = new Vector3d(); + Vector3d dir = u.start.getDirection(Direction.NEXT), offset = new Vector3d(); calculateDirectedOffset(new Vector3d(position1), new Vector3d(position2), u.start, u.list, u.end, dir, offset); Point3d position1offset = new Point3d(position1); @@ -1638,7 +1678,7 @@ public class PipingRules { } else if (u.start.isEnd()) { updateEndComponentControlPoint(u.start, u.dir); } else if (u.start.isInline()) { - updateControlPointOrientation(u.start, u.dir); + u.start.orientToDirection(u.dir); } if (u.end.isTurn()) { //updateTurnControlPointTurn(u.end, u.end.getPrevious(), u.end.getNext()); @@ -1647,7 +1687,7 @@ public class PipingRules { } else if (u.end.isEnd()) { updateEndComponentControlPoint(u.end, u.dir); } else if (u.end.isInline()) { - updateControlPointOrientation(u.end, u.dir); + u.end.orientToDirection(u.dir); } } else { @@ -1776,7 +1816,7 @@ public class PipingRules { System.out.println(" " + newInlinePoint); icp.setWorldPosition(newInlinePoint); - updateControlPointOrientation(icp, dir); + icp.orientToDirection(dir); } /** @@ -1793,7 +1833,7 @@ public class PipingRules { System.out.println("PipingRules.updateEndComponentControlPoint() " + ecp); if (!ecp.isFixed()) // prevent overriding nozzle orientations.. - updateControlPointOrientation(ecp, dir); + ecp.orientToDirection(dir); for (PipeControlPoint pcp : ecp.getChildPoints()) { // TODO update position @@ -1801,21 +1841,6 @@ public class PipingRules { } } - private static void updateControlPointOrientation(PipeControlPoint pcp, Vector3d dir) { - Double angleO = pcp.getRotationAngle(); - double angle = 0.0; - if (angleO != null) - angle = angleO; - boolean reversed = pcp._getReversed(); - Quat4d q = null; - if (dir != null) { - q = pcp.getControlPointOrientationQuat(dir, angle, reversed); - } else { - q = pcp.getControlPointOrientationQuat(angle, reversed); - } - pcp.setWorldOrientation(q); - } - /** * Updates all branches when branch's position has been changed * @@ -1881,7 +1906,7 @@ public class PipingRules { tcp.setTurnAxis(new Vector3d(MathTools.Y_AXIS)); } - updateControlPointOrientation(tcp,prev); + tcp.orientToDirection(prev); if (DEBUG) System.out.println("PipingTools.updateTurnControlPointTurn " + prev + " " + next + " " + turnAngle + " " + turnAxis); diff --git a/org.simantics.plant3d/src/org/simantics/plant3d/utils/ComponentUtils.java b/org.simantics.plant3d/src/org/simantics/plant3d/utils/ComponentUtils.java index 6bbabe1e..913fceb9 100644 --- a/org.simantics.plant3d/src/org/simantics/plant3d/utils/ComponentUtils.java +++ b/org.simantics.plant3d/src/org/simantics/plant3d/utils/ComponentUtils.java @@ -378,9 +378,6 @@ public class ComponentUtils { public static PipelineComponent addComponent(P3DRootNode root, PipelineComponent component, InsertInstruction inst) throws Exception { PipelineComponent newComponent = ComponentUtils.createComponent(root, inst.typeUri); - if (inst.name != null) - newComponent.setName(inst.name); - PipeControlPoint newPcp = newComponent.getControlPoint(); PipeControlPoint toPcp = component.getControlPoint(); @@ -408,6 +405,8 @@ public class ComponentUtils { sizeChange = ((InlineComponent)newComponent).isSizeChange(); } + // Calculate component position and direction vectors + // 'dir' is a unit vector that represents the direction from 'component' to 'newComponent' if (toPcp.isInline()) { switch (position) { case NEXT: @@ -437,6 +436,7 @@ public class ComponentUtils { break; case PREVIOUS: pos = new Vector3d(start); + dir.negate(); break; case SPLIT: pos = new Vector3d(toPcp.getWorldPosition()); @@ -444,9 +444,9 @@ public class ComponentUtils { default: break; } - } else if (toPcp.isDirected()) { - dir = new Vector3d(toPcp.getDirection(Direction.NEXT)); + // 'dir' always points out of a nozzle regardless of insertion direction + dir = new Vector3d(toPcp.getDirectedControlPointDirection()); pos = new Vector3d(toPcp.getWorldPosition()); } else if (toPcp.isTurn() && toPcp.asFixedAngle()) { dir = new Vector3d(toPcp.getDirection(position == PositionType.NEXT ? Direction.NEXT : Direction.PREVIOUS)); @@ -469,8 +469,12 @@ public class ComponentUtils { } } - String name = component.getPipeRun().getUniqueName(typeName); - newComponent.setName(name); + if (inst.name != null) { + newComponent.setName(inst.name); + } else { + String name = component.getPipeRun().getUniqueName(typeName); + newComponent.setName(name); + } pipeRun.addChild(newComponent); if (newPcp.isSizeChange()) @@ -487,18 +491,22 @@ public class ComponentUtils { } else if (newComponent instanceof TurnComponent) { TurnComponent turnComponent = (TurnComponent)newComponent; if (turnComponent.isVariableAngle()) { - newPcp.setTurnAngle(inst.angle); + newPcp.setTurnAngle(Math.toRadians(inst.angle)); newComponent.setParameter("turnAngle", inst.angle); } if (inst.rotationAngle != null) ((TurnComponent) newComponent).setRotationAngle(inst.rotationAngle); } - newComponent.updateParameters(); Vector3d v = new Vector3d(dir); if (insertAdjustable) { + // Prevent moving of adjacent components - always insert at end of a connected variable length component + if (position == PositionType.NEXT && component.getNext() != null || + position == PositionType.PREVIOUS && component.getPrevious() != null) + insertPosition = PositionType.PREVIOUS; + if (insertPosition == PositionType.NEXT) v.scale(newComponent.getControlPoint().getInlineLength()); else if (insertPosition == PositionType.SPLIT) @@ -508,12 +516,11 @@ public class ComponentUtils { } else { v.scale(newComponent.getControlPoint().getInlineLength()); } + switch (position) { case NEXT: - pos.add(v); - break; case PREVIOUS: - pos.sub(v); + pos.add(v); break; case SPLIT: break; @@ -525,14 +532,20 @@ public class ComponentUtils { case NEXT: if (toPcp.isDualInline()) toPcp = toPcp.getDualSub(); - newPcp.insert(toPcp, Direction.NEXT); newPcp.setWorldPosition(pos); + if (toPcp.getNext() != null) + PipingRules.splitVariableLengthComponent(newComponent, (InlineComponent)component, false); + else + newPcp.insert(toPcp, Direction.NEXT); break; case PREVIOUS: if (toPcp.isDualSub()) toPcp = toPcp.parent; - newPcp.insert(toPcp, Direction.PREVIOUS); newPcp.setWorldPosition(pos); + if (toPcp.getPrevious() != null) + PipingRules.splitVariableLengthComponent(newComponent, (InlineComponent)component, false); + else + newPcp.insert(toPcp, Direction.PREVIOUS); break; case SPLIT: PipingRules.splitVariableLengthComponent(newComponent, (InlineComponent)component, true);