]> gerrit.simantics Code Review - simantics/3d.git/blobdiff - org.simantics.processeditor/src/org/simantics/processeditor/common/PipingRules.java
Removing ancient 3d framework
[simantics/3d.git] / org.simantics.processeditor / src / org / simantics / processeditor / common / PipingRules.java
diff --git a/org.simantics.processeditor/src/org/simantics/processeditor/common/PipingRules.java b/org.simantics.processeditor/src/org/simantics/processeditor/common/PipingRules.java
deleted file mode 100644 (file)
index a4a926a..0000000
+++ /dev/null
@@ -1,1134 +0,0 @@
-/*******************************************************************************\r
- * Copyright (c) 2007- VTT Technical Research Centre of Finland.\r
- * All rights reserved. This program and the accompanying materials\r
- * are made available under the terms of the Eclipse Public License v1.0\r
- * which accompanies this distribution, and is available at\r
- * http://www.eclipse.org/legal/epl-v10.html\r
- *\r
- * Contributors:\r
- *     VTT Technical Research Centre of Finland - initial API and implementation\r
- *******************************************************************************/\r
-package org.simantics.processeditor.common;\r
-\r
-import java.util.ArrayList;\r
-import java.util.Collection;\r
-\r
-import javax.vecmath.AxisAngle4d;\r
-import javax.vecmath.Point3d;\r
-import javax.vecmath.Vector3d;\r
-\r
-import org.simantics.db.Graph;\r
-import org.simantics.db.Resource;\r
-import org.simantics.processeditor.ProcessResource;\r
-import org.simantics.processeditor.stubs.PipeControlPoint;\r
-import org.simantics.processeditor.stubs.PipeRun;\r
-import org.simantics.processeditor.stubs.PipelineComponent;\r
-import org.simantics.proconf.g3d.base.G3DTools;\r
-import org.simantics.proconf.g3d.base.MathTools;\r
-import org.simantics.utils.ui.ErrorLogger;\r
-\r
-\r
-/**\r
- * Rules that update pipeline.\r
- * TODO : optimize, remove stubs\r
- * \r
- * FIXME : transformations\r
- * \r
- * TODO : FixedAngleTurnComponents are handled like VariableAngleTurnComponents\r
- * \r
- * \r
- * @author Marko Luukkainen <Marko.Luukkainen@vtt.fi>\r
- *\r
- */\r
-public class PipingRules {\r
-       \r
-       private static final boolean DEBUG = false;\r
-       private static final boolean DUMMY = false;\r
-       \r
-       private static final double MIN_TURN_ANGLE = 0.01;\r
-       \r
-       private static final int REMOVE_NONE = 0;\r
-       private static final int REMOVE_START = 1;\r
-       private static final int REMOVE_END = 2;\r
-       private static final int REMOVE_BOTH = 3;\r
-       \r
-       private enum PathLegUpdateType {NONE,PREV,NEXT,PREV_S,NEXT_S};\r
-       \r
-       /**\r
-     * Rule\r
-     * \r
-     * @param resources\r
-     * @param pp\r
-     * @throws TransactionException\r
-     */\r
-    public static void pipeControlPointPositionUpdate(Graph g, Resource pp) {\r
-       \r
-       PipeControlPoint pcp = new PipeControlPoint(g,pp);\r
-        if (DEBUG) System.out.println("PipeControlPoint changed " + pp);\r
-        \r
-        boolean changed = ControlPointTools.isControlPointChanged(pcp);\r
-\r
-        \r
-        if (changed) {\r
-               if (pcp.isInstanceOf(ProcessResource.plant3Dresource.PathLegEndControlPoint)) {\r
-                       updatePathLegEndControlPoint(pcp);\r
-               } else {\r
-                       updateInlineControlPoint(pcp);\r
-               }\r
-        } \r
-        \r
-    }\r
-    \r
-  \r
-    \r
-    public static class ExpandIterInfo {\r
-       // these two are turn control points\r
-       private PipeControlPoint start; \r
-       private PipeControlPoint end;\r
-       private int type;\r
-       \r
-       public ExpandIterInfo() {\r
-               \r
-       }\r
-       \r
-       public ExpandIterInfo(PipeControlPoint tcp, int type) {\r
-               if (type == REMOVE_START)\r
-                       start = tcp;\r
-               else \r
-                       end = tcp;\r
-               this.type = type;\r
-       }\r
-       \r
-       public ExpandIterInfo(PipeControlPoint start, PipeControlPoint end) {\r
-               this.start = start;\r
-               this.end = end;\r
-               this.type = REMOVE_BOTH;\r
-       }\r
-       \r
-               public PipeControlPoint getEnd() {\r
-                       return end;\r
-               }\r
-               public void setEnd(PipeControlPoint end) {\r
-                       this.end = end;\r
-               }\r
-               public PipeControlPoint getStart() {\r
-                       return start;\r
-               }\r
-               public void setStart(PipeControlPoint start) {\r
-                       this.start = start;\r
-               }\r
-               public int getType() {\r
-                       return type;\r
-               }\r
-               public void setType(int type) {\r
-                       this.type = type;\r
-               }\r
-       \r
-       \r
-    }\r
-    \r
-    private static void updatePathLegEndControlPoint(PipeControlPoint pcp) {\r
-       if (DEBUG) System.out.println("PipingTools.updateRunEndControlPoint() " + pcp.getResource());\r
-       if (pcp.getNext() != null) {\r
-               updatePathLegNext(pcp,pcp,PathLegUpdateType.NEXT_S);\r
-       }\r
-       if (pcp.getPrevious() != null) {\r
-               updatePathLegPrev(pcp,pcp,PathLegUpdateType.PREV_S);\r
-       }\r
-       \r
-    }\r
-    \r
-    private static void updateInlineControlPoint(PipeControlPoint pcp)  {\r
-       if (DEBUG) System.out.println("PipingTools.updateInlineControlPoint() " + pcp.getResource());\r
-       PipeControlPoint start = ControlPointTools.findPreviousEnd(pcp);\r
-        updatePathLegNext(start,pcp,PathLegUpdateType.NONE);\r
-    }\r
-    \r
-    private static PipeControlPoint insertElbow(PipeControlPoint pcp1 , PipeControlPoint pcp2, Point3d pos)  {\r
-       if (DEBUG) System.out.println("PipingRules.insertElbow() " + pcp1.getResource() + " " + pcp2.getResource()+ " " + pos);\r
-       PipelineComponent elbow = PipingTools2.instantiatePipelineComponent(pcp1.getGraph(), ControlPointTools.getPipeRun(pcp1).getResource(), ProcessResource.plant3Dresource.Elbow);\r
-       PipeControlPoint pcp = elbow.getControlPoint();\r
\r
-               ControlPointTools.insertControlPoint(pcp, pcp1,pcp2);\r
-               \r
-               ControlPointTools.setWorldPosition(pcp, pos);\r
-\r
-        return pcp;\r
-    }\r
-    \r
-    private static void updatePathLegNext(PipeControlPoint start, PipeControlPoint updated, PathLegUpdateType lengthChange){\r
-       ArrayList<PipeControlPoint> list = new ArrayList<PipeControlPoint>();\r
-       PipeControlPoint end = ControlPointTools.findNextEnd(start,list);\r
-       // this is for inline cp that is also path leg end\r
-       if (start.equals(updated))\r
-               lengthChange = PathLegUpdateType.NEXT;\r
-       else if (end.equals(updated))\r
-               lengthChange = PathLegUpdateType.PREV;                  \r
-       updatePathLegNext(start, list, end, updated, lengthChange);\r
-    }\r
-    \r
-    private static void updatePathLegNext(PipeControlPoint start, ArrayList<PipeControlPoint> list, PipeControlPoint end, PipeControlPoint updated, PathLegUpdateType lengthChange) {\r
-        updatePathLeg(start,list,end,false,0,new ArrayList<ExpandIterInfo>(),updated, lengthChange);\r
-    }\r
-    \r
-    private static class UpdateStruct2 {\r
-       public PipeControlPoint start;\r
-               public Point3d startPoint;\r
-               public ArrayList<PipeControlPoint> list;\r
-               public PipeControlPoint end;\r
-               public Point3d endPoint;\r
-               public Vector3d dir;\r
-               public Vector3d offset;\r
-               public boolean hasOffsets;\r
-               public int iter;\r
-               public boolean reversed;\r
-               public ArrayList<ExpandIterInfo> toRemove;\r
-               public PipeControlPoint updated;\r
-               public UpdateStruct2(PipeControlPoint start, Point3d startPoint, ArrayList<PipeControlPoint> list, PipeControlPoint end, Point3d endPoint, Vector3d dir, Vector3d offset, boolean hasOffsets, int iter, boolean reversed, ArrayList<ExpandIterInfo> toRemove, PipeControlPoint updated) {\r
-                       super();\r
-                       this.start = start;\r
-                       this.startPoint = startPoint;\r
-                       this.list = list;\r
-                       this.end = end;\r
-                       this.endPoint = endPoint;\r
-                       this.dir = dir;\r
-                       this.offset = offset;\r
-                       this.hasOffsets = hasOffsets;\r
-                       this.iter = iter;\r
-                       this.reversed = reversed;\r
-                       this.toRemove = toRemove;\r
-                       this.updated = updated;\r
-               }\r
-               \r
-               public String toString() {\r
-                       return start.getResource() + " " + end.getResource() + " " + dir + " " + hasOffsets + " " + offset + " " + iter + " " + toRemove.size();\r
-               }\r
-               \r
-    }\r
-    \r
-    private static boolean calculateOffset(Point3d startPoint, Point3d endPoint, ArrayList<PipeControlPoint> list, Vector3d dir, Vector3d offset) {\r
-       boolean hasOffsets = false;\r
-       dir.set(startPoint);\r
-       dir.sub(endPoint);\r
-       dir.normalize();\r
-       offset.set(0.0,0.0,0.0);\r
-        for (PipeControlPoint icp : list) {\r
-               if (icp.isInstanceOf(ProcessResource.plant3Dresource.OffsettingPoint)) {\r
-                       hasOffsets = true;\r
-                       offset.add(ControlPointTools.getSizeChangeOffsetVector(icp,dir));\r
-               }\r
-               else if (icp.isInstanceOf(ProcessResource.plant3Dresource.DualSubControlPoint)) \r
-                       ErrorLogger.defaultLogError("Updating pipe run, found offset controlpoint " + icp.getResource(), new Exception("ASSERT!"));\r
-        }\r
-        return hasOffsets;\r
-    }\r
-    \r
-    /**\r
-     * @param start starting point of the pipe run\r
-     * @param list list of inline control points in the pipe run\r
-     * @param end ending point of the pipe run\r
-     * @param reversed boolean flag indicating wether start or end control point was modified (if true then end point was modified)\r
-     * @throws TransactionException\r
-     */\r
-    private static void updatePathLeg(PipeControlPoint start, ArrayList<PipeControlPoint> list, PipeControlPoint end, boolean reversed, int iter, ArrayList<ExpandIterInfo> toRemove, PipeControlPoint updated, PathLegUpdateType lengthChange) {\r
-        // FIXME: direction is calculated wrong way!\r
-       boolean hasOffsets = false;\r
-        Vector3d offset = new Vector3d();\r
-        Point3d startPoint = G3DTools.getPoint(start.getWorldPosition());\r
-       Point3d endPoint = G3DTools.getPoint(end.getWorldPosition());\r
-       Vector3d dir = new Vector3d ();\r
-       hasOffsets = calculateOffset(startPoint, endPoint, list, dir, offset);\r
-        updatePathLeg(new UpdateStruct2(start, startPoint, list, end, endPoint, dir, offset, hasOffsets, iter, reversed, toRemove, updated), lengthChange);\r
-        \r
-    }\r
-    \r
-    private static void updatePathLeg(UpdateStruct2 u, PathLegUpdateType lengthChange){\r
-       int directed = 0;\r
-        if (u.start.isInstanceOf(ProcessResource.plant3Dresource.DirectedControlPoint))\r
-               directed ++;\r
-        if (u.end.isInstanceOf(ProcessResource.plant3Dresource.DirectedControlPoint))\r
-               directed++;\r
-        switch (directed) {\r
-        case 0:\r
-               updateFreePathLeg(u,lengthChange);\r
-               break;\r
-        case 1:\r
-               updateDirectedPathLeg(u,lengthChange);\r
-               break;\r
-        case 2:\r
-               updateDualDirectedPathLeg(u,lengthChange);\r
-               break;\r
-        }\r
-       \r
-       }\r
-    \r
-    private static void updateFreePathLeg(UpdateStruct2 u, PathLegUpdateType lengthChange) {\r
-       if (DEBUG) System.out.println("PipingRules.updateFreePipeRun " + u + " " + lengthChange);\r
-       checkExpandPathLeg(u, lengthChange);\r
-       }\r
-    \r
-    private static void updateInlineControlPoints(UpdateStruct2 u, boolean checkSizes) {\r
-       if (DEBUG) System.out.println("PipingTools.updateInlineControlPoints() " + u);\r
-       \r
-       if (!u.hasOffsets) {\r
-               // FIXME : cache positions\r
-               if (!checkSizes) {\r
-                       for (PipeControlPoint icp : u.list) {\r
-                               updateInlineControlPoint(icp, u.startPoint, u.endPoint,u.dir);\r
-                       }\r
-                       return;\r
-               }\r
-               \r
-               ArrayList<PipeControlPoint> pathLegPoints = new ArrayList<PipeControlPoint>();\r
-               pathLegPoints.add(u.start);\r
-                       for (PipeControlPoint icp : u.list) {\r
-                               //updateInlineControlPoint(icp, u.startPoint, u.endPoint,u.dir);\r
-                               updateBranchControlPointBranches(icp);\r
-                               pathLegPoints.add(icp);\r
-                       }\r
-                       pathLegPoints.add(u.end);\r
-                       \r
-                       // TODO : values can be cached in the loop\r
-                       for (int i = 1; i < pathLegPoints.size(); i++) {\r
-                               PipeControlPoint icp = pathLegPoints.get(i);\r
-\r
-                               PipeControlPoint prev;\r
-                               Point3d prevPos;\r
-                               prev = pathLegPoints.get(i-1);\r
-                               prevPos = G3DTools.getPoint(prev.getWorldPosition());\r
-                               Point3d currentPos = G3DTools.getPoint(icp.getWorldPosition());\r
-                               \r
-                               if (icp.isInstanceOf(ProcessResource.plant3Dresource.VariableLengthControlPoint)) {     \r
-                                       if (i != pathLegPoints.size() - 1) {\r
-                                               PipeControlPoint next;\r
-                                               Point3d nextPos;\r
-                                               next = pathLegPoints.get(i + 1);\r
-                                               nextPos = G3DTools.getPoint(next.getWorldPosition());\r
-                                               Vector3d dir = new Vector3d(nextPos);\r
-                                               dir.sub(prevPos);\r
-                                               double l = dir.lengthSquared();          // distance between control points (square)\r
-                                               double l2prev = ControlPointTools.getInlineLength(prev);          // distance taken by components\r
-                                               double l2next = ControlPointTools.getInlineLength(next); \r
-                                               double l2 = l2prev + l2next;\r
-                                               double l2s = MathTools.square(l2);\r
-                                               if (l2s < l) {                         // check if there is enough space for variable length component.\r
-                                                       // components fit\r
-                                                       dir.normalize();\r
-                                                       double length = Math.sqrt(l) - l2; // true length of the variable length component \r
-                                                       dir.scale(length*0.5 + l2prev);      // calculate center position of the component\r
-                                                       dir.add(prevPos);\r
-                                                       ControlPointTools.setWorldPosition(icp,dir);\r
-                                                       icp.setRelatedScalarDouble(ProcessResource.plant3Dresource.HasLength, length);\r
-                                               } else {\r
-                                                       //components leave no space to the component and it must be removed\r
-                                                       ControlPointTools.removeControlPoint(icp);\r
-                                               }\r
-\r
-                                       } else {\r
-                                               // this is variable length component at the end of the piperun.\r
-                                               // the problem is that we want to keep unconnected end of the component in the same\r
-                                               // place, but center of the component must be moved.\r
-                                               double currentLength = icp.getSingleRelatedScalarDouble(ProcessResource.plant3Dresource.HasLength);\r
-                                               Vector3d dir = new Vector3d();\r
-                                               dir.sub(currentPos,prevPos);\r
-                                               dir.normalize();\r
-                                               Point3d endPos = new Point3d(dir);\r
-                                               endPos.scale(currentLength * 0.5);\r
-                                               endPos.add(currentPos);             //this is the free end of the component\r
-                                               \r
-                                               double offset = ControlPointTools.getInlineLength(prev);\r
-                                               Point3d beginPos = new Point3d(dir);\r
-                                               beginPos.scale(offset);\r
-                                               beginPos.add(prevPos);              //this is the connected end of the component\r
-                                               \r
-                                               double l = beginPos.distance(endPos);\r
-                                               \r
-                                               dir.scale(l*0.5);\r
-                                               beginPos.add(dir);                  //center position\r
-                                               \r
-                                               if (DEBUG) System.out.println("PipingRules.updateInlineControlPoints() setting variable length to " + l);\r
-                                               icp.setRelatedScalarDouble(ProcessResource.plant3Dresource.HasLength, l);\r
-                                               \r
-                                               ControlPointTools.setWorldPosition(icp, beginPos);\r
-                                       }\r
-                                       i++;\r
-                                       \r
-                               } else if (!prev.isInstanceOf(ProcessResource.plant3Dresource.VariableLengthControlPoint)){\r
-                                       // If this and previous control point are not variable length pcps, we'll have to check if there is no empty space between them.\r
-                                       // I there is, we'll have to create new variable length component between them.\r
-                                       Vector3d dir = new Vector3d(currentPos);\r
-                                       dir.sub(prevPos);\r
-                                       double l = dir.lengthSquared();\r
-                                       double l2prev = ControlPointTools.getInlineLength(prev);\r
-                                       double l2next = ControlPointTools.getInlineLength(icp);\r
-                                       double l2 = l2prev + l2next;\r
-                                       double l2s = l2 * l2;\r
-                                       if (l > l2s) {\r
-                                               PipelineComponent component = PipingTools2.instantiatePipelineComponent(prev.getGraph(), ControlPointTools.getPipeRun(prev).getResource(), ProcessResource.plant3Dresource.Straight);\r
-                                               PipeControlPoint scp = component.getControlPoint();\r
-                                               ControlPointTools.insertControlPoint(scp, prev, icp);\r
-                                               \r
-                                               dir.normalize();\r
-                                               double length = Math.sqrt(l) - l2; // true length of the variable length component \r
-                                               dir.scale(length*0.5 + l2prev);      // calculate center position of the component\r
-                                               dir.add(prevPos);\r
-                                               ControlPointTools.setWorldPosition(scp, dir);\r
-                                               scp.setRelatedScalarDouble(ProcessResource.plant3Dresource.HasLength, length);\r
-                                       }\r
-                               }\r
-                       }\r
-               } else {\r
-                       u.endPoint.sub(u.offset);\r
-                       // FIXME : straights\r
-                       for (PipeControlPoint icp : u.list) {\r
-                               updateInlineControlPoint(icp, u.startPoint, u.endPoint,u.dir);\r
-                               updateBranchControlPointBranches(icp);\r
-                               if (icp.isInstanceOf(ProcessResource.plant3Dresource.OffsettingPoint)) {\r
-                                       // TODO : offset vector is already calculated and should be\r
-                                       // cached\r
-                                       u.offset = ControlPointTools.getSizeChangeOffsetVector(icp, u.dir);\r
-                                       updateOffsetPoint( icp, u.offset);\r
-                                       u.startPoint.add(u.offset);\r
-                                       u.endPoint.add(u.offset);\r
-                               }\r
-                       }\r
-               }\r
-    }\r
-    \r
-    \r
-    \r
-    private static void ppNoOffset(UpdateStruct2 u) {\r
-       if (DEBUG)System.out.println("PipingRules.ppNoOffset() " + u);\r
-       Vector3d offset = new Vector3d();\r
-               if (u.hasOffsets) {\r
-               u.dir.normalize();\r
-               for (PipeControlPoint icp : u.list) {\r
-                       if (icp.isInstanceOf(ProcessResource.plant3Dresource.OffsettingPoint)) {\r
-                               offset.add(ControlPointTools.getSizeChangeOffsetVector(icp,u.dir));\r
-                       }\r
-                       else if (icp.isInstanceOf(ProcessResource.plant3Dresource.DualSubControlPoint)) \r
-                               ErrorLogger.defaultLogError("Updating pipe run, found offset controlpoint " + icp.getResource(), new Exception("ASSERT!"));\r
-               }\r
-               }\r
-               u.offset = offset;\r
-               checkExpandPathLeg(u,PathLegUpdateType.NONE);\r
-    }\r
-    \r
-    private static void ppNoDir(PipeControlPoint start, Point3d startPoint,ArrayList<PipeControlPoint> list, PipeControlPoint end,Point3d endPoint, boolean hasOffsets,int iter,boolean reversed, ArrayList<ExpandIterInfo> toRemove, PipeControlPoint updated)  {\r
-       if (DEBUG)System.out.println("PipingRules.ppNoDir() " + start.getResource() + " " + end.getResource() + " " + iter + " " + toRemove.size());\r
-       // FIXME : extra loop (dir should be calculated here)\r
-       Vector3d dir = new Vector3d();\r
-       Vector3d offset = new Vector3d();\r
-       hasOffsets = calculateOffset(startPoint, endPoint, list, dir, offset);\r
-       ppNoOffset(new UpdateStruct2(start, startPoint, list, end, endPoint, dir, null, hasOffsets, iter, reversed, toRemove,updated));\r
-    }\r
-    \r
-    private static void checkExpandPathLeg(UpdateStruct2 u, PathLegUpdateType lengthChange)  {\r
-       if (DEBUG)System.out.println("PipingRules.checkExpandPathLeg() " + u + " " + lengthChange);\r
-       if (lengthChange != PathLegUpdateType.NONE) {\r
-               // FIXME : turns cannot be checked before inline cps are updated, since their position affects calculation of turns \r
-               processPathLeg(u,false,false);\r
-               int type = checkTurns(u,lengthChange);\r
-               if (type == REMOVE_NONE) {\r
-                               processPathLeg(u,false,true);\r
-                       } else {\r
-                               expandPathLeg(u, type);\r
-                       }\r
-       } else {\r
-               processPathLeg(u,false,true);\r
-       }\r
-    }\r
-    \r
-    private static void updateDirectedPathLeg(UpdateStruct2 u, PathLegUpdateType lengthChange) {\r
-               if (DEBUG)System.out.println("PipingRules.updateDirectedPipeRun() " + u + " " + lengthChange);\r
-               PipeControlPoint dcp;\r
-               PipeControlPoint other;\r
-               boolean canMoveOther = false;\r
-               boolean dcpStart = false;\r
-               Point3d position;\r
-               if (u.start.isInstanceOf(ProcessResource.plant3Dresource.DirectedControlPoint)) {\r
-                       dcp = u.start;\r
-                       other = u.end;\r
-                       position = u.startPoint;\r
-                       dcpStart = true;\r
-                       if (!u.reversed)\r
-                               canMoveOther = true;\r
-               } else {\r
-                       dcp = u.end;\r
-                       other = u.start;\r
-                       position = u.endPoint;\r
-                       if (u.reversed)\r
-                               canMoveOther = true;\r
-               }\r
-\r
-               Vector3d directedDirection = ControlPointTools.getDirectedControlPointDirection(dcp);\r
-               Point3d directedEndPoint = new Point3d(u.endPoint);\r
-               if (u.hasOffsets)\r
-                       directedEndPoint.add(u.offset);\r
-\r
-               double mu[] = new double[2];\r
-\r
-               Vector3d closest;\r
-               Vector3d t = new Vector3d();\r
-      \r
-               if (dcpStart) {\r
-                       closest = MathTools.closestPointOnStraight(directedEndPoint, u.startPoint, directedDirection, mu);\r
-                       t.sub(closest, directedEndPoint);\r
-               } else {\r
-                       closest = MathTools.closestPointOnStraight(u.startPoint, directedEndPoint, directedDirection, mu);\r
-                       t.sub(closest, u.startPoint);\r
-               }\r
-\r
-      \r
-      double distance = t.lengthSquared();\r
-      boolean aligned = (distance < 0.001);\r
-      if (aligned) {\r
-         checkExpandPathLeg(u,lengthChange);\r
-      } else {\r
-         if (u.iter > 0) {\r
-                  backIter(u);\r
-         } else {\r
-                       PipeControlPoint nextToMoved;\r
-                       \r
-                               if (u.list.size() > 0)\r
-                                       if (dcpStart)\r
-                                               nextToMoved = u.list.get(0);\r
-                                       else\r
-                                               nextToMoved = u.list.get(u.list.size() - 1);\r
-                               else if (dcpStart)\r
-                                       nextToMoved = u.end;\r
-                               else\r
-                                       nextToMoved = u.start;\r
-                               if (other.isInstanceOf(ProcessResource.plant3Dresource.VariableAngleTurnControlPoint)) {\r
-                                       \r
-                                       // TODO calculate needed space from next run end.\r
-                                       if (mu[0] < 1.0) {\r
-                                               if (dcpStart) {\r
-                                                       closest.set(u.startPoint);      \r
-                                               } else {\r
-                                                       closest.set(u.endPoint);\r
-                                               }\r
-                                               closest.add(directedDirection);\r
-                                       }\r
-\r
-                                       if (canMoveOther) {\r
-                                               if (DEBUG)System.out.println("PipingRules.updateDirectedPipeRun() moved end " + other.getResource() + " to " + closest);\r
-                                               ControlPointTools.setWorldPosition(other, closest);\r
-                                               if (dcpStart) {\r
-                                                       ppNoOffset(new UpdateStruct2(u.start, u.startPoint, u.list, u.end, new Point3d(closest), directedDirection,null, u.hasOffsets, u.iter, u.reversed, u.toRemove,u.updated));\r
-                                                       if (u.end.getNext() != null)\r
-                                                               updatePathLegNext(u.end,u.updated,PathLegUpdateType.NEXT);\r
-                                               } else {\r
-                                                       ppNoOffset(new UpdateStruct2(u.start, new Point3d(closest), u.list, u.end, u.endPoint, directedDirection,null, u.hasOffsets, u.iter, u.reversed, u.toRemove,u.updated));        \r
-                                                       if (u.start.getPrevious() != null)\r
-                                                               updatePathLegPrev(u.start,u.updated,PathLegUpdateType.PREV);\r
-                                               }\r
-                                       } else {\r
-                                               // TODO : calculate needed space from next run end.\r
-                                               insertElbowUpdate(u, dcp, nextToMoved, dcpStart, position, directedDirection);\r
-                                       }\r
-                               } else if (other.isInstanceOf(ProcessResource.plant3Dresource.UndirectedControlPoint) &&\r
-                                                  other.getSubPointOf() != null) {\r
-                                       // FIXME : this code was for updating branches\r
-                                       Vector3d bintersect = new Vector3d();\r
-                                       PipeControlPoint bcp = other.getSubPointOf();\r
-                                       if (bcp != null && canMoveOther) {\r
-                                               Point3d bstart = new Point3d();\r
-                                               Point3d bend = new Point3d();\r
-                                               Vector3d bdir = new Vector3d();\r
-                                               ControlPointTools.getInlineControlPointEnds(bcp, bstart, bend, bdir);\r
-                                               Vector3d nintersect = new Vector3d();\r
-                                               \r
-                                               MathTools.intersectStraightStraight(position, directedDirection, bstart,\r
-                                                       bdir, nintersect, bintersect, mu);\r
-                                               Vector3d dist = new Vector3d(nintersect);\r
-                                               dist.sub(bintersect);\r
-                                               canMoveOther = mu[1] > 0.0 && mu[1] < 1.0 && dist.lengthSquared() < 0.01;\r
-                                       } else {\r
-                                               // TODO : endControlPoints are undirected: calculcate correct position for it\r
-                                               throw new UnsupportedOperationException("not implemented");\r
-                                       }\r
-                                       if (canMoveOther) { \r
-                                               if (DEBUG) System.out.println("PipingRules.updateDirectedPipeRun() moved end " + other.getResource() + " to " + bintersect);\r
-                                               // is required branch position is in possible range\r
-                                               ControlPointTools.setWorldPosition(bcp, bintersect);\r
-                                               if (dcpStart) {\r
-                                                       checkExpandPathLeg(new UpdateStruct2(u.start, u.startPoint, u.list, u.end, new Point3d(bintersect),directedDirection, u.offset, u.hasOffsets, u.iter, u.reversed, u.toRemove,u.updated),lengthChange);\r
-                                               } else {\r
-                                                       checkExpandPathLeg(new UpdateStruct2(u.start, new Point3d(bintersect), u.list, u.end, u.endPoint,directedDirection, u.offset, u.hasOffsets, u.iter, u.reversed, u.toRemove,u.updated),lengthChange);    \r
-                                               }\r
-                                       } else {\r
-                                               // branch cannot be moved into right position, new turn\r
-                                               // / elbow must be inserted\r
-                                               insertElbowUpdate(u , dcp, nextToMoved, dcpStart, position, directedDirection);\r
-                                       }\r
-\r
-                               } else { // assume that control point cannot be moved, but can be rotated\r
-                                       insertElbowUpdate(u, dcp, nextToMoved, dcpStart, position, directedDirection);\r
-                               }\r
-         }\r
-      }\r
-       }\r
-    \r
-    \r
-    \r
-    private static void updateDualDirectedPathLeg(UpdateStruct2 u, PathLegUpdateType lengthChange) {\r
-               if (DEBUG) System.out.println("PipingRules.updateDualDirectedPipeRun() " + u + " " + lengthChange);\r
-\r
-               PipeControlPoint dcp1 = u.start;\r
-               PipeControlPoint dcp2 = u.end;\r
-               Point3d position1 = u.startPoint;\r
-               Point3d position2 = u.endPoint;\r
-               Point3d position1offset = new Point3d(position1);\r
-               position1offset.sub(u.offset);\r
-               Point3d position2offset = new Point3d(position2);\r
-               position2offset.add(u.offset);\r
-               Vector3d dir1 = ControlPointTools.getDirectedControlPointDirection(dcp1);\r
-               Vector3d dir2 = ControlPointTools.getDirectedControlPointDirection(dcp2);\r
-               Vector3d p1 = MathTools.closestPointOnStraight(position1offset, position2, dir2);\r
-               Vector3d p2 = MathTools.closestPointOnStraight(position2offset, position1, dir1);\r
-               double d1 = position1.distance(new Point3d(p1));\r
-               double d2 = position2.distance(new Point3d(p2));\r
-\r
-               boolean aligned = (d1 < 0.01 && d2 < 0.01);\r
-               if (aligned) {\r
-                       processPathLeg(u);\r
-               } else {\r
-                       if (u.iter > 0) {\r
-                               backIter(u);\r
-                       } else {\r
-                               PipeControlPoint dcp;\r
-                               PipeControlPoint next;\r
-                               if (!u.reversed) {\r
-                                       dcp = dcp1;\r
-                                       if (u.list.size() > 0)\r
-                                               next = u.list.get(0);\r
-                                       else\r
-                                               next = dcp2;\r
-                               } else {\r
-                                       dcp = dcp2;\r
-                                       if (u.list.size() > 0)\r
-                                               next = u.list.get(u.list.size() - 1);\r
-                                       else\r
-                                               next = dcp1;\r
-                               }\r
-\r
-                               PipeRun pipeline = ControlPointTools.getPipeRun(dcp1);\r
-                               PipelineComponent elbow1 = PipingTools2.instantiatePipelineComponent(u.start.getGraph(), pipeline.getResource(), ProcessResource.plant3Dresource.Elbow);\r
-                               PipelineComponent elbow2 = PipingTools2.instantiatePipelineComponent(u.start.getGraph(), pipeline.getResource(), ProcessResource.plant3Dresource.Elbow);\r
-                               \r
-                               PipeControlPoint tcp1 = elbow1.getControlPoint();\r
-                               PipeControlPoint tcp2 = elbow2.getControlPoint();\r
-                               \r
-                               // Straight s1 = getStraight(dcp, next);\r
-                               ControlPointTools.insertControlPoint(tcp1, dcp, next);\r
-                               // s1 = getStraight(tcp1, next);\r
-                               ControlPointTools.insertControlPoint(tcp2, tcp1, next);\r
-                               p1 = G3DTools.getVector(dcp.getLocalPosition());\r
-                               if (!u.reversed)\r
-                                       p1.add(dir1);\r
-                               else\r
-                                       p1.add(dir2);\r
-                               \r
-                               if (!u.reversed)\r
-                                       p2 = MathTools.closestPointOnStraight(new Point3d(p1), position2, dir2);\r
-                               else\r
-                                       p2 = MathTools.closestPointOnStraight(new Point3d(p1), position1, dir1);\r
-                               \r
-                               ControlPointTools.setWorldPosition(tcp1, p1);\r
-                               ControlPointTools.setWorldPosition(tcp2, p2);\r
-                               \r
-                               if (DEBUG) System.out.println("PipingRules.updateDualDirectedPipeRun() created two turns " + tcp1.getResource() + " " + tcp2.getResource());\r
-\r
-                               if (!u.reversed) {\r
-                                       Vector3d dd = new Vector3d(p2);\r
-                                       dd.sub(p1);\r
-                                       dir2.negate();\r
-                                       processPathLeg(new UpdateStruct2(u.start, u.startPoint,new ArrayList<PipeControlPoint>(), tcp1, new Point3d(p1),dir1, new Vector3d(), false, 0, false,new ArrayList<ExpandIterInfo>(), u.updated));\r
-                                       processPathLeg(new UpdateStruct2(tcp1,new Point3d(p1), new ArrayList<PipeControlPoint>(),tcp2, new Point3d(p2), dd,new Vector3d(), false, 0, false,new ArrayList<ExpandIterInfo>(), u.updated));\r
-                                       // offset is recalculated\r
-                                       processPathLegNoOffset(new UpdateStruct2(tcp2, new Point3d(p2), u.list,u.end, u.endPoint, dir2, null, u.hasOffsets,u.iter, u.reversed, u.toRemove, u.updated));\r
-                               } else {\r
-                                       Vector3d dd = new Vector3d(p1);\r
-                                       dd.sub(p2);\r
-                                       dir2.negate();\r
-                                       processPathLeg(new UpdateStruct2(tcp1,new Point3d(p1), new ArrayList<PipeControlPoint>(),u.end, u.endPoint, dir2, new Vector3d(), false, 0,false, new ArrayList<ExpandIterInfo>(), u.updated));\r
-                                       processPathLeg(new UpdateStruct2(tcp2,new Point3d(p2), new ArrayList<PipeControlPoint>(),tcp1, new Point3d(p1), dd,new Vector3d(), false, 0, false,new ArrayList<ExpandIterInfo>(), u.updated));\r
-                                       // offset is recalculated\r
-                                       processPathLegNoOffset(new UpdateStruct2(u.start, u.startPoint,u.list, tcp2, new Point3d(p2),dir1, null, u.hasOffsets, u.iter, u.reversed,u.toRemove, u.updated));\r
-                               }\r
-                       }\r
-               }\r
-       }\r
-    \r
-    private static void insertElbowUpdate(UpdateStruct2 u, PipeControlPoint dcp, PipeControlPoint next, boolean dcpStart, Point3d position, Vector3d directedDirection) {\r
-        \r
-       Vector3d closest = new Vector3d(position);\r
-               closest.add(directedDirection);\r
-               PipeControlPoint tcp = insertElbow(dcp, next, new Point3d(closest));\r
-\r
-               if (DEBUG) System.out.println("PipingRules.updateDirectedPipeRun() inserted " + tcp.getResource());\r
-               \r
-               if (dcpStart) {\r
-                       // update pipe run from new turn to other end\r
-                       ppNoDir(tcp, new Point3d(closest), u.list, u.end, u.endPoint, u.hasOffsets, u.iter, u.reversed, u.toRemove, u.updated);\r
-                       // update pipe run from directed to new turn\r
-                       processPathLeg(new UpdateStruct2(u.start, u.startPoint, new ArrayList<PipeControlPoint>(), tcp, new Point3d(closest), directedDirection, new Vector3d(), false, 0, false, new ArrayList<ExpandIterInfo>(),u.updated));                  \r
-               } else {\r
-                       // update pipe run from other end to new turn\r
-                       ppNoDir(u.start, u.startPoint, u.list, tcp, new Point3d(closest),  u.hasOffsets, u.iter, u.reversed, u.toRemove,u.updated);\r
-                       // update pipe run from new turn to directed\r
-                       processPathLeg(new UpdateStruct2(tcp, new Point3d(closest), new ArrayList<PipeControlPoint>(), u.end, u.endPoint, directedDirection, new Vector3d(), false, 0, false, new ArrayList<ExpandIterInfo>(),u.updated));\r
-               }\r
-    }\r
-    \r
-    /**\r
-     * Checks if turns can be removed (turn angle near zero)\r
-     */\r
-    private static int checkTurns(UpdateStruct2 u, PathLegUpdateType lengthChange) {\r
-               if (DEBUG)\r
-                       System.out.println("PipingRules.checkTurns() " + u.start.getResource()\r
-                                       + " " + u.end.getResource());\r
-               boolean startRemoved = false;\r
-               boolean endRemoved = false;\r
-               if (u.start.isInstanceOf(ProcessResource.plant3Dresource.VariableAngleTurnControlPoint)) {\r
-                       // this won't work properly if inline control points are not updated\r
-                       PipeControlPoint startPrev = u.start.getPrevious();\r
-                       if (startPrev != null) {\r
-                               double a;\r
-                               if (!u.hasOffsets) {\r
-                                       a = updateTurnControlPointTurn( u.start, startPrev, u.end);\r
-                               } else {\r
-                                       Point3d ep = new Point3d(u.endPoint);\r
-                                       ep.add(u.offset);\r
-                                       a = updateTurnControlPointTurn( u.start,u.startPoint, G3DTools.getPoint(startPrev.getLocalPosition()), ep);\r
-\r
-                               }\r
-                               if (a < MIN_TURN_ANGLE)\r
-                                       startRemoved = true;\r
-                               else if (lengthChange == PathLegUpdateType.PREV || lengthChange == PathLegUpdateType.PREV_S){\r
-                                       PathLegUpdateType type;\r
-                                       if (lengthChange == PathLegUpdateType.PREV_S)\r
-                                               type = PathLegUpdateType.PREV;\r
-                                       else\r
-                                               type = PathLegUpdateType.NONE;\r
-                                       updatePathLegPrev(u.start, u.start, type);\r
-                               }\r
-                       }\r
-               }\r
-               if (u.end.isInstanceOf(ProcessResource.plant3Dresource.VariableAngleTurnControlPoint)) {\r
-\r
-                       PipeControlPoint endNext = u.end.getNext();\r
-                       if (endNext != null) {\r
-                               double a;\r
-                               if (!u.hasOffsets) {\r
-                                       a = updateTurnControlPointTurn(u.end,u.start, endNext);\r
-                               } else {\r
-                                       Point3d sp = new Point3d(u.startPoint);\r
-                                       sp.sub(u.offset);\r
-                                       a = updateTurnControlPointTurn(u.end, u.endPoint, sp, G3DTools.getPoint(endNext.getLocalPosition()));\r
-                               }\r
-                               if (a < MIN_TURN_ANGLE)\r
-                                       endRemoved = true;\r
-                               else if (lengthChange == PathLegUpdateType.NEXT || lengthChange == PathLegUpdateType.NEXT_S){\r
-                                       PathLegUpdateType type;\r
-                                       if (lengthChange == PathLegUpdateType.NEXT_S)\r
-                                               type = PathLegUpdateType.NEXT;\r
-                                       else\r
-                                               type = PathLegUpdateType.NONE;\r
-                                       updatePathLegNext(u.end, u.end,type);\r
-                               }\r
-                       }\r
-               }\r
-               if (DEBUG)\r
-                       System.out.println("PipingRules.checkTurns() res " + startRemoved + " " + endRemoved);\r
-               if (!startRemoved && !endRemoved)\r
-                       return REMOVE_NONE;\r
-               if (startRemoved && endRemoved)\r
-                       return REMOVE_BOTH;\r
-               if (startRemoved)\r
-                       return REMOVE_START;\r
-               return REMOVE_END;\r
-       }\r
-    \r
-    /**\r
-        * Expands piperun search over turns that are going to be removed\r
-        * \r
-        */\r
-    private static void expandPathLeg(UpdateStruct2 u, int type) {\r
-       if (DEBUG) System.out.println("PipingRules.expandPipeline " + u.start.getResource() + " " + u.end.getResource());\r
-       ArrayList<PipeControlPoint> newList = new ArrayList<PipeControlPoint> ();\r
-       switch (type) {\r
-       case REMOVE_NONE :\r
-               throw new RuntimeException("Error in piping rules");\r
-       case REMOVE_START :\r
-               u.toRemove.add(new ExpandIterInfo(u.start,REMOVE_START));\r
-               u.start = ControlPointTools.findPreviousEnd(u.start);\r
-               u.startPoint = G3DTools.getPoint(u.start.getLocalPosition());\r
-               ControlPointTools.findNextEnd(u.start,newList);\r
-               newList.addAll(u.list);\r
-               u.list = newList;\r
-               break;\r
-       case REMOVE_END :\r
-               u.toRemove.add(new ExpandIterInfo(u.end,REMOVE_END));\r
-               u.end = ControlPointTools.findNextEnd(u.end,newList);\r
-               u.endPoint = G3DTools.getPoint(u.end.getLocalPosition());\r
-               u.list.addAll(newList);\r
-               break;\r
-       case REMOVE_BOTH :\r
-               u.toRemove.add(new ExpandIterInfo(u.start,u.end));\r
-               u.start = ControlPointTools.findPreviousEnd(u.start);\r
-               u.startPoint = G3DTools.getPoint(u.start.getLocalPosition());\r
-               ControlPointTools.findNextEnd(u.start,newList);\r
-               newList.addAll(u.list);\r
-               u.list = newList;\r
-               newList = new ArrayList<PipeControlPoint> ();\r
-               u.end = ControlPointTools.findNextEnd(u.end,newList);\r
-               u.endPoint = G3DTools.getPoint(u.end.getLocalPosition());\r
-               u.list.addAll(newList);\r
-               break;\r
-       default:\r
-               throw new RuntimeException("Error in piping rules");\r
-                       \r
-       }\r
-       u.offset = new Vector3d();\r
-       if (u.hasOffsets) {\r
-               u.dir.normalize();\r
-               for (PipeControlPoint icp : u.list) {\r
-                       if (icp.isInstanceOf(ProcessResource.plant3Dresource.OffsettingPoint)) {\r
-                               u.offset.add(ControlPointTools.getSizeChangeOffsetVector(icp,u.dir));\r
-                       }\r
-                       else if (icp.isInstanceOf(ProcessResource.plant3Dresource.DualSubControlPoint)) \r
-                               ErrorLogger.defaultLogError("Updating pipe run, found offset controlpoint " + icp.getResource(), new Exception("ASSERT!"));\r
-               }\r
-               }\r
-       if (DEBUG) System.out.println("PipingRules.expandPipeline expanded " + u.start.getResource() + " " + u.end.getResource());\r
-       u.iter++;\r
-       updatePathLeg(u,PathLegUpdateType.NONE);\r
-    }\r
-    \r
-    /**\r
-        * reverts one iteration of turn removing back)\r
-     */\r
-    private static void backIter(UpdateStruct2 u) {\r
-               \r
-               if (DEBUG) System.out.println("PipingRules.backIter" + u.start.getResource() + " " + u.end.getResource());      \r
-               if (u.iter == 0)\r
-                       throw new RuntimeException("Error in piping rules");\r
-               ExpandIterInfo info = u.toRemove.get(u.toRemove.size()-1);\r
-               u.toRemove.remove(u.toRemove.size()-1);\r
-               if (info.getType() == REMOVE_START || info.getType() == REMOVE_BOTH) {\r
-                       while (u.list.size() > 0) {\r
-                               PipeControlPoint icp = u.list.get(0);\r
-                               if (icp.getPrevious().getResource().equals(info.getStart().getResource()))  \r
-                                       break;\r
-                               u.list.remove(icp);\r
-                       }\r
-                       u.start = info.getStart();      \r
-               } \r
-               if (info.getType() == REMOVE_END || info.getType() == REMOVE_BOTH) {\r
-                       while (u.list.size() > 0) {\r
-                               PipeControlPoint icp = u.list.get(u.list.size() - 1);\r
-                               if (icp.getNext().getResource().equals(info.getEnd().getResource())) \r
-                                       break;\r
-                               u.list.remove(icp);\r
-                       }\r
-                       u.end = info.getEnd();\r
-               }\r
-               u.offset = new Vector3d();\r
-               if (u.hasOffsets) {\r
-               u.dir.normalize();\r
-               for (PipeControlPoint icp : u.list) {\r
-                       if (icp.isInstanceOf(ProcessResource.plant3Dresource.OffsettingPoint)) {\r
-                               u.offset.add(ControlPointTools.getSizeChangeOffsetVector(icp,u.dir));\r
-                       }\r
-                       else if (icp.isInstanceOf(ProcessResource.plant3Dresource.DualSubControlPoint)) \r
-                               ErrorLogger.defaultLogError("Updating pipe run, found offset controlpoint " + icp.getResource(), new Exception("ASSERT!"));\r
-               }\r
-               }\r
-               processPathLeg(u);\r
-       \r
-    }\r
-    \r
-    /**\r
-     * Processes pipe run (removes necessary turns and updates run ends)\r
-     */\r
-   // private static void processPathLeg(PipeControlPoint start, Point3d startPoint,ArrayList<InlineControlPoint> list, PipeControlPoint end,Point3d endPoint, Vector3d dir,Vector3d offset, boolean hasOffsets,int iter, boolean reversed, ArrayList<ExpandIterInfo> toRemove) throws TransactionException {\r
-         \r
-    private static void processPathLeg(UpdateStruct2 u) {\r
-       if (DEBUG) System.out.println("PipingRules.processPathLeg " + u.start.getResource() + " " + u.end.getResource());\r
-       processPathLeg(u, true, true);\r
-    }\r
-    \r
-    \r
-    private static void processPathLeg(UpdateStruct2 u, boolean updateEnds, boolean updateInline) {\r
-       if (DEBUG) System.out.println("PipingRules.processPathLeg " + u.start.getResource() + " " + u.end.getResource());\r
-       if (u.toRemove.size() > 0) {\r
-               for (ExpandIterInfo info : u.toRemove) {\r
-                       if (info.getStart() != null) {\r
-                               ControlPointTools.removeControlPoint(info.getStart());\r
-                       }\r
-                       if (info.getEnd() != null) {\r
-                               ControlPointTools.removeControlPoint(info.getEnd());\r
-                       }\r
-               }\r
-               // ControlPointTools.removeControlPoint may remove mo0re than one CP;\r
-               // we must populate inline CP list again.\r
-               u.list.clear();\r
-               ControlPointTools.findNextEnd(u.start, u.list);\r
-               }\r
-       // FIXME : inline CPs are update twice because their positions must be updated before and after ends.      \r
-       updateInlineControlPoints(u,false);\r
-               if (updateEnds) {\r
-                       if (u.start.isInstanceOf(ProcessResource.plant3Dresource.TurnControlPoint)) {\r
-                               updateTurnControlPointTurn(u.start, u.start.getPrevious(), u.start.getNext());\r
-                               updatePathLegPrev(u.start, u.start, PathLegUpdateType.NONE);\r
-                       } else if (u.start.isInstanceOf(ProcessResource.plant3Dresource.EndComponentControlPoint)) {\r
-                               updateEndComponentControlPoint(u.start, u.startPoint, u.endPoint);\r
-                       }\r
-                       if (u.end.isInstanceOf(ProcessResource.plant3Dresource.TurnControlPoint)) {\r
-                               updateTurnControlPointTurn( u.end, u.end.getPrevious(), u.end.getNext());\r
-                               updatePathLegNext(u.end, u.end, PathLegUpdateType.NONE);\r
-                       } else if (u.end.isInstanceOf(ProcessResource.plant3Dresource.EndComponentControlPoint)) {\r
-                               updateEndComponentControlPoint(u.end, u.startPoint, u.endPoint);\r
-                       }\r
-                       \r
-               } else {\r
-                       if (u.start.isInstanceOf(ProcessResource.plant3Dresource.EndComponentControlPoint)) {\r
-                               updateEndComponentControlPoint(u.start, u.startPoint, u.endPoint);\r
-                       }\r
-                       if (u.end.isInstanceOf(ProcessResource.plant3Dresource.EndComponentControlPoint)) {\r
-                               updateEndComponentControlPoint( u.end, u.startPoint, u.endPoint);\r
-                       }\r
-               }\r
-               if(updateInline)\r
-                       updateInlineControlPoints(u,true);\r
-       \r
-    }\r
-    \r
-    /**\r
-        * Processes pipe run and recalculates offset\r
-     */\r
-    //private static void processPathLeg(PipeControlPoint start, Point3d startPoint,ArrayList<InlineControlPoint> list, PipeControlPoint end,Point3d endPoint, Vector3d dir, boolean hasOffsets,int iter, boolean reversed, ArrayList<ExpandIterInfo> toRemove) throws TransactionException {\r
-    private static void processPathLegNoOffset(UpdateStruct2 u) {\r
-       if (DEBUG) System.out.println("PipingRules.processPathLeg " + u.start.getResource() + " " + u.end.getResource());\r
-       Vector3d offset = new Vector3d();\r
-       if (u.hasOffsets) {\r
-               u.dir.normalize();\r
-           for (PipeControlPoint icp : u.list) {\r
-               if (icp.isInstanceOf(ProcessResource.plant3Dresource.OffsetComponent)) {\r
-                       offset.add(ControlPointTools.getSizeChangeOffsetVector(icp,u.dir));\r
-               } else if (icp.isInstanceOf(ProcessResource.plant3Dresource.DualSubControlPoint)) {\r
-                       ErrorLogger.defaultLogError("Updating pipe run, found offset controlpoint " + icp.getResource(), new Exception("ASSERT!"));\r
-               }\r
-           }\r
-       }       \r
-       processPathLeg(u);\r
-    }\r
-    \r
-    private static void updateOffsetPoint(PipeControlPoint sccp, Vector3d offset) {\r
-               Point3d world = G3DTools.getPoint(sccp.getWorldPosition());\r
-               world.add(offset);\r
-               PipeControlPoint ocp = sccp.getSubPoint().iterator().next();\r
-               ControlPointTools.setWorldPosition(ocp, world);\r
-    }\r
-    \r
-    private static void updatePathLegPrev(PipeControlPoint start, PipeControlPoint updated, PathLegUpdateType lengthChange) {\r
-       ArrayList<PipeControlPoint> list = new ArrayList<PipeControlPoint>();\r
-       PipeControlPoint end = ControlPointTools.findPreviousEnd(start,list);\r
-       updatePathLegPrev(start, list, end,updated,lengthChange);\r
-    }\r
-    \r
-    private static void updatePathLegPrev(PipeControlPoint start, ArrayList<PipeControlPoint> list, PipeControlPoint end, PipeControlPoint updated, PathLegUpdateType lengthChange) {\r
-       // reverses the list\r
-       ArrayList<PipeControlPoint> nextList = new ArrayList<PipeControlPoint>();\r
-       for (PipeControlPoint icp : list) {\r
-               if (icp.isInstanceOf(ProcessResource.plant3Dresource.DualSubControlPoint)) {\r
-                       nextList.add(0, icp.getSubPointOf());\r
-               } else {\r
-                       nextList.add(0,icp);\r
-               }\r
-               \r
-       }\r
-       updatePathLeg(end, nextList, start, true,0,new ArrayList<ExpandIterInfo>(),updated,lengthChange);\r
-        \r
-    }\r
-\r
-    \r
-    /**\r
-     * Updates InlineControlPoints position when straight pipe's end(s) have\r
-     * been changed)\r
-     * \r
-     * @param pipeline\r
-     * @param icp\r
-     * @param nextPoint\r
-     * @param prevPoint\r
-     */\r
-    private static void updateInlineControlPoint( PipeControlPoint icp, Point3d nextPoint, Point3d prevPoint, Vector3d dir) {\r
-       if (DEBUG) System.out.println("PipingRules.updateInlineControlPoint() " + icp.getResource());\r
-        \r
-       Point3d inlinePoint = G3DTools.getPoint(icp.getLocalPosition());\r
-        if (DEBUG) System.out.print("InlineControlPoint update "+icp.getResource() + " " + inlinePoint + " " + prevPoint + " " + nextPoint);\r
-        Vector3d newInlinePoint = null;\r
-        boolean branchUpdate = false;\r
-        PipeControlPoint becp = null;\r
-        for (PipeControlPoint pcp : icp.getSubPoint())\r
-               if (pcp.isInstanceOf(ProcessResource.plant3Dresource.UndirectedControlPoint)) {\r
-                       branchUpdate = true;\r
-                       becp = pcp;\r
-                       break;\r
-               }\r
-                       \r
-       if (DUMMY || !branchUpdate) {\r
-               newInlinePoint = MathTools.closestPointOnEdge(new Vector3d(inlinePoint), new Vector3d(nextPoint), new Vector3d(prevPoint));\r
-       } else {\r
-               \r
-               // FIXME : can only handle one branch\r
-               PipeControlPoint p = null;\r
-               if (becp.getNext() != null) {\r
-                       p = ControlPointTools.findNextEnd(becp);\r
-               } else if (becp.getPrevious() != null) {\r
-                       p = ControlPointTools.findPreviousEnd(becp);\r
-               } \r
-               if (p == null) {\r
-                       newInlinePoint = MathTools.closestPointOnEdge(new Vector3d(inlinePoint), new Vector3d(nextPoint), new Vector3d(prevPoint));\r
-               } else {\r
-                       Point3d branchLegEnd = G3DTools.getPoint(p.getLocalPosition());\r
-                       Vector3d dir2 = new Vector3d(inlinePoint);\r
-                       dir2.sub(branchLegEnd);\r
-                       Vector3d dir1 = new Vector3d(nextPoint);\r
-                       dir1.sub(prevPoint);\r
-                       newInlinePoint = new Vector3d();\r
-                       double mu[] = new double[2];\r
-                       MathTools.intersectStraightStraight(new Vector3d(prevPoint), dir1, new Vector3d(branchLegEnd), dir2, newInlinePoint, new Vector3d(),mu);\r
-                       if (DEBUG) System.out.println(mu[0]);\r
-                       // FIXME : reserve space \r
-                       if (mu[0] < 0.0) {\r
-                               newInlinePoint = new Vector3d(prevPoint);\r
-                       } else if (mu[0] > 1.0) {\r
-                               newInlinePoint = new Vector3d(nextPoint);\r
-                       }\r
-               }\r
-       }\r
-       if (DEBUG) System.out.println(" " + newInlinePoint);\r
-        \r
-       ControlPointTools.setWorldPosition(icp, newInlinePoint);\r
-       updateControlPointOrientation(icp);\r
-    }\r
-    \r
-    /**\r
-     * Updates InlineControlPoints position when straight pipe's end(s) have\r
-     * been changed)\r
-     * \r
-     * @param pipeline\r
-     * @param icp\r
-     * @param nextPoint\r
-     * @param prevPoint\r
-     */\r
-    private static void updateEndComponentControlPoint( PipeControlPoint ecp, Point3d start, Point3d end) {\r
-       if (DEBUG) System.out.println("PipingRules.updateEndComponentControlPoint() " + ecp.getResource());\r
-//        PipeControlPoint next = ecp.getNext();\r
-//        PipeControlPoint prev = ecp.getPrevious();\r
-//        if (next != null) {\r
-//             end = G3DTools.getPoint(next.getLocalPosition());\r
-//             start = G3DTools.getPoint(ecp.getLocalPosition());\r
-//        } else if (prev != null) {\r
-//             end = G3DTools.getPoint(ecp.getLocalPosition());\r
-//             start = G3DTools.getPoint(prev.getLocalPosition());\r
-//        } else {\r
-//             // TODO : warning?\r
-//             return;\r
-//        }\r
-       //Vector3d dir = new Vector3d (end);\r
-        //dir.sub(start);\r
-        //dir.normalize();\r
-       //G3DTools.setTuple(ecp.getDirection(), dir);\r
-       \r
-       updateControlPointOrientation(ecp);\r
-       \r
-       for (PipeControlPoint pcp : ecp.getSubPoint()) {\r
-               // TODO update position\r
-               updatePathLegEndControlPoint(pcp);\r
-       }\r
-    }\r
-    \r
-    private static void updateControlPointOrientation(PipeControlPoint pcp) {\r
-       // FIXME : hack to bypass variable length components orientation\r
-       if (pcp.getAtMostOneRelatedObject(ProcessResource.g3dResource.HasWorldOrientation) == null)\r
-               return;\r
-       Double angleO = pcp.getAtMostOneRelatedScalarDouble(ProcessResource.plant3Dresource.HasRotationAngle);\r
-       double angle = 0.0;\r
-       if (angleO != null)\r
-               angle = angleO;\r
-       \r
-       AxisAngle4d aa = ControlPointTools.getControlPointWorldRotation(pcp, angle);\r
-       ControlPointTools.setWorldOrientation(pcp,aa);\r
-       \r
-    }\r
-\r
-    /**\r
-     * Updates all branches when branch's position has been changed\r
-     * @param bcp\r
-     */\r
-    private static void updateBranchControlPointBranches(PipeControlPoint bcp) {\r
-       if (DEBUG) System.out.println("PipingRules.updateBranchControlPointBranches() " + bcp.getResource());\r
-        Collection<PipeControlPoint> branches = bcp.getSubPoint();\r
-        if (branches.size() == 0) {\r
-            if (DEBUG) System.out.println("No Branches found");\r
-            return;\r
-        }\r
-        for (PipeControlPoint pcp : branches) {\r
-               updatePathLegEndControlPoint(pcp);\r
-        }\r
-    }\r
-    \r
-    /**\r
-     * Recalculates turn control point's internal data (turn angle and offset)\r
-     * @param tcp\r
-     * @param prev\r
-     * @param next\r
-     */\r
-    private static double updateTurnControlPointTurn( PipeControlPoint tcp, PipeControlPoint prev, PipeControlPoint next) {\r
-       if (DEBUG) System.out.println("PipingTools.updateTurnControlPointTurn()" + tcp.getResource());\r
-        if (next == null || prev == null)\r
-            return Math.PI; // FIXME : argh\r
-        Point3d middlePoint = G3DTools.getPoint(tcp.getWorldPosition());\r
-        Point3d nextPoint = G3DTools.getPoint(next.getWorldPosition());    \r
-        Point3d prevPoint = G3DTools.getPoint(prev.getWorldPosition());     \r
-        return updateTurnControlPointTurn(tcp, middlePoint, prevPoint, nextPoint);\r
-    }\r
-    \r
-    /**\r
-     * Recalculates turn control point's internal data (turn angle and offset)\r
-     * @param tcp\r
-     * @param middlePoint\r
-     * @param nextPoint\r
-     * @param prevPoint\r
-     */\r
-    private static double updateTurnControlPointTurn( PipeControlPoint tcp, Point3d middlePoint, Point3d prevPoint, Point3d nextPoint) {\r
-       \r
-       Vector3d dir1 = new Vector3d(middlePoint);\r
-        dir1.sub(prevPoint);\r
-        Vector3d dir2 = new Vector3d(nextPoint);\r
-        dir2.sub(middlePoint);\r
-        if (DEBUG) System.out.println("PipingTools.updateTurnControlPointTurn " + tcp.getResource() + " " + prevPoint + " " + middlePoint + " " + nextPoint);\r
-        return updateTurnControlPointTurn(tcp, dir1, dir2);\r
-    }\r
-    \r
-    private static double updateTurnControlPointTurn(PipeControlPoint tcp, Vector3d dir1, Vector3d dir2) {\r
-        double turnAngle = dir1.angle(dir2);\r
-         double angle = Math.PI - turnAngle;\r
-         \r
-         double elbowRadius = tcp.getSingleRelatedScalarDouble(ProcessResource.plant3Dresource.HasTurnRadius);\r
-         double R = elbowRadius / Math.tan(angle * 0.5);\r
-         Vector3d turnAxis = new Vector3d();\r
-         turnAxis.cross(dir1, dir2);\r
-         turnAxis.normalize();\r
-         tcp.setRelatedScalarDouble(ProcessResource.plant3Dresource.HasTurnAngle,turnAngle);\r
-         tcp.setRelatedScalarDouble(ProcessResource.plant3Dresource.HasLength, R);//setComponentOffsetValue(R);\r
-         G3DTools.setTuple3(tcp.getSingleRelatedObject(ProcessResource.plant3Dresource.HasTurnAxis), turnAxis);\r
-         if (DEBUG) System.out.println("PipingTools.updateTurnControlPointTurn " + dir1 + " " + dir2 + " " + turnAngle + " " + turnAxis);\r
-         return turnAngle;\r
-    }\r
-    \r
-}\r