From 8b06e290cf681e2157824428395988063686e7b3 Mon Sep 17 00:00:00 2001 From: Marko Luukkainen Date: Mon, 12 Aug 2019 12:26:46 +0300 Subject: [PATCH] Support for fixed turn components gitlab #23 Change-Id: Idfee9d27e1209748199446734f94988e0f7d0e71 --- .../graph/plant3d.pgraph | 9 +- .../graph/plant3d_builtins.pgraph | 21 ++++ .../plant3d/actions/AddComponentAction.java | 106 ++++++++++++------ .../geometry/ElbowGeometryProvider.java | 9 ++ .../plant3d/scenegraph/TurnComponent.java | 57 ++++++++++ .../controlpoint/PipeControlPoint.java | 77 ++++++++++--- .../scenegraph/controlpoint/PipingRules.java | 77 ++++++++++--- 7 files changed, 285 insertions(+), 71 deletions(-) diff --git a/org.simantics.plant3d.ontology/graph/plant3d.pgraph b/org.simantics.plant3d.ontology/graph/plant3d.pgraph index 46a6a34b..040dd889 100644 --- a/org.simantics.plant3d.ontology/graph/plant3d.pgraph +++ b/org.simantics.plant3d.ontology/graph/plant3d.pgraph @@ -105,12 +105,13 @@ P3D.HasBranch9 returnProps) { + double t = Math.tan((Math.PI - turnAngle) * 0.5); + double R = 0.0; + if (t > MathTools.NEAR_ZERO) + R = turnRadius / t; + returnProps.put("length", R); + } } diff --git a/org.simantics.plant3d/src/org/simantics/plant3d/scenegraph/TurnComponent.java b/org.simantics.plant3d/src/org/simantics/plant3d/scenegraph/TurnComponent.java index 5f8139f4..4f787b8c 100644 --- a/org.simantics.plant3d/src/org/simantics/plant3d/scenegraph/TurnComponent.java +++ b/org.simantics.plant3d/src/org/simantics/plant3d/scenegraph/TurnComponent.java @@ -7,13 +7,17 @@ import javax.vecmath.Vector3d; import org.simantics.g3d.math.MathTools; import org.simantics.g3d.property.annotations.GetPropertyValue; +import org.simantics.g3d.property.annotations.SetPropertyValue; import org.simantics.g3d.scenegraph.base.ParentNode; import org.simantics.objmap.graph.annotations.DynamicGraphType; import org.simantics.objmap.graph.annotations.GetType; +import org.simantics.objmap.graph.annotations.RelatedGetValue; +import org.simantics.objmap.graph.annotations.RelatedSetValue; import org.simantics.objmap.graph.annotations.SetType; import org.simantics.plant3d.ontology.Plant3D; import org.simantics.plant3d.scenegraph.controlpoint.ControlPointFactory; import org.simantics.plant3d.scenegraph.controlpoint.PipeControlPoint; +import org.simantics.plant3d.scenegraph.controlpoint.PipingRules; @DynamicGraphType(Plant3D.URIs.TurnComponent) public class TurnComponent extends PipelineComponent { @@ -59,11 +63,33 @@ public class TurnComponent extends PipelineComponent { return map; } + public boolean isVariableAngle() { + return !controlPoint.isFixed(); + } + @Override + public void updateParameters() { + super.updateParameters(); + if (!isVariableAngle()) { + Map calculated = getCalculatedParameters(); + if (calculated.containsKey("length")) { + controlPoint.setLength((Double)calculated.get("length")); + } + } + } + + @RelatedGetValue(Plant3D.URIs.HasTurnAngle) public Double getTurnAngle() { return getControlPoint().getTurnAngle(); } + @RelatedSetValue(Plant3D.URIs.HasTurnAngle) + public void setTurnAngle(Double a) { + if (!getControlPoint().isFixed()) + return; + getControlPoint().setTurnAngle(a); + } + @GetPropertyValue(name="Turn Angle", value="turn angle", tabId = "Default") public Double getTurnAngleDeg() { Double d = getControlPoint().getTurnAngle(); @@ -81,6 +107,37 @@ public class TurnComponent extends PipelineComponent { return getTurnAxis(); } + @RelatedGetValue(Plant3D.URIs.HasRotationAngle) + @GetPropertyValue(name="Rotation Angle", value=Plant3D.URIs.HasRotationAngle, tabId = "Default") + public Double getRotationAngle() { + if (!controlPoint.isFixed()) + return null; + Double d = controlPoint.getRotationAngle(); + if (d == null) + return 0.0; + return MathTools.radToDeg(d); + } + @RelatedSetValue(Plant3D.URIs.HasRotationAngle) + @SetPropertyValue(value=Plant3D.URIs.HasRotationAngle) + public void setRotationAngle(Double angle) { + if (!controlPoint.isFixed()) + return; + + if (angle == null || Double.isInfinite(angle) || Double.isNaN(angle)) { + return; + } + angle = MathTools.degToRad(angle); + if (controlPoint.getRotationAngle() != null && Math.abs(controlPoint.getRotationAngle()-angle) < MathTools.NEAR_ZERO) + return; + controlPoint.setRotationAngle(angle); + try { + PipingRules.requestUpdate(getControlPoint()); + } catch (Exception e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + @Override protected double[] getColor() { if (getControlPoint() == null || !getControlPoint().isFixed()) 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 ecaeb7ae..22c58ddb 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 @@ -283,6 +283,12 @@ public class PipeControlPoint extends G3DNode implements IP3DNode { return reversed; } + public boolean _getReversed() { + if (reversed == null) + return false; + return reversed; + } + public void setTurnAngle(Double turnAngle) { if (Double.isInfinite(turnAngle) || Double.isNaN(turnAngle)) { return; @@ -320,7 +326,7 @@ public class PipeControlPoint extends G3DNode implements IP3DNode { public void setReversed(Boolean reversed) { this.reversed = reversed; - firePropertyChanged("rotationAngle"); + firePropertyChanged("reversed"); } public Vector3d getSizeChangeOffsetVector(Vector3d dir) { @@ -466,28 +472,59 @@ public class PipeControlPoint extends G3DNode implements IP3DNode { return q1; } - public Vector3d getDirection() { - return getDirectedControlPointDirection(); + 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(); + 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(); + 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 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); } @@ -623,14 +660,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()) { @@ -645,6 +682,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"); } @@ -658,8 +697,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"); @@ -667,7 +704,9 @@ public class PipeControlPoint extends G3DNode implements IP3DNode { v.negate(); return v; } else { - if (isInline()) { + if (isVariableAngle()) + throw new RuntimeException("Cannot calculate path leg direction for unconnected variable angle control point"); + if (isInline()) { PipeControlPoint pcp = this; if (pcp.isDualInline()) { pcp = pcp.getSubPoint().get(0); @@ -683,7 +722,9 @@ 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"); } } 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 3fc04881..be66cf14 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 @@ -442,12 +442,28 @@ public class PipingRules { updatePathLeg(new UpdateStruct2(start, startPoint, list, end, endPoint, dir, offset, hasOffsets, iter, reversed, toRemove, updated), lengthChange); } - + + private static boolean asDirected(PipeControlPoint pcp, Direction direction) { + if (pcp.isDirected()) + return true; + if (pcp.isTurn() && pcp.isFixed()) { + if (!pcp._getReversed()) + return direction == Direction.NEXT; + else + return direction == Direction.PREVIOUS; + } + return false; + } + + private static Vector3d direction(PipeControlPoint pcp, Direction direction) { + return pcp.getDirection(direction); + } + private static void updatePathLeg(UpdateStruct2 u, PathLegUpdateType lengthChange) throws Exception { int directed = 0; - if (u.start.isDirected()) + if (asDirected(u.start, Direction.NEXT)) directed++; - if (u.end.isDirected()) + if (asDirected(u.end, Direction.PREVIOUS)) directed++; switch (directed) { case 0: @@ -467,7 +483,7 @@ public class PipingRules { if (DEBUG) System.out.println("PipingRules.updateFreePipeRun " + u + " " + lengthChange); checkExpandPathLeg(u, lengthChange); - if (u.start.isInline() || u.end.isInline()) + if (u.start.isInline() || u.end.isInline() || u.start.isFixed() || u.end.isFixed()) processPathLeg(u, true, false); } @@ -789,7 +805,7 @@ public class PipingRules { boolean dcpStart = false; boolean inlineEnd = false; Vector3d position; - if (u.start.isDirected()) { + if (asDirected(u.start, Direction.NEXT)) { dcp = u.start; other = u.end; position = u.startPoint; @@ -807,7 +823,7 @@ public class PipingRules { inlineEnd = u.start.isInline(); } - Vector3d directedDirection = dcp.getDirection(); + Vector3d directedDirection = direction(dcp, dcpStart ? Direction.NEXT : Direction.PREVIOUS); Point3d directedEndPoint = new Point3d(u.endPoint); if (u.hasOffsets) directedEndPoint.add(u.offset); @@ -828,6 +844,8 @@ public class PipingRules { double distance = t.length(); boolean aligned = (distance < ALLOWED_OFFSET); if (aligned) { + if (u.start.isInline() || u.end.isInline() || u.start.isFixed() || u.end.isFixed()) + processPathLeg(u, true, false); checkExpandPathLeg(u, lengthChange, inlineEnd); } else { @@ -944,8 +962,8 @@ public class PipingRules { position1offset.sub(u.offset); Point3d position2offset = new Point3d(position2); position2offset.add(u.offset); - Vector3d dir1 = dcp1.getDirection(); - Vector3d dir2 = dcp2.getDirection(); + Vector3d dir1 = direction(dcp1, Direction.NEXT); + Vector3d dir2 = direction(dcp2, Direction.PREVIOUS); Vector3d p1 = MathTools.closestPointOnStraight(position1offset, position2, dir2); Vector3d p2 = MathTools.closestPointOnStraight(position2offset, position1, dir1); double d1 = position1.distance(new Point3d(p1)); @@ -1516,12 +1534,43 @@ public class PipingRules { private static double updateTurnControlPointTurn(PipeControlPoint tcp, PipeControlPoint prev, PipeControlPoint next) { if (DEBUG) System.out.println("PipingTools.updateTurnControlPointTurn()" + tcp); - if (next == null || prev == null) - return Math.PI; // FIXME : argh - Vector3d middlePoint = tcp.getWorldPosition(); - Vector3d nextPoint = next.getWorldPosition(); - Vector3d prevPoint = prev.getWorldPosition(); - return updateTurnControlPointTurn(tcp, middlePoint, prevPoint, nextPoint); + + if (!tcp.isFixed()) { + if (next == null || prev == null) + return Math.PI; // FIXME : argh + Vector3d middlePoint = tcp.getWorldPosition(); + Vector3d nextPoint = next.getWorldPosition(); + Vector3d prevPoint = prev.getWorldPosition(); + return updateTurnControlPointTurn(tcp, middlePoint, prevPoint, nextPoint); + } else { + Vector3d dir; + if (!tcp._getReversed()) { + if (prev == null) + return Math.PI; // FIXME : argh + + Vector3d middlePoint = tcp.getWorldPosition(); + Vector3d prevPoint = prev.getWorldPosition(); + dir = new Vector3d(); + dir.sub(middlePoint, prevPoint); + + } else { + if (next == null) + return Math.PI; // FIXME : argh + + Vector3d middlePoint = tcp.getWorldPosition(); + Vector3d nextPoint = next.getWorldPosition(); + dir = new Vector3d(); + dir.sub(nextPoint,middlePoint); + } + dir.normalize(); + + Quat4d q = PipeControlPoint.getControlPointOrientationQuat(dir, tcp.getRotationAngle() != null ? tcp.getRotationAngle() : 0.0); + Vector3d v = new Vector3d(); + MathTools.rotate(q, MathTools.Y_AXIS,v); + tcp.setTurnAxis(v); + tcp.setWorldOrientation(q); + return tcp.getTurnAngle(); + } } /** -- 2.45.2