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 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 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_END = 2;
private static final int REMOVE_BOTH = 3;
-// private P3DRootNode root;
-
-// public PipingRules(P3DRootNode root) {
-// this.root = root;
-// }
+ // 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;
- private static List<PipeControlPoint> updates = new ArrayList<PipeControlPoint>();
+ private static List<PipeControlPoint> requestUpdates = new ArrayList<PipeControlPoint>();
+ private static List<PipeControlPoint> currentUpdates = new ArrayList<PipeControlPoint>();
- 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 (!PipingRules.enabled)
+ return;
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 (!PipingRules.enabled)
+ return false;
+
+ if (requestUpdates.size() == 0)
return false;
- List<PipeControlPoint> temp = new ArrayList<PipeControlPoint>(updates.size());
- synchronized(mutex) {
- temp.addAll(updates);
- updates.clear();
+
+ List<PipeControlPoint> temp = new ArrayList<PipeControlPoint>(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;
}
}
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)
allowInsertRemove = allowIR;
triedIR = false;
validate(pcp.getPipeRun());
- if (pcp.isPathLegEnd()) {
- updatePathLegEndControlPoint(pcp); // FXIME: Rules won't work properly, if they are not run twice.
- updatePathLegEndControlPoint(pcp);
+ if (pcp.asPathLegEnd()) {
+ 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)
public static void setEnabled(boolean enabled) {
PipingRules.enabled = enabled;
if(!enabled)
- updates.clear();
+ currentUpdates.clear();
}
public static boolean isEnabled() {
return enabled;
}
-
-// private void commit() {
-// root.getNodeMap().commit();
-// }
public static class ExpandIterInfo {
// these two are turn control points
System.out.println("PipingRules.insertElbow() " + pcp1 + " " + pcp2 + " " + pos);
if (pcp1.getNext() == pcp2 && pcp2.getPrevious() == pcp1) {
- } else if (pcp1.getNext() == pcp2 && pcp1.isDualInline() && pcp2.getPrevious() == pcp1.getSubPoint().get(0)) {
- pcp1 = pcp1.getSubPoint().get(0);
+ } else if (pcp1.getNext() == pcp2 && pcp1.isDualInline() && pcp2.getPrevious() == pcp1.getDualSub()) {
+ pcp1 = pcp1.getDualSub();
} else if (pcp1.getPrevious() == pcp2 && pcp2.getNext() == pcp1) {
PipeControlPoint t = pcp1;
pcp1 = pcp2;
pcp2 = t;
- } else if (pcp2.isDualInline() && pcp1.getPrevious() == pcp2.getSubPoint().get(0) && pcp2.getNext() == pcp1) {
+ } else if (pcp2.isDualInline() && pcp1.getPrevious() == pcp2.getDualSub() && pcp2.getNext() == pcp1) {
PipeControlPoint t = pcp1;
- pcp1 = pcp2.getSubPoint().get(0);
+ pcp1 = pcp2.getDualSub();
pcp2 = t;
} else {
throw new RuntimeException();
TurnComponent elbow = ComponentUtils.createTurn((P3DRootNode)pcp1.getRootNode());
PipeControlPoint pcp = elbow.getControlPoint();
if (pcp1.isDualInline())
- pcp1 = pcp1.getSubPoint().get(0);
+ pcp1 = pcp1.getDualSub();
String name = pcp1.getPipeRun().getUniqueName("Elbow");
elbow.setName(name);
pcp1.getPipeRun().addChild(elbow);
System.out.println("PipingRules.insertStraight() " + pcp1 + " " + pcp2 + " " + pos);
if (pcp1.getNext() == pcp2 && pcp2.getPrevious() == pcp1) {
- } else if (pcp1.getNext() == pcp2 && pcp1.isDualInline() && pcp2.getPrevious() == pcp1.getSubPoint().get(0)) {
- pcp1 = pcp1.getSubPoint().get(0);
+ } else if (pcp1.getNext() == pcp2 && pcp1.isDualInline() && pcp2.getPrevious() == pcp1.getDualSub()) {
+ pcp1 = pcp1.getDualSub();
} else if (pcp1.getPrevious() == pcp2 && pcp2.getNext() == pcp1) {
PipeControlPoint t = pcp1;
pcp1 = pcp2;
pcp2 = t;
- } else if (pcp2.isDualInline() && pcp1.getPrevious() == pcp2.getSubPoint().get(0) && pcp2.getNext() == pcp1) {
+ } else if (pcp2.isDualInline() && pcp1.getPrevious() == pcp2.getDualSub() && pcp2.getNext() == pcp1) {
PipeControlPoint t = pcp1;
- pcp1 = pcp2.getSubPoint().get(0);
+ pcp1 = pcp2.getDualSub();
pcp2 = t;
} else {
throw new RuntimeException();
InlineComponent component = ComponentUtils.createStraight((P3DRootNode)pcp1.getRootNode());
PipeControlPoint scp = component.getControlPoint();
if (pcp1.isDualInline())
- pcp1 = pcp1.getSubPoint().get(0);
+ pcp1 = pcp1.getDualSub();
String name = pcp1.getPipeRun().getUniqueName("Pipe");
component.setName(name);
pcp1.getPipeRun().addChild(component);
InlineComponent component = ComponentUtils.createStraight((P3DRootNode)pcp.getRootNode());
PipeControlPoint scp = component.getControlPoint();
if (pcp.isDualInline() && direction == Direction.NEXT)
- pcp = pcp.getSubPoint().get(0);
+ pcp = pcp.getDualSub();
String name = pcp.getPipeRun().getUniqueName("Pipe");
component.setName(name);
pcp.getPipeRun().addChild(component);
}
private static void updatePathLegNext(PipeControlPoint start, PipeControlPoint updated, PathLegUpdateType lengthChange) throws Exception {
- ArrayList<PipeControlPoint> list = new ArrayList<PipeControlPoint>();
- 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;
- updatePathLegNext(start, list, end, updated, lengthChange);
+ UpdateStruct2 us = createUS(start, Direction.NEXT, 0, new ArrayList<ExpandIterInfo>(), updated);
+ if (us == null) {
+ System.out.println("Null update struct " + start);
+ return;
+ }
+ updatePathLeg(us, lengthChange);
}
-
- private static void updatePathLegNext(PipeControlPoint start, ArrayList<PipeControlPoint> list, PipeControlPoint end, PipeControlPoint updated, PathLegUpdateType lengthChange) throws Exception {
- updatePathLeg(start, list, end, false, 0, new ArrayList<ExpandIterInfo>(), updated, lengthChange);
+
+ private static void updatePathLegPrev(PipeControlPoint start, PipeControlPoint updated, PathLegUpdateType lengthChange) throws Exception {
+ UpdateStruct2 us = createUS(start, Direction.PREVIOUS, 0, new ArrayList<ExpandIterInfo>(), updated);
+ if (us == null) {
+ System.out.println("Null update struct " + start);
+ return;
+ }
+ updatePathLeg(us, lengthChange);
}
private static class UpdateStruct2 {
}
+ @SuppressWarnings("unused")
private static boolean calculateOffset(Vector3d startPoint, Vector3d endPoint, ArrayList<PipeControlPoint> list, Vector3d dir, Vector3d offset) {
boolean hasOffsets = false;
- dir.set(startPoint);
- dir.sub(endPoint);
- if (dir.lengthSquared() > MathTools.NEAR_ZERO)
- dir.normalize();
- offset.set(0.0, 0.0, 0.0);
+ List<PipeControlPoint> offsets = new ArrayList<PipeControlPoint>(list.size());
for (PipeControlPoint icp : list) {
if (icp.isOffset()) {
- hasOffsets = true;
- offset.add(icp.getSizeChangeOffsetVector(dir));
+ offsets.add(icp);
} else if (icp.isDualSub())
ErrorLogger.defaultLogError("Updating pipe run, found offset controlpoint " + icp, new Exception("ASSERT!"));
}
+ 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);
+ return false;
+ } else {
+ Vector3d sp = new Vector3d(startPoint);
+ Point3d ep = new Point3d(endPoint);
+ dir.set(ep);
+ dir.sub(sp);
+ double l = dir.lengthSquared();
+ if (l > MathTools.NEAR_ZERO)
+ dir.scale(1.0/Math.sqrt(l));
+ int iter = 100;
+ while (iter >= 0) {
+ iter--;
+ offset.set(0.0, 0.0, 0.0);
+
+ for (PipeControlPoint icp : offsets) {
+ Vector3d v = icp.getSizeChangeOffsetVector(dir);
+ offset.add(v);
+ }
+ Point3d nep = new Point3d(endPoint);
+ nep.sub(offset);
+ if (nep.distance(ep) < 0.0000000001) {
+ break;
+ }
+ ep = nep;
+ dir.set(ep);
+ dir.sub(sp);
+ l = dir.lengthSquared();
+ if (l > MathTools.NEAR_ZERO)
+ dir.scale(1.0/Math.sqrt(l));
+ }
+ hasOffsets = true;
+ }
+
+ if (DEBUG && hasOffsets)
+ System.out.println("calcOffset s:"+ startPoint + " e:" + endPoint + " d:" + dir + " o:"+offset) ;
return hasOffsets;
}
-
- /**
- * @param start
- * starting point of the pipe run
- * @param list
- * list of inline control points in the pipe run
- * @param end
- * ending point of the pipe run
- * @param reversed
- * boolean flag indicating wether start or end control point was
- * modified (if true then end point was modified)
- * @throws TransactionException
- */
- private static void updatePathLeg(PipeControlPoint start, ArrayList<PipeControlPoint> list, PipeControlPoint end, boolean reversed, int iter, ArrayList<ExpandIterInfo> toRemove, PipeControlPoint updated, PathLegUpdateType lengthChange) throws Exception {
+
+ private static UpdateStruct2 createUS(PipeControlPoint start, Direction direction, int iter, ArrayList<ExpandIterInfo> toRemove, PipeControlPoint updated) {
+ ArrayList<PipeControlPoint> list = new ArrayList<PipeControlPoint>();
+ PipeControlPoint end = null;
+ if (direction == Direction.NEXT) {
+ end = start.findNextEnd(list);
+ } else {
+ ArrayList<PipeControlPoint> prevList = new ArrayList<PipeControlPoint>();
+ PipeControlPoint tend = start.findPreviousEnd(prevList);
+ for (PipeControlPoint icp : prevList) {
+ if (icp.isDualSub()) {
+ list.add(0, icp.getParentPoint());
+ } else {
+ list.add(0, icp);
+ }
+ }
+ end = start;
+ start = tend;
+ }
if (start == end)
- return;
- // FIXME: direction is calculated wrong way!
+ return null;
boolean hasOffsets = false;
Vector3d offset = new Vector3d();
Vector3d startPoint = start.getWorldPosition();
Vector3d endPoint = end.getWorldPosition();
Vector3d dir = new Vector3d();
hasOffsets = calculateOffset(startPoint, endPoint, list, dir, offset);
- updatePathLeg(new UpdateStruct2(start, startPoint, list, end, endPoint, dir, offset, hasOffsets, iter, reversed, toRemove, updated), lengthChange);
-
+ return new UpdateStruct2(start, startPoint, list, end, endPoint, dir, offset, hasOffsets, iter, direction == Direction.PREVIOUS, toRemove, updated);
}
-
+
+ private static boolean asDirected(PipeControlPoint pcp, Direction direction) {
+ if (pcp.isDirected())
+ return true;
+ if (pcp.asFixedAngle()) {
+ if (!pcp._getReversed())
+ return direction == Direction.NEXT;
+ else
+ return direction == Direction.PREVIOUS;
+ }
+ return false;
+ }
+
+ private static Vector3d direction(PipeControlPoint pcp, Direction direction) {
+ return pcp.getDirection(direction);
+ }
+
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 (u.start.isDirected())
+ if (asDirected(u.start, Direction.NEXT))
directed++;
- if (u.end.isDirected())
+ 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 (DEBUG)
System.out.println("PipingRules.updateFreePipeRun " + u + " " + lengthChange);
checkExpandPathLeg(u, lengthChange);
- if (u.start.isInline() || u.end.isInline())
+ if (u.start.isInline() || u.end.isInline() || u.start.asFixedAngle()|| u.end.asFixedAngle())
processPathLeg(u, true, false);
}
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.
+ 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) {
- // 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);
+
+
+ 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<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
- for (int i = 1; i < pathLegPoints.size(); i++) {
+ // 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);
- PipeControlPoint prev;
- Vector3d prevPos;
- prev = pathLegPoints.get(i - 1);
- prevPos = prev.getWorldPosition();
- Vector3d currentPos = icp.getWorldPosition();
+ 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;
- Vector3d nextPos;
- next = pathLegPoints.get(i + 1);
- 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 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.
- // 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.add(prevPos);
- icp.setWorldPosition(dir);
- icp.setLength(length);
- } else {
- // components leave no space to the component and it
- // must be removed
- if (icp.isDeletable())
- icp._remove();
- }
+ if (prev != null && next != null) {
+
+ recalcline = recalcline | updateVariableLength(icp, prev, next);
} else {
// this is variable length component at the end of the
// 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.
- double currentLength = icp.getLength();
-
- 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();
-
- 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));
+ 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.
// I there is, we'll have to create new variable length
// component between them.
- 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 {
- u.endPoint.sub(u.offset);
- // FIXME : straights
+ } else { // with offset
+ Vector3d sp = new Vector3d(start);
+ Vector3d ep = new Vector3d(end);
+ ep.sub(u.offset);
+
+ ArrayList<PipeControlPoint> pathLegPoints = new ArrayList<PipeControlPoint>();
+ pathLegPoints.add(u.start);
+
for (PipeControlPoint icp : u.list) {
- updateInlineControlPoint(icp, u.startPoint, u.endPoint, u.dir);
+ updateInlineControlPoint(icp, sp, ep, u.dir);
updateBranchControlPointBranches(icp);
+ pathLegPoints.add(icp);
+ if (icp.isOffset()) {
+ // TODO : offset vector is already calculated and should be
+ // cached
+ Vector3d offset = icp.getSizeChangeOffsetVector(u.dir);
+ updateOffsetPoint(icp, offset);
+ sp.add(offset);
+ ep.add(offset);
+ }
+ }
+ pathLegPoints.add(u.end);
+
+ if (!checkSizes)
+ return;
+
+ sp = new Vector3d(u.startPoint);
+ ep = new Vector3d(u.endPoint);
+ ep.sub(u.offset);
+
+ for (int i = 0; i < pathLegPoints.size(); i++) {
+ PipeControlPoint icp = pathLegPoints.get(i);
+
+ 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.getDualSub();
+
+ if (icp.isVariableLength()) {
+ if (prev != null && next != null) {
+ recalcline = recalcline | updateVariableLength(icp, prev, next);
+
+ } else {
+ // this is variable length component at the end of the
+ // piperun.
+ // 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 != null ? prev : next);
+ }
+ } 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.
+ // 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
- u.offset = icp.getSizeChangeOffsetVector(u.dir);
- updateOffsetPoint(icp, u.offset);
- u.startPoint.add(u.offset);
- u.endPoint.add(u.offset);
+ Vector3d offset = icp.getSizeChangeOffsetVector(u.dir);
+ sp.add(offset);
+ ep.add(offset);
}
}
}
+ 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.length(); // distance between control points
+ double l2prev = prev.getInlineLength(); // distance taken by components
+ double l2next = next.getInlineLength();
+ double l2 = l2prev + l2next;
+ 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();
+ 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
+ if (icp.isDeletable()) {
+ if (!allowInsertRemove) {
+ icp.setLength(MIN_INLINE_LENGTH);
+ icp.getPipelineComponent().setError("Not enough available space");
+ triedIR = true;
+ return false;
+ }
+ if (DEBUG)
+ 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;
+ }
+ }
+
+ 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);
+ insertStraight(prev, icp, dir, length);
+ return true;
+ } else {
+ triedIR = true;
+ }
+ }
+ return false;
+ }
+
+ private static void updateVariableLengthEnd(PipeControlPoint icp, PipeControlPoint prev) {
+ 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 {
}
private static void checkExpandPathLeg(UpdateStruct2 u, PathLegUpdateType lengthChange) throws Exception {
- checkExpandPathLeg(u, lengthChange, false);
+ checkExpandPathLeg(u, lengthChange, u.updated.isInline() && u.updated.isOffset());
}
- private static void checkExpandPathLeg(UpdateStruct2 u, PathLegUpdateType lengthChange, boolean forceUpdate) throws Exception {
+ private static void checkExpandPathLeg(UpdateStruct2 u, PathLegUpdateType lengthChange, boolean updateEnds) throws Exception {
if (DEBUG)
System.out.println("PipingRules.checkExpandPathLeg() " + u + " " + lengthChange);
if (lengthChange != PathLegUpdateType.NONE) {
// FIXME : turns cannot be checked before inline cps are updated,
// since their position affects calculation of turns
- processPathLeg(u, forceUpdate, false);
+ processPathLeg(u, updateEnds, false);
int type = checkTurns(u, lengthChange);
if (type == REMOVE_NONE) {
- processPathLeg(u, forceUpdate, true);
+ processPathLeg(u, updateEnds, true);
} else {
expandPathLeg(u, type);
}
} else {
- processPathLeg(u, forceUpdate, true);
+ processPathLeg(u, updateEnds, true);
}
}
boolean dcpStart = false;
boolean inlineEnd = false;
Vector3d position;
- if (u.start.isDirected()) {
+ if (asDirected(u.start, Direction.NEXT)) {
dcp = u.start;
other = u.end;
position = u.startPoint;
inlineEnd = u.start.isInline();
}
- Vector3d directedDirection = dcp.getDirection();
+ Vector3d directedDirection = direction(dcp, dcpStart ? Direction.NEXT : Direction.PREVIOUS);
+ if (directedDirection == null) {
+ //updateTurnControlPointTurn(dcp, dcp.getPrevious(), dcp.getNext());
+ updateTurnControlPointTurn(dcp, null, null);
+ 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);
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) {
+ if (u.start.isInline() || u.end.isInline() || u.start.asFixedAngle() || u.end.asFixedAngle())
+ processPathLeg(u, true, false);
checkExpandPathLeg(u, lengthChange, inlineEnd);
} else {
if (other.isVariableAngle()) {
// TODO calculate needed space from next run end.
- if (mu[0] < 1.0) {
+ double space = spaceForTurn(other);
+ if (mu[0] < space) {
if (dcpStart) {
closest.set(u.startPoint);
} else {
closest.set(u.endPoint);
}
- closest.add(directedDirection);
+ Vector3d v = new Vector3d(directedDirection);
+ v.scale(space);
+ closest.add(v);
}
if (canMoveOther) {
position1offset.sub(u.offset);
Point3d position2offset = new Point3d(position2);
position2offset.add(u.offset);
- Vector3d dir1 = dcp1.getDirection();
- Vector3d dir2 = dcp2.getDirection();
+ 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);
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 {
}
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);
}
}
+
+ 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 ((TurnComponent)tcp.getPipelineComponent()).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);
// this won't work properly if inline control points are not updated
PipeControlPoint startPrev = u.start.getPrevious();
if (startPrev != null) {
- double a;
- if (!u.hasOffsets) {
- a = updateTurnControlPointTurn(u.start, startPrev, u.end);
- } else {
- Vector3d ep = new Vector3d(u.endPoint);
- ep.add(u.offset);
- a = updateTurnControlPointTurn(u.start, u.startPoint, startPrev.getPosition(), ep);
-
- }
+ double a = updateTurnControlPointTurn(u.start, null, u.dir);
if (a < MIN_TURN_ANGLE && u.start.isDeletable())
startRemoved = true;
else if (lengthChange == PathLegUpdateType.PREV || lengthChange == PathLegUpdateType.PREV_S) {
PipeControlPoint endNext = u.end.getNext();
if (endNext != null) {
- double a;
- if (!u.hasOffsets) {
- a = updateTurnControlPointTurn(u.end, u.start, endNext);
- } else {
- Vector3d sp = new Vector3d(u.startPoint);
- sp.sub(u.offset);
- a = updateTurnControlPointTurn(u.end, u.endPoint, sp, endNext.getPosition());
- }
+ // TODO: u.end, u.dir, null
+ double a = updateTurnControlPointTurn(u.end, null, null);
if (a < MIN_TURN_ANGLE && u.end.isDeletable())
endRemoved = true;
else if (lengthChange == PathLegUpdateType.NEXT || lengthChange == PathLegUpdateType.NEXT_S) {
private static void processPathLeg(UpdateStruct2 u, boolean updateEnds, boolean updateInline) throws Exception {
if (DEBUG)
- System.out.println("PipingRules.processPathLeg " + u.start + " " + u.end);
+ System.out.println("PipingRules.processPathLeg " + (updateEnds ? "ends " : "") + (updateInline ? "inline " : "") + u.start + " " + u.end);
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();
}
}
- // 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);
if (updateEnds) {
if (u.start.isTurn()) {
- updateTurnControlPointTurn(u.start, u.start.getPrevious(), u.start.getNext());
+ //updateTurnControlPointTurn(u.start, u.start.getPrevious(), u.start.getNext());
+ updateTurnControlPointTurn(u.start, null, null);
// updatePathLegPrev(u.start, u.start, PathLegUpdateType.NONE);
} else if (u.start.isEnd()) {
updateEndComponentControlPoint(u.start, u.startPoint, u.endPoint);
updateControlPointOrientation(u.start);
}
if (u.end.isTurn()) {
- updateTurnControlPointTurn(u.end, u.end.getPrevious(), u.end.getNext());
+ //updateTurnControlPointTurn(u.end, u.end.getPrevious(), u.end.getNext());
+ updateTurnControlPointTurn(u.end, null, null);
// updatePathLegNext(u.end, u.end, PathLegUpdateType.NONE);
} else if (u.end.isEnd()) {
updateEndComponentControlPoint(u.end, u.startPoint, u.endPoint);
// end,Point3d endPoint, Vector3d dir, boolean hasOffsets,int iter, boolean
// reversed, ArrayList<ExpandIterInfo> toRemove) throws TransactionException
// {
+ @SuppressWarnings("unused")
private static void processPathLegNoOffset(UpdateStruct2 u) throws Exception {
if (DEBUG)
System.out.println("PipingRules.processPathLeg " + u.start + " " + u.end);
private static void updateOffsetPoint(PipeControlPoint sccp, Vector3d offset) {
Vector3d world = sccp.getWorldPosition();
world.add(offset);
- PipeControlPoint ocp = sccp.getSubPoint().iterator().next();
+ PipeControlPoint ocp = sccp.getDualSub();
ocp.setWorldPosition(world);
}
- private static void updatePathLegPrev(PipeControlPoint start, PipeControlPoint updated, PathLegUpdateType lengthChange) throws Exception {
- ArrayList<PipeControlPoint> list = new ArrayList<PipeControlPoint>();
- PipeControlPoint end = start.findPreviousEnd(list);
- updatePathLegPrev(start, list, end, updated, lengthChange);
- }
-
- private static void updatePathLegPrev(PipeControlPoint start, ArrayList<PipeControlPoint> list, PipeControlPoint end, PipeControlPoint updated, PathLegUpdateType lengthChange) throws Exception {
- // reverses the list
- ArrayList<PipeControlPoint> nextList = new ArrayList<PipeControlPoint>();
- 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<ExpandIterInfo>(), updated, lengthChange);
-
- }
-
/**
* Updates InlineControlPoints position when straight pipe's end(s) have
* been changed)
* @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.getChildPoints())
+ 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);
private static void updateEndComponentControlPoint(PipeControlPoint ecp, Vector3d start, Vector3d end) throws Exception {
if (DEBUG)
System.out.println("PipingRules.updateEndComponentControlPoint() " + ecp);
- // PipeControlPoint next = ecp.getNext();
- // PipeControlPoint prev = ecp.getPrevious();
- // if (next != null) {
- // end = G3DTools.getPoint(next.getLocalPosition());
- // start = G3DTools.getPoint(ecp.getLocalPosition());
- // } else if (prev != null) {
- // end = G3DTools.getPoint(ecp.getLocalPosition());
- // start = G3DTools.getPoint(prev.getLocalPosition());
- // } else {
- // // TODO : warning?
- // return;
- // }
- // Vector3d dir = new Vector3d (end);
- // dir.sub(start);
- // dir.normalize();
- // G3DTools.setTuple(ecp.getDirection(), dir);
- if (!ecp.isFixed())
- updateControlPointOrientation(ecp);
-
- for (PipeControlPoint pcp : ecp.getSubPoint()) {
+ //FIXME : end control point cannot be fixed!
+ //if (!ecp.isFixed())
+ updateControlPointOrientation(ecp);
+
+ for (PipeControlPoint pcp : ecp.getChildPoints()) {
// TODO update position
updatePathLegEndControlPoint(pcp);
}
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);
}
System.out.println("PipingRules.updateBranchControlPointBranches() " + bcp);
if (bcp.isDualInline())
return;
- Collection<PipeControlPoint> branches = bcp.getSubPoint();
+ Collection<PipeControlPoint> branches = bcp.getChildPoints();
if (branches.size() == 0) {
if (DEBUG)
System.out.println("No Branches found");
}
}
- /**
- * Recalculates turn control point's internal data (turn angle and offset)
- *
- * @param tcp
- * @param prev
- * @param next
- */
- private static double updateTurnControlPointTurn(PipeControlPoint tcp, PipeControlPoint prev, PipeControlPoint next) {
- if (DEBUG)
- System.out.println("PipingTools.updateTurnControlPointTurn()" + tcp);
- if (next == null || prev == null)
- return Math.PI; // FIXME : argh
- Vector3d middlePoint = tcp.getWorldPosition();
- Vector3d nextPoint = next.getWorldPosition();
- Vector3d prevPoint = prev.getWorldPosition();
- return updateTurnControlPointTurn(tcp, middlePoint, prevPoint, nextPoint);
- }
-
- /**
- * Recalculates turn control point's internal data (turn angle and offset)
- *
- * @param tcp
- * @param middlePoint
- * @param nextPoint
- * @param prevPoint
- */
- private static double updateTurnControlPointTurn(PipeControlPoint tcp, Vector3d middlePoint, Vector3d prevPoint, Vector3d nextPoint) {
-
- Vector3d dir1 = new Vector3d(middlePoint);
- dir1.sub(prevPoint);
- Vector3d dir2 = new Vector3d(nextPoint);
- dir2.sub(middlePoint);
- if (DEBUG)
- System.out.println("PipingTools.updateTurnControlPointTurn " + tcp + " " + prevPoint + " " + middlePoint + " " + nextPoint);
- return updateTurnControlPointTurn(tcp, dir1, dir2);
- }
-
- private static double updateTurnControlPointTurn(PipeControlPoint tcp, Vector3d dir1, Vector3d dir2) {
- double turnAngle = dir1.angle(dir2);
-
- double angle = Math.PI - turnAngle;
-
- Vector3d turnAxis = new Vector3d();
- turnAxis.cross(dir1, dir2);
- if (turnAxis.lengthSquared() > MathTools.NEAR_ZERO) {
- double elbowRadius = tcp.getPipelineComponent().getPipeRun().getTurnRadius();
- double R = elbowRadius / Math.tan(angle * 0.5);
+ private static double updateTurnControlPointTurn(PipeControlPoint tcp, Vector3d prev, Vector3d next) {
+ if (next == null) {
+ UpdateStruct2 us = createUS(tcp, Direction.NEXT, 0, new ArrayList<PipingRules.ExpandIterInfo>(), tcp);
+ if (us != null)
+ next = us.dir;
+ }
+ if (prev == null) {
+ UpdateStruct2 us = createUS(tcp, Direction.PREVIOUS, 0, new ArrayList<PipingRules.ExpandIterInfo>(), tcp);
+ if (us != null) {
+ prev = us.dir;
+ }
+ }
+
+ if (!tcp.asFixedAngle()) {
+
- turnAxis.normalize();
- tcp.setTurnAngle(turnAngle);
- tcp.setLength(R);// setComponentOffsetValue(R);
- tcp.setTurnAxis(turnAxis);
-// tcp.setPosition(tcp.getPosition());
+ if (next == null || prev == null) {
+ if (tcp.getTurnAngle() != null)
+ return tcp.getTurnAngle();
+ return Math.PI; // FIXME : argh
+ }
+ 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);
+
+ turnAxis.normalize();
+ tcp.setTurnAngle(turnAngle);
+ tcp.setLength(R);// setComponentOffsetValue(R);
+ tcp.setTurnAxis(turnAxis);
+ // tcp.setPosition(tcp.getPosition());
+ } else {
+ turnAngle = 0.0;
+ tcp.setTurnAngle(0.0);
+ tcp.setLength(0.0);
+ tcp.setTurnAxis(new Vector3d(MathTools.Y_AXIS));
+ }
+
+ updateControlPointOrientation(tcp);
+
+ if (DEBUG)
+ System.out.println("PipingTools.updateTurnControlPointTurn " + prev + " " + next + " " + turnAngle + " " + turnAxis);
+ return turnAngle;
} else {
- turnAngle = 0.0;
- tcp.setTurnAngle(0.0);
- tcp.setLength(0.0);
- tcp.setTurnAxis(MathTools.Y_AXIS);
+
+ 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 = null;
+ if (!tcp._getReversed()) {
+ dir = prev;
+ } else {
+ dir = next;
+ dir.negate();
+ }
+ if (dir == null) {
+ return Math.PI; // FIXME : argh
+ }
+
+ Quat4d q = PipeControlPoint.getControlPointOrientationQuat(dir, tcp.getRotationAngle() != null ? tcp.getRotationAngle() : 0.0);
+ Vector3d v = new Vector3d();
+ MathTools.rotate(q, MathTools.Y_AXIS,v);
+ tcp.setTurnAxis(v);
+ tcp.setWorldOrientation(q);
+ if (tcp.getTurnAngle() != null)
+ return tcp.getTurnAngle();
+ return Math.PI; // FIXME : argh
}
- updateControlPointOrientation(tcp);
- if (DEBUG)
- System.out.println("PipingTools.updateTurnControlPointTurn " + dir1 + " " + dir2 + " " + turnAngle + " " + turnAxis);
- return turnAngle;
+
+
}
public static List<PipeControlPoint> getControlPoints(PipeRun pipeRun) {
PipeControlPoint pcp = pipeRun.getControlPoints().iterator().next();
while (pcp.getPrevious() != null) {
PipeControlPoint prev = pcp.getPrevious();
- if (prev.getPipeRun() != pipeRun)
- break;
+ if (prev.getPipeRun() != pipeRun && prev.getPipeRun() != null) { // bypass possible corruption
+ break;
+ }
pcp = prev;
}
if (pcp.isDualSub()) {
}
public static void reverse(PipeRun pipeRun) {
- List<PipeControlPoint> list = getControlPoints(pipeRun);
+
+ while (true) {
+ List<PipeControlPoint> points = getControlPoints(pipeRun);
+ PipeControlPoint pcp = points.get(0);
+ if (pcp.isSizeChange() && pcp.getChildPoints().size() > 0) {
+ pipeRun = pcp.getPipeRun();
+ } else {
+ break;
+ }
+ }
+ List<PipeRun> all = new ArrayList<PipeRun>();
+ List<List<PipeControlPoint>> pcps = new ArrayList<List<PipeControlPoint>>();
+ while (true) {
+ all.add(pipeRun);
+ List<PipeControlPoint> points = getControlPoints(pipeRun);
+ pcps.add(points);
+ PipeControlPoint pcp = points.get(points.size()-1);
+ if (pcp.getChildPoints().size() > 0) {
+ PipeRun pipeRun2 = pcp.getChildPoints().get(0).getPipeRun();
+ if (pipeRun == pipeRun2)
+ break;
+ else
+ pipeRun = pipeRun2;
+ } else {
+ break;
+ }
+ }
+ for (int i = 0 ; i < all.size(); i++) {
+ List<PipeControlPoint> list = pcps.get(i);
+ _reverse(list);
+ }
+ for (int i = 0 ; i < all.size(); i++) {
+ boolean last = i == all.size() - 1;
+ List<PipeControlPoint> list = pcps.get(i);
+
+ if (!last) {
+ List<PipeControlPoint> list2 = pcps.get(i+1);
+ PipeControlPoint prev = list.get(list.size()-1);
+ PipeControlPoint next = list2.get(0);
+ System.out.println();
+ if (prev == next) {
+ // Reverse the component on the boundary.
+ InlineComponent ic = (InlineComponent)prev.getPipelineComponent();
+ PipeRun r1 = ic.getPipeRun();
+ PipeRun r2 = ic.getAlternativePipeRun();
+ if (r1 == null || r2 == null)
+ throw new RuntimeException("Components on PipeRun changes should refer to bot PipeRuns");
+ ic.deattach();
+ r2.addChild(ic);
+ ic.setPipeRun(r2);
+ ic.setAlternativePipeRun(r1);
+ } else {
+ throw new RuntimeException("PipeRun changes should contain shared control points");
+ }
+
+ }
+ }
+
+ }
+
+ private static void _reverse(List<PipeControlPoint> list) {
if (list.size() <= 1)
return; // nothing to do.
PipeControlPoint current = list.get(i);
PipeControlPoint currentSub = null;
if (current.isDualInline())
- currentSub = current.getSubPoint().get(0);
+ currentSub = current.getDualSub();
if (first) {
PipeControlPoint next = list.get(i+1);
if (next.isDualInline())
- next = next.getSubPoint().get(0);
- current.setNext(null);
+ next = next.getDualSub();
+ if (current.getNext() == next)
+ current.setNext(null);
current.setPrevious(next);
if (currentSub != null) {
- currentSub.setNext(null);
- currentSub.setPrevious(next);
+ if (currentSub.getNext() == next)
+ currentSub.setNext(null);
+ currentSub.setPrevious(next);
}
} else if (last) {
PipeControlPoint prev = list.get(i-1);
- current.setPrevious(null);
+ if (current.getPrevious() == prev)
+ current.setPrevious(null);
current.setNext(prev);
if (currentSub != null) {
- currentSub.setPrevious(null);
- currentSub.setNext(prev);
+ if (currentSub.getPrevious() == prev)
+ currentSub.setPrevious(null);
+ currentSub.setNext(prev);
}
} else {
PipeControlPoint prev = list.get(i-1);
PipeControlPoint next = list.get(i+1);
if (next.isDualInline())
- next = next.getSubPoint().get(0);
+ next = next.getDualSub();
current.setPrevious(next);
if (currentSub != null) {
currentSub.setPrevious(next);
- currentSub.setNext(prev);
+ currentSub.setNext(prev);
}
}
- }
- }
-
- public static void merge(PipeRun run1, PipeRun r2) {
- Map<PipeControlPoint, Vector3d> positions = new HashMap<PipeControlPoint, Vector3d>();
- Map<PipeControlPoint, Quat4d> orientations = new HashMap<PipeControlPoint, Quat4d>();
- for (PipeControlPoint pcp : r2.getControlPoints()) {
- positions.put(pcp, pcp.getWorldPosition());
- orientations.put(pcp, pcp.getWorldOrientation());
- }
- for (PipeControlPoint pcp : r2.getControlPoints()) {
- r2.deattachChild(pcp);
- run1.addChild(pcp);
- PipelineComponent component = pcp.getPipelineComponent();
- if (component != null) {
- if (!(component instanceof Nozzle)) {
- component.deattach();
- run1.addChild(component);
- } else {
- Nozzle n = (Nozzle)component;
- n.setPipeRun(run1);
- }
+ //if (current.isTurn() && current.isFixed()) {
+ if (current.asFixedAngle()) {
+ current.setReversed(!current._getReversed());
}
+ if (current.isInline() && current.isReverse()) {
+ current.setReversed(!current._getReversed());
+ }
}
- r2.remove();
-
}
+
+
public static void validate(PipeRun pipeRun) {
if (pipeRun == null)
return;
Collection<PipeControlPoint> 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<PipeControlPoint> runPcps = getControlPoints(pipeRun);
if (runPcps.size() != count) {
- System.out.println("Run is not connected");
+ System.out.println("Run " + pipeRun.getName() + " contains unconnected control points, found " + runPcps.size() + " connected, " + pcps.size() + " total.");
+ for (PipeControlPoint pcp : pcps) {
+ if (!runPcps.contains(pcp)) {
+ System.out.println("Unconnected " + pcp + " " + pcp.getPipelineComponent());
+ }
+ }
+ }
+ for (PipeControlPoint pcp : pcps) {
+ if (pcp.getPipeRun() == null) {
+ System.out.println("PipeRun ref missing " + pcp + " " + pcp.getPipelineComponent());
+ }
+ if (!pcp.isDirected() && pcp.getNext() == null && pcp.getPrevious() == null)
+ System.out.println("Orphan undirected " + pcp + " " + pcp.getPipelineComponent());
}
for (PipeControlPoint pcp : pcps) {
if (pcp.getParentPoint() == null) {
PipeControlPoint sub = null;
if (pcp.isDualInline())
- sub = pcp.getSubPoint().get(0);
+ sub = pcp.getDualSub();
PipeControlPoint next = pcp.getNext();
PipeControlPoint prev = pcp.getPrevious();
if (next != null) {
}
public static void splitVariableLengthComponent(PipelineComponent newComponent, InlineComponent splittingComponent, boolean assignPos) throws Exception{
- assert(!splittingComponent.getControlPoint().isFixed());
- assert(!(newComponent instanceof InlineComponent && !newComponent.getControlPoint().isFixed()));
+ assert(!splittingComponent.getControlPoint().isFixedLength());
+ assert(!(newComponent instanceof InlineComponent && !newComponent.getControlPoint().isFixedLength()));
PipeControlPoint newCP = newComponent.getControlPoint();
PipeControlPoint splittingCP = splittingComponent.getControlPoint();
PipeControlPoint nextCP = splittingCP.getNext();
/* there are many different cases to insert new component when
it splits existing VariableLengthinlineComponent.
-
- 1. VariableLengthComponet is connected from both sides:
- - insert new component between VariableLength component and component connected to it
- - insert new VariableLengthComponent between inserted component and component selected in previous step
+
+ 1. VariableLengthComponet is connected from both sides:
+ - insert new component between VariableLength component and component connected to it
+ - insert new VariableLengthComponent between inserted component and component selected in previous step
2. VariableLengthComponent is connected from one side
- - Use previous case or:
- - Insert new component to empty end
- - Insert new VariableLength component to inserted components empty end
-
+ - Use previous case or:
+ - Insert new component to empty end
+ - Insert new VariableLength component to inserted components empty end
+
3. VariableLength is not connected to any component.
- - Should not be possible, at least in current implementation.
- - Could be done using second case
+ - Should not be possible, at least in current implementation.
+ - Could be done using second case
*/
// this should not be possible
throw new RuntimeException("VariableLengthComponent " + splittingComponent + " is not connected to anything.");
}
- double reservedLength = splittingComponent.getControlPoint().getLength();
double newLength = newComponent.getControlPoint().getLength();
vn.interpolate(next, 0.5);
- PipeControlPoint newVariableLengthCP = null;//insertStraight(pcp1, pcp2, pos, length);
if (nextCP == null) {
newCP.insert(splittingCP, Direction.NEXT);
- newVariableLengthCP = insertStraight(newCP, Direction.NEXT, new Vector3d(vn), ln);
+ insertStraight(newCP, Direction.NEXT, new Vector3d(vn), ln);
splittingCP.setWorldPosition(new Vector3d(vp));
// ControlPointTools.setWorldPosition(splittingCP, vp);
// splittingCP.setRelatedScalarDouble(ProcessResource.plant3Dresource.HasLength, lp);
} else if (prevCP == null) {
newCP.insert(splittingCP, Direction.PREVIOUS);
- newVariableLengthCP = insertStraight(newCP, Direction.PREVIOUS, new Vector3d(vp), lp);
+ insertStraight(newCP, Direction.PREVIOUS, new Vector3d(vp), lp);
splittingCP.setWorldPosition(new Vector3d(vn));
// splittingCP.setRelatedScalarDouble(ProcessResource.plant3Dresource.HasLength, ln);
} else {
newCP.insert(splittingCP, nextCP);
- newVariableLengthCP = insertStraight(newCP, nextCP, new Vector3d(vn), ln);
+ insertStraight(newCP, nextCP, new Vector3d(vn), ln);
splittingCP.setWorldPosition(new Vector3d(vp));
// splittingCP.setRelatedScalarDouble(ProcessResource.plant3Dresource.HasLength, lp);
}
public static void addSizeChange(boolean reversed, PipeRun pipeRun, PipeRun other, InlineComponent reducer, PipeControlPoint previous, PipeControlPoint next) {
PipeControlPoint pcp = reducer.getControlPoint();
- PipeControlPoint ocp = pcp.getSubPoint().get(0);
+ PipeControlPoint ocp = pcp.getDualSub();
if (!reversed) {
String name = pipeRun.getUniqueName("Reducer");
reducer.setName(name);