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=d00e4018de1407887cb1982e578bb2b3d967a4a5;hb=7e518e75a4de0f84f2b0d1b60640e2ed6c530fcd;hp=e8e39c081d7c1461e297777bd08336335a9641e9;hpb=e9988b476c8634d67cae75c53a8d084f463d5419;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 e8e39c08..d00e4018 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 @@ -138,8 +138,11 @@ public class PipingRules { public static void setEnabled(boolean enabled) { PipingRules.enabled = enabled; - if(!enabled) - currentUpdates.clear(); + if(!enabled) { + synchronized (ruleMutex) { + currentUpdates.clear(); + } + } } public static boolean isEnabled() { @@ -277,6 +280,9 @@ public class PipingRules { scp.insert(pcp1, pcp2); scp.setWorldPosition(pos); + Vector3d dir = new Vector3d(); + dir.sub(pcp2.getWorldPosition(), pcp1.getWorldPosition()); + updateControlPointOrientation(scp, dir); scp.setLength(length); validate(scp.getPipeRun()); return scp; @@ -363,26 +369,18 @@ public class PipingRules { } - @SuppressWarnings("unused") - private static boolean calculateOffset(Vector3d startPoint, Vector3d endPoint, PipeControlPoint start, ArrayList list, PipeControlPoint end, Vector3d dir, Vector3d offset) { - boolean hasOffsets = false; - List offsets = new ArrayList(list.size()); - // Only start offset affects the calculation - if (start.isOffset()) - offsets.add(start); - for (PipeControlPoint icp : list) { - if (icp.isOffset()) { - offsets.add(icp); - } else if (icp.isDualSub()) - ErrorLogger.defaultLogError("Updating pipe run, found offset controlpoint " + icp, new Exception("ASSERT!")); - } + public static boolean calculateDirectedOffset(Vector3d startPoint, Vector3d endPoint, PipeControlPoint start, ArrayList list, PipeControlPoint end, Vector3d dir, Vector3d offset) { + return calculateOffset(startPoint, endPoint, start, list, end, dir, offset, true); + } + + public static boolean calculateOffset(Vector3d startPoint, Vector3d endPoint, PipeControlPoint start, ArrayList list, PipeControlPoint end, Vector3d dir, Vector3d offset) { + return calculateOffset(startPoint, endPoint, start, list, end, dir, offset, false); + } + + private static boolean calculateOffset(Vector3d startPoint, Vector3d endPoint, PipeControlPoint start, ArrayList list, PipeControlPoint end, Vector3d dir, Vector3d offset, boolean directed) { + List offsets = getOffsetPoints(start, list); if (offsets.size() == 0) { - dir.set(endPoint); - dir.sub(startPoint); - double l = dir.lengthSquared(); - if (l > MathTools.NEAR_ZERO) - dir.scale(1.0/Math.sqrt(l)); - offset.set(0.0, 0.0, 0.0); + setZeroOffset(startPoint, endPoint, dir, offset); return false; } else { Vector3d sp = new Vector3d(startPoint); @@ -392,8 +390,9 @@ public class PipingRules { double l = dir.lengthSquared(); if (l > MathTools.NEAR_ZERO) dir.scale(1.0/Math.sqrt(l)); + int iter = 100; - while (iter >= 0) { + while (true) { iter--; offset.set(0.0, 0.0, 0.0); @@ -401,11 +400,16 @@ public class PipingRules { Vector3d v = icp.getSizeChangeOffsetVector(dir); offset.add(v); } + + if (directed) + break; + Point3d nep = new Point3d(endPoint); nep.sub(offset); - if (nep.distance(ep) < 0.0000000001) { + if (nep.distance(ep) < 0.0000000001 || iter <= 0) { break; - } + } + ep = nep; dir.set(ep); dir.sub(sp); @@ -413,14 +417,37 @@ public class PipingRules { if (l > MathTools.NEAR_ZERO) dir.scale(1.0/Math.sqrt(l)); } - hasOffsets = true; + + if (DEBUG) + System.out.println("calcOffset s:"+ startPoint + " e:" + endPoint + " d:" + dir + " o:"+offset) ; + + return true; } - - if (DEBUG && hasOffsets) - System.out.println("calcOffset s:"+ startPoint + " e:" + endPoint + " d:" + dir + " o:"+offset) ; - return hasOffsets; } + public static void setZeroOffset(Vector3d startPoint, Vector3d endPoint, Vector3d dir, Vector3d offset) { + dir.set(endPoint); + dir.sub(startPoint); + double l = dir.lengthSquared(); + if (l > MathTools.NEAR_ZERO) + dir.scale(1.0/Math.sqrt(l)); + offset.set(0.0, 0.0, 0.0); + } + + public static List getOffsetPoints(PipeControlPoint start, ArrayList list) { + List offsets = new ArrayList(list.size()); + // Only start offset affects the calculation + if (start.isOffset()) + offsets.add(start); + for (PipeControlPoint icp : list) { + if (icp.isOffset()) { + offsets.add(icp); + } else if (icp.isDualSub()) + ErrorLogger.defaultLogError("Updating pipe run, found offset controlpoint " + icp, new Exception("ASSERT!")); + } + return offsets; + } + private static UpdateStruct2 createUS(PipeControlPoint start, Direction direction, int iter, ArrayList toRemove, PipeControlPoint updated) { ArrayList list = new ArrayList(); PipeControlPoint end = null; @@ -450,6 +477,21 @@ public class PipingRules { return new UpdateStruct2(start, startPoint, list, end, endPoint, dir, offset, hasOffsets, iter, direction == Direction.PREVIOUS, toRemove, updated); } + private static Vector3d pathLegDirection(PipeControlPoint start) { + ArrayList list = new ArrayList(); + PipeControlPoint end = start.findNextEnd(list); + if (start == end) { + return start.getDirection(Direction.NEXT); + } + + Vector3d offset = new Vector3d(); + Vector3d startPoint = start.getWorldPosition(); + Vector3d endPoint = end.getWorldPosition(); + Vector3d dir = new Vector3d(); + calculateOffset(startPoint, endPoint, start, list, end, dir, offset); + return dir; + } + private static boolean asDirected(PipeControlPoint pcp, Direction direction) { if (pcp.isDirected()) return true; @@ -887,7 +929,11 @@ public class PipingRules { Vector3d dir = new Vector3d(); dir.sub(currentPos, prevPos); - boolean simple = currentUpdates.contains(icp); + boolean simple; + synchronized (ruleMutex) { + simple = currentUpdates.contains(icp); + } + if (simple) { // Update based on position -> adjust length double currentLength = (dir.length() - prev.getInlineLength()) * 2.0; @@ -1016,22 +1062,27 @@ public class PipingRules { return; } } - Point3d directedEndPoint = new Point3d(u.endPoint); - if (u.hasOffsets) - directedEndPoint.sub(u.offset); + + Point3d otherPosition = new Point3d(dcpStart ? u.endPoint : u.startPoint); + if (u.hasOffsets) { + Vector3d dir = new Vector3d(), offset = new Vector3d(); + calculateDirectedOffset(u.startPoint, u.endPoint, u.start, u.list, u.end, dir, offset); + u.dir = dir; + u.offset = offset; + + if (dcpStart) + otherPosition.add(offset); + else + otherPosition.sub(offset); + } double mu[] = new double[2]; Vector3d closest; Vector3d t = new Vector3d(); - if (dcpStart) { - closest = MathTools.closestPointOnStraight(directedEndPoint, u.startPoint, directedDirection, mu); - t.sub(closest, directedEndPoint); - } else { - closest = MathTools.closestPointOnStraight(u.startPoint, directedEndPoint, directedDirection, mu); - t.sub(closest, u.startPoint); - } + closest = MathTools.closestPointOnStraight(otherPosition, position, directedDirection, mu); + t.sub(closest, otherPosition); double distance = t.length(); boolean aligned = (distance < ALLOWED_OFFSET); @@ -1049,7 +1100,6 @@ public class PipingRules { //if (u.start.isInline() || u.end.isInline() || u.start.asFixedAngle() || u.end.asFixedAngle()) // processPathLeg(u, true, false); checkExpandPathLeg(u, lengthChange, inlineEnd || u.start.isInline() || u.end.isInline() || u.start.asFixedAngle() || u.end.asFixedAngle()); - } else { if (u.iter > 0) { backIter(u); @@ -1082,13 +1132,26 @@ public class PipingRules { if (canMoveOther) { if (DEBUG) System.out.println("PipingRules.updateDirectedPipeRun() moved end " + other + " to " + closest); + + // Not aligned - we need to recalculate the offset to reflect new end points. + Vector3d offset; + if (u.hasOffsets) { + offset = new Vector3d(); + Vector3d newDir = new Vector3d(); + calculateDirectedOffset(position, closest, u.start, u.list, u.end, newDir, offset); + closest.add(offset); + } else { + offset = new Vector3d(); + } + other.setWorldPosition(closest); + if (dcpStart) { - ppNoOffset(new UpdateStruct2(u.start, u.startPoint, u.list, u.end, new Vector3d(closest), directedDirection, null, u.hasOffsets, u.iter, u.reversed, u.toRemove, u.updated),true); + checkExpandPathLeg(new UpdateStruct2(u.start, u.startPoint, u.list, u.end, new Vector3d(closest), directedDirection, offset, u.hasOffsets, u.iter, u.reversed, u.toRemove, u.updated), PathLegUpdateType.NONE, true); if (u.end.getNext() != null) updatePathLegNext(u.end, u.updated, PathLegUpdateType.NEXT); } else { - ppNoOffset(new UpdateStruct2(u.start, new Vector3d(closest), u.list, u.end, u.endPoint, directedDirection, null, u.hasOffsets, u.iter, u.reversed, u.toRemove, u.updated),true); + checkExpandPathLeg(new UpdateStruct2(u.start, new Vector3d(closest), u.list, u.end, u.endPoint, directedDirection, offset, u.hasOffsets, u.iter, u.reversed, u.toRemove, u.updated), PathLegUpdateType.NONE, true); if (u.start.getPrevious() != null) updatePathLegPrev(u.start, u.updated, PathLegUpdateType.PREV); } @@ -1096,7 +1159,6 @@ public class PipingRules { // TODO : calculate needed space from next run end. if (allowInsertRemove) insertElbowUpdate(u, dcp, nextToMoved, dcpStart, position, directedDirection); - else triedIR = true; } @@ -1148,8 +1210,6 @@ public class PipingRules { } } } - - } private static void updateDualDirectedPathLeg(UpdateStruct2 u, PathLegUpdateType lengthChange) throws Exception { @@ -1160,14 +1220,19 @@ public class PipingRules { PipeControlPoint dcp2 = u.end; Point3d position1 = new Point3d(u.startPoint); Point3d position2 = new Point3d(u.endPoint); + + Vector3d dir = new Vector3d(), offset = new Vector3d(); + calculateDirectedOffset(new Vector3d(position1), new Vector3d(position2), u.start, u.list, u.end, dir, offset); + Point3d position1offset = new Point3d(position1); - position1offset.sub(u.offset); + position1offset.add(offset); Point3d position2offset = new Point3d(position2); - position2offset.add(u.offset); + position2offset.sub(offset); Vector3d dir1 = direction(dcp1, Direction.NEXT); Vector3d dir2 = direction(dcp2, Direction.PREVIOUS); - Vector3d p1 = MathTools.closestPointOnStraight(position1offset, position2, dir2); - Vector3d p2 = MathTools.closestPointOnStraight(position2offset, position1, dir1); + + Vector3d p1 = MathTools.closestPointOnStraight(position1, position2offset, dir2); + Vector3d p2 = MathTools.closestPointOnStraight(position2, position1offset, dir1); double d1 = position1.distance(new Point3d(p1)); double d2 = position2.distance(new Point3d(p2)); @@ -1207,9 +1272,9 @@ public class PipingRules { p1.add(v); if (!u.reversed) - p2 = MathTools.closestPointOnStraight(new Point3d(p1), position2, dir2); + p2 = MathTools.closestPointOnStraight(new Point3d(p1), position2offset, dir2); else - p2 = MathTools.closestPointOnStraight(new Point3d(p1), position1, dir1); + p2 = MathTools.closestPointOnStraight(new Point3d(p1), position1offset, dir1); // By default, the elbows are placed next to each other, by using 90 deg angles. // If the distance between elbows is not enough, we must move the other elbow (and create more shallow angle elbows) @@ -1269,34 +1334,49 @@ public class PipingRules { if (other == null) return tr; // space for 90 deg Vector3d dir = dcp.getDirectedControlPointDirection(); - Vector3d dp = dcp.getWorldPosition(); - Vector3d op = other.getWorldPosition(); - double u[] = new double[1]; - Vector3d closest = MathTools.closestPointOnStraight(op, dp, dir,u); - if (MathTools.distanceSquared(closest, op) <= MIN_INLINE_LENGTH) { - if (u[0] > -MIN_INLINE_LENGTH) - return 0.0; // point following turn is directly in the front of the nozzle. - else - return tr*2.0; // point following turn is directly behind the nozzle, in theory, we should return Double.Inf... + Vector3d dir2; + if (other == ne) { + dir2 = pathLegDirection(tcp); + } else { + dir2 = pathLegDirection(pe); + dir2.negate(); } + + double d = dir.dot(dir2); + if (d > 0.9999) + return 0.0; // point following turn is directly in the front of the nozzle. + else if (d < -0.9999) + return tr*2.0; // point following turn is directly behind the nozzle, in theory, we should return Double.Inf... + double curr = tr*0.1; int iter = 10; - Vector3d v1 = new Vector3d(); - Vector3d v2 = new Vector3d(); - while (iter > 0) { - Vector3d tp = new Vector3d(dp); - MathTools.mad(tp, dir, curr); - v1.sub(tp, dp); // Vector from nozzle to turn - v2.sub(op,tp); // Vector from turn to other - double a = v1.angle(v2); - double t = Math.tan((Math.PI - a) * 0.5); - double R = 0.0; - if (t > MathTools.NEAR_ZERO) - R = tr / t; - if (R <= curr) - break; - curr = R*1.001; - iter--; + Vector3d tp0 = tcp.getPosition(); + try { + Vector3d dp = dcp.getWorldPosition(); + while (iter > 0) { + Vector3d tp = new Vector3d(dir); + tp.scaleAdd(curr, dp); + tcp.setPosition(tp); + if (other == ne) { + dir2 = pathLegDirection(tcp); + } else { + dir2 = pathLegDirection(pe); + dir2.negate(); + } + + double a = dir.angle(dir2); + double t = Math.tan(a * 0.5); + double R = 0.0; + if (t > MathTools.NEAR_ZERO) + R = tr * t; + if (R <= curr) + break; + curr = R*1.001; + iter--; + } + } + finally { + tcp.setPosition(tp0); } return curr; } @@ -1308,26 +1388,19 @@ public class PipingRules { // closest.add(directedDirection); PipeControlPoint tcp = null; - Vector3d closest; + Vector3d closest = new Vector3d(directedDirection); + closest.scaleAdd(dcp.getPipeRun().getTurnRadius(), position); 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); } - double d = MathTools.distance(position, closest); - double s = spaceForTurn(tcp,dcp); - if (d < s) { - d = s - d; - Vector3d p = new Vector3d(directedDirection); - p.scale(d); - p.add(closest); - tcp.setPosition(p); - closest = p; - } - + double s = spaceForTurn(tcp,dcp); + Vector3d p = new Vector3d(directedDirection); + p.scaleAdd(s, position); + tcp.setPosition(p); + closest = p; if (DEBUG) System.out.println("PipingRules.updateDirectedPipeRun() inserted " + tcp); @@ -1771,13 +1844,11 @@ public class PipingRules { } double turnAngle = prev.angle(next); - double angle = Math.PI - turnAngle; - Vector3d turnAxis = new Vector3d(); turnAxis.cross(prev, next); if (turnAxis.lengthSquared() > MathTools.NEAR_ZERO) { double elbowRadius = ((TurnComponent)tcp.getPipelineComponent()).getTurnRadius(); - double R = elbowRadius / Math.tan(angle * 0.5); + double R = elbowRadius * Math.tan(turnAngle * 0.5); turnAxis.normalize(); tcp.setTurnAngle(turnAngle);