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;
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 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
public PipeControlPoint(PipelineComponent component) {
this.component = component;
return isFixed;
}
-
public void setFixed(boolean fixed) {
this.isFixed = fixed;
}
return type == PointType.INLINE;
}
+ /**
+ * 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();
}
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();
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;
} 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()) {
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 {
} 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()) {
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);
}
}
}
}
public void getControlPointEnds(Tuple3d p1, Tuple3d p2) {
- PipeControlPoint sub = isAxial() ? this : getSubPoint().get(0);
+ PipeControlPoint sub = isAxial() || isDirected() || isTurn() ? this : getSubPoint().get(0);
Vector3d pos = getWorldPosition(), pos2 = sub == this ? pos : sub.getWorldPosition();
Vector3d dir1 = getPathLegDirection(Direction.PREVIOUS);
}
}
}
-
+
public void _remove() {
+ _remove(true);
+ }
+
+ public void _remove(boolean renconnect) {
if (component == null && next == null && previous == null)
return;
+ if (DEBUG) System.out.println(this + " Remove " + renconnect);
if (isDualInline() || isDualSub()) {
removeDualPoint();
return;
}
+ if (getParentPoint() != null) {
+ getParentPoint()._remove(renconnect);
+ }
PipeRun pipeRun = getPipeRun();
if (pipeRun == null)
return;
return;
}
if (currentNext != null && currentPrev != null) {
- boolean link = true;
+ boolean link = renconnect;
if (currentNext.isBranchEnd()) {
link = false;
// currentNext.setPrevious(null);
additionalRemove.remove();
}
+ /**
+ * 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 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 (getSubPoint().get(0).getNext() == null && getSubPoint().get(0).getPrevious() == null) {
+ remove();
+ return true;
+ }
+ }
+ return false;
+ }
+ }
private void checkRemove(PipeRun pipeRun) {
Collection<PipeControlPoint> points = pipeRun.getControlPoints();