]> 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 aa5eacf9338550c88ef2e6692677c349dd0f82c3..0c7e3b26ed4935f297f94c12ab7386a01faaf488 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;
@@ -43,6 +45,8 @@ public class PipeControlPoint extends G3DNode implements IP3DNode {
        private boolean isSizeChange = false;  // changes size of the pipe. The next control point / component is on different PipeRun
        private boolean isSub = false;         // child point for offset / size change
 
+       private boolean disposed = false;
+       
        public PipeControlPoint(PipelineComponent component) {
                this.component = component;
                if (component.getPipeRun() != null)
@@ -145,6 +149,11 @@ public class PipeControlPoint extends G3DNode implements IP3DNode {
        public boolean isInline() {
                return type == PointType.INLINE;
        }
+       
+       public boolean asPathLegEnd() {
+           // Ends and Turns are path leg ends by default, but also unconnected inline are path leg ends.
+           return isPathLegEnd() || getNext() == null || getPrevious() == null;
+       }
 
        /**
         * True for end components, if control point defines absolute position direction, which rules cannot modify. 
@@ -324,9 +333,9 @@ public class PipeControlPoint extends G3DNode implements IP3DNode {
         // We need to calculate turnAngle and rotationAngle
            Vector3d dirOut = getPathLegDirection(direction == Direction.NEXT ? Direction.NEXT : Direction.PREVIOUS);
         Vector3d dir = getPathLegDirection(direction == Direction.NEXT ? Direction.PREVIOUS : Direction.NEXT);
+        if (dir == null || dirOut == null)
+            return;
         dir.negate();
-        dirOut.normalize();
-        dir.normalize();
         double angle = dir.angle(dirOut);
         //super._setNext(null);
         if (direction == Direction.NEXT)
@@ -341,6 +350,7 @@ public class PipeControlPoint extends G3DNode implements IP3DNode {
         if (MathTools.createRotation(dirOutN, dirOut, dir, aa)) {
             setRotationAngle(aa.angle);
             setTurnAngle(angle);
+            if (DEBUG) System.out.println("convertToFixed " + dir + " " + dirOut + " " +dirOutN + " " +angle + " "+ aa.angle);
         }
        }
 
@@ -370,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;
@@ -420,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");
        }
@@ -437,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");
        }
@@ -447,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(rotationAngle, rotationAngle))
+                       return;
                this.rotationAngle = rotationAngle;
                firePropertyChanged("rotationAngle");
        }
 
        public void setReversed(Boolean reversed) {
+               if (this.reversed == reversed)
+                       return;
                this.reversed = reversed;
                firePropertyChanged("reversed");
        }
@@ -506,63 +525,98 @@ 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);
-                       if (dir.lengthSquared() > MathTools.NEAR_ZERO)
-                               dir.normalize();
-                       return getControlPointOrientationQuat(dir, angle);
+                       return getPathLegDirection(Direction.NEXT);
                } else {
                        Vector3d dir = getPathLegDirection(Direction.PREVIOUS);
-                       dir.negate();
-                       if (dir.lengthSquared() > MathTools.NEAR_ZERO)
-                               dir.normalize();
-                       return getControlPointOrientationQuat(dir, turnAxis, angle);
+                       if (dir != null) dir.negate();
+                       return dir;
                }
        }
-
-       public Quat4d getControlPointOrientationQuat(double angle, boolean reversed) {
-
+       
+       public Quat4d getControlPointOrientationQuat(double angle) {
+               Vector3d dir = getPathLegDirection();
                if (turnAxis == null) {
-                       Vector3d dir = getPathLegDirection(Direction.NEXT);
-                       if (dir.lengthSquared() > MathTools.NEAR_ZERO)
-                               dir.normalize();
-                       Quat4d q =  getControlPointOrientationQuat(dir, angle);
-                       if (reversed) {
-                               Quat4d q2 = new Quat4d();
-                               q2.set(new AxisAngle4d(MathTools.Y_AXIS, Math.PI));
-                               q.mulInverse(q2);
-                       }
-                       return q;
+                       return getControlPointOrientationQuat(dir, angle);
                } else {
-                       Vector3d dir = getPathLegDirection(Direction.PREVIOUS);
-                       dir.negate();
-                       if (dir.lengthSquared() > MathTools.NEAR_ZERO)
-                               dir.normalize();
                        return getControlPointOrientationQuat(dir, turnAxis, angle);
                }
        }
+       
+       public Quat4d getControlPointOrientationQuat(Vector3d dir, double angle, boolean reversed) {
+           if (turnAxis == null) {
+            if (dir.lengthSquared() > MathTools.NEAR_ZERO)
+                dir.normalize();
+            Quat4d q =  getControlPointOrientationQuat(dir, angle);
+            if (reversed) {
+                Quat4d q2 = new Quat4d();
+                q2.set(new AxisAngle4d(MathTools.Y_AXIS, Math.PI));
+                q.mulInverse(q2);
+            }
+            return q;
+        } else {
+            if (dir.lengthSquared() > MathTools.NEAR_ZERO)
+                dir.normalize();
+            return getControlPointOrientationQuat(dir, turnAxis, angle);
+        }
+       }
 
+       public Quat4d getControlPointOrientationQuat(double angle, boolean reversed) {
+               Vector3d dir = getPathLegDirection();
+               return getControlPointOrientationQuat(dir, angle, reversed);
+       }
 
-
-       public static Quat4d getControlPointOrientationQuat(Vector3d dir, double angle) {
-               if (dir.lengthSquared() < MathTools.NEAR_ZERO)
+       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.lengthSquared() < MathTools.NEAR_ZERO)
+               if (dir == null || dir.lengthSquared() < MathTools.NEAR_ZERO)
                        return MathTools.getIdentityQuat();
 
                final Vector3d front = new Vector3d(1.0,0.0,0.0);
@@ -571,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();
@@ -604,8 +659,8 @@ public class PipeControlPoint extends G3DNode implements IP3DNode {
                if (isDualSub())
                        throw new RuntimeException("Dual sub points cannot be inserted.");
                // size change control point cannot be inserted this way, because it ends PipeRun
-               if (isSizeChange())
-                       throw new RuntimeException("Size change points cannot be inserted.");
+//             if (isSizeChange())
+//                     throw new RuntimeException("Size change points cannot be inserted.");
                PipeRun piperun = previous.getPipeRun();
                // and just to make sure that control point structure is not corrupted
                if (getPipeRun() != null) {
@@ -695,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())
@@ -735,6 +787,14 @@ public class PipeControlPoint extends G3DNode implements IP3DNode {
                return dir;
        }
        
+       /**
+        * Returns direction vector. 
+        * 
+        * For directed control points, always returns outwards pointing vector.
+        * 
+        * @param direction
+        * @return normalized vector, or null
+        */
        public Vector3d getDirection(Direction direction) {
         if (isDirected())
             return getDirectedControlPointDirection();
@@ -755,6 +815,7 @@ public class PipeControlPoint extends G3DNode implements IP3DNode {
                     Vector3d offset = new Vector3d();
                     MathTools.rotate(q2, v, offset);
                     MathTools.rotate(q, offset, dir);
+                    dir.normalize();
                     return dir;
                 }
             } else {
@@ -773,6 +834,7 @@ public class PipeControlPoint extends G3DNode implements IP3DNode {
                     Vector3d offset = new Vector3d();
                     MathTools.rotate(q2, v, offset);
                     MathTools.rotate(q, offset, dir);
+                    dir.normalize();
                     return dir;
                 }
             }
@@ -780,6 +842,14 @@ public class PipeControlPoint extends G3DNode implements IP3DNode {
         return null;
     }
 
+       /**
+        * Returns path leg direction of the control point.
+        * 
+        * This method differs from getDirection by also returning inward pointing vectors for directed control points.
+        * 
+        * @param direction
+        * @return
+        */
        public Vector3d getPathLegDirection(Direction direction) {
                if (direction == Direction.NEXT) {
                        if (next != null) {
@@ -789,6 +859,10 @@ public class PipeControlPoint extends G3DNode implements IP3DNode {
                                }
                                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) {
@@ -806,12 +880,20 @@ public class PipeControlPoint extends G3DNode implements IP3DNode {
                                                }
                                                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);
@@ -826,6 +908,10 @@ public class PipeControlPoint extends G3DNode implements IP3DNode {
                                        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)  {
@@ -844,6 +930,10 @@ public class PipeControlPoint extends G3DNode implements IP3DNode {
                                                }
                                                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();
@@ -852,6 +942,10 @@ public class PipeControlPoint extends G3DNode implements IP3DNode {
                                        } 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);
@@ -867,9 +961,8 @@ public class PipeControlPoint extends G3DNode implements IP3DNode {
 
                PipeControlPoint sub = isAxial() ? this : getDualSub();
                Vector3d pos = getWorldPosition(), pos2 = sub == this ? pos : sub.getWorldPosition();
-               Vector3d dir = sub.getPathLegDirection(Direction.NEXT);
+               Vector3d dir = sub.getInlineDir();
                
-               dir.normalize();
                dir.scale(length * 0.5);
                p1.set(pos);
                p2.set(pos2);
@@ -881,14 +974,16 @@ public class PipeControlPoint extends G3DNode implements IP3DNode {
                PipeControlPoint sub = isAxial() || isDirected() || isTurn() ? this : getChildPoints().get(0);
                Vector3d pos = getWorldPosition(), pos2 = sub == this ? pos : sub.getWorldPosition();
                
-               Vector3d dir1 = getPathLegDirection(Direction.PREVIOUS);
-               dir1.normalize();
-               Vector3d dir2 = sub.getPathLegDirection(Direction.NEXT);
-               dir2.normalize();
+               Vector3d dir1;
+               Vector3d dir2;
                if (isInline()) {
-                       dir1.scale(length * 0.5);
+                       dir2 = getInlineDir();
                        dir2.scale(length * 0.5);
+                       dir1 = new Vector3d(dir2);
+                       dir1.negate();
                } else {
+                       dir1 = getPathLegDirection(Direction.PREVIOUS);
+                       dir2 = sub.getPathLegDirection(Direction.NEXT);
                        dir1.scale(length);
                        dir2.scale(length);
                }
@@ -898,22 +993,34 @@ public class PipeControlPoint extends G3DNode implements IP3DNode {
                p2.add(dir2);
        }
 
+       /**
+        * Get both path leg directions, with (0,0,0) if no connection exists. The returned vectors are not normalized.
+        * 
+        * @param v1  Set to the direction towards the previous control point on output
+        * @param v2  Set to the direction towards the next control point on output
+        */
        public void getEndDirections(Tuple3d v1, Tuple3d v2) {
                PipeControlPoint sub = isAxial() ? this : getDualSub();
                
                Vector3d dir1 = getPathLegDirection(Direction.PREVIOUS);
-               dir1.normalize();
                Vector3d dir2 = sub.getPathLegDirection(Direction.NEXT);
-               dir2.normalize();
-               v1.set(dir1);
-               v2.set(dir2);
+               
+               if (dir1 != null)
+                       v1.set(dir1);
+               else
+                       v1.set(0,0,0);
+               
+               if (dir2 != null)
+                       v2.set(dir2);
+               else
+                       v2.set(0,0,0);
        }
 
        public void getInlineControlPointEnds(Tuple3d p1, Tuple3d p2, Vector3d dir) {
                assert (isInline());
 
                Vector3d pos = getWorldPosition();
-               dir.set(getPathLegDirection(Direction.NEXT));
+               dir.set(getInlineDir());
                dir.normalize();
                dir.scale(length * 0.5);
                p1.set(pos);
@@ -927,7 +1034,7 @@ public class PipeControlPoint extends G3DNode implements IP3DNode {
 
                Vector3d pos = getWorldPosition();
                center.set(pos);
-               dir.set(getPathLegDirection(Direction.NEXT));
+               dir.set(getInlineDir());
                dir.normalize();
                dir.scale(length * 0.5);
                p1.set(pos);
@@ -936,6 +1043,22 @@ public class PipeControlPoint extends G3DNode implements IP3DNode {
                p2.add(dir);
        }
 
+       public Vector3d getInlineDir() {
+               Vector3d dir = getPathLegDirection(Direction.NEXT);
+               if (dir == null) {
+                       dir = getPathLegDirection(Direction.PREVIOUS);
+                       if (dir != null) {
+                               // Use reverse direction
+                               dir.scale(-1.0);
+                       } else {
+                               // Control point is not connected at all, use current orientation
+                               dir = new Vector3d(1,0,0);
+                               MathTools.rotate(getWorldOrientation(), dir, dir);
+                       }
+               }
+               return dir;
+       }
+
        public double getInlineLength() {
                if (type == PointType.TURN)
                        return length;
@@ -944,21 +1067,37 @@ public class PipeControlPoint extends G3DNode implements IP3DNode {
                return 0;
        }
 
+       /**
+        * Return the position indicated by the argument. If the indicated direction is not connected, the
+        * control point's wolrd position is returned instead.
+        * 
+        * @param type  A selector for the position to be returned
+        * @return  The selected position
+        */
        public Vector3d getRealPosition(PositionType type) {
                Vector3d pos = getWorldPosition();
                switch (type) {
                case NEXT: {
-                       Vector3d dir = getPathLegDirection(Direction.NEXT);
                        double length = getInlineLength();
-                       dir.normalize();
+                       Vector3d dir;
+                       if (isInline()) {
+                               dir = getInlineDir();
+                       } else {
+                               dir = getPathLegDirection(Direction.NEXT);
+                       }
                        dir.scale(length);
                        pos.add(dir);
                        break;
                }
                case PREVIOUS: {
-                       Vector3d dir = getPathLegDirection(Direction.PREVIOUS);
                        double length = getInlineLength();
-                       dir.normalize();
+                       Vector3d dir;
+                       if (isInline()) {
+                               dir = getInlineDir();
+                               dir.negate();
+                       } else {
+                               dir = getPathLegDirection(Direction.PREVIOUS);
+                       }
                        dir.scale(length);
                        pos.add(dir);
                        break;
@@ -1065,17 +1204,19 @@ public class PipeControlPoint extends G3DNode implements IP3DNode {
        
 
        public void _remove(boolean renconnect) {
-               if (component == null && next == null && previous == null)
-                       return;
-               if (DEBUG) System.out.println(this + " Remove " + renconnect);
+           if (disposed)
+               return;
+               
+           if (DEBUG) System.out.println(this + " Remove " + renconnect);
 
                if (getParentPoint() != null) {
                    getParentPoint()._remove(renconnect);
                    return;
                }
                PipeRun pipeRun = getPipeRun();
-               if (pipeRun == null)
-                       return;
+//             PipeRUn removal has been changed, so pipeRun may be null.
+//             if (pipeRun == null)
+//                     return;
 
                PipeControlPoint additionalRemove = null;
                if (!PipingRules.isEnabled()) {
@@ -1088,8 +1229,10 @@ public class PipeControlPoint extends G3DNode implements IP3DNode {
                        PipeControlPoint currentNext = next;
                        if (currentNext == null && currentPrev == null) {
                                removeComponent();
-                               pipeRun.remChild(this);
-                               checkRemove(pipeRun);
+                               if (pipeRun != null) {
+                                   pipeRun.remChild(this);
+                                   checkRemove(pipeRun);
+                               }
                                return;
                        }
                        if (currentNext != null && currentPrev != null) {
@@ -1109,9 +1252,7 @@ public class PipeControlPoint extends G3DNode implements IP3DNode {
                                if (link) {
                                    if (currentPrev.isDirected() && currentNext.isDirected())
                                        link = false;
-                                   else if (this.isDualInline()) {
-                                       link = false;
-                                   } else if (this.isDualSub()) {
+                                   else if (this.isDualSub()) {
                                        throw new RuntimeException("_remove() is called for parent point, somehow got to child point. " + this);
                                    }
                                }
@@ -1208,7 +1349,7 @@ public class PipeControlPoint extends G3DNode implements IP3DNode {
                        } else if (currentNext != null) {
                                if (currentNext.isDualInline()) {
                                        PipeControlPoint sccp = currentNext;
-                                       PipeControlPoint ocp = getDualSub();
+                                       PipeControlPoint ocp = currentNext.getDualSub();
                                        if (ocp == null) {
                                                throw new RuntimeException("Removing PipeControlPoint " + this+ " structure damaged, no offset control point");
                                        }
@@ -1255,12 +1396,15 @@ public class PipeControlPoint extends G3DNode implements IP3DNode {
                }
 
                removeComponent();
-               pipeRun.remChild(this);
-               checkRemove(pipeRun);
-               if (PipingRules.isEnabled() && pipeRun.getParent() != null && pipeRun.getControlPoints().size() > 0)
-                       PipingRules.validate(pipeRun);
+               if (pipeRun != null) {
+               pipeRun.remChild(this);
+               checkRemove(pipeRun);
+               if (PipingRules.isEnabled() && pipeRun.getParent() != null && pipeRun.getControlPoints().size() > 0)
+                       PipingRules.validate(pipeRun);
+               }
                if (additionalRemove != null)
                        additionalRemove.remove();
+               disposed = true;
        }
 
        /**
@@ -1301,6 +1445,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();
@@ -1353,6 +1498,8 @@ public class PipeControlPoint extends G3DNode implements IP3DNode {
     }
 
        private boolean checkRemove(PipeRun pipeRun) {
+           if (pipeRun == null)
+               return false;
                Collection<PipeControlPoint> points = pipeRun.getControlPoints();
                if (points.size() == 0) {
                        pipeRun.remove();
@@ -1445,6 +1592,8 @@ public class PipeControlPoint extends G3DNode implements IP3DNode {
        public void setOrientation(Quat4d orientation) {
                if (MathTools.equals(orientation, getOrientation()))
                        return;
+               if (getPipelineComponent() != null && (getPipelineComponent() instanceof Nozzle))
+                   System.out.println();
                super.setOrientation(orientation);
                if (getParentPoint() == null && component != null)
                        component._setWorldOrientation(getWorldOrientation());
@@ -1462,7 +1611,7 @@ public class PipeControlPoint extends G3DNode implements IP3DNode {
                        component._setWorldPosition(getWorldPosition());
                updateSubPoint();
        }
-
+       
        private void updateSubPoint() {
                if (isOffset()) {
                        if (next == null && previous == null) {