]> gerrit.simantics Code Review - simantics/3d.git/blob - org.simantics.plant3d/src/org/simantics/plant3d/scenegraph/TurnComponent.java
1bf674410cbf1be7aaebc6fe20ad082b1cf06519
[simantics/3d.git] / org.simantics.plant3d / src / org / simantics / plant3d / scenegraph / TurnComponent.java
1 package org.simantics.plant3d.scenegraph;
2
3 import java.util.ArrayList;
4 import java.util.HashMap;
5 import java.util.List;
6 import java.util.Map;
7
8 import javax.vecmath.Vector3d;
9
10 import org.simantics.g3d.math.MathTools;
11 import org.simantics.g3d.property.annotations.GetComboProperty;
12 import org.simantics.g3d.property.annotations.GetComboPropertyValue;
13 import org.simantics.g3d.property.annotations.GetPropertyValue;
14 import org.simantics.g3d.property.annotations.SetComboPropertyValue;
15 import org.simantics.g3d.property.annotations.SetPropertyValue;
16 import org.simantics.g3d.scenegraph.base.ParentNode;
17 import org.simantics.g3d.tools.NodeTools;
18 import org.simantics.objmap.graph.annotations.DynamicGraphType;
19 import org.simantics.objmap.graph.annotations.GetType;
20 import org.simantics.objmap.graph.annotations.RelatedGetValue;
21 import org.simantics.objmap.graph.annotations.RelatedSetValue;
22 import org.simantics.objmap.graph.annotations.SetType;
23 import org.simantics.plant3d.ontology.Plant3D;
24 import org.simantics.plant3d.scenegraph.controlpoint.ControlPointFactory;
25 import org.simantics.plant3d.scenegraph.controlpoint.PipeControlPoint;
26 import org.simantics.plant3d.scenegraph.controlpoint.PipingRules;
27
28 @DynamicGraphType(Plant3D.URIs.TurnComponent)
29 public class TurnComponent extends PipelineComponent {
30
31         
32         private String type;
33         private PipeControlPoint controlPoint;
34         private Integer turnRadiusIndex;
35         
36         @GetType(Plant3D.URIs.TurnComponent)
37         public String getType() {
38                 return type;
39         }
40         
41         @SetType(Plant3D.URIs.TurnComponent)
42         public void setType(String type) throws Exception{
43                 this.type = type;
44                 controlPoint = ControlPointFactory.create(this);
45         }
46         
47         @Override
48         public PipeControlPoint getControlPoint() {
49                 return controlPoint;
50         }
51         
52         @Override
53         public void setParent(ParentNode<?> parent, String name) {
54                 super.setParent(parent, name);
55                 setPipeRun((PipeRun)parent);
56         }
57         
58         @Override
59         public Map<String, Object> updateParameterMap() {
60                 Map<String,Object> map = new HashMap<String, Object>();
61                 
62                 if (getPipeRun() != null) {
63                 map.put("turnRadius", getTurnRadius());
64                 map.put("radius", getDiameter() * 0.5);
65                 }
66                 if (controlPoint != null && controlPoint.getTurnAngle() != null  && !Double.isNaN(controlPoint.getTurnAngle())) {
67                         map.put("turnAngle", controlPoint.getTurnAngle());
68                 }
69                 return map;
70         }
71         
72         public boolean isVariableAngle() {
73                 return !controlPoint.isFixed();
74         }
75         
76         @Override
77         public void updateParameters() {
78                 super.updateParameters();
79                 if (controlPoint.asFixedAngle()) {
80                         Map<String,Object> calculated = getCalculatedParameters();
81                         if (calculated.containsKey("length")) {
82                                 controlPoint.setLength((Double)calculated.get("length"));
83                         }
84                         PipingRules.requestUpdate(getControlPoint());
85                 }
86         }
87         
88         public Double getTurnAngle() {
89             return getControlPoint().getTurnAngle();
90         }
91         
92         @RelatedGetValue(Plant3D.URIs.HasTurnAngle)
93         public Double _getTurnAngle() {
94             if (!getControlPoint().asFixedAngle())
95                 return null;
96                 return getControlPoint().getTurnAngle();
97         }
98         
99         @RelatedSetValue(Plant3D.URIs.HasTurnAngle)
100         public void setTurnAngle(Double a) {
101                 if (!getControlPoint().asFixedAngle())
102                         return;
103                 getControlPoint().setTurnAngle(a);            
104         }
105         
106         @GetPropertyValue(name="Turn Angle", value="turn angle", tabId = "Default")
107         public Double getTurnAngleDeg() {
108                 Double d = getControlPoint().getTurnAngle();
109                 if (d == null)
110                         return null;
111                 return MathTools.radToDeg(d);
112         }
113         
114         public Vector3d getTurnAxis() {
115                 return getControlPoint().getTurnAxis();
116         }
117         
118     public Double getTurnRadius() {
119             if (turnRadiusIndex != null)
120                 return getPipeRun().getTurnRadiusArray()[turnRadiusIndex];
121             return getPipeRun().getTurnRadiusArray()[0];
122         }
123         
124         @RelatedGetValue(Plant3D.URIs.HasTurnRadiusIndex)
125         @GetComboPropertyValue(name="Turn Radius", value=Plant3D.URIs.HasTurnRadiusIndex, tabId = "Default")
126         public Integer getTurnRadiusIndex() 
127         {
128         // TODO: For backwards compatibility, we do not accept null values. 
129         //       One development path would allow null index, and setting custom turn radius for the component.
130         if (turnRadiusIndex == null)
131                 return 0;
132             return turnRadiusIndex;
133         }
134         
135         @RelatedSetValue(Plant3D.URIs.HasTurnRadiusIndex)
136         @SetComboPropertyValue(value=Plant3D.URIs.HasTurnRadiusIndex)
137     public void setTurnRadiusIndex(Integer turnRadiusIndex) {
138             if (this.turnRadiusIndex == turnRadiusIndex)
139                 return;
140             if (turnRadiusIndex == null)
141                 return;
142             if (turnRadiusIndex != null && getPipeRun() != null) {
143                 if (getPipeRun().getTurnRadiusArray().length <= turnRadiusIndex)
144                     return;
145             }
146             this.turnRadiusIndex = turnRadiusIndex;
147         firePropertyChanged(Plant3D.URIs.HasTurnRadiusIndex);
148         PipingRules.requestUpdate(getControlPoint());
149     }
150         
151         @GetComboProperty(value=Plant3D.URIs.HasTurnRadiusIndex)
152         public List<Double> _getTurnRadii() {
153             List<Double> values = new ArrayList<Double>();
154             for (double d : getPipeRun().getTurnRadiusArray())
155                 values.add(d);
156             return values;
157         }
158         
159         
160         @RelatedGetValue(Plant3D.URIs.HasRotationAngle)
161         @GetPropertyValue(name="Rotation Angle", value=Plant3D.URIs.HasRotationAngle, tabId = "Default")
162         public Double getRotationAngle() {
163                 if (!controlPoint.asFixedAngle())
164                         return null;
165                 Double d = controlPoint.getRotationAngle();
166                 if (d == null)
167                         return 0.0;
168                 return MathTools.radToDeg(d);
169         }
170         @RelatedSetValue(Plant3D.URIs.HasRotationAngle)
171         @SetPropertyValue(value=Plant3D.URIs.HasRotationAngle)
172         public void setRotationAngle(Double angle) {
173                 if (!controlPoint.asFixedAngle())
174                         return;
175                 
176                 if (angle == null || Double.isInfinite(angle) || Double.isNaN(angle)) {
177                         return;
178                 }
179                 angle = MathTools.degToRad(angle);
180                 if (controlPoint.getRotationAngle() != null && Math.abs(controlPoint.getRotationAngle()-angle) < MathTools.NEAR_ZERO)
181                         return;
182                 controlPoint.setRotationAngle(angle);
183                 PipingRules.requestUpdate(getControlPoint());
184         }
185         
186         @RelatedGetValue(Plant3D.URIs.IsReversed)
187         @GetPropertyValue(name="Reverse", value=Plant3D.URIs.IsReversed, tabId = "Default")
188         public Boolean isReversed() {
189                 if (!controlPoint.asFixedAngle())
190                         return null;
191                 Boolean d = controlPoint._getReversed();
192                 return d;
193         }
194         @RelatedSetValue(Plant3D.URIs.IsReversed)
195         public void setReversed(Boolean reverse) {
196                 if (!controlPoint.asFixedAngle())
197                         return;
198                 
199                 if (reverse == null) {
200                         return;
201                 }
202                 controlPoint.setReversed(reverse);
203                 PipingRules.requestUpdate(getControlPoint()); 
204         }
205         
206         @Override
207         protected double[] getColor() {
208                 if (getControlPoint() == null || !getControlPoint().isFixed())
209                         return new double[]{0.6,0.6,0.6};
210                 else
211                         return new double[]{1.0,0.0,0.0};
212         }
213         
214         /**
215          * Turn is a section of a circle; this method returns center of that circle.
216          * @return
217          */
218         public Vector3d getCenterPosition() {
219             // getPosition() is control point position, located outside of turn
220         // we need to calculate position in the middle of the turn
221         double t = Math.tan((Math.PI - getControlPoint().getTurnAngle()) * 0.5);
222         double tr = getTurnRadius();
223         double R = 0.0;
224         if (t > MathTools.NEAR_ZERO)
225             R = tr / t;
226         Vector3d localC = new Vector3d(-R, 0.0, -tr);
227         // worldC is center of a circle
228         Vector3d worldC = NodeTools.getWorldPosition(this,localC);
229         return worldC;
230         }
231         
232         /**
233          * Returns position in the middle of turn component
234          * @return
235          */
236         public Vector3d getMiddlePosition() {
237             Vector3d pos = getWorldPosition();
238             Vector3d worldC = getCenterPosition();
239             
240             // calculate vector from center to edge, which is middle of the turn
241         pos.sub(worldC);
242         pos.normalize();
243         pos.scale(getTurnRadius());
244         pos.add(worldC);
245         return pos;
246         }
247 }