1 package org.simantics.plant3d.scenegraph;
3 import java.util.ArrayList;
4 import java.util.Arrays;
5 import java.util.Collection;
6 import java.util.Collections;
7 import java.util.Comparator;
8 import java.util.HashMap;
11 import java.util.Objects;
13 import org.simantics.g3d.math.MathTools;
14 import org.simantics.g3d.property.annotations.GetPropertyValue;
15 import org.simantics.g3d.property.annotations.PropertyTabBlacklist;
16 import org.simantics.g3d.property.annotations.SetPropertyValue;
17 import org.simantics.g3d.scenegraph.IG3DNode;
18 import org.simantics.g3d.vtk.common.VtkView;
19 import org.simantics.objmap.graph.annotations.GraphType;
20 import org.simantics.objmap.graph.annotations.RelatedElementsAdd;
21 import org.simantics.objmap.graph.annotations.RelatedElementsGet;
22 import org.simantics.objmap.graph.annotations.RelatedElementsRem;
23 import org.simantics.objmap.graph.annotations.RelatedGetValue;
24 import org.simantics.objmap.graph.annotations.RelatedSetValue;
25 import org.simantics.plant3d.ontology.Plant3D;
26 import org.simantics.plant3d.scenegraph.controlpoint.PipeControlPoint;
29 import vtk.vtkRenderer;
31 @GraphType(Plant3D.URIs.PipeRun)
32 @PropertyTabBlacklist("Transform")
33 public class PipeRun extends P3DParentNode<IP3DNode> {
35 private double pipeDiameter = 0.1;
36 private double[] turnRadius = new double[] {0.2};
39 public void update(vtkRenderer ren) {
44 public void visualize(VtkView panel) {
49 public Collection<vtkProp3D> getActors() {
50 return Collections.emptyList();
54 public void stopVisualize() {
58 @SuppressWarnings("deprecation")
59 @RelatedGetValue(Plant3D.URIs.HasTurnRadius)
60 @GetPropertyValue(value=Plant3D.URIs.HasTurnRadius, name = "Elbow radius")
61 public double getTurnRadius() {
65 @SuppressWarnings("deprecation")
66 @RelatedSetValue(Plant3D.URIs.HasTurnRadius)
67 @SetPropertyValue(Plant3D.URIs.HasTurnRadius)
68 public void setTurnRadius(double turnRadius) {
69 if (this.turnRadius[0] == turnRadius)
71 this.turnRadius[0] = turnRadius;
72 firePropertyChanged(Plant3D.URIs.HasTurnRadius);
73 firePropertyChanged(Plant3D.URIs.HasTurnRadiusArray);
76 @RelatedGetValue(Plant3D.URIs.HasTurnRadiusArray)
77 @GetPropertyValue(value=Plant3D.URIs.HasTurnRadiusArray, name = "Elbow radius array")
78 public double[] getTurnRadiusArray() {
82 @RelatedSetValue(Plant3D.URIs.HasTurnRadiusArray)
83 @SetPropertyValue(Plant3D.URIs.HasTurnRadiusArray)
84 public void setTurnRadiusArray(double[] turnRadiusArray) {
85 if (turnRadiusArray == null || turnRadiusArray.length == 0 || Arrays.equals(this.turnRadius, turnRadiusArray))
87 this.turnRadius = turnRadiusArray;
88 firePropertyChanged(Plant3D.URIs.HasTurnRadiusArray);
91 @RelatedGetValue(Plant3D.URIs.HasPipeDiameter)
92 @GetPropertyValue(value=Plant3D.URIs.HasPipeDiameter, name = "Diameter")
93 public double getPipeDiameter() {
97 @RelatedSetValue(Plant3D.URIs.HasPipeDiameter)
98 @SetPropertyValue(Plant3D.URIs.HasPipeDiameter)
99 public void setPipeDiameter(double pipeDiameter) {
100 if (Objects.equals(this.pipeDiameter, pipeDiameter))
103 this.pipeDiameter = pipeDiameter;
104 firePropertyChanged(Plant3D.URIs.HasPipeDiameter);
107 @RelatedElementsAdd(Plant3D.URIs.children)
108 public void addChild(PipelineComponent node) {
109 addNode(Plant3D.URIs.children,node);
112 @RelatedElementsGet(Plant3D.URIs.children)
113 public Collection<PipelineComponent> getChild() {
114 Collection<PipelineComponent> coll = new ArrayList<PipelineComponent>();
115 for (IG3DNode n : getNodes(Plant3D.URIs.children)) {
116 coll.add((PipelineComponent)n);
121 @RelatedElementsRem(Plant3D.URIs.children)
122 public void _remChild(PipelineComponent node) {
123 //since we do not now, if DB remove is actually remove or detach, we have to use detach. NodeMap will handle Component removals.
124 deattachNode(Plant3D.URIs.children, node);
127 public void remChild(PipelineComponent node) {
128 removeNode(Plant3D.URIs.children, node);
132 public void remove() {
133 // since we do not now, if DB remove is actually remove or detach, we have to use detach. NodeMap will handle Component removals.
134 Collection<PipelineComponent> comps = getChild();
135 for (PipelineComponent c : comps)
141 public List<PipelineComponent> getSortedChild() {
142 List<PipelineComponent> coll = new ArrayList<PipelineComponent>();
143 for (IG3DNode n : getNodes(Plant3D.URIs.children)) {
144 coll.add((PipelineComponent)n);
146 Collections.sort(coll, new ComponentComparator());
149 private static String PIPECP = "pipecp";
151 public void addChild(PipeControlPoint node) {
152 addNode(PIPECP,node);
155 public void remChild(PipeControlPoint node) {
156 removeNode(PIPECP, node);
159 public void deattachChild(PipeControlPoint node) {
160 deattachNode(PIPECP, node);
163 public Collection<PipeControlPoint> getControlPoints() {
164 Collection<PipeControlPoint> coll = new ArrayList<PipeControlPoint>();
165 for (IG3DNode n : getNodes(PIPECP)) {
166 coll.add((PipeControlPoint)n);
172 public boolean equalSpecs(PipeRun other) {
173 if (!MathTools.equals(pipeDiameter,other.pipeDiameter))
175 if (turnRadius.length != other.turnRadius.length)
177 for (int i = 0; i < turnRadius.length; i++) {
178 if (!MathTools.equals(turnRadius[i],other.turnRadius[i]))
184 public boolean canMerge(PipeRun other) {
185 return MathTools.equals(pipeDiameter,other.pipeDiameter);
189 * Merges contents of PipeRun r2 to this PipeRun. Note: does not connect boundary components!
192 public void merge(PipeRun r2) {
193 Map<Integer, Integer> turnIndexMap = null;
194 if (!this.equalSpecs(r2)) {
195 if (!this.canMerge(r2))
196 throw new IllegalArgumentException("PipeRuns cannot be merged");
198 turnIndexMap = new HashMap<>();
199 List<Double> mergedTurnRadius = new ArrayList<>();
200 for (double t : this.getTurnRadiusArray()) {
201 mergedTurnRadius.add(t);
203 for (int i2 = 0; i2 < r2.getTurnRadiusArray().length; i2++) {
204 double t2 = r2.getTurnRadiusArray()[i2];
205 boolean found = false;
206 for (int i = 0; i < mergedTurnRadius.size(); i++) {
207 if (MathTools.equals(mergedTurnRadius.get(i), t2)) {
208 turnIndexMap.put(i2, i);
214 turnIndexMap.put(i2, mergedTurnRadius.size());
215 mergedTurnRadius.add(t2);
218 for (PipeControlPoint pcp : r2.getControlPoints()) {
219 PipelineComponent comp = pcp.getPipelineComponent();
220 if (comp instanceof TurnComponent) {
224 if (mergedTurnRadius.size() > this.getTurnRadiusArray().length) {
225 double arr[] = new double[mergedTurnRadius.size()];
226 for (int i = 0; i < mergedTurnRadius.size(); i++) {
227 arr[i] = mergedTurnRadius.get(i);
229 this.setTurnRadiusArray(arr);
232 // Move components and control points
233 Collection<PipeControlPoint> pcps = r2.getControlPoints();
234 for (PipeControlPoint pcp : pcps) {
235 r2.deattachChild(pcp);
237 PipelineComponent component = pcp.getPipelineComponent();
238 if (component != null) {
239 if (!(component instanceof Nozzle)) {
240 component.deattach();
241 this.addChild(component);
243 Nozzle n = (Nozzle)component;
248 // Use new turn radii indexes
249 if (turnIndexMap != null) {
250 for (PipeControlPoint pcp : pcps) {
251 PipelineComponent component = pcp.getPipelineComponent();
252 if (component instanceof TurnComponent) {
253 TurnComponent tc = (TurnComponent)component;
254 if (tc.getTurnRadiusIndex() == null || tc.getTurnRadiusIndex() < 0)
256 tc.setTurnRadiusIndex(turnIndexMap.get(tc.getTurnRadiusIndex()));
264 private class ComponentComparator implements Comparator<PipelineComponent> {
266 public int compare(PipelineComponent o1, PipelineComponent o2) {
270 PipelineComponent c = o1.getPrevious();