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=e240dc585426b972dd93a42174ce99e24f4403c1;hb=0702c03a4c063b77af27ea492fafdd05c426bb62;hp=abd899ac23ae0af43f07b3020894fa29b9b0bfc9;hpb=2c16b9949ab2b8cdbdbff7bbda91eb862b1176ed;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 abd899ac..e240dc58 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 @@ -15,6 +15,7 @@ import javax.vecmath.Vector3d; import org.simantics.g3d.math.MathTools; import org.simantics.g3d.property.annotations.GetPropertyValue; import org.simantics.g3d.scenegraph.G3DNode; +import org.simantics.g3d.scenegraph.base.ParentNode; import org.simantics.plant3d.scenegraph.IP3DNode; import org.simantics.plant3d.scenegraph.Nozzle; import org.simantics.plant3d.scenegraph.P3DRootNode; @@ -331,9 +332,9 @@ public class PipeControlPoint extends G3DNode implements IP3DNode { // 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); + if (dir == null || dirOut == null) + return; dir.negate(); - dirOut.normalize(); - dir.normalize(); double angle = dir.angle(dirOut); //super._setNext(null); if (direction == Direction.NEXT) @@ -518,14 +519,10 @@ public class PipeControlPoint extends G3DNode implements IP3DNode { 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(); + if (dir != null) dir.negate(); return getControlPointOrientationQuat(dir, turnAxis, angle); } } @@ -563,7 +560,7 @@ public class PipeControlPoint extends G3DNode implements IP3DNode { public static Quat4d getControlPointOrientationQuat(Vector3d dir, double angle) { - if (dir.lengthSquared() < MathTools.NEAR_ZERO) + if (dir == null || dir.lengthSquared() < MathTools.NEAR_ZERO) return MathTools.getIdentityQuat(); @@ -578,7 +575,7 @@ public class PipeControlPoint extends G3DNode implements IP3DNode { } public static Quat4d getControlPointOrientationQuat(Vector3d dir, Vector3d up, double angle) { - if (dir.lengthSquared() < MathTools.NEAR_ZERO) + if (dir == null || dir.lengthSquared() < MathTools.NEAR_ZERO) return MathTools.getIdentityQuat(); final Vector3d front = new Vector3d(1.0,0.0,0.0); @@ -620,8 +617,8 @@ public class PipeControlPoint extends G3DNode implements IP3DNode { if (isDualSub()) 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("Size change points cannot be inserted."); +// if (isSizeChange()) +// 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) { @@ -751,6 +748,14 @@ public class PipeControlPoint extends G3DNode implements IP3DNode { return dir; } + /** + * Returns direction vector. + * + * For directed control points, always returns outwards pointing vector. + * + * @param direction + * @return normalized vector, or null + */ public Vector3d getDirection(Direction direction) { if (isDirected()) return getDirectedControlPointDirection(); @@ -771,6 +776,7 @@ public class PipeControlPoint extends G3DNode implements IP3DNode { Vector3d offset = new Vector3d(); MathTools.rotate(q2, v, offset); MathTools.rotate(q, offset, dir); + dir.normalize(); return dir; } } else { @@ -789,6 +795,7 @@ public class PipeControlPoint extends G3DNode implements IP3DNode { Vector3d offset = new Vector3d(); MathTools.rotate(q2, v, offset); MathTools.rotate(q, offset, dir); + dir.normalize(); return dir; } } @@ -796,6 +803,14 @@ public class PipeControlPoint extends G3DNode implements IP3DNode { return null; } + /** + * Returns path leg direction of the control point. + * + * This method differs from getDirection by also returning inward pointing vectors for directed control points. + * + * @param direction + * @return + */ public Vector3d getPathLegDirection(Direction direction) { if (direction == Direction.NEXT) { if (next != null) { @@ -805,6 +820,10 @@ public class PipeControlPoint extends G3DNode implements IP3DNode { } 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) { @@ -822,12 +841,20 @@ public class PipeControlPoint extends G3DNode implements IP3DNode { } 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); @@ -842,6 +869,10 @@ public class PipeControlPoint extends G3DNode implements IP3DNode { 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) { @@ -860,6 +891,10 @@ public class PipeControlPoint extends G3DNode implements IP3DNode { } 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(); @@ -868,6 +903,10 @@ public class PipeControlPoint extends G3DNode implements IP3DNode { } 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); @@ -883,9 +922,8 @@ public class PipeControlPoint extends G3DNode implements IP3DNode { PipeControlPoint sub = isAxial() ? this : getDualSub(); Vector3d pos = getWorldPosition(), pos2 = sub == this ? pos : sub.getWorldPosition(); - Vector3d dir = sub.getPathLegDirection(Direction.NEXT); + Vector3d dir = sub.getInlineDir(); - dir.normalize(); dir.scale(length * 0.5); p1.set(pos); p2.set(pos2); @@ -897,14 +935,16 @@ public class PipeControlPoint extends G3DNode implements IP3DNode { PipeControlPoint sub = isAxial() || isDirected() || isTurn() ? this : getChildPoints().get(0); Vector3d pos = getWorldPosition(), pos2 = sub == this ? pos : sub.getWorldPosition(); - Vector3d dir1 = getPathLegDirection(Direction.PREVIOUS); - dir1.normalize(); - Vector3d dir2 = sub.getPathLegDirection(Direction.NEXT); - dir2.normalize(); + Vector3d dir1; + Vector3d dir2; if (isInline()) { - dir1.scale(length * 0.5); + dir2 = getInlineDir(); dir2.scale(length * 0.5); + dir1 = new Vector3d(dir2); + dir1.negate(); } else { + dir1 = getPathLegDirection(Direction.PREVIOUS); + dir2 = sub.getPathLegDirection(Direction.NEXT); dir1.scale(length); dir2.scale(length); } @@ -914,22 +954,34 @@ public class PipeControlPoint extends G3DNode implements IP3DNode { p2.add(dir2); } + /** + * Get both path leg directions, with (0,0,0) if no connection exists. The returned vectors are not normalized. + * + * @param v1 Set to the direction towards the previous control point on output + * @param v2 Set to the direction towards the next control point on output + */ public void getEndDirections(Tuple3d v1, Tuple3d v2) { PipeControlPoint sub = isAxial() ? this : getDualSub(); Vector3d dir1 = getPathLegDirection(Direction.PREVIOUS); - dir1.normalize(); Vector3d dir2 = sub.getPathLegDirection(Direction.NEXT); - dir2.normalize(); - v1.set(dir1); - v2.set(dir2); + + if (dir1 != null) + v1.set(dir1); + else + v1.set(0,0,0); + + if (dir2 != null) + v2.set(dir2); + else + v2.set(0,0,0); } public void getInlineControlPointEnds(Tuple3d p1, Tuple3d p2, Vector3d dir) { assert (isInline()); Vector3d pos = getWorldPosition(); - dir.set(getPathLegDirection(Direction.NEXT)); + dir.set(getInlineDir()); dir.normalize(); dir.scale(length * 0.5); p1.set(pos); @@ -943,7 +995,7 @@ public class PipeControlPoint extends G3DNode implements IP3DNode { Vector3d pos = getWorldPosition(); center.set(pos); - dir.set(getPathLegDirection(Direction.NEXT)); + dir.set(getInlineDir()); dir.normalize(); dir.scale(length * 0.5); p1.set(pos); @@ -952,6 +1004,22 @@ public class PipeControlPoint extends G3DNode implements IP3DNode { p2.add(dir); } + public Vector3d getInlineDir() { + Vector3d dir = getPathLegDirection(Direction.NEXT); + if (dir == null) { + dir = getPathLegDirection(Direction.PREVIOUS); + if (dir != null) { + // Use reverse direction + dir.scale(-1.0); + } else { + // Control point is not connected at all, use current orientation + dir = new Vector3d(1,0,0); + MathTools.rotate(getWorldOrientation(), dir, dir); + } + } + return dir; + } + public double getInlineLength() { if (type == PointType.TURN) return length; @@ -960,22 +1028,27 @@ public class PipeControlPoint extends G3DNode implements IP3DNode { return 0; } + /** + * Return the position indicated by the argument. If the indicated direction is not connected, the + * control point's wolrd position is returned instead. + * + * @param type A selector for the position to be returned + * @return The selected position + */ public Vector3d getRealPosition(PositionType type) { Vector3d pos = getWorldPosition(); switch (type) { case NEXT: { - Vector3d dir = getPathLegDirection(Direction.NEXT); + Vector3d dir = getInlineDir(); double length = getInlineLength(); - dir.normalize(); dir.scale(length); pos.add(dir); break; } case PREVIOUS: { - Vector3d dir = getPathLegDirection(Direction.PREVIOUS); + Vector3d dir = getInlineDir(); double length = getInlineLength(); - dir.normalize(); - dir.scale(length); + dir.scale(-length); pos.add(dir); break; } @@ -1228,7 +1301,7 @@ public class PipeControlPoint extends G3DNode implements IP3DNode { } else if (currentNext != null) { if (currentNext.isDualInline()) { PipeControlPoint sccp = currentNext; - PipeControlPoint ocp = getDualSub(); + PipeControlPoint ocp = currentNext.getDualSub(); if (ocp == null) { throw new RuntimeException("Removing PipeControlPoint " + this+ " structure damaged, no offset control point"); } @@ -1470,6 +1543,8 @@ public class PipeControlPoint extends G3DNode implements IP3DNode { public void setOrientation(Quat4d orientation) { if (MathTools.equals(orientation, getOrientation())) return; + if (getPipelineComponent() != null && (getPipelineComponent() instanceof Nozzle)) + System.out.println(); super.setOrientation(orientation); if (getParentPoint() == null && component != null) component._setWorldOrientation(getWorldOrientation());