]> gerrit.simantics Code Review - simantics/3d.git/commitdiff
Changed inline component update to take account required space 26/3026/1
authorMarko Luukkainen <marko.luukkainen@semantum.fi>
Wed, 17 Jul 2019 16:02:06 +0000 (19:02 +0300)
committerMarko Luukkainen <marko.luukkainen@semantum.fi>
Wed, 17 Jul 2019 16:02:06 +0000 (19:02 +0300)
gitlab #14

Change-Id: Ia0085d15647c666fd2a6802a9490a7f8e3f3d95b

org.simantics.g3d/src/org/simantics/g3d/math/MathTools.java
org.simantics.plant3d/src/org/simantics/plant3d/scenegraph/controlpoint/PipeControlPoint.java
org.simantics.plant3d/src/org/simantics/plant3d/scenegraph/controlpoint/PipingRules.java

index 63ac1ccc402b3a844e09bec7ec99417242fab272..08a1e7b0420c1b73c794362def6daa888d39b8cb 100644 (file)
@@ -33,8 +33,8 @@ import org.simantics.g3d.math.EulerTools.Order;
  */
 public class MathTools {
     
-    public static double NEAR_ZERO = 0.0000001;
-    public static double NEAR_HALF = 0.4999999;
+    public static double NEAR_ZERO = 0.000000001;
+    public static double NEAR_HALF = 0.499999999;
     
     public static final Vector3d Z_AXIS = new Vector3d(0.0,0.0,1.0);
        public static final Vector3d Y_AXIS = new Vector3d(0.0,1.0,0.0);
index b8198bda253fc0f57c6864e627f112df1f95780b..555a662089a41240b3ac17861b6130a657d68997 100644 (file)
@@ -1018,6 +1018,15 @@ public class PipeControlPoint extends G3DNode implements IP3DNode {
                p1.remChild(ocp);
                p2.remChild(sccp);
                
+               // TODO : now we assume that this is size change, and we do
+               if (ocp.next != null)
+                       ocp.next.setPrevious(null);
+               if (ocp.previous != null)
+                       ocp.previous.setNext(null);
+               if (sccp.next != null)
+                       sccp.next.setPrevious(null);
+               if (sccp.previous != null)
+                       sccp.previous.setNext(null);
                ocp.setNext(null);
                ocp.setPrevious(null);
                sccp.setNext(null);
@@ -1076,11 +1085,11 @@ public class PipeControlPoint extends G3DNode implements IP3DNode {
        public void setPosition(Vector3d position) {
                if (MathTools.equals(position, getPosition()))
                        return;
+               if (Double.isNaN(position.x) || Double.isNaN(position.y) || Double.isNaN(position.z))
+                       throw new IllegalArgumentException("NaN is not supported");
                super.setPosition(position);
                if (getParentPoint() == null && component != null)
                        component._setWorldPosition(getWorldPosition());
-               if (isDualSub())
-                       System.out.println();
                updateSubPoint();
        }
        
index 26e2bb52de68974d253cd4befea10e7e26fd9bd6..5ec468e27993ab8531290f18537d245225773178 100644 (file)
@@ -25,18 +25,14 @@ public class PipingRules {
        private static final boolean DEBUG = false;
        private static final boolean DUMMY = false;
 
-       private static final double MIN_TURN_ANGLE = 0.01;
+       private static double MIN_TURN_ANGLE = 0.001; // Threshold for removing turn components.
+       private static double ALLOWED_OFFSET = 0.001; // Allowed offset for directed path legs
 
        private static final int REMOVE_NONE = 0;
        private static final int REMOVE_START = 1;
        private static final int REMOVE_END = 2;
        private static final int REMOVE_BOTH = 3;
        
-//     private P3DRootNode root;
-       
-//     public PipingRules(P3DRootNode root) {
-//             this.root = root;
-//     }
 
        private enum PathLegUpdateType {
                NONE, PREV, NEXT, PREV_S, NEXT_S
@@ -91,11 +87,11 @@ public class PipingRules {
                        triedIR = false;
                        validate(pcp.getPipeRun());
                        if (pcp.isPathLegEnd()) {
-                               updatePathLegEndControlPoint(pcp); // FXIME: Rules won't work properly, if they are not run twice.
-                               //updatePathLegEndControlPoint(pcp);
+                               updatePathLegEndControlPoint(pcp); // FIXME: Rules won't work properly, if they are not run twice.
+                               updatePathLegEndControlPoint(pcp);
                        } else {
                                updateInlineControlPoint(pcp);
-                               //updateInlineControlPoint(pcp);
+                               updateInlineControlPoint(pcp);
                        }
                        validate(pcp.getPipeRun());
                        if (!allowInsertRemove)
@@ -281,16 +277,39 @@ public class PipingRules {
                ArrayList<PipeControlPoint> list = new ArrayList<PipeControlPoint>();
                PipeControlPoint end = start.findNextEnd(list);
                // this is for inline cp that is also path leg end
-               if (start.equals(updated))
-                       lengthChange = PathLegUpdateType.NEXT;
-               else if (end.equals(updated))
-                       lengthChange = PathLegUpdateType.PREV;
+               if (lengthChange == PathLegUpdateType.NONE) {
+                       if (start.equals(updated))
+                               lengthChange = PathLegUpdateType.NEXT;
+                       else if (end.equals(updated))
+                               lengthChange = PathLegUpdateType.PREV;
+               }
                updatePathLegNext(start, list, end, updated, lengthChange);
        }
 
        private static void updatePathLegNext(PipeControlPoint start, ArrayList<PipeControlPoint> list, PipeControlPoint end, PipeControlPoint updated, PathLegUpdateType lengthChange) throws Exception {
                updatePathLeg(start, list, end, false, 0, new ArrayList<ExpandIterInfo>(), updated, lengthChange);
        }
+       
+       private static void updatePathLegPrev(PipeControlPoint start, PipeControlPoint updated, PathLegUpdateType lengthChange) throws Exception {
+               ArrayList<PipeControlPoint> list = new ArrayList<PipeControlPoint>();
+               PipeControlPoint end = start.findPreviousEnd(list);
+               // TODO: this method is not symmetric with updatePathLegNext, which may alter lengthChange parameter?
+               updatePathLegPrev(start, list, end, updated, lengthChange);
+       }
+
+       private static void updatePathLegPrev(PipeControlPoint start, ArrayList<PipeControlPoint> list, PipeControlPoint end, PipeControlPoint updated, PathLegUpdateType lengthChange) throws Exception {
+               // reverses the list
+               ArrayList<PipeControlPoint> nextList = new ArrayList<PipeControlPoint>();
+               for (PipeControlPoint icp : list) {
+                       if (icp.isDualSub()) {
+                               nextList.add(0, icp.getParentPoint());
+                       } else {
+                               nextList.add(0, icp);
+                       }
+               }
+               updatePathLeg(end, nextList, start, true, 0, new ArrayList<ExpandIterInfo>(), updated, lengthChange);
+
+       }
 
        private static class UpdateStruct2 {
                public PipeControlPoint start;
@@ -457,25 +476,23 @@ public class PipingRules {
                        System.out.println("PipingRules.updateInlineControlPoints() " + u);
 
                if (!u.hasOffsets) {
-                       // FIXME : cache positions
-                       if (!checkSizes) {
-                               Vector3d start = new Vector3d(u.startPoint);
-                               Vector3d end = new Vector3d(u.endPoint);
-                               // create offsets.
-                               MathTools.mad(start, u.dir, 0.1);
-                               MathTools.mad(end, u.dir, -0.1);
-                               for (PipeControlPoint icp : u.list) {
-                                       updateInlineControlPoint(icp, start, end, u.dir);
-                                       
-                                       if (icp.isOffset()) {
-                                               // TODO : offset vector is already calculated and should be
-                                               // cached
-                                               Vector3d off = icp.getSizeChangeOffsetVector(u.dir);
-                                               updateOffsetPoint(icp, off);
-                                       }
+                       
+                       Vector3d start = new Vector3d(u.startPoint);
+                       Vector3d end = new Vector3d(u.endPoint);
+                       // create offsets.
+                       MathTools.mad(start, u.dir, u.start.getInlineLength());
+                       MathTools.mad(end, u.dir, -u.end.getInlineLength());
+                       for (PipeControlPoint icp : u.list) {
+                               updateInlineControlPoint(icp, start, end, u.dir);
+                               
+                               if (icp.isOffset()) {
+                                       // TODO : offset vector is already calculated and should be cached
+                                       Vector3d off = icp.getSizeChangeOffsetVector(u.dir);
+                                       updateOffsetPoint(icp, off);
                                }
-                               return;
                        }
+                       if (!checkSizes)
+                               return;                 
 
                        ArrayList<PipeControlPoint> pathLegPoints = new ArrayList<PipeControlPoint>();
                        pathLegPoints.add(u.start);
@@ -541,7 +558,7 @@ public class PipingRules {
                                        }
                                }
                        }
-               } else {
+               } else { // with offset
                        Vector3d sp = new Vector3d(u.startPoint);
                        Vector3d ep = new Vector3d(u.endPoint);
                        ep.sub(u.offset);
@@ -635,8 +652,12 @@ public class PipingRules {
                } else {
                        // components leave no space to the component and it
                        // must be removed
-                       if (icp.isDeletable())
+                       
+                       if (icp.isDeletable()) {
+                               if (DEBUG)
+                                       System.out.println("PipingRules.updateVariableLength removing " + icp);
                                icp._remove();
+                       }
                }
        }
        
@@ -774,8 +795,8 @@ public class PipingRules {
                        t.sub(closest, u.startPoint);
                }
 
-               double distance = t.lengthSquared();
-               boolean aligned = (distance < 0.002);
+               double distance = t.length();
+               boolean aligned = (distance < ALLOWED_OFFSET);
                if (aligned) {
                        checkExpandPathLeg(u, lengthChange, inlineEnd);
                        
@@ -803,7 +824,9 @@ public class PipingRules {
                                                } else {
                                                        closest.set(u.endPoint);
                                                }
-                                               closest.add(directedDirection);
+                                               Vector3d v = new Vector3d(directedDirection);
+                                               v.scale(spaceForTurn(other));
+                                               closest.add(v);
                                        }
 
                                        if (canMoveOther) {
@@ -898,7 +921,7 @@ public class PipingRules {
                double d1 = position1.distance(new Point3d(p1));
                double d2 = position2.distance(new Point3d(p2));
 
-               boolean aligned = (d1 < 0.01 && d2 < 0.01);
+               boolean aligned = (d1 < ALLOWED_OFFSET && d2 < ALLOWED_OFFSET);
                if (aligned) {
                        processPathLeg(u);
                } else {
@@ -967,16 +990,42 @@ public class PipingRules {
                }
                
        }
+       
+       private static double spaceForTurn(PipeControlPoint tcp) {
+               // TODO : this returns now space for 90 deg turn.
+               // The challenge: position of tcp affects the turn angle, which then affects the required space. Perhaps we need to iterate...
+               // Additionally, if the path legs contain offset, using just positions of opposite path leg ends is not enough,    
+               return tcp.getPipeRun().getTurnRadius();
+       }
 
        private static void insertElbowUpdate(UpdateStruct2 u, PipeControlPoint dcp, PipeControlPoint next, boolean dcpStart, Vector3d position, Vector3d directedDirection) throws Exception{
 
-               Vector3d closest = new Vector3d(position);
-               closest.add(directedDirection);
+               
+//             Vector3d closest = new Vector3d(position);
+//             closest.add(directedDirection);
+               
                PipeControlPoint tcp = null;
-               if (dcpStart)
-                       tcp = insertElbow(dcp, next, new Vector3d(closest));
-               else
-                       tcp = insertElbow(next, dcp, new Vector3d(closest));
+               Vector3d closest;
+               if (dcpStart) {
+                       closest = MathTools.closestPointOnStraight(next.getWorldPosition(), position, directedDirection);
+                       tcp = insertElbow(dcp, next, closest);
+               } else {
+                       closest = MathTools.closestPointOnStraight(dcp.getWorldPosition(), position, directedDirection);
+                       tcp = insertElbow(next, dcp, closest);
+               }
+               // TODO properly calculate required distance between start and inserted elbow.
+               double d = MathTools.distance(position, closest);
+               double s = spaceForTurn(tcp);
+               if (d < s)  {
+                       d = s - d;
+                       Vector3d p = new Vector3d(directedDirection);
+                       p.scale(d);
+                       p.add(closest);
+                       tcp.setPosition(p);
+                       closest = p;
+               }
+               
+               
 
                if (DEBUG)
                        System.out.println("PipingRules.updateDirectedPipeRun() inserted " + tcp);
@@ -1184,9 +1233,13 @@ public class PipingRules {
                if (u.toRemove.size() > 0) {
                        for (ExpandIterInfo info : u.toRemove) {
                                if (info.getStart() != null) {
+                                       if (DEBUG)
+                                               System.out.println("PipingRules.processPathLeg removing start " + info.getStart());
                                        info.getStart()._remove();
                                }
                                if (info.getEnd() != null) {
+                                       if (DEBUG)
+                                               System.out.println("PipingRules.processPathLeg removing end " + info.getEnd());
                                        info.getEnd()._remove();
                                }
                        }
@@ -1263,27 +1316,6 @@ public class PipingRules {
                ocp.setWorldPosition(world);
        }
 
-       private static void updatePathLegPrev(PipeControlPoint start, PipeControlPoint updated, PathLegUpdateType lengthChange) throws Exception {
-               ArrayList<PipeControlPoint> list = new ArrayList<PipeControlPoint>();
-               PipeControlPoint end = start.findPreviousEnd(list);
-               updatePathLegPrev(start, list, end, updated, lengthChange);
-       }
-
-       private static void updatePathLegPrev(PipeControlPoint start, ArrayList<PipeControlPoint> list, PipeControlPoint end, PipeControlPoint updated, PathLegUpdateType lengthChange) throws Exception {
-               // reverses the list
-               ArrayList<PipeControlPoint> nextList = new ArrayList<PipeControlPoint>();
-               for (PipeControlPoint icp : list) {
-                       if (icp.isDualSub()) {
-                               nextList.add(0, icp.getParentPoint());
-                       } else {
-                               nextList.add(0, icp);
-                       }
-
-               }
-               updatePathLeg(end, nextList, start, true, 0, new ArrayList<ExpandIterInfo>(), updated, lengthChange);
-
-       }
-
        /**
         * Updates InlineControlPoints position when straight pipe's end(s) have
         * been changed)
@@ -1293,54 +1325,72 @@ public class PipingRules {
         * @param nextPoint
         * @param prevPoint
         */
-       private static void updateInlineControlPoint(PipeControlPoint icp, Vector3d nextPoint, Vector3d prevPoint, Vector3d dir) {
+       private static void updateInlineControlPoint(PipeControlPoint icp, Vector3d prev, Vector3d next,  Vector3d dir) {
                if (DEBUG)
                        System.out.println("PipingRules.updateInlineControlPoint() " + icp);
 
                Vector3d inlinePoint = icp.getWorldPosition();
+               Vector3d prevPoint = new Vector3d(prev);
+               Vector3d nextPoint = new Vector3d(next);
+               if (!icp.isVariableLength()) {
+                       // Reserve space for fixed length components. 
+                       MathTools.mad(prevPoint, dir, icp.getInlineLength());
+                       MathTools.mad(nextPoint, dir, -icp.getInlineLength());
+                       if (MathTools.distance(prevPoint, nextPoint) < ALLOWED_OFFSET) {
+                               prevPoint = prev;
+                               nextPoint = next;
+                       }
+               }
+               boolean canCalc = MathTools.distance(prevPoint, nextPoint) > ALLOWED_OFFSET;
                if (DEBUG)
                        System.out.print("InlineControlPoint update " + icp + " " + inlinePoint + " " + prevPoint + " " + nextPoint);
                Vector3d newInlinePoint = null;
-               boolean branchUpdate = false;
-               PipeControlPoint becp = null;
-               for (PipeControlPoint pcp : icp.getSubPoint())
-                       if (pcp.isNonDirected()) {
-                               branchUpdate = true;
-                               becp = pcp;
-                               break;
-                       }
-
-               if (DUMMY || !branchUpdate) {
-                       newInlinePoint = MathTools.closestPointOnEdge(new Vector3d(inlinePoint), new Vector3d(nextPoint), new Vector3d(prevPoint));
-               } else {
-
-                       // FIXME : can only handle one branch
-                       PipeControlPoint p = null;
-                       if (becp.getNext() != null) {
-                               p = becp.findNextEnd();
-                       } else if (becp.getPrevious() != null) {
-                               p = becp.findPreviousEnd();
-                       }
-                       if (p == null) {
-                               newInlinePoint = MathTools.closestPointOnEdge(new Vector3d(inlinePoint), new Vector3d(nextPoint), new Vector3d(prevPoint));
+               if (canCalc) {
+                       boolean branchUpdate = false;
+                       PipeControlPoint becp = null;
+                       for (PipeControlPoint pcp : icp.getSubPoint())
+                               if (pcp.isNonDirected()) {
+                                       branchUpdate = true;
+                                       becp = pcp;
+                                       break;
+                               }
+       
+                       if (DUMMY || !branchUpdate) {
+                               newInlinePoint = MathTools.closestPointOnEdge(new Vector3d(inlinePoint), prevPoint, nextPoint);
+                               
                        } else {
-                               Vector3d branchLegEnd = p.getWorldPosition();
-                               Vector3d dir2 = new Vector3d(inlinePoint);
-                               dir2.sub(branchLegEnd);
-                               Vector3d dir1 = new Vector3d(nextPoint);
-                               dir1.sub(prevPoint);
-                               newInlinePoint = new Vector3d();
-                               double mu[] = new double[2];
-                               MathTools.intersectStraightStraight(new Vector3d(prevPoint), dir1, new Vector3d(branchLegEnd), dir2, newInlinePoint, new Vector3d(), mu);
-                               if (DEBUG)
-                                       System.out.println(mu[0]);
-                               // FIXME : reserve space
-                               if (mu[0] < 0.0) {
-                                       newInlinePoint = new Vector3d(prevPoint);
-                               } else if (mu[0] > 1.0) {
-                                       newInlinePoint = new Vector3d(nextPoint);
+       
+                               // FIXME : can only handle one branch
+                               PipeControlPoint p = null;
+                               if (becp.getNext() != null) {
+                                       p = becp.findNextEnd();
+                               } else if (becp.getPrevious() != null) {
+                                       p = becp.findPreviousEnd();
+                               }
+                               if (p == null) {
+                                       newInlinePoint = MathTools.closestPointOnEdge(new Vector3d(inlinePoint), prevPoint, nextPoint);
+                               } else if (canCalc){
+                                       Vector3d branchLegEnd = p.getWorldPosition();
+                                       Vector3d dir2 = new Vector3d(inlinePoint);
+                                       dir2.sub(branchLegEnd);
+                                       Vector3d dir1 = new Vector3d(nextPoint);
+                                       dir1.sub(prevPoint);
+                                       newInlinePoint = new Vector3d();
+                                       double mu[] = new double[2];
+                                       MathTools.intersectStraightStraight(new Vector3d(prevPoint), dir1, new Vector3d(branchLegEnd), dir2, newInlinePoint, new Vector3d(), mu);
+                                       if (DEBUG)
+                                               System.out.println(mu[0]);
+                                       // FIXME : reserve space
+                                       if (mu[0] < 0.0) {
+                                               newInlinePoint = new Vector3d(prevPoint);
+                                       } else if (mu[0] > 1.0) {
+                                               newInlinePoint = new Vector3d(nextPoint);
+                                       }
                                }
                        }
+               } else {
+                       // prevPoint == nextPoint
+                       newInlinePoint = new Vector3d(prevPoint);
                }
                if (DEBUG)
                        System.out.println(" " + newInlinePoint);