]> gerrit.simantics Code Review - simantics/3d.git/blob - org.simantics.plant3d/src/org/simantics/plant3d/scenegraph/PipelineComponent.java
Merge "Fix NPE in branch point synchronization"
[simantics/3d.git] / org.simantics.plant3d / src / org / simantics / plant3d / scenegraph / PipelineComponent.java
1 package org.simantics.plant3d.scenegraph;
2
3 import java.util.Collections;
4 import java.util.Map;
5
6 import javax.vecmath.Quat4d;
7 import javax.vecmath.Tuple3d;
8 import javax.vecmath.Vector3d;
9
10 import org.simantics.g3d.math.MathTools;
11 import org.simantics.g3d.property.annotations.GetPropertyValue;
12 import org.simantics.g3d.property.annotations.PropertyContributor;
13 import org.simantics.objmap.graph.annotations.RelatedGetObj;
14 import org.simantics.objmap.graph.annotations.RelatedSetObj;
15 import org.simantics.plant3d.ontology.Plant3D;
16 import org.simantics.plant3d.scenegraph.controlpoint.PipeControlPoint;
17 import org.simantics.plant3d.scenegraph.controlpoint.PipeControlPoint.Type;
18 import org.simantics.plant3d.scenegraph.controlpoint.PipingRules;
19
20 /**
21  * 
22  * @author Marko Luukkainen <marko.luukkainen@vtt.fi>
23  *
24  */
25 @PropertyContributor
26 public abstract class PipelineComponent extends GeometryNode {
27
28         
29         private PipeRun pipeRun;
30         private PipeRun alternativePipeRun;
31         private PipelineComponent next;
32         private PipelineComponent previous;
33         
34         /**
35          * Sets the pipe run.
36          * 
37          * With in-line,turn, and end components, the pipe run is the parent object in the scene-graph.
38          * With nozzles, the pipe run setting is explicit (nozzle has to be linked to the piperun, since the parent object is equipment).
39          * With size change components (in-line), there is also alternative pipe run, which must match the next component's pipe run.
40          * 
41          * @param pipeRun
42          */
43         public void setPipeRun(PipeRun pipeRun) {
44                 if (pipeRun == this.pipeRun)
45                         return;
46                 this.pipeRun = pipeRun;
47                 if (getControlPoint() != null) {
48                         getControlPoint().deattach();
49                         if (pipeRun != null) {
50                                 pipeRun.addChild(getControlPoint());
51                         }
52                 }
53                 updateParameters();
54         }
55         
56         @RelatedGetObj(Plant3D.URIs.HasAlternativePipeRun)
57         public PipeRun getAlternativePipeRun() {
58                 return alternativePipeRun;
59         }
60         
61         @RelatedSetObj(Plant3D.URIs.HasAlternativePipeRun)
62         public void setAlternativePipeRun(PipeRun pipeRun) {
63                 if (this.alternativePipeRun == pipeRun)
64                         return;
65                 this.alternativePipeRun = pipeRun;
66                 if (getControlPoint().isDualInline()) {
67                         PipeControlPoint sub = getControlPoint().getSubPoint().get(0);
68                         if (sub.getParent() != this.alternativePipeRun)
69                                 this.alternativePipeRun.addChild(sub);
70                 }
71                 firePropertyChanged(Plant3D.URIs.HasAlternativePipeRun);
72         }
73         
74         @Override
75         public void updateParameters() {
76                 setParameterMap(updateParameterMap());
77                 super.updateParameters();
78         }
79         
80         public abstract void setType(String typeURI) throws Exception;
81         
82         @RelatedGetObj(Plant3D.URIs.HasNext)
83         public PipelineComponent getNext() {
84                 return next;
85         }
86         
87         @RelatedSetObj(Plant3D.URIs.HasNext)
88         public void setNext(PipelineComponent comp) {
89                 if (next == comp)
90                         return;
91                 if (this.next != null)
92                     this.next._removeRef(this);
93                 this.next = comp;
94                 this.syncnext = false;
95                 syncNext();
96                 firePropertyChanged(Plant3D.URIs.HasNext);
97                 if (comp != null)
98                         comp.sync();
99 //              System.out.println(this + " next " + comp);
100         }
101         
102         
103         @RelatedGetObj(Plant3D.URIs.HasPrevious)
104         public PipelineComponent getPrevious() {
105                 return previous;
106         }
107         
108         @RelatedSetObj(Plant3D.URIs.HasPrevious)
109         public void setPrevious(PipelineComponent comp) {
110                 if (previous == comp)
111                         return;
112                 if (this.previous != null)
113                     this.previous._removeRef(this);
114                 this.previous = comp;
115                 this.syncprev = false;
116                 syncPrevious();
117                 firePropertyChanged(Plant3D.URIs.HasPrevious);
118                 if (comp != null)
119                         comp.sync();
120 //              System.out.println(this + " prev " + comp);
121         }
122         private PipelineComponent branch0;
123         
124         @RelatedGetObj(Plant3D.URIs.HasBranch0)
125         public PipelineComponent getBranch0() {
126                 return branch0;
127         }
128         
129         @RelatedSetObj(Plant3D.URIs.HasBranch0)
130         public void setBranch0(PipelineComponent comp) {
131                 if (branch0 == comp)
132                         return;
133                 if (this.branch0 != null)
134                     this.branch0._removeRef(this);
135                 this.branch0 = comp;
136                 this.syncbr0 = false;
137                 syncBranch0();
138                 firePropertyChanged(Plant3D.URIs.HasBranch0);
139                 if (comp != null)
140                         comp.sync();
141 //              System.out.println(this + " next " + comp);
142         }
143
144         @GetPropertyValue(name="Previous",tabId="Debug",value=Plant3D.URIs.HasPrevious)
145     public String getPreviousDebug() {
146         if (previous == null)
147             return null;
148         return previous.getName();
149     }
150     
151     @GetPropertyValue(name="Next",tabId="Debug",value=Plant3D.URIs.HasNext)
152     public String getNextDebug() {
153         if (next == null)
154             return null;
155         return next.getName();
156     }
157     
158         @GetPropertyValue(name="Branch0",tabId="Debug",value=Plant3D.URIs.HasBranch0)
159     public String getBR0Debug() {
160         if (branch0 == null)
161             return null;
162         return branch0.getName();
163     }
164
165         
166         
167         private PipeControlPoint getBranchPoint() {
168                 PipeControlPoint branchPoint;
169                 if (getControlPoint().getSubPoint().size() > 0) {
170                         branchPoint = getControlPoint().getSubPoint().get(0);
171                 } else {
172                         if (branch0.getPipeRun() == null)
173                                 return null;
174                         branchPoint = new PipeControlPoint(this,branch0.getPipeRun());
175                         branchPoint.setFixed(false);
176                         branchPoint.setType(Type.END);
177                         branchPoint.parent = getControlPoint();
178                         getControlPoint().children.add(branchPoint);
179                         branchPoint.setWorldOrientation(getControlPoint().getWorldOrientation());
180                         branchPoint.setWorldPosition(getControlPoint().getWorldPosition());
181                 }
182                 return branchPoint;
183         }
184         
185         private boolean _connectNext(PipeControlPoint pcp, PipeControlPoint nextPCP) {
186                 if (nextPCP == null)
187                         return false;
188                 if (pcp.getNext() != nextPCP) {
189                         pcp.setNext(nextPCP);
190                 }
191                 if (pcp.isDualInline()) {
192                         PipeControlPoint sub = pcp.getSubPoint().get(0);
193                         if (sub.getNext() != nextPCP)
194                                 sub.setNext(nextPCP);
195                 }
196                 return true;
197         }
198         
199         private boolean  _connectPrev(PipeControlPoint pcp, PipeControlPoint prevPCP) {
200                 if (prevPCP == null)
201                         return false;
202                 if (prevPCP.isDualInline())
203                         prevPCP = prevPCP.getSubPoint().get(0);
204                 if (pcp.getPrevious() != prevPCP) {
205                         pcp.setPrevious(prevPCP);
206                 }
207                 if (pcp.isDualInline()) {
208                         PipeControlPoint sub = pcp.getSubPoint().get(0);
209                         if (sub.getPrevious() != prevPCP)
210                                 sub.setPrevious(prevPCP);
211                 }
212                 return true;
213         }
214         
215         // When link to a component is removed, also link to the other direction must be removed at the same time, or
216         // Control point structure is left into illegal state.
217         private void _removeRef(PipelineComponent comp) {
218             if (next == comp) {
219                 next = null;
220                 syncnext = false;
221             syncNext();
222             } else if (previous == comp) {
223                 previous = null;
224                 syncprev = false;
225             syncPrevious();
226             } else if (branch0 == comp) {
227                 branch0 = null;
228                 syncbr0 = false;
229                 syncBranch0();
230             }
231         }
232         
233         boolean syncnext = false;
234     private void syncNext() {
235         if (syncnext)
236             return;
237         syncnext = _syncNext();
238     }
239         
240         
241         private boolean _syncNext() {
242             PipeControlPoint pcp = getControlPoint();
243                 if (pcp != null) {
244                     
245                         if (next != null ) {
246                                 if (next.getControlPoint() != null) {
247                                         
248                                         // TODO, relying that the other direction is connected.
249                                         boolean nxt = next.getPrevious() == this;
250                                         boolean br0 = next.getBranch0() == this;
251                                         if (nxt){
252                                                 return _connectNext(pcp, next.getControlPoint());       
253                                         } else if (br0) {
254                                                 return _connectNext(pcp, next.getBranchPoint());
255                                         } else {
256                                             return false;
257                                         }
258                                 } else {
259                                         return false;
260                                 }
261                                 
262                         } else if (pcp.getNext() != null) {
263                             pcp.setNext(null);
264                             return true;
265                         }
266                 } else {
267                         return false;
268                 }
269                 return true;
270         }
271         
272         boolean syncprev = false;
273     private void syncPrevious() {
274         if (syncprev)
275             return;
276         syncprev = _syncPrevious();
277     }
278         
279         private boolean _syncPrevious() {
280             PipeControlPoint pcp = getControlPoint();
281                 if (pcp != null) {
282                         if (previous != null ) {
283                                 if (previous.getControlPoint() != null) {
284                                         
285                                         // TODO, relying that the other direction is connected.
286                                         boolean prev = previous.getNext() == this;
287                                         boolean br0 = previous.getBranch0() == this;
288                                         if (prev){
289                                                 return _connectPrev(pcp, previous.getControlPoint());   
290                                         } else if (br0) {
291                                                 return _connectPrev(pcp, previous.getBranchPoint());
292                                         } else {
293                                             return false;
294                                         }
295                                 } else {
296                                         return false;
297                                 }
298                                 
299                         } else if (pcp.getPrevious() != null) {
300                             pcp.setPrevious(null);
301                             return true;
302                         }
303                 } else {
304                         return false;
305                 }
306                 return true;
307         }
308         
309         boolean syncbr0 = false;
310         private void syncBranch0() {
311             if (syncbr0)
312                 return;
313             syncbr0 = _syncBranch0();
314         }
315         
316         private boolean _syncBranch0() {
317                 if (getControlPoint() != null) {
318                         if (getControlPoint().isDualInline()) {
319                                 branch0 = null;
320                                 return false;
321                         }
322                         if (branch0 != null) {
323                                 if (branch0.getControlPoint() != null) {
324                                         PipeControlPoint branchPoint = getBranchPoint();
325                                         if (branchPoint == null)
326                                             return false;
327                                         PipeControlPoint pcp = branch0.getControlPoint();
328                                         // TODO, relying that the other direction is connected.
329                                         boolean next = branch0.getPrevious() == this; // this --> branch0
330                                         boolean prev = branch0.getNext() == this;
331                                         if (next) {
332                                                 _connectNext(branchPoint, pcp);
333                                         } else if (prev){
334                                                 _connectPrev(branchPoint, pcp); 
335                                         } else {
336                                             return false;
337                                         }
338                                         
339                                 } else {
340                                         return false;
341                                 }
342                                 
343                         } else if (getControlPoint().getSubPoint().size() > 0) { // TODO : this may cause problems? (Removes branch point, before branch has been set?)
344                                 getControlPoint().getSubPoint().get(0).remove();
345                                 getControlPoint().children.clear();
346                                 return true;
347                         }
348                 } else {
349                         return false;
350                 }
351                 return true;
352         }
353         
354         public void sync() {
355                 syncPrevious();
356                 syncNext();
357                 syncBranch0();
358         }
359         
360         public void sync2() {
361 //              if (getControlPoint().isDualInline()) {
362 //                      PipeControlPoint sub = getControlPoint().getSubPoint().get(0);
363 //                      next.getControlPoint().getPipeRun().addChild(sub);
364 //              }
365                 getControlPoint()._setWorldOrientation(getWorldOrientation());
366                 getControlPoint()._setWorldPosition(getWorldPosition());
367         }
368         
369         public Map<String,Object> updateParameterMap() {
370                 return Collections.EMPTY_MAP;
371         }
372         
373         public PipeRun getPipeRun() {
374                 return pipeRun;
375         }
376         
377         public abstract String getType();
378         public abstract PipeControlPoint getControlPoint();
379         
380         @Override
381         public void remove() {
382                 PipeControlPoint pcp = getControlPoint();
383                 // Second check is needed, when remove process is initiated from control point.
384                 if (pcp != null && pcp.getPipelineComponent() != null) {
385                         pcp.remove();
386                 }
387                 super.remove();
388         }
389
390         @Override
391         protected double[] getColor() {
392                 if (getControlPoint() == null || !getControlPoint().isFixed())
393                         return new double[]{0.7,0.7,0.7};
394                 else
395                         return new double[]{1.0,0.0,0.0};
396         }
397         
398         @Override
399         protected double[] getSelectedColor() {
400                 return new double[]{0.5,0,0.5};
401         }
402         
403         @Override
404         public void setOrientation(Quat4d orientation) {
405                 if (MathTools.equals(orientation, getOrientation()))
406                         return;
407                 super.setOrientation(orientation);
408                 if (getControlPoint() != null) {
409                         getControlPoint()._setWorldOrientation(getWorldOrientation());
410                         try {
411                                 PipingRules.requestUpdate(getControlPoint());
412                         } catch (Exception e) {
413                                 // TODO Auto-generated catch block
414                                 e.printStackTrace();
415                         }       
416                 }
417         }
418         
419         @Override
420         public void setPosition(Vector3d position) {
421                 if (MathTools.equals(position, getPosition()))
422                         return;
423                 super.setPosition(position);
424                 if (getControlPoint() != null) {
425                         getControlPoint()._setWorldPosition(getWorldPosition());
426                         try {
427                                 PipingRules.requestUpdate(getControlPoint());
428                         } catch (Exception e) {
429                                 // TODO Auto-generated catch block
430                                 e.printStackTrace();
431                         }
432                 }
433         }
434         
435         
436         public void _setWorldPosition(Vector3d position) {
437                 Vector3d localPos = getLocalPosition(position);
438                 super.setPosition(localPos);
439         }
440         
441         public void _setWorldOrientation(Quat4d orientation) {
442                 Quat4d localOr = getLocalOrientation(orientation);
443                 super.setOrientation(localOr);
444         }
445         
446         @GetPropertyValue(name="Flow Length", value="flowlength", tabId = "Default")
447         public Double getFlowLength() {
448                 PipeControlPoint pcp = getControlPoint(); 
449                 if (pcp == null)
450                         return null;
451                 switch (pcp.getType()) {
452                         case INLINE:
453                                 return pcp.getLength();
454                         case END:
455                                 return null;
456                         case TURN: {
457                                 double r = getPipeRun().getTurnRadius();
458                                 double a = pcp.getTurnAngle();
459                                 return a*r;
460                         }
461                          default:
462                                  return null;
463                 }
464         }
465         
466         public void getControlPointEnds(Tuple3d p1, Tuple3d p2) {
467                 getControlPoint().getControlPointEnds(p1, p2);
468         }
469         
470         public Vector3d getNormal() {
471                 Vector3d v = new Vector3d();
472                 MathTools.rotate(getWorldOrientation(), MathTools.Z_AXIS, v);
473                 return v;
474         }
475         
476 }