X-Git-Url: https://gerrit.simantics.org/r/gitweb?a=blobdiff_plain;f=org.simantics.plant3d%2Fsrc%2Forg%2Fsimantics%2Fplant3d%2Fscenegraph%2Fcontrolpoint%2FPipeControlPoint.java;h=abd899ac23ae0af43f07b3020894fa29b9b0bfc9;hb=2c16b9949ab2b8cdbdbff7bbda91eb862b1176ed;hp=93186779e60d580aa31d23a95585ce4886ff9f7b;hpb=27fb679643fab3ef9aa46d04c5ced2ea82cf60c2;p=simantics%2F3d.git 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 93186779..abd899ac 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 @@ -16,6 +16,8 @@ import org.simantics.g3d.math.MathTools; import org.simantics.g3d.property.annotations.GetPropertyValue; import org.simantics.g3d.scenegraph.G3DNode; import org.simantics.plant3d.scenegraph.IP3DNode; +import org.simantics.plant3d.scenegraph.Nozzle; +import org.simantics.plant3d.scenegraph.P3DRootNode; import org.simantics.plant3d.scenegraph.PipeRun; import org.simantics.plant3d.scenegraph.PipelineComponent; @@ -33,13 +35,16 @@ public class PipeControlPoint extends G3DNode implements IP3DNode { private PipelineComponent component; private PointType type; - private boolean isFixed = true; - private boolean isRotate = false; - private boolean isReverse = false; - private boolean isDeletable = true; - private boolean isSizeChange = false; - private boolean isSub = false; - + private boolean isFixed = true; // In-line: fixed-length Turn: fixed-angle + private boolean isMod = false; // Can user modify fixed value manually + private boolean isRotate = false; // rotates around path leg axis. + private boolean isReverse = false; // definition direction can be swapped + private boolean isDeletable = true; // can be removed by rules + private boolean isSizeChange = false; // changes size of the pipe. The next control point / component is on different PipeRun + private boolean isSub = false; // child point for offset / size change + + private boolean disposed = false; + public PipeControlPoint(PipelineComponent component) { this.component = component; if (component.getPipeRun() != null) @@ -83,10 +88,18 @@ public class PipeControlPoint extends G3DNode implements IP3DNode { return isFixed; } - public void setFixed(boolean fixed) { this.isFixed = fixed; } + + @GetPropertyValue(name="Mod",tabId="Debug",value="mod") + public boolean isMod() { + return isMod; + } + + public void setMod(boolean isMod) { + this.isMod = isMod; + } @GetPropertyValue(name="Rotate",tabId="Debug",value="rotate") public boolean isRotate() { @@ -134,11 +147,26 @@ public class PipeControlPoint extends G3DNode implements IP3DNode { public boolean isInline() { return type == PointType.INLINE; } + + public boolean asPathLegEnd() { + // Ends and Turns are path leg ends by default, but also unconnected inline are path leg ends. + return isPathLegEnd() || getNext() == null || getPrevious() == null; + } + /** + * True for end components, if control point defines absolute position direction, which rules cannot modify. + * This is typical for nozzles. + * @return + */ public boolean isDirected() { return isFixed && isEnd(); } + /** + * True for end components, if control is opposite to directed, and rules can modify position and orientation. + * This is typical for caps, and other end components. + * @return + */ public boolean isNonDirected() { return !isFixed && isEnd(); } @@ -146,10 +174,35 @@ public class PipeControlPoint extends G3DNode implements IP3DNode { public boolean isVariableLength() { return !isFixed && isInline(); } + + /** + * Fixed length in-line component is such that piping rules cannot modify the length. + * @return + */ + public boolean isFixedLength() { + return isFixed && isInline(); + } public boolean isVariableAngle() { return !isFixed && isTurn(); } + + /** + * Fixed angle turn component is such that piping rules cannot modify the angle. + * @return + */ + public boolean isFixedAngle() { + return isFixed && isTurn(); + } + + /** + * Does the turn behave like fixed angle? + * For variable angle turns, the turn angle is defined by connected components, and without them, we must handle the component as fixed angle. + * @return + */ + public boolean asFixedAngle() { + return isTurn() && (isFixed || next == null || previous == null); + } public boolean isBranchEnd() { return isDeletable && isEnd(); @@ -197,32 +250,70 @@ public class PipeControlPoint extends G3DNode implements IP3DNode { } public void setNext(PipeControlPoint next) { + if (isSub) { + getParentPoint().setNext(next); + return; + } + if (next != null && next.isDualSub()) + next = next.parent; + if (_setNext(next)) { + for (PipeControlPoint pcp : children) { + if (pcp.isSub) + pcp._setNext(next); + } + updateSubPoint(); + } + } + + public void setPrevious(PipeControlPoint prev) { + if (isSub) { + getParentPoint().setPrevious(prev); + return; + } + if (prev != null && prev.isDualInline()) + prev = prev.children.get(0); + if (_setPrevious(prev)) { + for (PipeControlPoint pcp : children) { + if (pcp.isSub) + pcp._setPrevious(prev); + } + updateSubPoint(); + } + } + + protected boolean _setNext(PipeControlPoint next) { if (isEnd() && previous != null && next != null) throw new RuntimeException("End control points are allowed to have only one connection"); if (next == this) throw new RuntimeException("Cannot connect to self"); if (this.next == next) - return; + return false; if (DEBUG) System.out.println(this + " next " + next); + if (next == null && isVariableAngle() && previous != null && !isRemoved()) { + convertVariableAngleToFixed(Direction.NEXT); + } this.next = next; if (component != null) { if (parent == null || isSub) component.setNext(next != null ? next.component : null); else component.setBranch0(next != null ? next.component : null); - updateSubPoint(); + } - + return true; } - public void setPrevious(PipeControlPoint previous) { + protected boolean _setPrevious(PipeControlPoint previous) { if (isEnd() && next != null && previous != null) throw new RuntimeException("End control points are allowed to have only one connection"); if (previous == this) throw new RuntimeException("Cannot connect to self"); if (this.previous == previous) - return; + return false; if (DEBUG) System.out.println(this + " previous " + previous); + if (previous == null && isVariableAngle() && next != null && !isRemoved()) { + convertVariableAngleToFixed(Direction.PREVIOUS); + } this.previous = previous; if (component != null) { if (parent == null || isSub) @@ -231,13 +322,40 @@ public class PipeControlPoint extends G3DNode implements IP3DNode { component.setBranch0(previous != null ? previous.component : null); updateSubPoint(); } - + return true; + } + + private void convertVariableAngleToFixed(Direction direction) { + // We are removing reference, which transforms variable angle to fixed angle. + // Since fixed angle is defined differently, we need to calculate fixed angle parameters based on current data + // We need to calculate turnAngle and rotationAngle + Vector3d dirOut = getPathLegDirection(direction == Direction.NEXT ? Direction.NEXT : Direction.PREVIOUS); + Vector3d dir = getPathLegDirection(direction == Direction.NEXT ? Direction.PREVIOUS : Direction.NEXT); + dir.negate(); + dirOut.normalize(); + dir.normalize(); + double angle = dir.angle(dirOut); + //super._setNext(null); + if (direction == Direction.NEXT) + next = null; + else + previous = null; + setRotationAngle(0.0); + setReversed(direction == Direction.NEXT ? false : true); + Vector3d dirOutN = getPathLegDirection(direction == Direction.NEXT ? Direction.NEXT : Direction.PREVIOUS); + dirOutN.normalize(); + AxisAngle4d aa = new AxisAngle4d(); + if (MathTools.createRotation(dirOutN, dirOut, dir, aa)) { + setRotationAngle(aa.angle); + setTurnAngle(angle); + if (DEBUG) System.out.println("convertToFixed " + dir + " " + dirOut + " " +dirOutN + " " +angle + " "+ aa.angle); + } } public PipeControlPoint parent; public List children = new ArrayList(); - public List getSubPoint() { + public List getChildPoints() { return children; } @@ -268,7 +386,7 @@ public class PipeControlPoint extends G3DNode implements IP3DNode { this.length = l; firePropertyChanged("length"); if (isDualInline()) - getSubPoint().get(0).setLength(l); + getDualSub().setLength(l); } @GetPropertyValue(name="Turn Angle",tabId="Debug",value="turnAngle") @@ -288,7 +406,9 @@ public class PipeControlPoint extends G3DNode implements IP3DNode { @GetPropertyValue(name="Rotation Angle",tabId="Debug",value="rotationAngle") public Double getRotationAngle() { - return rotationAngle; + if (isRotate || asFixedAngle()) + return rotationAngle; + return null; } @GetPropertyValue(name="Reversed",tabId="Debug",value="reversed") @@ -409,26 +529,34 @@ public class PipeControlPoint extends G3DNode implements IP3DNode { return getControlPointOrientationQuat(dir, turnAxis, angle); } } + + public Quat4d getControlPointOrientationQuat(Vector3d dir, double angle, boolean reversed) { + if (turnAxis == null) { + if (dir.lengthSquared() > MathTools.NEAR_ZERO) + dir.normalize(); + Quat4d q = getControlPointOrientationQuat(dir, angle); + if (reversed) { + Quat4d q2 = new Quat4d(); + q2.set(new AxisAngle4d(MathTools.Y_AXIS, Math.PI)); + q.mulInverse(q2); + } + return q; + } else { + if (dir.lengthSquared() > MathTools.NEAR_ZERO) + dir.normalize(); + return getControlPointOrientationQuat(dir, turnAxis, angle); + } + } public Quat4d getControlPointOrientationQuat(double angle, boolean reversed) { if (turnAxis == null) { Vector3d dir = getPathLegDirection(Direction.NEXT); - if (dir.lengthSquared() > MathTools.NEAR_ZERO) - dir.normalize(); - Quat4d q = getControlPointOrientationQuat(dir, angle); - if (reversed) { - Quat4d q2 = new Quat4d(); - q2.set(new AxisAngle4d(MathTools.Y_AXIS, Math.PI)); - q.mulInverse(q2); - } - return q; + return getControlPointOrientationQuat(dir, angle, reversed); } else { Vector3d dir = getPathLegDirection(Direction.PREVIOUS); dir.negate(); - if (dir.lengthSquared() > MathTools.NEAR_ZERO) - dir.normalize(); - return getControlPointOrientationQuat(dir, turnAxis, angle); + return getControlPointOrientationQuat(dir, angle, reversed); } } @@ -509,7 +637,7 @@ public class PipeControlPoint extends G3DNode implements IP3DNode { PipeControlPoint offsetCP = null; if (isOffset()) { - offsetCP = getSubPoint().get(0); + offsetCP = getDualSub(); } if (previousNext != null && previousNext == next) { if (previous.isDualInline()) { @@ -534,7 +662,7 @@ public class PipeControlPoint extends G3DNode implements IP3DNode { } if (next.isDualInline()) { - next.getSubPoint().get(0).setPrevious(this); + next.getDualSub().setPrevious(this); } } else if (previousPrevious != null && previousPrevious == next) { // control point were given in reverse order @@ -552,7 +680,7 @@ public class PipeControlPoint extends G3DNode implements IP3DNode { offsetCP.setPrevious(next); } if (previous.isDualInline()) { - previous.getSubPoint().get(0).setPrevious(this); + previous.getDualSub().setPrevious(this); } this.setPrevious(next); next.setNext(this); @@ -584,7 +712,7 @@ public class PipeControlPoint extends G3DNode implements IP3DNode { pcp.getParentPoint().setNext(this); } if (isDualInline()) { - getSubPoint().get(0).setPrevious(this); + getDualSub().setPrevious(this); } } else { // if direction is previous, user must have given sizechange @@ -594,7 +722,7 @@ public class PipeControlPoint extends G3DNode implements IP3DNode { // we must link pcp to newCP's OffsetPoint PipeControlPoint nocp = null; if (isDualInline()) { - nocp = getSubPoint().get(0); + nocp = getDualSub(); nocp.setNext(pcp); } if (nocp == null) { @@ -604,7 +732,7 @@ public class PipeControlPoint extends G3DNode implements IP3DNode { } this.setNext(pcp); if (pcp.isDualInline()) { - PipeControlPoint ocp = pcp.getSubPoint().get(0); + PipeControlPoint ocp = pcp.getDualSub(); if (nocp == null) ocp.setPrevious(this); else @@ -626,7 +754,7 @@ public class PipeControlPoint extends G3DNode implements IP3DNode { public Vector3d getDirection(Direction direction) { if (isDirected()) return getDirectedControlPointDirection(); - if (isTurn() && isFixed()) { + if (isTurn() && asFixedAngle()) { if (direction == Direction.NEXT) { if (previous != null) { PipeControlPoint pcp = this; @@ -673,7 +801,7 @@ public class PipeControlPoint extends G3DNode implements IP3DNode { if (next != null) { PipeControlPoint pcp = this; if (pcp.isDualInline()) { - pcp = pcp.getSubPoint().get(0); + pcp = pcp.getDualSub(); } Vector3d v = new Vector3d(); v.sub(next.getWorldPosition(),pcp.getWorldPosition()); @@ -681,12 +809,12 @@ public class PipeControlPoint extends G3DNode implements IP3DNode { } else { if (previous == null) { if (!isDirected()) - throw new RuntimeException("Cannot calculate path leg direction for unconnected control point"); + throw new RuntimeException("Cannot calculate path leg direction for unconnected control point " + this); return getDirectedControlPointDirection(); } else { - if (isVariableAngle()) - throw new RuntimeException("Cannot calculate path leg direction for unconnected variable angle control point"); + 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()) { @@ -701,10 +829,10 @@ public class PipeControlPoint extends G3DNode implements IP3DNode { Vector3d v = new Vector3d(); v.sub(getWorldPosition(),previous.getWorldPosition()); return v; - } else if (isTurn() && isFixed() && !_getReversed()) { + } else if (isTurn() && asFixedAngle() && !_getReversed()) { return getDirection(Direction.NEXT); } - throw new RuntimeException("Missing implementation"); + throw new RuntimeException("Missing implementation " + this); } } } else { @@ -718,17 +846,17 @@ public class PipeControlPoint extends G3DNode implements IP3DNode { } else { if (next == null) { if (!isDirected()) - throw new RuntimeException("Cannot calculate path leg direction for unconnected control point"); + throw new RuntimeException("Cannot calculate path leg direction for unconnected control point " + this); Vector3d v = getDirectedControlPointDirection(); v.negate(); return v; } else { - if (isVariableAngle()) - throw new RuntimeException("Cannot calculate path leg direction for unconnected variable angle control point"); + 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.getSubPoint().get(0); + pcp = pcp.getDualSub(); } Vector3d v = new Vector3d(); v.sub(pcp.getWorldPosition(),next.getWorldPosition()); @@ -741,10 +869,10 @@ public class PipeControlPoint extends G3DNode implements IP3DNode { Vector3d v = new Vector3d(); v.sub(getWorldPosition(),next.getWorldPosition()); return v; - } else if (isTurn() && isFixed() && _getReversed()) { + } else if (isTurn() && asFixedAngle() && _getReversed()) { return getDirection(Direction.PREVIOUS); } - throw new RuntimeException("Missing implementation"); + throw new RuntimeException("Missing implementation " + this); } } } @@ -753,7 +881,7 @@ public class PipeControlPoint extends G3DNode implements IP3DNode { public void getInlineControlPointEnds(Tuple3d p1, Tuple3d p2) { assert (isInline()); - PipeControlPoint sub = isAxial() ? this : getSubPoint().get(0); + PipeControlPoint sub = isAxial() ? this : getDualSub(); Vector3d pos = getWorldPosition(), pos2 = sub == this ? pos : sub.getWorldPosition(); Vector3d dir = sub.getPathLegDirection(Direction.NEXT); @@ -766,7 +894,7 @@ public class PipeControlPoint extends G3DNode implements IP3DNode { } public void getControlPointEnds(Tuple3d p1, Tuple3d p2) { - PipeControlPoint sub = isAxial() ? this : getSubPoint().get(0); + PipeControlPoint sub = isAxial() || isDirected() || isTurn() ? this : getChildPoints().get(0); Vector3d pos = getWorldPosition(), pos2 = sub == this ? pos : sub.getWorldPosition(); Vector3d dir1 = getPathLegDirection(Direction.PREVIOUS); @@ -787,7 +915,7 @@ public class PipeControlPoint extends G3DNode implements IP3DNode { } public void getEndDirections(Tuple3d v1, Tuple3d v2) { - PipeControlPoint sub = isAxial() ? this : getSubPoint().get(0); + PipeControlPoint sub = isAxial() ? this : getDualSub(); Vector3d dir1 = getPathLegDirection(Direction.PREVIOUS); dir1.normalize(); @@ -938,20 +1066,38 @@ public class PipeControlPoint extends G3DNode implements IP3DNode { } } } - + public void _remove() { - if (component == null && next == null && previous == null) - return; - if (isDualInline() || isDualSub()) { - removeDualPoint(); - return; + _remove(true); + } + + + public PipeControlPoint getDualSub() { + if (isDualInline()) + return getChildPoints().get(0); + else + throw new IllegalStateException("Current control point is not dual inline"); + } + + + public void _remove(boolean renconnect) { + if (disposed) + return; + + if (DEBUG) System.out.println(this + " Remove " + renconnect); + + if (getParentPoint() != null) { + getParentPoint()._remove(renconnect); + return; } PipeRun pipeRun = getPipeRun(); - if (pipeRun == null) - return; +// PipeRUn removal has been changed, so pipeRun may be null. +// if (pipeRun == null) +// return; PipeControlPoint additionalRemove = null; if (!PipingRules.isEnabled()) { + component = null; setPrevious(null); setNext(null); } else { @@ -960,44 +1106,51 @@ public class PipeControlPoint extends G3DNode implements IP3DNode { PipeControlPoint currentNext = next; if (currentNext == null && currentPrev == null) { removeComponent(); - pipeRun.remChild(this); + if (pipeRun != null) { + pipeRun.remChild(this); + checkRemove(pipeRun); + } return; } if (currentNext != null && currentPrev != null) { - boolean link = true; + boolean link = renconnect; if (currentNext.isBranchEnd()) { link = false; - // currentNext.setPrevious(null); - // currentNext.setNext(null); currentNext.remove(); currentNext = null; setNext(null); } if (currentPrev.isBranchEnd()) { link = false; - // currentPrev.setPrevious(null); - // currentPrev.setNext(null); currentPrev.remove(); currentPrev = null; setPrevious(null); } - if (link && currentPrev.isDirected() && currentNext.isDirected()) { - link = false; + if (link) { + if (currentPrev.isDirected() && currentNext.isDirected()) + link = false; + else if (this.isDualInline()) { + link = false; + } else if (this.isDualSub()) { + throw new RuntimeException("_remove() is called for parent point, somehow got to child point. " + this); + } } if (currentNext == null) { // Nothing to do } else if (currentNext.isDualInline()) { PipeControlPoint sccp = currentNext; - PipeControlPoint ocp = sccp.getSubPoint().get(0); + PipeControlPoint ocp = currentNext.getDualSub(); if (ocp == null) { throw new RuntimeException("Removing PipeControlPoint " + this+ " structure damaged, no offset control point"); } if (link) { sccp.setPrevious(currentPrev); - ocp.setPrevious(currentPrev); + //ocp.setPrevious(currentPrev); + assert(ocp.getPrevious() == currentPrev); } else { sccp.setPrevious(null); - ocp.setPrevious(null); + //ocp.setPrevious(null); + assert(ocp.getPrevious() == null); } setNext(null); } else if (currentNext.isDualSub()) { @@ -1009,6 +1162,16 @@ public class PipeControlPoint extends G3DNode implements IP3DNode { currentNext.setPrevious(null); } setNext(null); + } else if (isDualInline()) { + if (currentNext.previous != getDualSub()) { + throw new RuntimeException("Removing PipeControlPoint "+ this+ " structure damaged"); + } + if (link) { + currentNext.setPrevious(currentPrev); + } else { + currentNext.setPrevious(null); + } + setNext(null); } else { throw new RuntimeException("Removing PipeControlPoint "+ this+ " structure damaged"); } @@ -1018,15 +1181,17 @@ public class PipeControlPoint extends G3DNode implements IP3DNode { throw new RuntimeException("Removing PipeControlPoint " + this + " structure damaged, previous control point is size change control point"); } else if (currentPrev.isDualSub()) { PipeControlPoint ocp = currentPrev; - PipeControlPoint sccp = ocp.getParentPoint(); + PipeControlPoint sccp = currentPrev.getParentPoint(); if (sccp == null) throw new RuntimeException("Removing PipeControlPoint " + this + " structure damaged, no size change control point"); if (link) { - ocp.setNext(currentNext); + //ocp.setNext(currentNext); sccp.setNext(currentNext); + assert(ocp.getNext() == currentNext); } else { - ocp.setNext(null); + //ocp.setNext(null); sccp.setNext(null); + assert(ocp.getNext() == null); } setPrevious(null); } else if (currentPrev.next == this) { @@ -1060,36 +1225,42 @@ public class PipeControlPoint extends G3DNode implements IP3DNode { } else { // FIXME : pipe run must be split into two parts, since the control point structure is no more continuous. } - } else if (next != null) { - if (next.isDualInline()) { - PipeControlPoint sccp = next; - PipeControlPoint ocp = sccp.getSubPoint().get(0); + } else if (currentNext != null) { + if (currentNext.isDualInline()) { + PipeControlPoint sccp = currentNext; + PipeControlPoint ocp = getDualSub(); if (ocp == null) { throw new RuntimeException("Removing PipeControlPoint " + this+ " structure damaged, no offset control point"); } sccp.setPrevious(null); - ocp.setPrevious(null); - } else if (next.isDualSub()) { + assert(ocp.getPrevious() == null); + //ocp.setPrevious(null); + } else if (currentNext.isDualSub()) { throw new RuntimeException("Removing PipeControlPoint " + this + " structure damaged, next control point is offset control point"); - } else if (next.previous == this) { - next.setPrevious(null); + } else if (currentNext.previous == this) { + currentNext.setPrevious(null); + } else if (isDualInline()) { + if (currentNext.previous != getDualSub()) { + throw new RuntimeException("Removing PipeControlPoint "+ this+ " structure damaged"); + } + currentNext.setPrevious(null); } else { throw new RuntimeException("Removing PipeControlPoint "+ this+ " structure damaged"); } setNext(null); } else { //(previous != null) - if(previous.isDualInline()) { + if(currentPrev.isDualInline()) { throw new RuntimeException("Removing PipeControlPoint " + this + " structure damaged, previous control point is size change control point"); - } else if (previous.isDualSub()) { - PipeControlPoint ocp = previous; - PipeControlPoint sccp = ocp.getParentPoint(); + } else if (currentPrev.isDualSub()) { + PipeControlPoint ocp = currentPrev; + PipeControlPoint sccp = currentPrev.getParentPoint(); if (sccp == null) { throw new RuntimeException("Removing PipeControlPoint " + this + " structure damaged, no size change control point"); } - ocp.setNext(null); sccp.setNext(null); - } else if (previous.next == this) { - previous.setNext(null); + assert(ocp.getNext() == null); + } else if (currentPrev.next == this) { + currentPrev.setNext(null); } else { throw new RuntimeException("Removing PipeControlPoint "+ this+ " structure damaged"); } @@ -1104,89 +1275,146 @@ public class PipeControlPoint extends G3DNode implements IP3DNode { } removeComponent(); - pipeRun.remChild(this); - checkRemove(pipeRun); - if (PipingRules.isEnabled() && pipeRun.getParent() != null && pipeRun.getControlPoints().size() > 0) - PipingRules.validate(pipeRun); + if (pipeRun != null) { + pipeRun.remChild(this); + checkRemove(pipeRun); + if (PipingRules.isEnabled() && pipeRun.getParent() != null && pipeRun.getControlPoints().size() > 0) + PipingRules.validate(pipeRun); + } if (additionalRemove != null) additionalRemove.remove(); + disposed = true; } + /** + * Removes control point and attempts to reconnect next/prev + * + * If this point is size change (PipeRuns are different on both sides), then reconnection cannot be made. + */ public void remove() { PipeControlPoint currentPrev = previous; PipeControlPoint currentNext = next; _remove(); try { if (currentNext != null) - PipingRules.requestUpdate(currentNext); + if (!currentNext.checkRemove()) + PipingRules.requestUpdate(currentNext); if (currentPrev != null) - PipingRules.requestUpdate(currentPrev); + if (!currentPrev.checkRemove()) + PipingRules.requestUpdate(currentPrev); } catch (Exception e) { e.printStackTrace(); } } + + + /** + * Removes control point without attempting to reconnect next/prev. + * This usually leads to creation of another PipeRun for the control points after this point. + */ + public void removeAndSplit() { + PipeControlPoint currentPrev = previous; + PipeControlPoint currentNext = next; + + if (next != null && previous != null) { + P3DRootNode root = (P3DRootNode)getPipelineComponent().getRootNode(); + PipeRun nextPipeRun = new PipeRun(); + nextPipeRun.setName(root.getUniqueName("PipeRun")); + root.addChild(nextPipeRun); + + PipeRun previousRun = previous.getPipeRun(); + nextPipeRun.setPipeDiameter(previousRun.getPipeDiameter()); + nextPipeRun.setTurnRadiusArray(previousRun.getTurnRadiusArray()); + + PipelineComponent n = next.getPipelineComponent(); + while (n != null) { + if (n.getPipeRun() != previousRun) + break; + if (! (n instanceof Nozzle)) { + n.deattach(); + nextPipeRun.addChild(n); + } else + n.setPipeRun(nextPipeRun); + n = n.getNext(); + } + } + _remove(false); + try { + if (currentNext != null) + if (!currentNext.checkRemove()) + PipingRules.requestUpdate(currentNext); + if (currentPrev != null) + if (!currentPrev.checkRemove()) + PipingRules.requestUpdate(currentPrev); + } catch (Exception e) { + e.printStackTrace(); + } + } + + /** + * This is called when adjacent control point is removed. + * + * This call should remove the give point, if the point cannot exist alone. + * At the moment there is one such case: branch. + * + * @return + */ + protected boolean checkRemove() { + if (getParentPoint() != null) { + return getParentPoint().checkRemove(); + } else { + if (getPipelineComponent() == null) + return true; // already removed + if (getPipelineComponent().getType().equals("Plant3D.URIs.Builtin_BranchSplitComponent")) { + if (getChildPoints().get(0).getNext() == null && getChildPoints().get(0).getPrevious() == null) { + remove(); + return true; + } + } + return checkRemove(getPipeRun()); + } + } - private void checkRemove(PipeRun pipeRun) { + private boolean checkRemove(PipeRun pipeRun) { + if (pipeRun == null) + return false; Collection points = pipeRun.getControlPoints(); if (points.size() == 0) { pipeRun.remove(); + return true; } else if (points.size() == 1) { PipeControlPoint pcp = points.iterator().next(); - if (pcp.isDeletable()) - pcp._remove(); - } - } - - private void removeDualPoint() { - if (previous != null) - previous.setNext(null); - if (next != null) - next.setPrevious(null); - PipeControlPoint ocp; - PipeControlPoint sccp; - if (isDualInline()) { - sccp = this; - ocp = getSubPoint().get(0); - } else { - ocp = this; - sccp = getParentPoint(); + if (pcp.isDeletable() && pcp.getNext() == null && pcp.getPrevious() == null) { + pcp._remove(); // This call will recursively call also this method... + return true; + } + } else if (points.size() == 2) { + } - PipeRun p1 = ocp.getPipeRun(); - PipeRun p2 = sccp.getPipeRun(); - - ocp.removeComponent(); - sccp.removeComponent(); - - if (p1 != null) - p1.remChild(ocp); - if (p2 != null) - p2.remChild(sccp); - - // TODO : now we assume that this is size change, and we do - if (ocp.next != null) - ocp.next.setPrevious(null); - if (ocp.previous != null) - ocp.previous.setNext(null); - if (sccp.next != null) - sccp.next.setPrevious(null); - if (sccp.previous != null) - sccp.previous.setNext(null); - ocp.setNext(null); - ocp.setPrevious(null); - sccp.setNext(null); - sccp.setPrevious(null); - - if (p1 != null) - checkRemove(p1); - if (p2 != null) - checkRemove(p2); + return false; } private void removeSubPoints() { for (PipeControlPoint p : children) { - // TODO : this may affect delete routine, since classification of the point changes. p.parent = null; - p._remove(); + p.component = null; + //p._remove(); + PipeControlPoint currentNext = p.getNext(); + PipeControlPoint currentPrev = p.getPrevious(); + p._setNext(null); + p._setPrevious(null); + PipeRun run = p.getPipeRun(); + if (run != null) { + run.remChild(p); + checkRemove(run); + } + if (currentNext != null) + if (!currentNext.checkRemove()) + PipingRules.requestUpdate(currentNext); + if (currentPrev != null) + if (!currentPrev.checkRemove()) + PipingRules.requestUpdate(currentPrev); + } children.clear(); } @@ -1194,6 +1422,10 @@ public class PipeControlPoint extends G3DNode implements IP3DNode { private void removeParentPoint() { throw new RuntimeException("Child points cannot be removed directly"); } + + public boolean isRemoved() { + return component == null; + } private void removeComponent() { if (component == null) @@ -1259,20 +1491,20 @@ public class PipeControlPoint extends G3DNode implements IP3DNode { private void updateSubPoint() { if (isOffset()) { if (next == null && previous == null) { - for (PipeControlPoint sub : getSubPoint()) { + for (PipeControlPoint sub : getChildPoints()) { sub.setWorldPosition(getWorldPosition()); sub.setWorldOrientation(getWorldOrientation()); } return; } - for (PipeControlPoint sub : getSubPoint()) { + for (PipeControlPoint sub : getChildPoints()) { Vector3d wp = getWorldPosition(); wp.add(getSizeChangeOffsetVector()); sub.setWorldPosition(wp); sub.setWorldOrientation(getWorldOrientation()); } } else { - for (PipeControlPoint sub : getSubPoint()) { + for (PipeControlPoint sub : getChildPoints()) { sub.setWorldPosition(getWorldPosition()); sub.setWorldOrientation(getWorldOrientation()); }