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=386cc56a211d3245d6bb07137550d538d31a50f6;hb=6f6aa87201058478da5a0253118f2be10d946982;hp=be66cf1441954cdebad851999b4b58c96599b7c4;hpb=8b06e290cf681e2157824428395988063686e7b3;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 be66cf14..386cc56a 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 @@ -44,29 +44,41 @@ public class PipingRules { private static boolean triedIR = false; - private static List updates = new ArrayList(); + private static List requestUpdates = new ArrayList(); + private static List currentUpdates = new ArrayList(); - private static Object mutex = new Object(); + private static Object updateMutex = new Object(); + private static Object ruleMutex = new Object(); public static void requestUpdate(PipeControlPoint pcp) { if (DEBUG) System.out.println("PipingRules request " + pcp); - synchronized (mutex) { - if (!updates.contains(pcp)) - updates.add(pcp); + synchronized (updateMutex) { + if (!requestUpdates.contains(pcp)) + requestUpdates.add(pcp); } } - public static synchronized boolean update() throws Exception { - if (updates.size() == 0) + public static boolean update() throws Exception { + if (requestUpdates.size() == 0) return false; - List temp = new ArrayList(updates.size()); - synchronized(mutex) { - temp.addAll(updates); - updates.clear(); + + List temp = new ArrayList(requestUpdates.size()); + synchronized(updateMutex) { + temp.addAll(requestUpdates); + requestUpdates.clear(); + } + synchronized (ruleMutex) { + currentUpdates.clear(); + currentUpdates.addAll(temp); + // TODO : we should remove already processed control points from currentUpdates after each _positionUpdate call. + for (PipeControlPoint pcp : currentUpdates) + _positionUpdate(pcp, true); + currentUpdates.clear(); + } + synchronized(updateMutex) { + requestUpdates.removeAll(temp); } - for (PipeControlPoint pcp : temp) - positionUpdate(pcp); return true; } @@ -76,6 +88,16 @@ public class PipingRules { } public static boolean positionUpdate(PipeControlPoint pcp, boolean allowIR) throws Exception { + synchronized (ruleMutex) { + currentUpdates.add(pcp); + boolean b = _positionUpdate(pcp, allowIR); + currentUpdates.clear(); + return b; + } + + } + + private static boolean _positionUpdate(PipeControlPoint pcp, boolean allowIR) throws Exception { if (updating || !enabled) return true; if (pcp.getPipeRun() == null) @@ -106,7 +128,7 @@ public class PipingRules { public static void setEnabled(boolean enabled) { PipingRules.enabled = enabled; if(!enabled) - updates.clear(); + currentUpdates.clear(); } public static boolean isEnabled() { @@ -527,15 +549,15 @@ public class PipingRules { pathLegPoints.add(u.end); // TODO : values can be cached in the loop - for (int i = 1; i < pathLegPoints.size(); i++) { + for (int i = 0; i < pathLegPoints.size(); i++) { PipeControlPoint icp = pathLegPoints.get(i); - PipeControlPoint prev = pathLegPoints.get(i - 1); - + PipeControlPoint prev = i > 0 ? pathLegPoints.get(i - 1) : null; + PipeControlPoint next = i < pathLegPoints.size() - 1 ? pathLegPoints.get(i + 1) : null; if (icp.isVariableLength()) { - if (i != pathLegPoints.size() - 1) { - PipeControlPoint next = pathLegPoints.get(i + 1); + if (prev != null && next != null) { + recalcline = recalcline | updateVariableLength(icp, prev, next); } else { @@ -544,11 +566,11 @@ public class PipingRules { // the problem is that we want to keep unconnected end // of the component in the same // place, but center of the component must be moved. - updateVariableLengthEnd(icp, prev); + updateVariableLengthEnd(icp, prev != null ? prev : next); } - } else if (!prev.isVariableLength()) { + } else if (prev != null && !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. @@ -587,18 +609,18 @@ public class PipingRules { ep = new Vector3d(u.endPoint); ep.sub(u.offset); - for (int i = 1; i < pathLegPoints.size(); i++) { + for (int i = 0; i < pathLegPoints.size(); i++) { PipeControlPoint icp = pathLegPoints.get(i); - PipeControlPoint prev = pathLegPoints.get(i - 1); - if (prev.isDualInline()) + PipeControlPoint prev = i > 0 ? pathLegPoints.get(i - 1) : null; + PipeControlPoint next = i < pathLegPoints.size() - 1 ? pathLegPoints.get(i + 1) : null; + + if (prev != null && prev.isDualInline()) prev = prev.getSubPoint().get(0); if (icp.isVariableLength()) { - if (i != pathLegPoints.size() - 1) { - PipeControlPoint next; - next = pathLegPoints.get(i + 1); + if (prev != null && next != null) { recalcline = recalcline | updateVariableLength(icp, prev, next); } else { @@ -607,9 +629,9 @@ public class PipingRules { // the problem is that we want to keep unconnected end // of the component in the same // place, but center of the component must be moved. - updateVariableLengthEnd(icp, prev); + updateVariableLengthEnd(icp, prev != null ? prev : next); } - } else if (!prev.isVariableLength()) { + } else if (prev != null && !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. @@ -708,43 +730,49 @@ public class PipingRules { } private static void updateVariableLengthEnd(PipeControlPoint icp, PipeControlPoint prev) { - double currentLength = icp.getLength(); - Vector3d currentPos = icp.getWorldPosition(); - Vector3d prevPos = prev.getWorldPosition(); - - Vector3d dir = new Vector3d(); - dir.sub(currentPos, prevPos); - - if (currentLength < MathTools.NEAR_ZERO) { - currentLength = (dir.length() - prev.getInlineLength()) * 2.0; - } - - if (dir.lengthSquared() > MathTools.NEAR_ZERO) - dir.normalize(); - Point3d endPos = new Point3d(dir); - endPos.scale(currentLength * 0.5); - endPos.add(currentPos); // this is the free end of the - // component - - double offset = prev.getInlineLength(); - Point3d beginPos = new Point3d(dir); - beginPos.scale(offset); - beginPos.add(prevPos); // this is the connected end of - // the component - - double l = beginPos.distance(endPos); - - if (Double.isNaN(l)) - System.out.println("Length for " + icp + " is NaN"); - - dir.scale(l * 0.5); - beginPos.add(dir); // center position - - if (DEBUG) - System.out.println("PipingRules.updateInlineControlPoints() setting variable length to " + l); - icp.setLength(l); - - icp.setWorldPosition(new Vector3d(beginPos)); + Vector3d currentPos = icp.getWorldPosition(); + Vector3d prevPos = prev.getWorldPosition(); + + Vector3d dir = new Vector3d(); + dir.sub(currentPos, prevPos); + + boolean simple = currentUpdates.contains(icp); + if (simple) { + // Update based on position -> adjust length + double currentLength = (dir.length() - prev.getInlineLength()) * 2.0; + icp.setLength(currentLength); + } else { + // Update based on neighbour movement -> adjust length and position, so that free end stays in place. + double currentLength = icp.getLength(); + if (currentLength < MathTools.NEAR_ZERO) { + currentLength = (dir.length() - prev.getInlineLength()) * 2.0; + } + + if (dir.lengthSquared() > MathTools.NEAR_ZERO) + dir.normalize(); + Point3d endPos = new Point3d(dir); + endPos.scale(currentLength * 0.5); + endPos.add(currentPos); // this is the free end of the component + + double offset = prev.getInlineLength(); + Point3d beginPos = new Point3d(dir); + beginPos.scale(offset); + beginPos.add(prevPos); // this is the connected end of the component + + double l = beginPos.distance(endPos); + + if (Double.isNaN(l)) + System.out.println("Length for " + icp + " is NaN"); + + dir.scale(l * 0.5); + beginPos.add(dir); // center position + + if (DEBUG) + System.out.println("PipingRules.updateInlineControlPoints() setting variable length to " + l); + icp.setLength(l); + + icp.setWorldPosition(new Vector3d(beginPos)); + } } private static void ppNoOffset(UpdateStruct2 u) throws Exception { @@ -824,6 +852,13 @@ public class PipingRules { } Vector3d directedDirection = direction(dcp, dcpStart ? Direction.NEXT : Direction.PREVIOUS); + if (directedDirection == null) { + updateTurnControlPointTurn(dcp, dcp.getPrevious(), dcp.getNext()); + directedDirection = direction(dcp, dcpStart ? Direction.NEXT : Direction.PREVIOUS); + if (directedDirection == null) { + return; + } + } Point3d directedEndPoint = new Point3d(u.endPoint); if (u.hasOffsets) directedEndPoint.add(u.offset); @@ -993,17 +1028,27 @@ public class PipingRules { } p1 = dcp.getWorldPosition(); - // FIXME: calculate position of the elbows properly. + Vector3d v = new Vector3d(); if (!u.reversed) - p1.add(dir1); + v.set(dir1); else - p1.add(dir2); + v.set(dir2); + + // Reserve space for 90 deg elbow + double off = dcp1.getPipeRun().getTurnRadius(); + v.scale(off); + p1.add(v); if (!u.reversed) p2 = MathTools.closestPointOnStraight(new Point3d(p1), position2, dir2); else p2 = MathTools.closestPointOnStraight(new Point3d(p1), position1, 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) + if (MathTools.distance(p1, p2) < off*2.05) { + p2.add(v); + } PipeControlPoint tcp1 = insertElbow(dcp, next, p1); PipeControlPoint tcp2 = insertElbow(tcp1, next, p2); @@ -1291,8 +1336,7 @@ public class PipingRules { info.getEnd()._remove(); } } - // ControlPointTools.removeControlPoint may remove mo0re than one - // CP; + // ControlPointTools.removeControlPoint may remove more than one CP; // we must populate inline CP list again. u.list.clear(); u.start.findNextEnd( u.list); @@ -1537,12 +1581,25 @@ public class PipingRules { if (!tcp.isFixed()) { if (next == null || prev == null) - return Math.PI; // FIXME : argh + return tcp.getTurnAngle(); Vector3d middlePoint = tcp.getWorldPosition(); Vector3d nextPoint = next.getWorldPosition(); Vector3d prevPoint = prev.getWorldPosition(); return updateTurnControlPointTurn(tcp, middlePoint, prevPoint, nextPoint); } else { + // Verify that fixed turn is properly defined. + // TODO : when reversed flag is changed, rotation angle should be recalculated, otherwise the orientation will change. + // TODO : should reverse flag toggle to be done already when we are removing defining side? + if (prev != null && next != null) { + // Nothing to do + } else if (prev == null) { + if (!tcp._getReversed()) + tcp.setReversed(true); + } else if (next == null) { + if (tcp._getReversed()) + tcp.setReversed(false); + } + Vector3d dir; if (!tcp._getReversed()) { if (prev == null) @@ -1560,7 +1617,7 @@ public class PipingRules { Vector3d middlePoint = tcp.getWorldPosition(); Vector3d nextPoint = next.getWorldPosition(); dir = new Vector3d(); - dir.sub(nextPoint,middlePoint); + dir.sub(middlePoint, nextPoint); } dir.normalize(); @@ -1612,7 +1669,7 @@ public class PipingRules { turnAngle = 0.0; tcp.setTurnAngle(0.0); tcp.setLength(0.0); - tcp.setTurnAxis(MathTools.Y_AXIS); + tcp.setTurnAxis(new Vector3d(MathTools.Y_AXIS)); } updateControlPointOrientation(tcp); if (DEBUG) @@ -1692,6 +1749,12 @@ public class PipingRules { } } + if (current.isTurn() && current.isFixed()) { + current.setReversed(!current._getReversed()); + } + if (current.isInline() && current.isReverse()) { + current.setReversed(!current._getReversed()); + } } } @@ -1725,13 +1788,14 @@ public class PipingRules { return; Collection pcps = pipeRun.getControlPoints(); int count = 0; + //System.out.println("Validate " + pipeRun.getName()); for (PipeControlPoint pcp : pcps) { if (pcp.getParentPoint() == null || pcp.getParentPoint().getPipeRun() != pipeRun) count++; } List runPcps = getControlPoints(pipeRun); if (runPcps.size() != count) { - System.out.println("Run is not connected"); + System.out.println("Run " + pipeRun.getName() + " contains unconnected control points"); } for (PipeControlPoint pcp : pcps) { if (!pcp.isDirected() && pcp.getNext() == null && pcp.getPrevious() == null)