From 3f17b6e42935927f12683fc26ecd5808bf66cde6 Mon Sep 17 00:00:00 2001 From: Marko Luukkainen Date: Mon, 2 Dec 2019 14:53:07 +0200 Subject: [PATCH] Showing error messages when components overlap each other * Removed code that forced PipingRules to iterate whole connected segment. * Adjusted PipingRule excecution on editor load. * Fixed inline coomponent updated, when the component was also path leg end. * Fixed variable length adjusting / removal code. gitlab #59 Change-Id: I4e1152f2a37b9a7cc7f93f18a9cf54616c62bbfd (cherry picked from commit 3c9eba53de061b8c5c5863dc05855dc0e71781b1) --- .../actions/TranslateInlineAction.java | 2 +- .../plant3d/editor/P3DContentOutlinePage.java | 57 +++++-- .../geometry/StraightGeometryProvider.java | 2 +- .../plant3d/scenegraph/PipelineComponent.java | 28 ++++ .../controlpoint/PipeControlPoint.java | 6 + .../scenegraph/controlpoint/PipingRules.java | 158 +++++++++++------- .../org/simantics/plant3d/utils/P3DUtil.java | 13 +- 7 files changed, 188 insertions(+), 78 deletions(-) diff --git a/org.simantics.plant3d/src/org/simantics/plant3d/actions/TranslateInlineAction.java b/org.simantics.plant3d/src/org/simantics/plant3d/actions/TranslateInlineAction.java index 9001d0a7..3aac1fd9 100644 --- a/org.simantics.plant3d/src/org/simantics/plant3d/actions/TranslateInlineAction.java +++ b/org.simantics.plant3d/src/org/simantics/plant3d/actions/TranslateInlineAction.java @@ -127,7 +127,7 @@ public class TranslateInlineAction extends TranslateAction{ //boolean step = ((e.getModifiers() & MouseEvent.CTRL_MASK) > 0); Vector3d pos = new Vector3d(node.getWorldPosition()); - System.out.println(pos + " " + translate); +// System.out.println(pos + " " + translate); //pos.add(translate); pos.set(translate); //pos = constaints(pos, step); diff --git a/org.simantics.plant3d/src/org/simantics/plant3d/editor/P3DContentOutlinePage.java b/org.simantics.plant3d/src/org/simantics/plant3d/editor/P3DContentOutlinePage.java index 893a0730..ed9c4a5b 100644 --- a/org.simantics.plant3d/src/org/simantics/plant3d/editor/P3DContentOutlinePage.java +++ b/org.simantics.plant3d/src/org/simantics/plant3d/editor/P3DContentOutlinePage.java @@ -6,8 +6,11 @@ import java.util.List; import org.eclipse.jface.action.IMenuListener; import org.eclipse.jface.action.IMenuManager; import org.eclipse.jface.action.MenuManager; +import org.eclipse.jface.resource.ImageDescriptor; import org.eclipse.jface.resource.JFaceResources; import org.eclipse.jface.resource.LocalResourceManager; +import org.eclipse.jface.viewers.DecorationOverlayIcon; +import org.eclipse.jface.viewers.IDecoration; import org.eclipse.jface.viewers.TreeViewer; import org.eclipse.swt.events.MenuDetectEvent; import org.eclipse.swt.events.MenuDetectListener; @@ -42,14 +45,33 @@ public class P3DContentOutlinePage extends VTKContentOutlinePage rootNode, NodeSelectionProvider2 provider) { super(rootNode,provider); - nozzleImage = manager.createImage(Activator.imageDescriptorFromPlugin(Activator.PLUGIN_ID, "icons/Nozzle.png")); - pipeImage = manager.createImage(Activator.imageDescriptorFromPlugin(Activator.PLUGIN_ID, "icons/Straight.png")); - tankImage = manager.createImage(Activator.imageDescriptorFromPlugin(Activator.PLUGIN_ID, "icons/tank.png")); - elbowImage = manager.createImage(Activator.imageDescriptorFromPlugin(Activator.PLUGIN_ID, "icons/Elbow.png")); - componentImage = manager.createImage(Activator.imageDescriptorFromPlugin(Activator.PLUGIN_ID, "icons/Component.png")); + ImageDescriptor nozzleDesc = Activator.imageDescriptorFromPlugin(Activator.PLUGIN_ID, "icons/Nozzle.png"); + ImageDescriptor straightDesc = Activator.imageDescriptorFromPlugin(Activator.PLUGIN_ID, "icons/Straight.png"); + ImageDescriptor tankDesc = Activator.imageDescriptorFromPlugin(Activator.PLUGIN_ID, "icons/tank.png"); + ImageDescriptor elbowDesc = Activator.imageDescriptorFromPlugin(Activator.PLUGIN_ID, "icons/Elbow.png"); + ImageDescriptor componentDesc = Activator.imageDescriptorFromPlugin(Activator.PLUGIN_ID, "icons/Component.png"); + nozzleImage = manager.createImage(nozzleDesc); + pipeImage = manager.createImage(straightDesc); + tankImage = manager.createImage(tankDesc); + elbowImage = manager.createImage(elbowDesc); + componentImage = manager.createImage(componentDesc); + + ImageDescriptor error = Activator.imageDescriptorFromPlugin("org.simantics.issues.ui", "icons/warning_decoration.png"); + nozzleErrorImage = manager.createImage(new DecorationOverlayIcon(nozzleDesc, error, IDecoration.BOTTOM_RIGHT)); + pipeErrorImage = manager.createImage(new DecorationOverlayIcon(straightDesc, error, IDecoration.BOTTOM_RIGHT)); + tankErrorImage = manager.createImage(new DecorationOverlayIcon(tankDesc, error, IDecoration.BOTTOM_RIGHT)); + elbowErrorImage = manager.createImage(new DecorationOverlayIcon(elbowDesc, error, IDecoration.BOTTOM_RIGHT)); + componentErrorImage = manager.createImage(new DecorationOverlayIcon(componentDesc, error, IDecoration.BOTTOM_RIGHT)); } @Override @@ -157,15 +179,30 @@ public class P3DContentOutlinePage extends VTKContentOutlinePage NEXT > NONE PREV_S > PREV > NONE private enum PathLegUpdateType { - NONE, PREV, NEXT, PREV_S, NEXT_S + NONE, // Only current path leg needs to be updated (for example, inline comp was moved) + PREV, // Current and previous path leg need to be updated + NEXT, // Current and next path leg need to be updated + PREV_S, // Current and previous two path legs need to be updated (turn was moved, which affect other path leg end turns, and thus following path legs + NEXT_S // Current and next two path legs need to be updated }; - private static boolean enabled = true; + private static boolean enabled = true; // private static boolean updating = false; private static boolean allowInsertRemove = true; private static boolean triedIR = false; @@ -113,12 +116,12 @@ public class PipingRules { allowInsertRemove = allowIR; triedIR = false; validate(pcp.getPipeRun()); - if (pcp.isPathLegEnd()) { + if (pcp.asPathLegEnd()) { updatePathLegEndControlPoint(pcp); // FIXME: Rules won't work properly, if they are not run twice. - updatePathLegEndControlPoint(pcp); + //updatePathLegEndControlPoint(pcp); } else { updateInlineControlPoint(pcp); - updateInlineControlPoint(pcp); + //updateInlineControlPoint(pcp); } validate(pcp.getPipeRun()); if (!allowInsertRemove) @@ -139,10 +142,6 @@ public class PipingRules { public static boolean isEnabled() { return enabled; } - -// private void commit() { -// root.getNodeMap().commit(); -// } public static class ExpandIterInfo { // these two are turn control points @@ -301,14 +300,7 @@ public class PipingRules { } private static void updatePathLegNext(PipeControlPoint start, PipeControlPoint updated, PathLegUpdateType lengthChange) throws Exception { - UpdateStruct2 us = createUS(start, Direction.NEXT, 0, new ArrayList(), updated); - if (lengthChange == PathLegUpdateType.NONE) { - if (start.equals(updated)) - lengthChange = PathLegUpdateType.NEXT; - else if (us.end.equals(updated)) - lengthChange = PathLegUpdateType.PREV; - } if (us == null) { System.out.println("Null update struct " + start); return; @@ -317,14 +309,7 @@ public class PipingRules { } private static void updatePathLegPrev(PipeControlPoint start, PipeControlPoint updated, PathLegUpdateType lengthChange) throws Exception { - // TODO: this method is not symmetric with updatePathLegNext, which may alter lengthChange parameter? UpdateStruct2 us = createUS(start, Direction.PREVIOUS, 0, new ArrayList(), updated); -// if (lengthChange == PathLegUpdateType.NONE) { -// if (start.equals(updated)) -// lengthChange = PathLegUpdateType.NEXT; -// else if (us.end.equals(updated)) -// lengthChange = PathLegUpdateType.PREV; -// } if (us == null) { System.out.println("Null update struct " + start); return; @@ -476,11 +461,27 @@ public class PipingRules { } private static void updatePathLeg(UpdateStruct2 u, PathLegUpdateType lengthChange) throws Exception { + boolean rs = true; + boolean re = true; + if (lengthChange == PathLegUpdateType.NONE) { + rs = false; + re = false; + } + updatePathLeg(u, lengthChange, rs, re); + } + + private static void updatePathLeg(UpdateStruct2 u, PathLegUpdateType lengthChange, boolean rs, boolean re) throws Exception { int directed = 0; if (asDirected(u.start, Direction.NEXT)) directed++; if (asDirected(u.end, Direction.PREVIOUS)) directed++; + if (rs) + u.start.getPipelineComponent().setError(null); + if (re) + u.end.getPipelineComponent().setError(null); + for (PipeControlPoint pcp : u.list) + pcp.getPipelineComponent().setError(null); switch (directed) { case 0: updateFreePathLeg(u, lengthChange); @@ -512,10 +513,12 @@ public class PipingRules { if (checkSizes) { // create offsets for leg ends. - MathTools.mad(start, u.dir, u.start.getInlineLength()); - MathTools.mad(end, u.dir, -u.end.getInlineLength()); + if (u.start.isTurn()) + MathTools.mad(start, u.dir, u.start.getInlineLength()); + if (u.end.isTurn()) + MathTools.mad(end, u.dir, -u.end.getInlineLength()); } - + boolean recalcline = false; if (!u.hasOffsets) { @@ -533,16 +536,28 @@ public class PipingRules { return; ArrayList pathLegPoints = new ArrayList(); + ArrayList fixedLengthPoints = new ArrayList(); pathLegPoints.add(u.start); + for (PipeControlPoint icp : u.list) { // updateInlineControlPoint(icp, u.startPoint, // u.endPoint,u.dir); updateBranchControlPointBranches(icp); pathLegPoints.add(icp); + if (!icp.isVariableLength()) + fixedLengthPoints.add(icp); } pathLegPoints.add(u.end); - // TODO : values can be cached in the loop + // updateInlineControlPoint keeps components between path leg ends, but does not ensure that fixed length components do no overlap each other + + for (int i = 0; i < fixedLengthPoints.size(); i++) { + PipeControlPoint prev = i == 0 ? null : fixedLengthPoints.get(i-1); + PipeControlPoint curr = fixedLengthPoints.get(i); + PipeControlPoint next = i == fixedLengthPoints.size() -1 ? null : fixedLengthPoints.get(i+1); + updateFixedLength(curr, prev, next, start,end, u.dir); + } + for (int i = 0; i < pathLegPoints.size(); i++) { PipeControlPoint icp = pathLegPoints.get(i); @@ -645,48 +660,72 @@ public class PipingRules { if (recalcline) { u.list.clear(); u.start.findNextEnd(u.list); + } + if (checkSizes) { + double pathLegLength = MathTools.distance(u.startPoint, u.endPoint); + double availableLength = pathLegLength; + if (u.start.isTurn()) + availableLength -= u.start.getInlineLength(); + if (u.end.isTurn()) + availableLength -= u.end.getInlineLength(); + for (PipeControlPoint pcp : u.list) { + if (!pcp.isVariableLength()) + availableLength-= pcp.getLength(); + } + if (availableLength < 0.0) { + u.start.getPipelineComponent().setError("Not enough available space"); + u.end.getPipelineComponent().setError("Not enough available space"); + for (PipeControlPoint pcp : u.list) + pcp.getPipelineComponent().setError("Not enough available space"); + } +// System.out.println(u.start.getPipelineComponent().toString() + " " + pathLegLength + " " + availableLength + " " + u.end.getPipelineComponent().toString() + " " + u.start.getInlineLength() + " " + u.end.getInlineLength()); } } + private static void updateFixedLength(PipeControlPoint icp, PipeControlPoint prev, PipeControlPoint next, Vector3d s, Vector3d e, Vector3d dir) { + if (prev != null) { + checkOverlap(icp, prev); + } + if (next != null) + checkOverlap(icp, next); + } + + private static void checkOverlap(PipeControlPoint icp, PipeControlPoint prev) { + double d = MathTools.distance(prev.getWorldPosition(), icp.getWorldPosition()); + double r = icp.getInlineLength() + prev.getInlineLength(); + if (d < r) { + if (icp.getPipelineComponent().getError() == null) + icp.getPipelineComponent().setError("Overlapping"); + if (prev.getPipelineComponent().getError() == null) + prev.getPipelineComponent().setError("Overlapping"); + } + } + private static boolean updateVariableLength(PipeControlPoint icp, PipeControlPoint prev, PipeControlPoint next) { Vector3d prevPos = prev.getWorldPosition(); Vector3d nextPos = next.getWorldPosition(); Vector3d dir = new Vector3d(nextPos); dir.sub(prevPos); - double l = dir.lengthSquared(); // distance between - // control points - // (square) - double l2prev = prev.getInlineLength(); // distance - // taken - // by - // components + double l = dir.length(); // distance between control points + double l2prev = prev.getInlineLength(); // distance taken by components double l2next = next.getInlineLength(); double l2 = l2prev + l2next; - double l2s = MathTools.square(l2); - if (l2s < l) { // check if there is enough space for - // variable length component. + double length = l - l2; // true length of the variable length component + if (length >= MIN_INLINE_LENGTH) { // check if there is enough space for variable length component. // components fit 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.scale(length * 0.5 + l2prev); // calculate center position of the component dir.add(prevPos); icp.setWorldPosition(dir); icp.setLength(length); return false; } else { - // components leave no space to the component and it - // must be removed - + // components leave no space to the component and it must be removed if (icp.isDeletable()) { if (!allowInsertRemove) { - icp.setLength(0.0001); + icp.setLength(MIN_INLINE_LENGTH); + icp.getPipelineComponent().setError("Not enough available space"); triedIR = true; return false; } @@ -694,6 +733,9 @@ public class PipingRules { System.out.println("PipingRules.updateVariableLength removing " + icp); icp._remove(); return true; + } else { + icp.setLength(MIN_INLINE_LENGTH); + icp.getPipelineComponent().setError("Not enough available space"); } return false; } @@ -712,12 +754,8 @@ public class PipingRules { 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 + 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); insertStraight(prev, icp, dir, length); return true; diff --git a/org.simantics.plant3d/src/org/simantics/plant3d/utils/P3DUtil.java b/org.simantics.plant3d/src/org/simantics/plant3d/utils/P3DUtil.java index 18d5b2cd..055ffa11 100644 --- a/org.simantics.plant3d/src/org/simantics/plant3d/utils/P3DUtil.java +++ b/org.simantics.plant3d/src/org/simantics/plant3d/utils/P3DUtil.java @@ -253,16 +253,17 @@ public class P3DUtil { } } - public static void finalizeDBLoad2(P3DRootNode rootNode) throws Exception{ - PipingRules.setEnabled(true); + public static void finalizeDBLoad2(P3DRootNode rootNode) throws Exception { + PipingRules.setEnabled(true); for (INode node : rootNode.getChild()) { if (node instanceof PipeRun) { - PipeRun run = (PipeRun)node; + PipeRun run = (PipeRun) node; for (PipeControlPoint pcp : run.getControlPoints()) - PipingRules.positionUpdate(pcp); - //PipingRules.requestUpdate(pcp); + if (pcp.asPathLegEnd()) + PipingRules.requestUpdate(pcp); } } - } + PipingRules.update(); + } } -- 2.45.2