]> gerrit.simantics Code Review - simantics/3d.git/blobdiff - org.simantics.plant3d/src/org/simantics/plant3d/scenegraph/controlpoint/PipeControlPoint.java
Fix error in inserting dual inline components
[simantics/3d.git] / org.simantics.plant3d / src / org / simantics / plant3d / scenegraph / controlpoint / PipeControlPoint.java
index 37f118cd05e00bd6b76db739cb661e85efed8ea6..cd4f407b22b6f65e3e80a91c2bc4cc5fae2df9a6 100644 (file)
@@ -4,6 +4,7 @@ import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collection;
 import java.util.List;
+import java.util.Objects;
 
 import javax.vecmath.AxisAngle4d;
 import javax.vecmath.Matrix3d;
@@ -15,6 +16,7 @@ import javax.vecmath.Vector3d;
 import org.simantics.g3d.math.MathTools;
 import org.simantics.g3d.property.annotations.GetPropertyValue;
 import org.simantics.g3d.scenegraph.G3DNode;
+import org.simantics.g3d.scenegraph.base.INode;
 import org.simantics.plant3d.scenegraph.IP3DNode;
 import org.simantics.plant3d.scenegraph.Nozzle;
 import org.simantics.plant3d.scenegraph.P3DRootNode;
@@ -378,9 +380,10 @@ public class PipeControlPoint extends G3DNode implements IP3DNode {
        }
 
        public void setLength(double l) {
-               if (Double.isInfinite(l) || Double.isNaN(l)) {
+               if (this.length == l)
+                       return;
+               if (Double.isInfinite(l) || Double.isNaN(l))
                        return;
-               }
                if (Math.abs(this.length-l) < MathTools.NEAR_ZERO)
                        return;
                this.length = l;
@@ -428,6 +431,8 @@ public class PipeControlPoint extends G3DNode implements IP3DNode {
                }
                if (this.turnAngle != null && Math.abs(this.turnAngle-turnAngle) < MathTools.NEAR_ZERO)
                        return;
+               if (Objects.equals(this.turnAngle, turnAngle))
+                       return;
                this.turnAngle = turnAngle;
                firePropertyChanged("turnAngle");
        }
@@ -445,6 +450,8 @@ public class PipeControlPoint extends G3DNode implements IP3DNode {
                }
                if (this.offset != null && Math.abs(this.offset-offset) < MathTools.NEAR_ZERO)
                        return;
+               if (Objects.equals(this.offset, offset))
+                       return;
                this.offset = offset;
                firePropertyChanged("offset");
        }
@@ -455,11 +462,15 @@ public class PipeControlPoint extends G3DNode implements IP3DNode {
                }
                if (this.rotationAngle != null && Math.abs(this.rotationAngle-rotationAngle) < MathTools.NEAR_ZERO)
                        return;
+               if (Objects.equals(this.rotationAngle, rotationAngle))
+                       return;
                this.rotationAngle = rotationAngle;
                firePropertyChanged("rotationAngle");
        }
 
        public void setReversed(Boolean reversed) {
+               if (this.reversed == reversed)
+                       return;
                this.reversed = reversed;
                firePropertyChanged("reversed");
        }
@@ -514,14 +525,42 @@ public class PipeControlPoint extends G3DNode implements IP3DNode {
                return type.name();
        }
 
-       public Quat4d getControlPointOrientationQuat(double angle) {
+       public Vector3d getPathLegEndpointVector() {
+               PipeControlPoint a = findPreviousEnd();
+               PipeControlPoint b = findNextEnd();
+               
+               if (a == null || b == null) {
+                       return getPathLegDirection();
+               }
+               
+               Vector3d p1 = a.getWorldPosition();
+               Vector3d p2 = b.getWorldPosition();
+               p2.sub(p1);
+               double l = p2.length();
+               if (l != 0.0) {
+                       p2.scale(1.0 / l);
+                       return p2;
+               }
+               else {
+                       return getPathLegDirection();
+               }
+       }
 
+       public Vector3d getPathLegDirection() {
                if (turnAxis == null) {
-                       Vector3d dir = getPathLegDirection(Direction.NEXT);
-                       return getControlPointOrientationQuat(dir, angle);
+                       return getPathLegDirection(Direction.NEXT);
                } else {
                        Vector3d dir = getPathLegDirection(Direction.PREVIOUS);
                        if (dir != null) dir.negate();
+                       return dir;
+               }
+       }
+       
+       public Quat4d getControlPointOrientationQuat(double angle) {
+               Vector3d dir = getPathLegDirection();
+               if (turnAxis == null) {
+                       return getControlPointOrientationQuat(dir, angle);
+               } else {
                        return getControlPointOrientationQuat(dir, turnAxis, angle);
                }
        }
@@ -545,34 +584,37 @@ public class PipeControlPoint extends G3DNode implements IP3DNode {
        }
 
        public Quat4d getControlPointOrientationQuat(double angle, boolean reversed) {
-
-               if (turnAxis == null) {
-                       Vector3d dir = getPathLegDirection(Direction.NEXT);
-                       return getControlPointOrientationQuat(dir, angle, reversed);
-               } else {
-                       Vector3d dir = getPathLegDirection(Direction.PREVIOUS);
-                       dir.negate();
-                       return getControlPointOrientationQuat(dir, angle, reversed);
-               }
+               Vector3d dir = getPathLegDirection();
+               return getControlPointOrientationQuat(dir, angle, reversed);
        }
 
-
-
-       public static Quat4d getControlPointOrientationQuat(Vector3d dir, double angle) {
+       public Quat4d getControlPointOrientationQuat(Vector3d dir, double angle) {
                if (dir == null || dir.lengthSquared() < MathTools.NEAR_ZERO)
                        return MathTools.getIdentityQuat();
 
-
-               Vector3d up = new Vector3d(0.0, 1.0, 0.0);
-               double a = up.angle(dir);
+               final P3DRootNode root = getRoot();
+               Vector3d up = root != null ? new Vector3d(root.getUpVector()) : new Vector3d(0.0, 1.0, 0.0);
+               final Vector3d legDir = getPathLegEndpointVector();
+               double a = up.angle(legDir);
                if (a < 0.1 || (Math.PI - a) < 0.1) {
-                       up.set(1.0, 0.0, 0.0);
+                       // Rotate components
+                       up.set(up.getY(), up.getZ(), up.getX());
                }
-
+               
+               // Project up vector into a normal of the leg direction before applying to 'dir'
+               MathTools.mad(up, legDir, -legDir.dot(up)/legDir.lengthSquared());
+               up.normalize();
 
                return getControlPointOrientationQuat(dir, up, angle);
        }
 
+       public P3DRootNode getRoot() {
+               INode n = getParent();
+               while (n != null && !(n instanceof P3DRootNode))
+                       n = n.getParent();
+               return (P3DRootNode) n;
+       }
+
        public static Quat4d getControlPointOrientationQuat(Vector3d dir, Vector3d up,  double angle) {
                if (dir == null || dir.lengthSquared() < MathTools.NEAR_ZERO)
                        return MathTools.getIdentityQuat();
@@ -583,7 +625,8 @@ public class PipeControlPoint extends G3DNode implements IP3DNode {
 
 
                Vector3d right = new Vector3d();
-
+               
+               up = new Vector3d(up);
                right.cross(dir, up);
                up.cross(right, dir);
                right.normalize();
@@ -707,9 +750,6 @@ public class PipeControlPoint extends G3DNode implements IP3DNode {
                        if (pcp.isDualSub()) {
                                pcp.getParentPoint().setNext(this);
                        }
-                       if (isDualInline()) {
-                           getDualSub().setPrevious(this);
-                       }
                } else {
                        // if direction is previous, user must have given sizechange
                        if (pcp.isDualSub())
@@ -748,9 +788,15 @@ public class PipeControlPoint extends G3DNode implements IP3DNode {
        }
        
        /**
-        * Returns direction vector. 
+        * Returns direction vector pointing towards an adjacent component for
+        * directed control points or turn control points with one open end. 
+        * 
+        * Always returns an outwards pointing vector.
         * 
-        * For directed control points, always returns outwards pointing vector.
+        * For any other type of component, the return value is null.
+        * 
+        * For turn components this only return a non-null value for the unconnected
+        * end of the component. 
         * 
         * @param direction
         * @return normalized vector, or null
@@ -794,6 +840,7 @@ public class PipeControlPoint extends G3DNode implements IP3DNode {
                     Vector3d offset = new Vector3d();
                     MathTools.rotate(q2, v, offset);
                     MathTools.rotate(q, offset, dir);
+                    dir.negate();
                     dir.normalize();
                     return dir;
                 }
@@ -812,107 +859,70 @@ public class PipeControlPoint extends G3DNode implements IP3DNode {
         */
        public Vector3d getPathLegDirection(Direction direction) {
                if (direction == Direction.NEXT) {
-                       if (next != null) {
-                               PipeControlPoint pcp = this;
-                               if (pcp.isDualInline()) {
-                                       pcp = pcp.getDualSub();
-                               }
-                               Vector3d v = new Vector3d();
-                               v.sub(next.getWorldPosition(),pcp.getWorldPosition());
-                               if (v.lengthSquared() > MathTools.NEAR_ZERO)
-                    v.normalize();
-                else
-                    return null;
-                               return v;
-                       } else {
-                               if (previous == null) {
-                                       if (!isDirected())
-                                               throw new RuntimeException("Cannot calculate path leg direction for unconnected control point " + this);
-                                       return getDirectedControlPointDirection();
+                       return getPathLegDirectionNext();
+               } else {
+                       return getPathLegDirectionPrevious();
+               }
+       }
 
-                               } else {
-                                       if (isVariableAngle() && !asFixedAngle())
-                                               throw new RuntimeException("Cannot calculate path leg direction for unconnected variable angle control point " + this);
-                                       if (isInline()) {
-                                               PipeControlPoint pcp = this;
-                                               if (pcp.isDualSub()) {
-                                                       pcp = pcp.getParentPoint();
-                                               }
-                                               Vector3d v = new Vector3d();
-                                               v.sub(pcp.getWorldPosition(),previous.getWorldPosition());
-                                               if (v.lengthSquared() > MathTools.NEAR_ZERO)
-                               v.normalize();
-                                               else
-                                                   return null;
-                                               return v;
-                                       } else if (isDirected()) {
-                                               return getDirectedControlPointDirection();
-                                       } else if (isEnd()) {
-                                               Vector3d v = new Vector3d();
-                                               v.sub(getWorldPosition(),previous.getWorldPosition());
-                                               if (v.lengthSquared() > MathTools.NEAR_ZERO)
-                            v.normalize();
-                        else
-                            return null;
-                                               return v;
-                                       } else if (isTurn() && asFixedAngle() && !_getReversed()) {
-                                               return getDirection(Direction.NEXT);
-                                       }
-                                       throw new RuntimeException("Missing implementation " + this);
-                               }
-                       }
+       public Vector3d getPathLegDirectionPrevious() {
+               if (previous != null) {
+                       PipeControlPoint pcp = this;
+                       if (isDualSub()) 
+                               pcp = getParentPoint();
+                       Vector3d v = new Vector3d();
+                       v.sub(previous.getWorldPosition(),pcp.getWorldPosition());
+                       if (v.lengthSquared() > MathTools.NEAR_ZERO)
+                       v.normalize();
+                   else
+                       return null;
+                       return v;
+               } else if (isDirected()) {
+                       Vector3d v = getDirectedControlPointDirection();
+                       v.negate();
+                       return v;
+               } else if (next == null)  {
+                       throw new RuntimeException("Cannot calculate path leg direction for unconnected control point " + this);
+               } else if (isVariableAngle() && !asFixedAngle()) {
+                       throw new RuntimeException("Cannot calculate path leg direction for unconnected variable angle control point " + this);
+               } else if (isInline() || isEnd()) {
+                       Vector3d v = getPathLegDirectionNext();
+                       if (v != null) v.negate();
+                       return v;
+               } else if (isTurn() && asFixedAngle() && _getReversed()) {
+                       return getDirection(Direction.PREVIOUS);
                } else {
-                       if (previous != null) {
-                               PipeControlPoint pcp = this;
-                               if (isDualSub()) 
-                                       pcp = getParentPoint();
-                               Vector3d v = new Vector3d();
-                               v.sub(previous.getWorldPosition(),pcp.getWorldPosition());
-                               if (v.lengthSquared() > MathTools.NEAR_ZERO)
-                    v.normalize();
-                else
-                    return null;
-                               return v;
-                       } else {
-                               if (next == null)  {
-                                       if (!isDirected())
-                                               throw new RuntimeException("Cannot calculate path leg direction for unconnected control point " + this);
-                                       Vector3d v = getDirectedControlPointDirection();
-                                       v.negate();
-                                       return v;
-                               } else {
-                                       if (isVariableAngle() && !asFixedAngle())
-                                               throw new RuntimeException("Cannot calculate path leg direction for unconnected variable angle control point " + this);
-                                       if (isInline()) {
-                                               PipeControlPoint pcp = this;
-                                               if (pcp.isDualInline()) {
-                                                       pcp = pcp.getDualSub();
-                                               }
-                                               Vector3d v = new Vector3d();
-                                               v.sub(pcp.getWorldPosition(),next.getWorldPosition());
-                                               if (v.lengthSquared() > MathTools.NEAR_ZERO)
-                            v.normalize();
-                        else
-                            return null;
-                                               return v;
-                                       } else if (isDirected()) {
-                                               Vector3d v = getDirectedControlPointDirection();
-                                               v.negate();
-                                               return v;
-                                       } else if (isEnd()) {
-                                               Vector3d v = new Vector3d();
-                                               v.sub(getWorldPosition(),next.getWorldPosition());
-                                               if (v.lengthSquared() > MathTools.NEAR_ZERO)
-                            v.normalize();
-                        else
-                            return null;
-                                               return v;
-                                       } else if (isTurn() && asFixedAngle() && _getReversed()) {
-                                               return getDirection(Direction.PREVIOUS);
-                                       }
-                                       throw new RuntimeException("Missing implementation " + this);
-                               }
+                       throw new RuntimeException("Missing implementation " + this);
+               }
+       }
+
+       public Vector3d getPathLegDirectionNext() {
+               if (next != null) {
+                       PipeControlPoint pcp = this;
+                       if (pcp.isDualInline()) {
+                               pcp = pcp.getDualSub();
                        }
+                       Vector3d v = new Vector3d();
+                       v.sub(next.getWorldPosition(),pcp.getWorldPosition());
+                       if (v.lengthSquared() > MathTools.NEAR_ZERO)
+                       v.normalize();
+                   else
+                       return null;
+                       return v;
+               } else if (isDirected()) {
+                       return getDirectedControlPointDirection();
+               } else if (previous == null) {
+                       throw new RuntimeException("Cannot calculate path leg direction for unconnected control point " + this);
+               } else if (isVariableAngle() && !asFixedAngle()) {
+                       throw new RuntimeException("Cannot calculate path leg direction for unconnected variable angle control point " + this);
+               } else if (isInline() || isEnd()) {
+                       Vector3d v = getPathLegDirectionPrevious();
+                       if (v != null) v.negate();
+                       return v;
+               } else if (isTurn() && asFixedAngle() && !_getReversed()) {
+                       return getDirection(Direction.NEXT);
+               } else {
+                       throw new RuntimeException("Missing implementation " + this);
                }
        }
 
@@ -1405,6 +1415,7 @@ public class PipeControlPoint extends G3DNode implements IP3DNode {
             
             PipeRun previousRun = previous.getPipeRun();
             nextPipeRun.setPipeDiameter(previousRun.getPipeDiameter());
+            nextPipeRun.setPipeThickness(previousRun.getPipeThickness());
             nextPipeRun.setTurnRadiusArray(previousRun.getTurnRadiusArray());
             
             PipelineComponent n = next.getPipelineComponent();
@@ -1570,7 +1581,7 @@ public class PipeControlPoint extends G3DNode implements IP3DNode {
                        component._setWorldPosition(getWorldPosition());
                updateSubPoint();
        }
-
+       
        private void updateSubPoint() {
                if (isOffset()) {
                        if (next == null && previous == null) {
@@ -1607,6 +1618,21 @@ public class PipeControlPoint extends G3DNode implements IP3DNode {
                updateSubPoint();
        }
 
+       public void orientToDirection(Vector3d dir) {
+               Double angleO = getRotationAngle();
+               double angle = 0.0;
+               if (angleO != null)
+                       angle = angleO;
+               boolean reversed = _getReversed();
+               Quat4d q = null;
+               if (dir != null) {
+                   q = getControlPointOrientationQuat(dir, angle, reversed);
+               } else {
+                   q = getControlPointOrientationQuat(angle, reversed);
+               }
+               setWorldOrientation(q);
+       }
+
        @Override
        public String toString() {
                return getClass().getName() + "@" + Integer.toHexString(hashCode());