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=93186779e60d580aa31d23a95585ce4886ff9f7b;hb=27fb679643fab3ef9aa46d04c5ced2ea82cf60c2;hp=555a662089a41240b3ac17861b6130a657d68997;hpb=3df8cfcbfc89a89a52055d15ded33a004afc93c5;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 555a6620..93186779 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 @@ -1,11 +1,13 @@ package org.simantics.plant3d.scenegraph.controlpoint; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collection; import java.util.List; import javax.vecmath.AxisAngle4d; import javax.vecmath.Matrix3d; +import javax.vecmath.Point3d; import javax.vecmath.Quat4d; import javax.vecmath.Tuple3d; import javax.vecmath.Vector3d; @@ -21,31 +23,35 @@ import vtk.vtkRenderer; public class PipeControlPoint extends G3DNode implements IP3DNode { - - public enum Type{INLINE,TURN,END}; + + private static boolean DEBUG = false; + + public enum PointType{INLINE,TURN,END}; public enum Direction{NEXT,PREVIOUS}; public enum PositionType {SPLIT,NEXT,PREVIOUS,PORT} - + private PipelineComponent component; - - private Type type; - private boolean fixed = true; - private boolean rotate = false; - private boolean deletable = true; - private boolean sub = false; - + + 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; + public PipeControlPoint(PipelineComponent component) { this.component = component; if (component.getPipeRun() != null) component.getPipeRun().addChild(this); - + } - + public PipeControlPoint(PipelineComponent component, PipeRun piperun) { this.component = component; piperun.addChild(this); } - + @Override public void update(vtkRenderer ren) { try { @@ -53,188 +59,206 @@ public class PipeControlPoint extends G3DNode implements IP3DNode { } catch (Exception e) { e.printStackTrace(); } - + } - + public PipeRun getPipeRun() { return (PipeRun)getParent(); } - + public PipelineComponent getPipelineComponent() { return component; } - - public Type getType() { + + public PointType getType() { return type; } - - public void setType(Type type) { + + public void setType(PointType type) { this.type = type; } - + @GetPropertyValue(name="Fixed",tabId="Debug",value="fixed") public boolean isFixed() { - return fixed; + return isFixed; } - - + + public void setFixed(boolean fixed) { - this.fixed = fixed; + this.isFixed = fixed; } - + @GetPropertyValue(name="Rotate",tabId="Debug",value="rotate") public boolean isRotate() { - return rotate; + return isRotate; } - - + public void setRotate(boolean rotate) { - this.rotate = rotate; + this.isRotate = rotate; } - + + @GetPropertyValue(name="Reverse",tabId="Debug",value="reverse") + public boolean isReverse() { + return isReverse; + } + + public void setReverse(boolean reverse) { + this.isReverse = reverse; + } + public void setSub(boolean sub) { - this.sub = sub; + this.isSub = sub; } - + @GetPropertyValue(name="Deletable",tabId="Debug",value="deletable") public boolean isDeletable() { - return deletable; + return isDeletable; } - + public void setDeletable(boolean deletable) { - this.deletable = deletable; + this.isDeletable = deletable; } - + public boolean isPathLegEnd() { - return type != Type.INLINE; + return type != PointType.INLINE; } - + public boolean isEnd() { - return type == Type.END; + return type == PointType.END; } - + public boolean isTurn() { - return type == Type.TURN; + return type == PointType.TURN; } - + public boolean isInline() { - return type == Type.INLINE; + return type == PointType.INLINE; } - + public boolean isDirected() { - return fixed && isEnd(); + return isFixed && isEnd(); } - + public boolean isNonDirected() { - return !fixed && isEnd(); + return !isFixed && isEnd(); } - + public boolean isVariableLength() { - return !fixed && isInline(); + return !isFixed && isInline(); } - + public boolean isVariableAngle() { - return !fixed && isTurn(); + return !isFixed && isTurn(); } - + public boolean isBranchEnd() { - return deletable && isEnd(); + return isDeletable && isEnd(); } - + public boolean isOffset() { return offset != null; } - + public boolean isDualSub() { - return parent != null && sub; + return parent != null && isSub; } - + public boolean isDualInline() { return children.size() == 1 && children.get(0).isDualSub(); } - + + public boolean isAxial() { + return isInline() && !isDualInline(); + } + public boolean isSizeChange() { - if (children.size() == 0) - return false; - if (!isDualInline()) - return false; - return getPipeRun() != children.get(0).getPipeRun(); + return isSizeChange; + // if (children.size() == 0) + // return false; + // if (!isDualInline()) + // return false; + // return getPipeRun() != children.get(0).getPipeRun(); } - + public void setSizeChange(boolean isSizeChange) { + this.isSizeChange = isSizeChange; + } + + private PipeControlPoint next; private PipeControlPoint previous; - + public PipeControlPoint getNext() { return next; } - + public PipeControlPoint getPrevious() { return previous; } - + public void setNext(PipeControlPoint next) { if (isEnd() && previous != null && next != null) throw new RuntimeException("End control points are allowed to have only one connection"); -// if (next != null && getPipeRun() == null) -// throw new RuntimeException("Cannot connect control point befor piperun has been set"); + if (next == this) + throw new RuntimeException("Cannot connect to self"); + if (this.next == next) + return; + if (DEBUG) System.out.println(this + " next " + next); this.next = next; if (component != null) { - if (parent == null || sub) + if (parent == null || isSub) component.setNext(next != null ? next.component : null); else component.setBranch0(next != null ? next.component : null); updateSubPoint(); } - + } - + public void setPrevious(PipeControlPoint previous) { if (isEnd() && next != null && previous != null) throw new RuntimeException("End control points are allowed to have only one connection"); -// if (previous != null && getPipeRun() == null) -// throw new RuntimeException("Cannot connect control point befor piperun has been set"); + if (previous == this) + throw new RuntimeException("Cannot connect to self"); + if (this.previous == previous) + return; + if (DEBUG) System.out.println(this + " previous " + previous); this.previous = previous; if (component != null) { - if (parent == null || sub) + if (parent == null || isSub) component.setPrevious(previous != null ? previous.component : null); else component.setBranch0(previous != null ? previous.component : null); updateSubPoint(); } - + } - + public PipeControlPoint parent; public List children = new ArrayList(); - + public List getSubPoint() { return children; } - + public PipeControlPoint getParentPoint() { return parent; } - - - - - - - + private double length; private Double turnAngle; private Vector3d turnAxis; private Double offset; private Double rotationAngle; - + private Boolean reversed; + @GetPropertyValue(name="Length",tabId="Debug",value="length") public double getLength() { return length; } - + public void setLength(double l) { if (Double.isInfinite(l) || Double.isNaN(l)) { return; @@ -246,29 +270,40 @@ public class PipeControlPoint extends G3DNode implements IP3DNode { if (isDualInline()) getSubPoint().get(0).setLength(l); } - + @GetPropertyValue(name="Turn Angle",tabId="Debug",value="turnAngle") public Double getTurnAngle() { return turnAngle; } - + @GetPropertyValue(name="Turn Axis",tabId="Debug",value="turnAxis") public Vector3d getTurnAxis() { return turnAxis; } - + @GetPropertyValue(name="Offset",tabId="Debug",value="offset") public Double getOffset() { return offset; } - + @GetPropertyValue(name="Rotation Angle",tabId="Debug",value="rotationAngle") public Double getRotationAngle() { return rotationAngle; } - + + @GetPropertyValue(name="Reversed",tabId="Debug",value="reversed") + public Boolean getReversed() { + return reversed; + } + + public boolean _getReversed() { + if (reversed == null) + return false; + return reversed; + } + public void setTurnAngle(Double turnAngle) { - if (Double.isInfinite(turnAngle) || Double.isNaN(turnAngle)) { + if (turnAngle == null || Double.isInfinite(turnAngle) || Double.isNaN(turnAngle)) { return; } if (this.turnAngle != null && Math.abs(this.turnAngle-turnAngle) < MathTools.NEAR_ZERO) @@ -276,12 +311,14 @@ public class PipeControlPoint extends G3DNode implements IP3DNode { this.turnAngle = turnAngle; firePropertyChanged("turnAngle"); } - + public void setTurnAxis(Vector3d turnAxis) { + if (this.turnAxis != null && MathTools.equals(turnAxis, this.turnAxis)) + return; this.turnAxis = turnAxis; firePropertyChanged("turnAxis"); } - + public void setOffset(Double offset) { if (Double.isInfinite(offset) || Double.isNaN(offset)) { return; @@ -291,7 +328,7 @@ public class PipeControlPoint extends G3DNode implements IP3DNode { this.offset = offset; firePropertyChanged("offset"); } - + public void setRotationAngle(Double rotationAngle) { if (Double.isInfinite(rotationAngle) || Double.isNaN(rotationAngle)) { return; @@ -301,7 +338,12 @@ public class PipeControlPoint extends G3DNode implements IP3DNode { this.rotationAngle = rotationAngle; firePropertyChanged("rotationAngle"); } - + + public void setReversed(Boolean reversed) { + this.reversed = reversed; + firePropertyChanged("reversed"); + } + public Vector3d getSizeChangeOffsetVector(Vector3d dir) { Quat4d q; if (rotationAngle == null) @@ -309,11 +351,11 @@ public class PipeControlPoint extends G3DNode implements IP3DNode { else q = getControlPointOrientationQuat(dir, rotationAngle); Vector3d v = new Vector3d(0.0,offset,0.0); - Vector3d offset = new Vector3d(); - MathTools.rotate(q, v, offset); - return offset; + Vector3d offset = new Vector3d(); + MathTools.rotate(q, v, offset); + return offset; } - + public Vector3d getSizeChangeOffsetVector() { Quat4d q; if (rotationAngle == null) @@ -321,126 +363,150 @@ public class PipeControlPoint extends G3DNode implements IP3DNode { else q = getControlPointOrientationQuat(rotationAngle); Vector3d v = new Vector3d(0.0,offset,0.0); - Vector3d offset = new Vector3d(); - MathTools.rotate(q, v, offset); - return offset; + Vector3d offset = new Vector3d(); + MathTools.rotate(q, v, offset); + return offset; } - + @GetPropertyValue(name="Next",tabId="Debug",value="next") private String getNextString() { if (next == null) return null; return next.toString(); } - + @GetPropertyValue(name="Previous",tabId="Debug",value="previous") private String getPrevString() { if (previous == null) return null; return previous.toString(); } - - public Quat4d getControlPointOrientationQuat(double angle) { - - if (turnAxis == null) { - Vector3d dir = getPathLegDirection(Direction.NEXT); - if (dir.lengthSquared() > MathTools.NEAR_ZERO) - dir.normalize(); - return getControlPointOrientationQuat(dir, angle); - } else { - Vector3d dir = getPathLegDirection(Direction.PREVIOUS); - dir.negate(); - if (dir.lengthSquared() > MathTools.NEAR_ZERO) - dir.normalize(); - return getControlPointOrientationQuat(dir, turnAxis, angle); - } - } - - - - public static Quat4d getControlPointOrientationQuat(Vector3d dir, double angle) { - if (dir.lengthSquared() < MathTools.NEAR_ZERO) - return MathTools.getIdentityQuat(); - - - Vector3d up = new Vector3d(0.0, 1.0, 0.0); - double a = up.angle(dir); - if (a < 0.1 || (Math.PI - a) < 0.1) { - up.set(1.0, 0.0, 0.0); + + @GetPropertyValue(name="Sub",tabId="Debug",value="sub") + private String getSubString() { + if (children.size() == 0) + return ""; + return Arrays.toString(children.toArray()); + } + + @GetPropertyValue(name="Type",tabId="Debug",value="type") + public String getTypeString() { + return type.name(); + } + + public Quat4d getControlPointOrientationQuat(double angle) { + + if (turnAxis == null) { + Vector3d dir = getPathLegDirection(Direction.NEXT); + if (dir.lengthSquared() > MathTools.NEAR_ZERO) + dir.normalize(); + return getControlPointOrientationQuat(dir, angle); + } else { + Vector3d dir = getPathLegDirection(Direction.PREVIOUS); + dir.negate(); + 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 getControlPointOrientationQuat(dir, up, angle); - } - - public static Quat4d getControlPointOrientationQuat(Vector3d dir, Vector3d up, double angle) { - if (dir.lengthSquared() < MathTools.NEAR_ZERO) - return MathTools.getIdentityQuat(); - - final Vector3d front = new Vector3d(1.0,0.0,0.0); - - Quat4d q1 = new Quat4d(); - - - Vector3d right = new Vector3d(); - - right.cross(dir, up); - up.cross(right, dir); - right.normalize(); - up.normalize(); - - Matrix3d m = new Matrix3d(); - m.m00 = dir.x; - m.m10 = dir.y; - m.m20 = dir.z; - m.m01 = up.x; - m.m11 = up.y; - m.m21 = up.z; - m.m02 = right.x; - m.m12 = right.y; - m.m22 = right.z; - - //q1.set(m); MathTools contains more stable conversion - MathTools.getQuat(m, q1); - -// if (DEBUG) System.out.println("PipingTools.getPipeComponentOrientationQuat() " + dir+ " " + up + " " + right); - - Quat4d q2 = new Quat4d(); - q2.set(new AxisAngle4d(front, angle)); - q1.mul(q2); - return q1; - } - - public Vector3d getDirection() { - return getDirectedControlPointDirection(); + return q; + } else { + Vector3d dir = getPathLegDirection(Direction.PREVIOUS); + dir.negate(); + if (dir.lengthSquared() > MathTools.NEAR_ZERO) + dir.normalize(); + return getControlPointOrientationQuat(dir, turnAxis, angle); + } + } + + + + public static Quat4d getControlPointOrientationQuat(Vector3d dir, double angle) { + if (dir.lengthSquared() < MathTools.NEAR_ZERO) + return MathTools.getIdentityQuat(); + + + Vector3d up = new Vector3d(0.0, 1.0, 0.0); + double a = up.angle(dir); + if (a < 0.1 || (Math.PI - a) < 0.1) { + up.set(1.0, 0.0, 0.0); + } + + + return getControlPointOrientationQuat(dir, up, angle); + } + + public static Quat4d getControlPointOrientationQuat(Vector3d dir, Vector3d up, double angle) { + if (dir.lengthSquared() < MathTools.NEAR_ZERO) + return MathTools.getIdentityQuat(); + + final Vector3d front = new Vector3d(1.0,0.0,0.0); + + Quat4d q1 = new Quat4d(); + + + Vector3d right = new Vector3d(); + + right.cross(dir, up); + up.cross(right, dir); + right.normalize(); + up.normalize(); + + Matrix3d m = new Matrix3d(); + m.m00 = dir.x; + m.m10 = dir.y; + m.m20 = dir.z; + m.m01 = up.x; + m.m11 = up.y; + m.m21 = up.z; + m.m02 = right.x; + m.m12 = right.y; + m.m22 = right.z; + + //q1.set(m); MathTools contains more stable conversion + MathTools.getQuat(m, q1); + + // if (DEBUG) System.out.println("PipingTools.getPipeComponentOrientationQuat() " + dir+ " " + up + " " + right); + + Quat4d q2 = new Quat4d(); + q2.set(new AxisAngle4d(front, angle)); + q1.mul(q2); + return q1; } - - - - - - public void insert(PipeControlPoint previous, PipeControlPoint next) { // inserting an offsetpoint is error, if (isDualSub()) - throw new RuntimeException(); + throw new RuntimeException("Dual sub points cannot be inserted."); // size change control point cannot be inserted this way, because it ends PipeRun if (isSizeChange()) - throw new RuntimeException(); + throw new RuntimeException("Size change points cannot be inserted."); PipeRun piperun = previous.getPipeRun(); // and just to make sure that control point structure is not corrupted if (getPipeRun() != null) { if (piperun != getPipeRun() || piperun != next.getPipeRun()) - throw new RuntimeException(); + throw new RuntimeException("All controls points must be located on the same pipe run"); } else { piperun.addChild(this); } - + // insert new BranchControlPoint between straight's control points PipeControlPoint previousNext = previous.getNext(); PipeControlPoint previousPrevious = previous.getPrevious(); - + PipeControlPoint offsetCP = null; if (isOffset()) { offsetCP = getSubPoint().get(0); @@ -458,7 +524,7 @@ public class PipeControlPoint extends G3DNode implements IP3DNode { previous.getParentPoint().setNext(this); } this.setNext(next); - + if (offsetCP == null) { next.setPrevious(this); } else { @@ -466,17 +532,17 @@ public class PipeControlPoint extends G3DNode implements IP3DNode { offsetCP.setNext(next); offsetCP.setPrevious(previous); } - + if (next.isDualInline()) { next.getSubPoint().get(0).setPrevious(this); } } else if (previousPrevious != null && previousPrevious == next) { - // control point were given in reverse order + // control point were given in reverse order if (next.isDualInline()) throw new RuntimeException(); if (previous.isDualSub()) throw new RuntimeException(); - + this.setNext(previous); if (offsetCP == null) { previous.setNext(this); @@ -493,16 +559,16 @@ public class PipeControlPoint extends G3DNode implements IP3DNode { if (next.isDualSub()) { next.getParentPoint().setNext(this); } - + } else { throw new RuntimeException(); } - + PipingRules.validate(piperun); } - - - + + + public void insert(PipeControlPoint pcp, Direction direction) { if (isDualSub()) throw new RuntimeException(); @@ -544,11 +610,11 @@ public class PipeControlPoint extends G3DNode implements IP3DNode { else ocp.setPrevious(nocp); } - + } PipingRules.validate(getPipeRun()); } - + public Vector3d getDirectedControlPointDirection() { assert (isDirected()); Vector3d dir = new Vector3d(); @@ -557,6 +623,51 @@ public class PipeControlPoint extends G3DNode implements IP3DNode { return dir; } + public Vector3d getDirection(Direction direction) { + if (isDirected()) + return getDirectedControlPointDirection(); + if (isTurn() && isFixed()) { + if (direction == Direction.NEXT) { + if (previous != null) { + PipeControlPoint pcp = this; + Vector3d dir = new Vector3d(); + dir.sub(pcp.getWorldPosition(),previous.getWorldPosition()); + if (dir.lengthSquared() > MathTools.NEAR_ZERO) + dir.normalize(); + else + return null; + Quat4d q = getControlPointOrientationQuat(dir, pcp.getRotationAngle() != null ? pcp.getRotationAngle() : 0.0); + AxisAngle4d aa = new AxisAngle4d(MathTools.Y_AXIS,pcp.getTurnAngle() == null ? 0.0 : pcp.getTurnAngle()); + Quat4d q2 = MathTools.getQuat(aa); + Vector3d v = new Vector3d(1.,0.,0.); + Vector3d offset = new Vector3d(); + MathTools.rotate(q2, v, offset); + MathTools.rotate(q, offset, dir); + return dir; + } + } else { + if (next != null) { + PipeControlPoint pcp = this; + Vector3d dir = new Vector3d(); + dir.sub(next.getWorldPosition(),pcp.getWorldPosition()); + if (dir.lengthSquared() > MathTools.NEAR_ZERO) + dir.normalize(); + else + return null; + Quat4d q = getControlPointOrientationQuat(dir, pcp.getRotationAngle() != null ? pcp.getRotationAngle() : 0.0); + AxisAngle4d aa = new AxisAngle4d(MathTools.Y_AXIS,pcp.getTurnAngle() == null ? 0.0 : pcp.getTurnAngle()); + Quat4d q2 = MathTools.getQuat(aa); + Vector3d v = new Vector3d(1.,0.,0.); + Vector3d offset = new Vector3d(); + MathTools.rotate(q2, v, offset); + MathTools.rotate(q, offset, dir); + return dir; + } + } + } + return null; + } + public Vector3d getPathLegDirection(Direction direction) { if (direction == Direction.NEXT) { if (next != null) { @@ -568,14 +679,14 @@ public class PipeControlPoint extends G3DNode implements IP3DNode { v.sub(next.getWorldPosition(),pcp.getWorldPosition()); return v; } else { - if (isVariableAngle()) - throw new RuntimeException("Cannot calculate path leg direction for unconnected variable angle control point"); if (previous == null) { if (!isDirected()) throw new RuntimeException("Cannot calculate path leg direction for unconnected control point"); return getDirectedControlPointDirection(); - + } else { + if (isVariableAngle()) + throw new RuntimeException("Cannot calculate path leg direction for unconnected variable angle control point"); if (isInline()) { PipeControlPoint pcp = this; if (pcp.isDualSub()) { @@ -590,6 +701,8 @@ public class PipeControlPoint extends G3DNode implements IP3DNode { Vector3d v = new Vector3d(); v.sub(getWorldPosition(),previous.getWorldPosition()); return v; + } else if (isTurn() && isFixed() && !_getReversed()) { + return getDirection(Direction.NEXT); } throw new RuntimeException("Missing implementation"); } @@ -603,8 +716,6 @@ public class PipeControlPoint extends G3DNode implements IP3DNode { v.sub(previous.getWorldPosition(),pcp.getWorldPosition()); return v; } else { - if (isVariableAngle()) - throw new RuntimeException("Cannot calculate path leg direction for unconnected variable angle control point"); if (next == null) { if (!isDirected()) throw new RuntimeException("Cannot calculate path leg direction for unconnected control point"); @@ -612,6 +723,8 @@ public class PipeControlPoint extends G3DNode implements IP3DNode { v.negate(); return v; } else { + if (isVariableAngle()) + throw new RuntimeException("Cannot calculate path leg direction for unconnected variable angle control point"); if (isInline()) { PipeControlPoint pcp = this; if (pcp.isDualInline()) { @@ -628,31 +741,37 @@ public class PipeControlPoint extends G3DNode implements IP3DNode { Vector3d v = new Vector3d(); v.sub(getWorldPosition(),next.getWorldPosition()); return v; + } else if (isTurn() && isFixed() && _getReversed()) { + return getDirection(Direction.PREVIOUS); } throw new RuntimeException("Missing implementation"); } } } } - + public void getInlineControlPointEnds(Tuple3d p1, Tuple3d p2) { assert (isInline()); + + PipeControlPoint sub = isAxial() ? this : getSubPoint().get(0); + Vector3d pos = getWorldPosition(), pos2 = sub == this ? pos : sub.getWorldPosition(); + Vector3d dir = sub.getPathLegDirection(Direction.NEXT); - Vector3d pos = getWorldPosition(); - Vector3d dir = getPathLegDirection(Direction.NEXT); dir.normalize(); dir.scale(length * 0.5); p1.set(pos); - p2.set(pos); + p2.set(pos2); p1.sub(dir); p2.add(dir); } - + public void getControlPointEnds(Tuple3d p1, Tuple3d p2) { - Vector3d pos = getWorldPosition(); + PipeControlPoint sub = isAxial() ? this : getSubPoint().get(0); + Vector3d pos = getWorldPosition(), pos2 = sub == this ? pos : sub.getWorldPosition(); + Vector3d dir1 = getPathLegDirection(Direction.PREVIOUS); dir1.normalize(); - Vector3d dir2 = getPathLegDirection(Direction.NEXT); + Vector3d dir2 = sub.getPathLegDirection(Direction.NEXT); dir2.normalize(); if (isInline()) { dir1.scale(length * 0.5); @@ -662,14 +781,25 @@ public class PipeControlPoint extends G3DNode implements IP3DNode { dir2.scale(length); } p1.set(pos); - p2.set(pos); + p2.set(pos2); p1.add(dir1); p2.add(dir2); } - + + public void getEndDirections(Tuple3d v1, Tuple3d v2) { + PipeControlPoint sub = isAxial() ? this : getSubPoint().get(0); + + Vector3d dir1 = getPathLegDirection(Direction.PREVIOUS); + dir1.normalize(); + Vector3d dir2 = sub.getPathLegDirection(Direction.NEXT); + dir2.normalize(); + v1.set(dir1); + v2.set(dir2); + } + public void getInlineControlPointEnds(Tuple3d p1, Tuple3d p2, Vector3d dir) { assert (isInline()); - + Vector3d pos = getWorldPosition(); dir.set(getPathLegDirection(Direction.NEXT)); dir.normalize(); @@ -679,10 +809,10 @@ public class PipeControlPoint extends G3DNode implements IP3DNode { p1.sub(dir); p2.add(dir); } - + public void getInlineControlPointEnds(Tuple3d center, Tuple3d p1, Tuple3d p2, Vector3d dir) { assert (isInline()); - + Vector3d pos = getWorldPosition(); center.set(pos); dir.set(getPathLegDirection(Direction.NEXT)); @@ -693,15 +823,15 @@ public class PipeControlPoint extends G3DNode implements IP3DNode { p1.sub(dir); p2.add(dir); } - + public double getInlineLength() { - if (type == Type.TURN) + if (type == PointType.TURN) return length; - else if (type == Type.INLINE) + else if (type == PointType.INLINE) return length * 0.5; return 0; } - + public Vector3d getRealPosition(PositionType type) { Vector3d pos = getWorldPosition(); switch (type) { @@ -728,11 +858,11 @@ public class PipeControlPoint extends G3DNode implements IP3DNode { case SPLIT: // do nothing break; - + } return pos; } - + public void getInlineMovement(Tuple3d start, Tuple3d end) { // FIXME : check type of neighbor components and allow movement on top of variable length components, // find proper range for movement (pcp's position is not) @@ -741,46 +871,46 @@ public class PipeControlPoint extends G3DNode implements IP3DNode { start.set(p.getWorldPosition()); end.set(n.getWorldPosition()); } - + public PipeControlPoint findNextEnd() { ArrayList t = new ArrayList(); - return findNextEnd( t); + return findNextEnd( t); } - + public PipeControlPoint findPreviousEnd() { ArrayList t = new ArrayList(); - return findPreviousEnd(t); + return findPreviousEnd(t); } - + public PipeControlPoint findNextEnd(List nextList) { - while (true) { - PipeControlPoint pcp = null; - PipeControlPoint p = null; - if (nextList.size() == 0) - p = this; - - else - p = nextList.get(nextList.size() - 1); - - pcp = p.getNext(); - if (pcp == null) { - pcp = p; - if (nextList.size() > 0) - nextList.remove(nextList.size() - 1); -// if (DEBUG) System.out.println(" " + pcp.getResource() + " not full"); - return pcp; - //break; - } - if (pcp.isPathLegEnd()) { - //if (DEBUG) System.out.println(" " + pcp.getResource()); - return pcp; - } else { - nextList.add(pcp); - // if (DEBUG) System.out.print(" " + pcp.getResource()); - } - } + while (true) { + PipeControlPoint pcp = null; + PipeControlPoint p = null; + if (nextList.size() == 0) + p = this; + + else + p = nextList.get(nextList.size() - 1); + + pcp = p.getNext(); + if (pcp == null) { + pcp = p; + if (nextList.size() > 0) + nextList.remove(nextList.size() - 1); + // if (DEBUG) System.out.println(" " + pcp.getResource() + " not full"); + return pcp; + //break; + } + if (pcp.isPathLegEnd()) { + //if (DEBUG) System.out.println(" " + pcp.getResource()); + return pcp; + } else { + nextList.add(pcp); + // if (DEBUG) System.out.print(" " + pcp.getResource()); + } + } } - + public PipeControlPoint findPreviousEnd(List prevList) { while (true) { PipeControlPoint pcp = null; @@ -796,19 +926,19 @@ public class PipeControlPoint extends G3DNode implements IP3DNode { pcp = p; if (prevList.size() > 0) prevList.remove(prevList.size() - 1); -// if (DEBUG) System.out.println(" " + pcp.getResource() + " not full"); + // if (DEBUG) System.out.println(" " + pcp.getResource() + " not full"); return pcp; } if (pcp.isPathLegEnd()) { -// if (DEBUG) System.out.println(" " + pcp.getResource()); + // if (DEBUG) System.out.println(" " + pcp.getResource()); return pcp; } else { prevList.add(pcp); -// if (DEBUG)System.out.print(" " + pcp.getResource()); + // if (DEBUG)System.out.print(" " + pcp.getResource()); } } } - + public void _remove() { if (component == null && next == null && previous == null) return; @@ -819,7 +949,7 @@ public class PipeControlPoint extends G3DNode implements IP3DNode { PipeRun pipeRun = getPipeRun(); if (pipeRun == null) return; - + PipeControlPoint additionalRemove = null; if (!PipingRules.isEnabled()) { setPrevious(null); @@ -837,16 +967,16 @@ public class PipeControlPoint extends G3DNode implements IP3DNode { boolean link = true; if (currentNext.isBranchEnd()) { link = false; -// currentNext.setPrevious(null); -// currentNext.setNext(null); + // currentNext.setPrevious(null); + // currentNext.setNext(null); currentNext.remove(); currentNext = null; setNext(null); } if (currentPrev.isBranchEnd()) { link = false; -// currentPrev.setPrevious(null); -// currentPrev.setNext(null); + // currentPrev.setPrevious(null); + // currentPrev.setNext(null); currentPrev.remove(); currentPrev = null; setPrevious(null); @@ -904,7 +1034,7 @@ public class PipeControlPoint extends G3DNode implements IP3DNode { currentPrev.setNext(currentNext); else currentPrev.setNext(null); - + setPrevious(null); } else { throw new RuntimeException("Removing PipeControlPoint " + this + " structure damaged"); @@ -913,7 +1043,19 @@ public class PipeControlPoint extends G3DNode implements IP3DNode { if (currentNext.isVariableLength() && currentPrev.isVariableLength()) { // we have to join them into single variable length component. additionalRemove = currentPrev; - //currentPrev.remove(); + // combine lengths and set the location of remaining control point to the center. + Point3d ps = new Point3d(); + Point3d pe = new Point3d(); + Point3d ns = new Point3d(); + Point3d ne = new Point3d(); + currentPrev.getInlineControlPointEnds(ps, pe); + currentNext.getInlineControlPointEnds(ns, ne); + double l = currentPrev.getLength() + currentNext.getLength(); + Vector3d cp = new Vector3d(); + cp.add(ps, ne); + cp.scale(0.5); + currentNext.setLength(l); + currentNext.setWorldPosition(cp); } } else { // FIXME : pipe run must be split into two parts, since the control point structure is no more continuous. @@ -958,9 +1100,9 @@ public class PipeControlPoint extends G3DNode implements IP3DNode { } else if (parent!= null) { removeParentPoint(); } - + } - + removeComponent(); pipeRun.remChild(this); checkRemove(pipeRun); @@ -969,7 +1111,7 @@ public class PipeControlPoint extends G3DNode implements IP3DNode { if (additionalRemove != null) additionalRemove.remove(); } - + public void remove() { PipeControlPoint currentPrev = previous; PipeControlPoint currentNext = next; @@ -983,7 +1125,7 @@ public class PipeControlPoint extends G3DNode implements IP3DNode { e.printStackTrace(); } } - + private void checkRemove(PipeRun pipeRun) { Collection points = pipeRun.getControlPoints(); if (points.size() == 0) { @@ -994,7 +1136,7 @@ public class PipeControlPoint extends G3DNode implements IP3DNode { pcp._remove(); } } - + private void removeDualPoint() { if (previous != null) previous.setNext(null); @@ -1011,13 +1153,15 @@ public class PipeControlPoint extends G3DNode implements IP3DNode { } PipeRun p1 = ocp.getPipeRun(); PipeRun p2 = sccp.getPipeRun(); - + ocp.removeComponent(); sccp.removeComponent(); - - p1.remChild(ocp); - p2.remChild(sccp); - + + 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); @@ -1031,11 +1175,13 @@ public class PipeControlPoint extends G3DNode implements IP3DNode { ocp.setPrevious(null); sccp.setNext(null); sccp.setPrevious(null); - - checkRemove(p1); - checkRemove(p2); + + if (p1 != null) + checkRemove(p1); + if (p2 != null) + checkRemove(p2); } - + private void removeSubPoints() { for (PipeControlPoint p : children) { // TODO : this may affect delete routine, since classification of the point changes. @@ -1044,33 +1190,50 @@ public class PipeControlPoint extends G3DNode implements IP3DNode { } children.clear(); } - + private void removeParentPoint() { throw new RuntimeException("Child points cannot be removed directly"); } - + private void removeComponent() { if (component == null) return; PipelineComponent next = component.getNext(); - PipelineComponent prev = component.getNext(); + PipelineComponent prev = component.getPrevious(); + PipelineComponent br0 = component.getBranch0(); + component.setNext(null); + component.setPrevious(null); + component.setBranch0(null); if (next != null) { if (next.getNext() == component) next.setNext(null); else if (next.getPrevious() == component) next.setPrevious(null); + else if (next.getBranch0() == component) + next.setBranch0(null); } if (prev != null) { if (prev.getNext() == component) prev.setNext(null); else if (prev.getPrevious() == component) prev.setPrevious(null); + else if (prev.getBranch0() == component) + prev.setBranch0(null); + } + if (br0 != null) { + if (br0.getNext() == component) + br0.setNext(null); + else if (br0.getPrevious() == component) + br0.setPrevious(null); + else if (br0.getBranch0() == component) + br0.setBranch0(null); } PipelineComponent comp = component; component = null; + comp.remove(); } - + @Override public void setOrientation(Quat4d orientation) { if (MathTools.equals(orientation, getOrientation())) @@ -1080,7 +1243,7 @@ public class PipeControlPoint extends G3DNode implements IP3DNode { component._setWorldOrientation(getWorldOrientation()); updateSubPoint(); } - + @Override public void setPosition(Vector3d position) { if (MathTools.equals(position, getPosition())) @@ -1092,7 +1255,7 @@ public class PipeControlPoint extends G3DNode implements IP3DNode { component._setWorldPosition(getWorldPosition()); updateSubPoint(); } - + private void updateSubPoint() { if (isOffset()) { if (next == null && previous == null) { @@ -1116,19 +1279,19 @@ public class PipeControlPoint extends G3DNode implements IP3DNode { } } - + public void _setWorldPosition(Vector3d position) { Vector3d localPos = getLocalPosition(position); super.setPosition(localPos); updateSubPoint(); } - + public void _setWorldOrientation(Quat4d orientation) { Quat4d localOr = getLocalOrientation(orientation); super.setOrientation(localOr); updateSubPoint(); } - + @Override public String toString() { return getClass().getName() + "@" + Integer.toHexString(hashCode());