]> gerrit.simantics Code Review - simantics/3d.git/blob - org.simantics.plant3d/src/org/simantics/plant3d/scenegraph/PipelineComponent.java
Compiler warning elimination
[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.HashMap;
5 import java.util.Map;
6 import java.util.Map.Entry;
7
8 import javax.vecmath.Quat4d;
9 import javax.vecmath.Tuple3d;
10 import javax.vecmath.Vector3d;
11
12 import org.simantics.g3d.math.MathTools;
13 import org.simantics.g3d.property.annotations.CompoundGetPropertyValue;
14 import org.simantics.g3d.property.annotations.CompoundSetPropertyValue;
15 import org.simantics.g3d.property.annotations.GetPropertyValue;
16 import org.simantics.g3d.property.annotations.PropertyContributor;
17 import org.simantics.objmap.graph.annotations.CompoundRelatedGetValue;
18 import org.simantics.objmap.graph.annotations.CompoundRelatedSetValue;
19 import org.simantics.objmap.graph.annotations.RelatedGetObj;
20 import org.simantics.objmap.graph.annotations.RelatedSetObj;
21 import org.simantics.plant3d.ontology.Plant3D;
22 import org.simantics.plant3d.scenegraph.controlpoint.PipeControlPoint;
23 import org.simantics.plant3d.scenegraph.controlpoint.PipeControlPoint.Direction;
24 import org.simantics.plant3d.scenegraph.controlpoint.PipeControlPoint.PointType;
25 import org.simantics.plant3d.scenegraph.controlpoint.PipeControlPoint.PositionType;
26 import org.simantics.plant3d.scenegraph.controlpoint.PipingRules;
27
28 /**
29  * 
30  * @author Marko Luukkainen <marko.luukkainen@vtt.fi>
31  *
32  */
33 @PropertyContributor
34 public abstract class PipelineComponent extends GeometryNode {
35     
36     private static boolean DEBUG = false;
37
38         
39         private PipeRun pipeRun;
40         private PipeRun alternativePipeRun;
41         private PipelineComponent next;
42         private PipelineComponent previous;
43         
44         public PipeRun getPipeRun() {
45                 return pipeRun;
46         }
47         
48         /**
49          * Sets the pipe run.
50          * 
51          * With in-line,turn, and end components, the pipe run is the parent object in the scene-graph.
52          * With nozzles, the pipe run setting is explicit (nozzle has to be linked to the piperun, since the parent object is equipment).
53          * With size change components (in-line), there is also alternative pipe run, which must match the next component's pipe run.
54          * 
55          * @param pipeRun
56          */
57         public void setPipeRun(PipeRun pipeRun) {
58                 if (pipeRun == this.pipeRun)
59                         return;
60                 this.pipeRun = pipeRun;
61                 if (getControlPoint() != null) {
62                         getControlPoint().deattach();
63                         if (pipeRun != null) {
64                                 pipeRun.addChild(getControlPoint());
65                         }
66                 }
67                 updateParameters();
68         }
69         
70         @RelatedGetObj(Plant3D.URIs.HasAlternativePipeRun)
71         public PipeRun getAlternativePipeRun() {
72                 return alternativePipeRun;
73         }
74         
75         @RelatedSetObj(Plant3D.URIs.HasAlternativePipeRun)
76         public void setAlternativePipeRun(PipeRun pipeRun) {
77                 if (this.alternativePipeRun == pipeRun)
78                         return;
79                 this.alternativePipeRun = pipeRun;
80                 if (getControlPoint().isDualInline()) {
81                         PipeControlPoint sub = getControlPoint().getSubPoint().get(0);
82                         if (sub.getParent() != this.alternativePipeRun)
83                                 this.alternativePipeRun.addChild(sub);
84                 }
85                 firePropertyChanged(Plant3D.URIs.HasAlternativePipeRun);
86         }
87         
88         @Override
89         public void updateParameters() {
90                 setParameterMap(updateParameterMap());
91                 super.updateParameters();
92         }
93         
94         @Override
95     @CompoundRelatedGetValue(objRelation=Plant3D.URIs.hasParameter,objType=Plant3D.URIs.Parameter,valRelation=Plant3D.URIs.hasParameterValue)
96     public Map<String, Object> getParameterMap() {
97         return super.getParameterMap();
98     }
99         
100     @Override
101     @CompoundRelatedSetValue(Plant3D.URIs.hasParameter)
102     public void setParameterMap(Map<String, Object> parameters) {
103         super.setParameterMap(parameters);
104     }
105     
106     @CompoundGetPropertyValue(name="Parameters",tabId="Parameters",value="parameters")
107     public Map<String,Object> getParameterMapUI() {
108         // TODO : how to filter parameters that are calculated by geometry provider?
109         Map<String,Object> map = new HashMap<String, Object>(getParameterMap());
110         map.remove("radius");
111         map.remove("radius2");
112         map.remove("offset");
113         return map;
114     }
115     
116     @CompoundSetPropertyValue(value="parameters")
117     public void setParameterMapUI(Map<String, Object> parameters) { 
118         Map<String, Object> curr = getParameterMap();
119         for (Entry<String, Object> entry : curr.entrySet()) {
120             if (!parameters.containsKey(entry.getKey()))
121                 parameters.put(entry.getKey(), entry.getValue());
122         }
123         setParameterMap(parameters);
124     }
125         
126         public abstract void setType(String typeURI) throws Exception;
127         
128         @RelatedGetObj(Plant3D.URIs.HasNext)
129         public PipelineComponent getNext() {
130                 return next;
131         }
132         
133         @RelatedSetObj(Plant3D.URIs.HasNext)
134         public void setNext(PipelineComponent comp) {
135                 if (next == comp)
136                     return;
137                 if (this.next != null)
138                     this.next._removeRef(this);
139         _setNext(comp);
140         this.syncnext = false;
141         if (DEBUG) System.out.println(this + " next " + comp);
142         syncNext();
143         firePropertyChanged(Plant3D.URIs.HasNext);
144         if (comp != null)
145             comp.sync();
146         }
147         
148         protected void _setNext(PipelineComponent comp) {
149             this.next = comp;
150         }
151         
152         
153         @RelatedGetObj(Plant3D.URIs.HasPrevious)
154         public PipelineComponent getPrevious() {
155                 return previous;
156         }
157         
158         @RelatedSetObj(Plant3D.URIs.HasPrevious)
159         public void setPrevious(PipelineComponent comp) {
160                 if (previous == comp)
161                         return;
162                 if (this.previous != null)
163                         this.previous._removeRef(this);
164                 _setPrevious(comp);
165                 this.syncprev = false;
166                 if (DEBUG) System.out.println(this + " prev " + comp);
167                 syncPrevious();
168                 firePropertyChanged(Plant3D.URIs.HasPrevious);
169                 if (comp != null)
170                         comp.sync();
171         }
172         
173         protected void _setPrevious(PipelineComponent comp) {
174         this.previous = comp;
175     }
176         
177         private PipelineComponent branch0;
178         
179         @RelatedGetObj(Plant3D.URIs.HasBranch0)
180         public PipelineComponent getBranch0() {
181                 return branch0;
182         }
183         
184         @RelatedSetObj(Plant3D.URIs.HasBranch0)
185         public void setBranch0(PipelineComponent comp) {
186                 if (branch0 == comp)
187                         return;
188                 if (this.branch0 != null)
189                         this.branch0._removeRef(this);
190                 this.branch0 = comp;
191                 this.syncbr0 = false;
192                 if (DEBUG) System.out.println(this + " br0 " + comp);
193                 syncBranch0();
194                 firePropertyChanged(Plant3D.URIs.HasBranch0);
195                 if (comp != null)
196                         comp.sync();
197         }
198
199         @GetPropertyValue(name="Previous",tabId="Debug",value=Plant3D.URIs.HasPrevious)
200         public String getPreviousDebug() {
201                 if (previous == null)
202                         return null;
203                 return previous.getName();
204         }
205         
206         @GetPropertyValue(name="Next",tabId="Debug",value=Plant3D.URIs.HasNext)
207         public String getNextDebug() {
208                 if (next == null)
209                         return null;
210                 return next.getName();
211         }
212         
213         @GetPropertyValue(name="Branch0",tabId="Debug",value=Plant3D.URIs.HasBranch0)
214         public String getBR0Debug() {
215                 if (branch0 == null)
216                         return null;
217                 return branch0.getName();
218         }
219
220         
221         
222         private PipeControlPoint getBranchPoint() {
223                 PipeControlPoint branchPoint;
224                 if (getControlPoint().getSubPoint().size() > 0) {
225                         branchPoint = getControlPoint().getSubPoint().get(0);
226                 } else {
227                         if (branch0.getPipeRun() == null)
228                                 return null;
229                         branchPoint = new PipeControlPoint(this,branch0.getPipeRun());
230                         branchPoint.setFixed(false);
231                         branchPoint.setType(PointType.END);
232                         branchPoint.parent = getControlPoint();
233                         getControlPoint().children.add(branchPoint);
234                         branchPoint.setWorldOrientation(getControlPoint().getWorldOrientation());
235                         branchPoint.setWorldPosition(getControlPoint().getWorldPosition());
236                 }
237                 return branchPoint;
238         }
239         
240         private boolean _connectNext(PipeControlPoint pcp, PipeControlPoint nextPCP) {
241                 if (nextPCP == null)
242                         return false;
243                 if (pcp.getNext() != nextPCP) {
244                         pcp.setNext(nextPCP);
245                 }
246                 if (pcp.isDualInline()) {
247                         PipeControlPoint sub = pcp.getSubPoint().get(0);
248                         if (sub.getNext() != nextPCP)
249                                 sub.setNext(nextPCP);
250                 }
251                 return true;
252         }
253         
254         private boolean  _connectPrev(PipeControlPoint pcp, PipeControlPoint prevPCP) {
255                 if (prevPCP == null)
256                         return false;
257                 if (prevPCP.isDualInline())
258                         prevPCP = prevPCP.getSubPoint().get(0);
259                 if (pcp.getPrevious() != prevPCP) {
260                         pcp.setPrevious(prevPCP);
261                 }
262                 if (pcp.isDualInline()) {
263                         PipeControlPoint sub = pcp.getSubPoint().get(0);
264                         if (sub.getPrevious() != prevPCP)
265                                 sub.setPrevious(prevPCP);
266                 }
267                 return true;
268         }
269         
270         // When link to a component is removed, also link to the other direction must be removed at the same time, or
271         // Control point structure is left into illegal state.
272         private void _removeRef(PipelineComponent comp) {
273                 if (next == comp) {
274                         _setNext(null);
275                         syncnext = false;
276                         if (DEBUG) System.out.println(this + " remove next " + comp);
277                         firePropertyChanged(Plant3D.URIs.HasNext);
278                         syncNext();
279                 } else if (previous == comp) {
280                         _setPrevious(null);
281                         syncprev = false;
282                         if (DEBUG) System.out.println(this + " remove prev " + comp);
283                         firePropertyChanged(Plant3D.URIs.HasPrevious);
284                         syncPrevious();
285                 } else if (branch0 == comp) {
286                         branch0 = null;
287                         syncbr0 = false;
288                         if (DEBUG) System.out.println(this + " remove br0 " + comp);
289                         firePropertyChanged(Plant3D.URIs.HasBranch0);
290                         syncBranch0();
291                 }
292         }
293         
294         boolean syncnext = false;
295         private void syncNext() {
296                 if (syncnext)
297                         return;
298                 syncnext = _syncNext();
299         }
300         
301         
302         private boolean _syncNext() {
303                 PipeControlPoint pcp = getControlPoint();
304                 if (pcp != null) {
305                         
306                         if (next != null ) {
307                                 if (next.getControlPoint() != null) {
308                                         
309                                         // TODO, relying that the other direction is connected.
310                                         boolean nxt = next.getPrevious() == this;
311                                         boolean br0 = next.getBranch0() == this;
312                                         if (nxt){
313                                                 return _connectNext(pcp, next.getControlPoint());       
314                                         } else if (br0) {
315                                                 return _connectNext(pcp, next.getBranchPoint());
316                                         } else {
317                                                 return false;
318                                         }
319                                 } else {
320                                         return false;
321                                 }
322                                 
323                         } else if (pcp.getNext() != null) {
324                                 pcp.setNext(null);
325                                 return true;
326                         }
327                 } else {
328                         return false;
329                 }
330                 return true;
331         }
332         
333         boolean syncprev = false;
334         private void syncPrevious() {
335                 if (syncprev)
336                         return;
337                 syncprev = _syncPrevious();
338         }
339         
340         private boolean _syncPrevious() {
341                 PipeControlPoint pcp = getControlPoint();
342                 if (pcp != null) {
343                         if (previous != null ) {
344                                 if (previous.getControlPoint() != null) {
345                                         
346                                         // TODO, relying that the other direction is connected.
347                                         boolean prev = previous.getNext() == this;
348                                         boolean br0 = previous.getBranch0() == this;
349                                         if (prev){
350                                                 return _connectPrev(pcp, previous.getControlPoint());   
351                                         } else if (br0) {
352                                                 return _connectPrev(pcp, previous.getBranchPoint());
353                                         } else {
354                                                 return false;
355                                         }
356                                 } else {
357                                         return false;
358                                 }
359                                 
360                         } else if (pcp.getPrevious() != null) {
361                                 pcp.setPrevious(null);
362                                 return true;
363                         }
364                 } else {
365                         return false;
366                 }
367                 return true;
368         }
369         
370         boolean syncbr0 = false;
371         private void syncBranch0() {
372                 if (syncbr0)
373                         return;
374                 syncbr0 = _syncBranch0();
375         }
376         
377         private boolean _syncBranch0() {
378                 if (getControlPoint() != null) {
379                         if (getControlPoint().isDualInline()) {
380                                 branch0 = null;
381                                 return false;
382                         }
383                         if (branch0 != null) {
384                                 if (branch0.getControlPoint() != null) {
385                                         PipeControlPoint branchPoint = getBranchPoint();
386                                         if (branchPoint == null)
387                                                 return false;
388                                         PipeControlPoint pcp = branch0.getControlPoint();
389                                         // TODO, relying that the other direction is connected.
390                                         boolean next = branch0.getPrevious() == this; // this --> branch0
391                                         boolean prev = branch0.getNext() == this;
392                                         if (next) {
393                                                 _connectNext(branchPoint, pcp);
394                                         } else if (prev){
395                                                 _connectPrev(branchPoint, pcp); 
396                                         } else {
397                                                 return false;
398                                         }
399                                         
400                                 } else {
401                                         return false;
402                                 }
403                                 
404                         } else if (getControlPoint().getSubPoint().size() > 0) { // TODO : this may cause problems? (Removes branch point, before branch has been set?)
405                                 //getControlPoint().getSubPoint().get(0).remove();
406                                 //getControlPoint().children.clear();
407                                 return true;
408                         }
409                 } else {
410                         return false;
411                 }
412                 return true;
413         }
414         
415         public void sync() {
416                 syncPrevious();
417                 syncNext();
418                 syncBranch0();
419         }
420         
421         public void sync2() {
422 //              if (getControlPoint().isDualInline()) {
423 //                      PipeControlPoint sub = getControlPoint().getSubPoint().get(0);
424 //                      next.getControlPoint().getPipeRun().addChild(sub);
425 //              }
426                 getControlPoint()._setWorldOrientation(getWorldOrientation());
427                 getControlPoint()._setWorldPosition(getWorldPosition());
428         }
429         
430         public Map<String,Object> updateParameterMap() {
431                 return Collections.emptyMap();
432         }
433         
434         public abstract String getType();
435         public abstract PipeControlPoint getControlPoint();
436         
437         @Override
438         public void remove() {
439             if (DEBUG) System.out.println(this + " remove");
440                 PipeControlPoint pcp = getControlPoint();
441                 // Second check is needed, when remove process is initiated from control point.
442                 if (pcp != null && pcp.getPipelineComponent() != null) {
443                         pcp.remove();
444                 }
445                 super.remove();
446         }
447         
448         public void removeAndSplit() {
449             PipeControlPoint pcp = getControlPoint();
450         // Second check is needed, when remove process is initiated from control point.
451         if (pcp != null && pcp.getPipelineComponent() != null) {
452             pcp.removeAndSplit();
453         }
454         super.remove();
455         }
456
457         @Override
458         protected double[] getColor() {
459                 if (getControlPoint() == null || !getControlPoint().isFixed())
460                         return new double[]{0.7,0.7,0.7};
461                 else
462                         return new double[]{1.0,0.0,0.0};
463         }
464         
465         @Override
466         protected double[] getSelectedColor() {
467                 return new double[]{0.5,0,0.5};
468         }
469         
470         @Override
471         public void setOrientation(Quat4d orientation) {
472                 if (MathTools.equals(orientation, getOrientation()))
473                         return;
474                 super.setOrientation(orientation);
475                 if (getControlPoint() != null) {
476                         getControlPoint()._setWorldOrientation(getWorldOrientation());
477                         PipingRules.requestUpdate(getControlPoint());
478                 }
479         }
480         
481         @Override
482         public void setPosition(Vector3d position) {
483                 if (MathTools.equals(position, getPosition()))
484                         return;
485                 super.setPosition(position);
486                 if (getControlPoint() != null) {
487                         getControlPoint()._setWorldPosition(getWorldPosition());
488                         PipingRules.requestUpdate(getControlPoint());
489                 }
490         }
491         
492         
493         public void _setWorldPosition(Vector3d position) {
494                 Vector3d localPos = getLocalPosition(position);
495                 super.setPosition(localPos);
496         }
497         
498         public void _setWorldOrientation(Quat4d orientation) {
499                 Quat4d localOr = getLocalOrientation(orientation);
500                 super.setOrientation(localOr);
501         }
502         
503         @GetPropertyValue(name="Flow Length", value="flowlength", tabId = "Default")
504         public Double getFlowLength() {
505                 PipeControlPoint pcp = getControlPoint(); 
506                 if (pcp == null)
507                         return null;
508                 switch (pcp.getType()) {
509                         case INLINE:
510                                 return pcp.getLength();
511                         case END:
512                                 return null;
513                         case TURN: {
514                                 double r = ((TurnComponent)this).getTurnRadius();
515                                 double a = pcp.getTurnAngle();
516                                 return a*r;
517                         }
518                         default:
519                                 return null;
520                 }
521         }
522         
523         /**
524          * Returns diameter of the pipe
525          * @return
526          */
527         public Double getDiameter() {
528             return getPipeRun().getPipeDiameter();
529         }
530         
531         /**
532          * Returns secondary diameter of the pipe for size change components
533          * @return
534          */
535         public Double getDiameter2() {
536             if (getAlternativePipeRun() == null)
537                 return null;
538             return getAlternativePipeRun().getPipeDiameter();
539         }
540         
541         public void getEnds(Tuple3d p1, Tuple3d p2) {
542                 getControlPoint().getControlPointEnds(p1, p2);
543         }
544         
545         public void getEndDirections(Tuple3d v1, Tuple3d v2) {
546                 getControlPoint().getEndDirections(v1, v2);
547         }
548         
549         public void getCentroid(Tuple3d p) {
550                 PipeControlPoint pcp = getControlPoint(); 
551                 if (pcp == null)
552                         throw new IllegalStateException("No centroid defined");
553                 
554                 switch (pcp.getType()) {
555                 case INLINE:
556                 case END:
557                         // Just return the world location
558                         if (!pcp.isSizeChange()) {
559                                 p.set(pcp.getWorldPosition());
560                                 return;
561                         }
562                         
563                         // Calculate center of mass for the frustum
564                         double r1 = getPipeRun().getPipeDiameter();
565                         double r2 = getAlternativePipeRun().getPipeDiameter();
566                         
567                         Vector3d p1 = new Vector3d(), p2 = new Vector3d();
568                         pcp.getInlineControlPointEnds(p1, p2);
569                         
570                         // Squared sum of radii
571                         double r12 = r1 + r2;
572                         r12 *= r12;
573                         
574                         // The larger of the radii form the base of a frustum
575                         double rmax = Math.max(r1, r2);
576                         
577                         // Relative distance from the base of the frustum
578                         double h = (r12 + 2*rmax*rmax) / (4 * (r12 - r1*r2));
579                         
580                         // Relative distance from p1 to p2
581                         if (r1 < r2)
582                                 h = 1 - h;
583                         
584                         p2.sub(p1);
585                         p1.scaleAdd(h, p2);
586                         
587                         p.set(p1);
588                         return;
589                 case TURN: {
590                         Vector3d loc = pcp.getRealPosition(PositionType.PREVIOUS);
591                         
592                         double r = ((TurnComponent)this).getTurnRadius();
593                         double a = pcp.getTurnAngle();
594                         double pipeRadius = pcp.getPipeRun().getPipeDiameter() / 2;
595                         
596                         // Unit vector in inlet flow direction
597                         Vector3d inletDir = pcp.getPathLegDirection(Direction.PREVIOUS);
598                         inletDir.scale(-1.0);
599                         inletDir.normalize();
600                         
601                         // Normal to both inletDir and turn axis in world coordinates
602                         Vector3d outletDir = pcp.getPathLegDirection(Direction.NEXT);
603                         Vector3d normal = new Vector3d(inletDir);
604                         normal.scaleAdd(-inletDir.dot(outletDir), outletDir);
605                         normal.normalize();
606                         
607                         // Location of turn axis
608                         Vector3d center = new Vector3d(normal);
609                         center.scaleAdd(r, loc);
610                         
611                         // Add vector components from axis to centroid
612                         double c = r + pipeRadius * pipeRadius / (4 * r);
613                         double c1 = c * Math.sin(a) / a;
614                         double c2 = c * (1 - Math.cos(a)) / a;
615                         normal.scale(-c1);
616                         inletDir.scale(c2);
617                         center.add(normal);
618                         center.add(inletDir);
619                 
620                         // Return value
621                         p.set(center);
622                         return;
623                 }
624                 default:
625                         throw new IllegalStateException("No centroid defined");
626                 }
627         }
628         
629         public double getVolume() {
630                 PipeControlPoint pcp = getControlPoint(); 
631                 if (pcp == null)
632                         throw new IllegalStateException("No centroid defined");
633                 
634                 double pipeRadius = getPipeRun().getPipeDiameter() / 2;
635                 
636                 switch (pcp.getType()) {
637                 case INLINE:
638                 case END:
639                         if (!pcp.isSizeChange()) {
640                                 // Just return the cylinder volume
641                                 return pcp.getLength() * Math.PI * pipeRadius * pipeRadius;
642                         }
643                         
644                         // Calculate center of mass for the frustum
645                         double r1 = pipeRadius;
646                         double r2 = getAlternativePipeRun().getPipeDiameter() / 2;
647                         return pcp.getLength() * Math.PI * (r1*r1 + r1*r2 + r2*r2) / 4;
648                 case TURN: {
649                         double r = ((TurnComponent)this).getTurnRadius();
650                         double a = pcp.getTurnAngle();
651                         return r * a * Math.PI * pipeRadius * pipeRadius;
652                 }
653                 default:
654                         throw new IllegalStateException("No centroid defined");
655                 }
656         }
657 }