X-Git-Url: https://gerrit.simantics.org/r/gitweb?a=blobdiff_plain;f=org.simantics.plant3d%2Fsrc%2Forg%2Fsimantics%2Fplant3d%2Fscenegraph%2Fcontrolpoint%2FPipingRules.java;h=3fc0488105fe8a24a8bd7197a188fb448ec3bfe7;hb=3b5c59eca31e9db10c1a1dc6d244d6fd4f3578a2;hp=26e2bb52de68974d253cd4befea10e7e26fd9bd6;hpb=178e59c935e6c4eaa7897d9bf8c5113ee822878b;p=simantics%2F3d.git diff --git a/org.simantics.plant3d/src/org/simantics/plant3d/scenegraph/controlpoint/PipingRules.java b/org.simantics.plant3d/src/org/simantics/plant3d/scenegraph/controlpoint/PipingRules.java index 26e2bb52..3fc04881 100644 --- a/org.simantics.plant3d/src/org/simantics/plant3d/scenegraph/controlpoint/PipingRules.java +++ b/org.simantics.plant3d/src/org/simantics/plant3d/scenegraph/controlpoint/PipingRules.java @@ -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 list = new ArrayList(); 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 list, PipeControlPoint end, PipeControlPoint updated, PathLegUpdateType lengthChange) throws Exception { updatePathLeg(start, list, end, false, 0, new ArrayList(), updated, lengthChange); } + + private static void updatePathLegPrev(PipeControlPoint start, PipeControlPoint updated, PathLegUpdateType lengthChange) throws Exception { + ArrayList list = new ArrayList(); + 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 list, PipeControlPoint end, PipeControlPoint updated, PathLegUpdateType lengthChange) throws Exception { + // reverses the list + ArrayList nextList = new ArrayList(); + 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(), updated, lengthChange); + + } private static class UpdateStruct2 { public PipeControlPoint start; @@ -456,26 +475,30 @@ public class PipingRules { if (DEBUG) System.out.println("PipingRules.updateInlineControlPoints() " + u); + Vector3d start = new Vector3d(u.startPoint); + Vector3d end = new Vector3d(u.endPoint); + + if (checkSizes) { + // create offsets for leg ends. + MathTools.mad(start, u.dir, u.start.getInlineLength()); + MathTools.mad(end, u.dir, -u.end.getInlineLength()); + } + + boolean recalcline = false; 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); - } + + + 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 pathLegPoints = new ArrayList(); pathLegPoints.add(u.start); @@ -497,7 +520,7 @@ public class PipingRules { if (icp.isVariableLength()) { if (i != pathLegPoints.size() - 1) { PipeControlPoint next = pathLegPoints.get(i + 1); - updateVariableLength(icp, prev, next); + recalcline = recalcline | updateVariableLength(icp, prev, next); } else { // this is variable length component at the end of the @@ -515,35 +538,12 @@ public class PipingRules { // space between them. // I there is, we'll have to create new variable length // component between them. - Vector3d currentPos = icp.getWorldPosition(); - Vector3d prevPos = prev.getWorldPosition(); - Vector3d dir = new Vector3d(currentPos); - dir.sub(prevPos); - double l = dir.lengthSquared(); - double l2prev = prev.getInlineLength(); - double l2next = icp.getInlineLength(); - double l2 = l2prev + l2next; - double l2s = l2 * l2; - if (l > l2s) { - if (allowInsertRemove) { - dir.normalize(); - double length = Math.sqrt(l) - l2; // true length of the - // variable length - // component - dir.scale(length * 0.5 + l2prev); // calculate center - // position of the - // component - dir.add(prevPos); - PipeControlPoint scp = insertStraight(prev, icp, dir, length); - } else { - triedIR = true; - } - } + recalcline = recalcline | possibleVaribleLengthInsert(icp, prev); } } - } else { - Vector3d sp = new Vector3d(u.startPoint); - Vector3d ep = new Vector3d(u.endPoint); + } else { // with offset + Vector3d sp = new Vector3d(start); + Vector3d ep = new Vector3d(end); ep.sub(u.offset); ArrayList pathLegPoints = new ArrayList(); @@ -564,6 +564,9 @@ public class PipingRules { } pathLegPoints.add(u.end); + if (!checkSizes) + return; + sp = new Vector3d(u.startPoint); ep = new Vector3d(u.endPoint); ep.sub(u.offset); @@ -580,7 +583,7 @@ public class PipingRules { if (i != pathLegPoints.size() - 1) { PipeControlPoint next; next = pathLegPoints.get(i + 1); - updateVariableLength(icp, prev, next); + recalcline = recalcline | updateVariableLength(icp, prev, next); } else { // this is variable length component at the end of the @@ -590,7 +593,15 @@ public class PipingRules { // place, but center of the component must be moved. updateVariableLengthEnd(icp, prev); } - } else if (icp.isOffset()) { + } else if (!prev.isVariableLength()) { + // If this and previous control point are not variable + // length pcps, we'll have to check if there is no empty + // space between them. + // I there is, we'll have to create new variable length + // component between them. + recalcline = recalcline | possibleVaribleLengthInsert(icp, prev); + } + if (icp.isOffset()) { // TODO : offset vector is already calculated and should be // cached Vector3d offset = icp.getSizeChangeOffsetVector(u.dir); @@ -599,9 +610,13 @@ public class PipingRules { } } } + if (recalcline) { + u.list.clear(); + u.start.findNextEnd(u.list); + } } - private static void updateVariableLength(PipeControlPoint icp, PipeControlPoint prev, PipeControlPoint next) { + private static boolean updateVariableLength(PipeControlPoint icp, PipeControlPoint prev, PipeControlPoint next) { Vector3d prevPos = prev.getWorldPosition(); Vector3d nextPos = next.getWorldPosition(); @@ -632,12 +647,48 @@ public class PipingRules { dir.add(prevPos); icp.setWorldPosition(dir); icp.setLength(length); + return false; } 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(); + return true; + } + return false; + } + } + + private static boolean possibleVaribleLengthInsert(PipeControlPoint icp, PipeControlPoint prev) throws Exception{ + Vector3d currentPos = icp.getWorldPosition(); + Vector3d prevPos = prev.getWorldPosition(); + Vector3d dir = new Vector3d(currentPos); + dir.sub(prevPos); + double l = dir.lengthSquared(); + double l2prev = prev.getInlineLength(); + double l2next = icp.getInlineLength(); + double l2 = l2prev + l2next; + double l2s = l2 * l2; + if (l > l2s) { + if (allowInsertRemove) { + dir.normalize(); + double length = Math.sqrt(l) - l2; // true length of the + // variable length + // component + dir.scale(length * 0.5 + l2prev); // calculate center + // position of the + // component + dir.add(prevPos); + PipeControlPoint scp = insertStraight(prev, icp, dir, length); + return true; + } else { + triedIR = true; + } } + return false; } private static void updateVariableLengthEnd(PipeControlPoint icp, PipeControlPoint prev) { @@ -774,8 +825,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 +854,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 +951,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 +1020,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 +1263,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 +1346,6 @@ public class PipingRules { ocp.setWorldPosition(world); } - private static void updatePathLegPrev(PipeControlPoint start, PipeControlPoint updated, PathLegUpdateType lengthChange) throws Exception { - ArrayList list = new ArrayList(); - PipeControlPoint end = start.findPreviousEnd(list); - updatePathLegPrev(start, list, end, updated, lengthChange); - } - - private static void updatePathLegPrev(PipeControlPoint start, ArrayList list, PipeControlPoint end, PipeControlPoint updated, PathLegUpdateType lengthChange) throws Exception { - // reverses the list - ArrayList nextList = new ArrayList(); - 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(), updated, lengthChange); - - } - /** * Updates InlineControlPoints position when straight pipe's end(s) have * been changed) @@ -1293,54 +1355,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); @@ -1396,8 +1476,11 @@ public class PipingRules { double angle = 0.0; if (angleO != null) angle = angleO; - - Quat4d q = pcp.getControlPointOrientationQuat(angle); + Boolean reversedO = pcp.getReversed(); + boolean reversed = false; + if (reversedO != null) + reversed = reversedO; + Quat4d q = pcp.getControlPointOrientationQuat(angle, reversed); pcp.setWorldOrientation(q); } @@ -1602,9 +1685,8 @@ public class PipingRules { System.out.println("Run is not connected"); } for (PipeControlPoint pcp : pcps) { - if (!pcp.isDirected()) - if (pcp.getNext() == null && pcp.getPrevious() == null) - System.out.println("Orphan " + pcp); + if (!pcp.isDirected() && pcp.getNext() == null && pcp.getPrevious() == null) + System.out.println("Orphan undirected " + pcp); } for (PipeControlPoint pcp : pcps) { if (pcp.getParentPoint() == null) {