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