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;
private Image elbowImage;
private Image componentImage;
+
+ private Image nozzleErrorImage;
+ private Image pipeErrorImage;
+ private Image tankErrorImage;
+ private Image elbowErrorImage;
+ private Image componentErrorImage;
+
public P3DContentOutlinePage(ParentNode<? extends INode> rootNode, NodeSelectionProvider2<Resource,INode> 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
if (element instanceof PipelineComponent) {
PipelineComponent comp = (PipelineComponent)element;
if (comp instanceof TurnComponent) {
- return elbowImage;
+ if (comp.getError() == null)
+ return elbowImage;
+ else
+ return elbowErrorImage;
} else if (comp instanceof EndComponent) {
- return componentImage;
+ if (comp.getError() == null)
+ return componentImage;
+ else
+ return componentErrorImage;
} else if (comp instanceof Nozzle) {
- return nozzleImage;
+ if (comp.getError() == null)
+ return nozzleImage;
+ else
+ return nozzleErrorImage;
} else if (comp.getControlPoint().isFixed()) {
- return componentImage;
+ if (comp.getError() == null)
+ return componentImage;
+ else
+ return componentErrorImage;
}
- return pipeImage;
+ if (comp.getError() == null)
+ return pipeImage;
+ else
+ return pipeErrorImage;
} else if (element instanceof Equipment) {
return tankImage;
} else if (element instanceof PipeRun) {
import java.util.ArrayList;
import java.util.Collection;
-import java.util.HashMap;
import java.util.List;
-import java.util.Map;
import javax.vecmath.Point3d;
import javax.vecmath.Quat4d;
import org.simantics.g3d.math.MathTools;
import org.simantics.plant3d.scenegraph.InlineComponent;
-import org.simantics.plant3d.scenegraph.Nozzle;
import org.simantics.plant3d.scenegraph.P3DRootNode;
import org.simantics.plant3d.scenegraph.PipeRun;
import org.simantics.plant3d.scenegraph.PipelineComponent;
private static final boolean DEBUG = false;
private static final boolean DUMMY = false;
- 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 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 double MIN_INLINE_LENGTH = 0.001; // Minimum length of inline components, when component removal is not allowed.
private static final int REMOVE_NONE = 0;
private static final int REMOVE_START = 1;
private static final int REMOVE_BOTH = 3;
+ // PathLeg iteration indicator. NEXT_S > 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;
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)
public static boolean isEnabled() {
return enabled;
}
-
-// private void commit() {
-// root.getNodeMap().commit();
-// }
public static class ExpandIterInfo {
// these two are turn control points
}
private static void updatePathLegNext(PipeControlPoint start, PipeControlPoint updated, PathLegUpdateType lengthChange) throws Exception {
-
UpdateStruct2 us = createUS(start, Direction.NEXT, 0, new ArrayList<ExpandIterInfo>(), 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;
}
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<ExpandIterInfo>(), 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;
}
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);
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) {
return;
ArrayList<PipeControlPoint> pathLegPoints = new ArrayList<PipeControlPoint>();
+ ArrayList<PipeControlPoint> fixedLengthPoints = new ArrayList<PipeControlPoint>();
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);
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;
}
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;
}
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;