1 package org.simantics.plant3d.scenegraph;
3 import java.util.ArrayList;
4 import java.util.HashMap;
8 import javax.vecmath.Vector3d;
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;
28 @DynamicGraphType(Plant3D.URIs.TurnComponent)
29 public class TurnComponent extends PipelineComponent {
33 private PipeControlPoint controlPoint;
34 private Integer turnRadiusIndex;
36 @GetType(Plant3D.URIs.TurnComponent)
37 public String getType() {
41 @SetType(Plant3D.URIs.TurnComponent)
42 public void setType(String type) throws Exception{
44 controlPoint = ControlPointFactory.create(this);
51 public PipeControlPoint getControlPoint() {
56 public void setParent(ParentNode<?> parent, String name) {
57 super.setParent(parent, name);
58 setPipeRun((PipeRun)parent);
62 public Map<String, Object> updateParameterMap() {
63 Map<String,Object> map = new HashMap<String, Object>();
65 if (getPipeRun() != null) {
66 map.put("turnRadius", getTurnRadius());
67 map.put("radius", getDiameter() * 0.5);
69 if (controlPoint != null && controlPoint.getTurnAngle() != null && !Double.isNaN(controlPoint.getTurnAngle())) {
70 map.put("turnAngle", controlPoint.getTurnAngle());
75 public boolean isVariableAngle() {
76 return !controlPoint.isFixed();
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"));
87 PipingRules.requestUpdate(getControlPoint());
91 public Double getTurnAngle() {
92 return getControlPoint().getTurnAngle();
95 @RelatedGetValue(Plant3D.URIs.HasTurnAngle)
96 public Double _getTurnAngle() {
97 if (!getControlPoint().asFixedAngle())
99 return getControlPoint().getTurnAngle();
102 @RelatedSetValue(Plant3D.URIs.HasTurnAngle)
103 public void setTurnAngle(Double a) {
104 if (!getControlPoint().asFixedAngle())
106 getControlPoint().setTurnAngle(a);
109 @GetPropertyValue(name="Turn Angle", value="turn angle", tabId = "Default")
110 public Double getTurnAngleDeg() {
111 Double d = getControlPoint().getTurnAngle();
114 return MathTools.radToDeg(d);
117 public Vector3d getTurnAxis() {
118 return getControlPoint().getTurnAxis();
121 public Double getTurnRadius() {
122 if (turnRadiusIndex != null)
123 return getPipeRun().getTurnRadiusArray()[turnRadiusIndex];
124 return getPipeRun().getTurnRadiusArray()[0];
127 @RelatedGetValue(Plant3D.URIs.HasTurnRadiusIndex)
128 @GetComboPropertyValue(name="Turn Radius", value=Plant3D.URIs.HasTurnRadiusIndex, tabId = "Default")
129 public Integer getTurnRadiusIndex()
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)
135 return turnRadiusIndex;
138 @RelatedSetValue(Plant3D.URIs.HasTurnRadiusIndex)
139 @SetComboPropertyValue(value=Plant3D.URIs.HasTurnRadiusIndex)
140 public void setTurnRadiusIndex(Integer turnRadiusIndex) {
141 if (this.turnRadiusIndex == turnRadiusIndex)
143 if (turnRadiusIndex == null || turnRadiusIndex < 0)
145 if (turnRadiusIndex != null && getPipeRun() != null) {
146 if (getPipeRun().getTurnRadiusArray().length <= turnRadiusIndex)
149 this.turnRadiusIndex = turnRadiusIndex;
150 firePropertyChanged(Plant3D.URIs.HasTurnRadiusIndex);
151 PipingRules.requestUpdate(getControlPoint());
154 @GetComboProperty(value=Plant3D.URIs.HasTurnRadiusIndex)
155 public List<Double> _getTurnRadii() {
156 List<Double> values = new ArrayList<Double>();
157 for (double d : getPipeRun().getTurnRadiusArray())
163 @RelatedGetValue(Plant3D.URIs.HasRotationAngle)
164 @GetPropertyValue(name="Rotation Angle", value=Plant3D.URIs.HasRotationAngle, tabId = "Default")
165 public Double getRotationAngle() {
166 if (!controlPoint.asFixedAngle())
168 Double d = controlPoint.getRotationAngle();
171 return MathTools.radToDeg(d);
173 @RelatedSetValue(Plant3D.URIs.HasRotationAngle)
174 @SetPropertyValue(value=Plant3D.URIs.HasRotationAngle)
175 public void setRotationAngle(Double angle) {
176 if (!controlPoint.asFixedAngle())
179 if (angle == null || Double.isInfinite(angle) || Double.isNaN(angle)) {
182 angle = MathTools.degToRad(angle);
183 if (controlPoint.getRotationAngle() != null && Math.abs(controlPoint.getRotationAngle()-angle) < MathTools.NEAR_ZERO)
185 controlPoint.setRotationAngle(angle);
186 PipingRules.requestUpdate(getControlPoint());
189 @RelatedGetValue(Plant3D.URIs.IsReversed)
190 @GetPropertyValue(name="Reverse", value=Plant3D.URIs.IsReversed, tabId = "Default")
191 public Boolean isReversed() {
192 if (!controlPoint.asFixedAngle())
194 Boolean d = controlPoint._getReversed();
197 @RelatedSetValue(Plant3D.URIs.IsReversed)
198 public void setReversed(Boolean reverse) {
199 if (!controlPoint.asFixedAngle())
202 if (reverse == null) {
205 controlPoint.setReversed(reverse);
206 PipingRules.requestUpdate(getControlPoint());
210 protected double[] getColor() {
211 if (getControlPoint() == null || !getControlPoint().isFixed())
212 return new double[]{0.6,0.6,0.6};
214 return new double[]{1.0,0.0,0.0};
218 * Turn is a section of a circle; this method returns center of that circle.
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();
227 if (t > MathTools.NEAR_ZERO)
229 Vector3d localC = new Vector3d(-R, 0.0, -tr);
230 // worldC is center of a circle
231 Vector3d worldC = NodeTools.getWorldPosition(this,localC);
236 * Returns position in the middle of turn component
239 public Vector3d getMiddlePosition() {
240 Vector3d pos = getWorldPosition();
241 Vector3d worldC = getCenterPosition();
243 // calculate vector from center to edge, which is middle of the turn
246 pos.scale(getTurnRadius());