From b93886889422a3111b05a6944b3bcb2cdd8c416a Mon Sep 17 00:00:00 2001 From: Marko Luukkainen Date: Fri, 1 Nov 2019 15:09:15 +0200 Subject: [PATCH] Allow multiple radii for turns. Now PipeRun turnRadius is an double array. TurnComponents contain turnRadiusIndex, which then picks specific radius for the turn. This change also contains minor refactoring for NodeMap implementations gitlab #43 Change-Id: I626a641135b5eff5819ce74288366ac0d9199ab8 --- .../simantics/g3d/csg/editor/CSGNodeMap.java | 20 ++----- .../g3d/vtk/common/AbstractVTKNodeMap.java | 27 ++++++--- .../graph/plant3d.pgraph | 22 +++---- .../simantics/plant3d/ontology/Plant3D.java | 16 +++++- .../simantics/plant3d/editor/P3DNodeMap.java | 33 +++++------ .../plant3d/scenegraph/GeometryComponent.java | 3 + .../simantics/plant3d/scenegraph/PipeRun.java | 32 +++++++++-- .../plant3d/scenegraph/PipelineComponent.java | 38 ++++++++----- .../plant3d/scenegraph/TurnComponent.java | 57 +++++++++++++------ .../controlpoint/PipeControlPoint.java | 2 +- .../scenegraph/controlpoint/PipingRules.java | 4 +- 11 files changed, 157 insertions(+), 97 deletions(-) diff --git a/org.simantics.g3d.csg/src/org/simantics/g3d/csg/editor/CSGNodeMap.java b/org.simantics.g3d.csg/src/org/simantics/g3d/csg/editor/CSGNodeMap.java index bcd28db4..48b710f6 100644 --- a/org.simantics.g3d.csg/src/org/simantics/g3d/csg/editor/CSGNodeMap.java +++ b/org.simantics.g3d.csg/src/org/simantics/g3d/csg/editor/CSGNodeMap.java @@ -88,11 +88,8 @@ public class CSGNodeMap extends AbstractVTKNodeMap { view.lock(); node.visualize(view); - - for (vtkProp3D act : node.getActors()) { - nodeToActor.add(node, act); - actorToNode.put(act, node); - } + + map(node, node.getActors()); view.unlock(); @@ -101,7 +98,7 @@ public class CSGNodeMap extends AbstractVTKNodeMap { private boolean hasActor(ICSGnode node) { - List list = nodeToActor.getValues(node); + Collection list = getRenderObjects(node); if (list == null || list.size() == 0) return false; return true; @@ -111,16 +108,11 @@ public class CSGNodeMap extends AbstractVTKNodeMap { if (Thread.currentThread() != view.getThreadQueue().getThread()) throw new RuntimeException("Illegal thread."); - List list = nodeToActor.getValues(node); - if (list != null) { - for (vtkProp obj : list) { - actorToNode.remove(obj); - } - nodeToActor.remove(node); + Collection list = getRenderObjects(node); + if (list.size() > 0) { + removeMap(node); view.lock(); - node.stopVisualize(); - view.unlock(); } } diff --git a/org.simantics.g3d.vtk/src/org/simantics/g3d/vtk/common/AbstractVTKNodeMap.java b/org.simantics.g3d.vtk/src/org/simantics/g3d/vtk/common/AbstractVTKNodeMap.java index 953ef198..2c37521b 100644 --- a/org.simantics.g3d.vtk/src/org/simantics/g3d/vtk/common/AbstractVTKNodeMap.java +++ b/org.simantics.g3d.vtk/src/org/simantics/g3d/vtk/common/AbstractVTKNodeMap.java @@ -56,8 +56,8 @@ public abstract class AbstractVTKNodeMap implements VT protected IMapping mapping; protected VtkView view; - protected MapList nodeToActor = new MapList(); - protected Map actorToNode = new HashMap(); + private MapList nodeToActor = new MapList(); + private Map actorToNode = new HashMap(); protected ParentNode rootNode; @@ -85,9 +85,7 @@ public abstract class AbstractVTKNodeMap implements VT e.printStackTrace(); } } - - - + protected abstract void addActor(E node); protected abstract void removeActor(E node); protected abstract void updateActor(E node,Set ids); @@ -114,6 +112,21 @@ public abstract class AbstractVTKNodeMap implements VT return nodeToActor.getValues((E)node); } + protected void map(E node, Collection props) { + for (vtkProp p : props) { + nodeToActor.add(node, p); + actorToNode.put(p, node); + } + } + + protected void removeMap(E node) { + Collection coll = nodeToActor.getValuesUnsafe(node); + for (vtkProp p : coll) { + actorToNode.remove(p); + } + nodeToActor.remove(node); + } + @SuppressWarnings("unchecked") @Override public ParentNode getRootNode() { @@ -218,7 +231,7 @@ public abstract class AbstractVTKNodeMap implements VT added.add(new Pair(node, id)); rangeModified = true; } - view.refresh(); + repaint(); } @SuppressWarnings("unchecked") @@ -394,7 +407,7 @@ public abstract class AbstractVTKNodeMap implements VT /** * When objects are removed (either from Java or Graph), after remove processing the Java objects remain in mapping cache. - * This causes problems with Undo and Redo, whcih the end up re-using the removed objects from mapping cache. + * This causes problems with Undo and Redo, which cause re-using the removed objects from mapping cache. * * This code here synchronizes removed and added objects to collect deletable objects. (a deletable object is one which is removed but not added). * diff --git a/org.simantics.plant3d.ontology/graph/plant3d.pgraph b/org.simantics.plant3d.ontology/graph/plant3d.pgraph index 7d0e4976..5621443e 100644 --- a/org.simantics.plant3d.ontology/graph/plant3d.pgraph +++ b/org.simantics.plant3d.ontology/graph/plant3d.pgraph @@ -113,32 +113,24 @@ P3D.HasLength { if (ids.contains(id)) { node.visualize(view); updateRenderObjectsFor(node); - updateTransform(node); + //updateTransform(node); break; } } @@ -83,7 +83,7 @@ public class P3DNodeMap extends AbstractVTKNodeMap { for (PipeControlPoint pcp : run.getControlPoints()) { updateActor(pcp, ids2); } - } + } if (ids.contains(G3D.URIs.hasPosition) || ids.contains(G3D.URIs.hasOrientation) || @@ -91,6 +91,10 @@ public class P3DNodeMap extends AbstractVTKNodeMap { ids.contains(G3D.URIs.hasWorldOrientation)) { updateTransform(node); } + if (ids.contains(Plant3D.URIs.HasTurnRadiusIndex)) { + node.visualize(view); + updateRenderObjectsFor(node); + } } private void updateTransform(IP3DNode node) { @@ -150,10 +154,8 @@ public class P3DNodeMap extends AbstractVTKNodeMap { node.visualize(view); - for (vtkProp3D act : node.getActors()) { - nodeToActor.add(node, act); - actorToNode.put(act, node); - } + map(node, node.getActors()); + if (DEBUG) System.out.println("Added " + node.getActors().size() + " actors"); if (node instanceof P3DParentNode) { @@ -171,7 +173,7 @@ public class P3DNodeMap extends AbstractVTKNodeMap { private boolean hasActor(IP3DVisualNode node) { - List list = nodeToActor.getValues(node); + Collection list = getRenderObjects(node); if (list == null || list.size() == 0) return false; return true; @@ -181,17 +183,12 @@ public class P3DNodeMap extends AbstractVTKNodeMap { if (Thread.currentThread() != view.getThreadQueue().getThread()) throw new RuntimeException("Illegal thread."); - List list = nodeToActor.getValues(node); - if (list != null) { - for (vtkProp obj : list) { - actorToNode.remove(obj); - } - nodeToActor.remove(node); - view.lock(); - - node.stopVisualize(); - - view.unlock(); + Collection list = getRenderObjects(node); + if (list.size() > 0) { + removeMap(node); + view.lock(); + node.stopVisualize(); + view.unlock(); } } diff --git a/org.simantics.plant3d/src/org/simantics/plant3d/scenegraph/GeometryComponent.java b/org.simantics.plant3d/src/org/simantics/plant3d/scenegraph/GeometryComponent.java index 0e53c1b6..6c6c1b66 100644 --- a/org.simantics.plant3d/src/org/simantics/plant3d/scenegraph/GeometryComponent.java +++ b/org.simantics.plant3d/src/org/simantics/plant3d/scenegraph/GeometryComponent.java @@ -135,6 +135,9 @@ public class GeometryComponent { Object newValue = parameters.get(id); if (currentValue == newValue) continue; + if (newValue == null) { + continue; + } if (currentValue instanceof Double) { if (Math.abs((Double)currentValue-(Double)newValue) < MathTools.NEAR_ZERO) continue; diff --git a/org.simantics.plant3d/src/org/simantics/plant3d/scenegraph/PipeRun.java b/org.simantics.plant3d/src/org/simantics/plant3d/scenegraph/PipeRun.java index 748141a5..36710e4f 100644 --- a/org.simantics.plant3d/src/org/simantics/plant3d/scenegraph/PipeRun.java +++ b/org.simantics.plant3d/src/org/simantics/plant3d/scenegraph/PipeRun.java @@ -29,7 +29,7 @@ import vtk.vtkRenderer; public class PipeRun extends P3DParentNode { private double pipeDiameter = 0.1; - private double turnRadius = 0.2; + private double[] turnRadius = new double[] {0.2}; @Override public void update(vtkRenderer ren) { @@ -54,15 +54,31 @@ public class PipeRun extends P3DParentNode { @RelatedGetValue(Plant3D.URIs.HasTurnRadius) @GetPropertyValue(value=Plant3D.URIs.HasTurnRadius, name = "Elbow radius") public double getTurnRadius() { - return turnRadius; + return turnRadius[0]; } @RelatedSetValue(Plant3D.URIs.HasTurnRadius) @SetPropertyValue(Plant3D.URIs.HasTurnRadius) public void setTurnRadius(double turnRadius) { - this.turnRadius = turnRadius; + this.turnRadius[0] = turnRadius; firePropertyChanged(Plant3D.URIs.HasTurnRadius); - } + firePropertyChanged(Plant3D.URIs.HasTurnRadiusArray); + } + + @RelatedGetValue(Plant3D.URIs.HasTurnRadiusArray) + @GetPropertyValue(value=Plant3D.URIs.HasTurnRadiusArray, name = "Elbow radius array") + public double[] getTurnRadiusArray() { + return turnRadius; + } + + @RelatedSetValue(Plant3D.URIs.HasTurnRadiusArray) + @SetPropertyValue(Plant3D.URIs.HasTurnRadiusArray) + public void setTurnRadiusArray(double[] turnRadiusArray) { + if (turnRadiusArray == null || turnRadiusArray.length == 0) + return; + this.turnRadius = turnRadiusArray; + firePropertyChanged(Plant3D.URIs.HasTurnRadiusArray); + } @RelatedGetValue(Plant3D.URIs.HasPipeDiameter) @GetPropertyValue(value=Plant3D.URIs.HasPipeDiameter, name = "Diameter") @@ -131,8 +147,12 @@ public class PipeRun extends P3DParentNode { public boolean equalSpecs(PipeRun other) { if (!MathTools.equals(pipeDiameter,other.pipeDiameter)) return false; - if (!MathTools.equals(turnRadius,other.turnRadius)) - return false; + if (turnRadius.length != other.turnRadius.length) + return false; + for (int i = 0; i < turnRadius.length; i++) { + if (!MathTools.equals(turnRadius[i],other.turnRadius[i])) + return false; + } return true; } diff --git a/org.simantics.plant3d/src/org/simantics/plant3d/scenegraph/PipelineComponent.java b/org.simantics.plant3d/src/org/simantics/plant3d/scenegraph/PipelineComponent.java index 35df6121..c0feb668 100644 --- a/org.simantics.plant3d/src/org/simantics/plant3d/scenegraph/PipelineComponent.java +++ b/org.simantics.plant3d/src/org/simantics/plant3d/scenegraph/PipelineComponent.java @@ -467,12 +467,7 @@ public abstract class PipelineComponent extends GeometryNode { super.setOrientation(orientation); if (getControlPoint() != null) { getControlPoint()._setWorldOrientation(getWorldOrientation()); - try { - PipingRules.requestUpdate(getControlPoint()); - } catch (Exception e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } + PipingRules.requestUpdate(getControlPoint()); } } @@ -483,12 +478,7 @@ public abstract class PipelineComponent extends GeometryNode { super.setPosition(position); if (getControlPoint() != null) { getControlPoint()._setWorldPosition(getWorldPosition()); - try { - PipingRules.requestUpdate(getControlPoint()); - } catch (Exception e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } + PipingRules.requestUpdate(getControlPoint()); } } @@ -514,7 +504,7 @@ public abstract class PipelineComponent extends GeometryNode { case END: return null; case TURN: { - double r = getPipeRun().getTurnRadius(); + double r = ((TurnComponent)this).getTurnRadius(); double a = pcp.getTurnAngle(); return a*r; } @@ -523,6 +513,24 @@ public abstract class PipelineComponent extends GeometryNode { } } + /** + * Returns diameter of the pipe + * @return + */ + public Double getDiameter() { + return getPipeRun().getPipeDiameter(); + } + + /** + * Returns secondary diameter of the pipe for size change components + * @return + */ + public Double getDiameter2() { + if (getAlternativePipeRun() == null) + return null; + return getAlternativePipeRun().getPipeDiameter(); + } + public void getEnds(Tuple3d p1, Tuple3d p2) { getControlPoint().getControlPointEnds(p1, p2); } @@ -574,7 +582,7 @@ public abstract class PipelineComponent extends GeometryNode { case TURN: { Vector3d loc = pcp.getRealPosition(PositionType.PREVIOUS); - double r = getPipeRun().getTurnRadius(); + double r = ((TurnComponent)this).getTurnRadius(); double a = pcp.getTurnAngle(); double pipeRadius = pcp.getPipeRun().getPipeDiameter() / 2; @@ -631,7 +639,7 @@ public abstract class PipelineComponent extends GeometryNode { double r2 = getAlternativePipeRun().getPipeDiameter() / 2; return pcp.getLength() * Math.PI * (r1*r1 + r1*r2 + r2*r2) / 4; case TURN: { - double r = getPipeRun().getTurnRadius(); + double r = ((TurnComponent)this).getTurnRadius(); double a = pcp.getTurnAngle(); return r * a * Math.PI * pipeRadius * pipeRadius; } 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 9a124349..e25fd8d4 100644 --- a/org.simantics.plant3d/src/org/simantics/plant3d/scenegraph/TurnComponent.java +++ b/org.simantics.plant3d/src/org/simantics/plant3d/scenegraph/TurnComponent.java @@ -25,6 +25,7 @@ public class TurnComponent extends PipelineComponent { private String type; private PipeControlPoint controlPoint; + private Integer turnRadiusIndex; @GetType(Plant3D.URIs.TurnComponent) public String getType() { @@ -52,10 +53,9 @@ public class TurnComponent extends PipelineComponent { public Map updateParameterMap() { Map map = new HashMap(); - PipeRun pipeRun = getPipeRun(); - if (pipeRun != null) { - map.put("turnRadius", pipeRun.getTurnRadius()); - map.put("radius", pipeRun.getPipeDiameter() * 0.5); + if (getPipeRun() != null) { + map.put("turnRadius", getTurnRadius()); + map.put("radius", getDiameter() * 0.5); } if (controlPoint != null && controlPoint.getTurnAngle() != null && !Double.isNaN(controlPoint.getTurnAngle())) { map.put("turnAngle", controlPoint.getTurnAngle()); @@ -103,6 +103,40 @@ public class TurnComponent extends PipelineComponent { return getControlPoint().getTurnAxis(); } + @GetPropertyValue(name="Turn Radius", value=Plant3D.URIs.HasTurnRadius, tabId = "Default") + public Double getTurnRadius() { + if (turnRadiusIndex != null) + return getPipeRun().getTurnRadiusArray()[turnRadiusIndex]; + return getPipeRun().getTurnRadiusArray()[0]; + } + + @RelatedGetValue(Plant3D.URIs.HasTurnRadiusIndex) + @GetPropertyValue(name="Turn Radius Index", value=Plant3D.URIs.HasTurnRadiusIndex, tabId = "Default") + public Integer getTurnRadiusIndex() + { + // TODO: For backwards compatibility, we do not accept null values. + // One development path would allow null index, and setting custom turn radius for the component. + if (turnRadiusIndex == null) + return 0; + return turnRadiusIndex; + } + + @RelatedSetValue(Plant3D.URIs.HasTurnRadiusIndex) + @SetPropertyValue(value=Plant3D.URIs.HasTurnRadiusIndex) + public void setTurnRadiusIndex(Integer turnRadiusIndex) { + if (this.turnRadiusIndex == turnRadiusIndex) + return; + if (turnRadiusIndex == null) + return; + if (turnRadiusIndex != null) { + if (getPipeRun().getTurnRadiusArray().length <= turnRadiusIndex) + return; + } + this.turnRadiusIndex = turnRadiusIndex; + firePropertyChanged(Plant3D.URIs.HasTurnRadiusIndex); + PipingRules.requestUpdate(getControlPoint()); + } + @RelatedGetValue(Plant3D.URIs.HasRotationAngle) @GetPropertyValue(name="Rotation Angle", value=Plant3D.URIs.HasRotationAngle, tabId = "Default") public Double getRotationAngle() { @@ -126,12 +160,7 @@ public class TurnComponent extends PipelineComponent { 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(); - } + PipingRules.requestUpdate(getControlPoint()); } @RelatedGetValue(Plant3D.URIs.IsReversed) @@ -143,7 +172,6 @@ public class TurnComponent extends PipelineComponent { return d; } @RelatedSetValue(Plant3D.URIs.IsReversed) - //@SetPropertyValue(value=Plant3D.URIs.IsReversed) public void setReversed(Boolean reverse) { if (!controlPoint.isFixed()) return; @@ -152,12 +180,7 @@ public class TurnComponent extends PipelineComponent { return; } controlPoint.setReversed(reverse); - try { - PipingRules.requestUpdate(getControlPoint()); - } catch (Exception e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } + PipingRules.requestUpdate(getControlPoint()); } @Override 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 6c932ad8..cb76b74f 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 @@ -1160,7 +1160,7 @@ public class PipeControlPoint extends G3DNode implements IP3DNode { PipeRun previousRun = previous.getPipeRun(); nextPipeRun.setPipeDiameter(previousRun.getPipeDiameter()); - nextPipeRun.setTurnRadius(previousRun.getTurnRadius()); + nextPipeRun.setTurnRadiusArray(previousRun.getTurnRadiusArray()); PipelineComponent n = next.getPipelineComponent(); while (n != null) { 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 6c121d80..727cf1a8 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 @@ -1083,7 +1083,7 @@ public class PipingRules { // TODO : this returns now space for 90 deg turn. // The challenge: position of tcp affects the turn angle, which then affects the required space. Perhaps we need to iterate... // Additionally, if the path legs contain offset, using just positions of opposite path leg ends is not enough, - return tcp.getPipeRun().getTurnRadius(); + return ((TurnComponent)tcp.getPipelineComponent()).getTurnRadius(); } private static void insertElbowUpdate(UpdateStruct2 u, PipeControlPoint dcp, PipeControlPoint next, boolean dcpStart, Vector3d position, Vector3d directedDirection) throws Exception{ @@ -1579,7 +1579,7 @@ public class PipingRules { Vector3d turnAxis = new Vector3d(); turnAxis.cross(prev, next); if (turnAxis.lengthSquared() > MathTools.NEAR_ZERO) { - double elbowRadius = tcp.getPipelineComponent().getPipeRun().getTurnRadius(); + double elbowRadius = ((TurnComponent)tcp.getPipelineComponent()).getTurnRadius(); double R = elbowRadius / Math.tan(angle * 0.5); turnAxis.normalize(); -- 2.45.2