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;
import org.simantics.plant3d.scenegraph.TurnComponent;
import org.simantics.plant3d.scenegraph.controlpoint.PipeControlPoint.Direction;
import org.simantics.plant3d.utils.ComponentUtils;
+import org.simantics.utils.datastructures.Pair;
import org.simantics.utils.ui.ErrorLogger;
public class PipingRules {
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.0005; // 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;
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 (updateMutex) {
if (!requestUpdates.contains(pcp))
}
public static boolean update() throws Exception {
+ if (!PipingRules.enabled)
+ return false;
+
if (requestUpdates.size() == 0)
return false;
allowInsertRemove = allowIR;
triedIR = false;
validate(pcp.getPipeRun());
- if (pcp.isPathLegEnd()) {
+ if (pcp.getParentPoint() != null)
+ pcp = pcp.getParentPoint();
+ 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
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 {
-
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;
}
updatePathLeg(us, lengthChange);
}
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;
+ }
updatePathLeg(us, lengthChange);
}
}
- private static boolean calculateOffset(Vector3d startPoint, Vector3d endPoint, ArrayList<PipeControlPoint> list, Vector3d dir, Vector3d offset) {
- boolean hasOffsets = false;
- List<PipeControlPoint> offsets = new ArrayList<PipeControlPoint>(list.size());
- for (PipeControlPoint icp : list) {
- if (icp.isOffset()) {
- offsets.add(icp);
- } else if (icp.isDualSub())
- ErrorLogger.defaultLogError("Updating pipe run, found offset controlpoint " + icp, new Exception("ASSERT!"));
- }
+ private static boolean calculateDirectedOffset(Vector3d startPoint, Vector3d endPoint, PipeControlPoint start, ArrayList<PipeControlPoint> list, PipeControlPoint end, Vector3d dir, Vector3d offset) {
+ return calculateOffset(startPoint, endPoint, start, list, end, dir, offset, true);
+ }
+
+ private static boolean calculateOffset(Vector3d startPoint, Vector3d endPoint, PipeControlPoint start, ArrayList<PipeControlPoint> list, PipeControlPoint end, Vector3d dir, Vector3d offset) {
+ return calculateOffset(startPoint, endPoint, start, list, end, dir, offset, false);
+ }
+
+ private static boolean calculateOffset(Vector3d startPoint, Vector3d endPoint, PipeControlPoint start, ArrayList<PipeControlPoint> list, PipeControlPoint end, Vector3d dir, Vector3d offset, boolean directed) {
+ List<PipeControlPoint> offsets = getOffsetPoints(start, list);
if (offsets.size() == 0) {
- dir.set(endPoint);
- dir.sub(startPoint);
- double l = dir.lengthSquared();
- if (l > MathTools.NEAR_ZERO)
- dir.scale(1.0/Math.sqrt(l));
- offset.set(0.0, 0.0, 0.0);
+ setZeroOffset(startPoint, endPoint, dir, offset);
return false;
} else {
Vector3d sp = new Vector3d(startPoint);
double l = dir.lengthSquared();
if (l > MathTools.NEAR_ZERO)
dir.scale(1.0/Math.sqrt(l));
+
int iter = 100;
while (iter >= 0) {
iter--;
Vector3d v = icp.getSizeChangeOffsetVector(dir);
offset.add(v);
}
+
+ if (directed)
+ break;
+
Point3d nep = new Point3d(endPoint);
nep.sub(offset);
if (nep.distance(ep) < 0.0000000001) {
break;
- }
+ }
+
ep = nep;
dir.set(ep);
dir.sub(sp);
if (l > MathTools.NEAR_ZERO)
dir.scale(1.0/Math.sqrt(l));
}
- hasOffsets = true;
+
+ if (DEBUG)
+ System.out.println("calcOffset s:"+ startPoint + " e:" + endPoint + " d:" + dir + " o:"+offset) ;
+
+ return true;
}
-
- if (DEBUG && hasOffsets)
- System.out.println("calcOffset s:"+ startPoint + " e:" + endPoint + " d:" + dir + " o:"+offset) ;
- return hasOffsets;
}
+ public static void setZeroOffset(Vector3d startPoint, Vector3d endPoint, Vector3d dir, Vector3d offset) {
+ dir.set(endPoint);
+ dir.sub(startPoint);
+ double l = dir.lengthSquared();
+ if (l > MathTools.NEAR_ZERO)
+ dir.scale(1.0/Math.sqrt(l));
+ offset.set(0.0, 0.0, 0.0);
+ }
+
+ public static List<PipeControlPoint> getOffsetPoints(PipeControlPoint start, ArrayList<PipeControlPoint> list) {
+ List<PipeControlPoint> offsets = new ArrayList<PipeControlPoint>(list.size());
+ // Only start offset affects the calculation
+ if (start.isOffset())
+ offsets.add(start);
+ for (PipeControlPoint icp : list) {
+ if (icp.isOffset()) {
+ offsets.add(icp);
+ } else if (icp.isDualSub())
+ ErrorLogger.defaultLogError("Updating pipe run, found offset controlpoint " + icp, new Exception("ASSERT!"));
+ }
+ return offsets;
+ }
+
private static UpdateStruct2 createUS(PipeControlPoint start, Direction direction, int iter, ArrayList<ExpandIterInfo> toRemove, PipeControlPoint updated) {
ArrayList<PipeControlPoint> list = new ArrayList<PipeControlPoint>();
PipeControlPoint end = null;
Vector3d startPoint = start.getWorldPosition();
Vector3d endPoint = end.getWorldPosition();
Vector3d dir = new Vector3d();
- hasOffsets = calculateOffset(startPoint, endPoint, list, dir, offset);
+ hasOffsets = calculateOffset(startPoint, endPoint, start, list, end, dir, offset);
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.isTurn() && pcp.isFixed()) {
+ if (pcp.asFixedAngle()) {
if (!pcp._getReversed())
return direction == Direction.NEXT;
else
}
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)
+ setErrorForce(u.start, null);
+ if (re)
+ setErrorForce(u.end, null);
+ for (PipeControlPoint pcp : u.list)
+ setErrorForce(pcp, 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() || u.start.isFixed() || u.end.isFixed())
+ if (u.start.isInline() || u.end.isInline() || u.start.asFixedAngle()|| u.end.asFixedAngle())
processPathLeg(u, true, false);
}
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) {
-
-
- 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);
- }
- }
- if (!checkSizes)
- return;
-
- ArrayList<PipeControlPoint> pathLegPoints = 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);
- }
- pathLegPoints.add(u.end);
-
- // TODO : values can be cached in the loop
- 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 (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);
- }
+ boolean recalcline = false;
- } 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);
- }
+ Vector3d sp = new Vector3d(start);
+ Vector3d ep = new Vector3d(end);
+ ep.sub(u.offset);
+
+ if (u.start.isOffset()) {
+ Vector3d offset = u.start.getSizeChangeOffsetVector(u.dir);
+ updateOffsetPoint(u.start, offset);
+ sp.add(offset);
+ ep.add(offset);
+ }
+
+ for (PipeControlPoint icp : u.list) {
+ updateInlineControlPoint(icp, sp, ep, u.dir);
+ 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);
}
- } 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);
+ }
+
+ if (!checkSizes)
+ return;
+
+ // Collect all path leg points for updating variable length components. This list will also contain leg ends (usually turns)
+ ArrayList<PipeControlPoint> pathLegPoints = new ArrayList<>();
+ // Collect all fixed length components with their offsets.
+ ArrayList<Pair<PipeControlPoint,Vector3d>> fixedLengthPoints = new ArrayList<>();
+
+ pathLegPoints.add(u.start);
+ fixedLengthPoints.add(new Pair<PipeControlPoint, Vector3d>(u.start, new Vector3d()));
+ Vector3d off = new Vector3d();
+ for (PipeControlPoint icp : u.list) {
+ pathLegPoints.add(icp);
+ updateBranchControlPointBranches(icp);
+ if (icp.isOffset()) {
+ fixedLengthPoints.add(new Pair<PipeControlPoint, Vector3d>(icp, new Vector3d(off)));
+ Vector3d offset = icp.getSizeChangeOffsetVector(u.dir);
+ off.add(offset);
+ } else if (!icp.isVariableLength()) {
+ fixedLengthPoints.add(new Pair<PipeControlPoint, Vector3d>(icp, new Vector3d(off)));
+ }
+ }
+ pathLegPoints.add(u.end);
+ fixedLengthPoints.add(new Pair<PipeControlPoint, Vector3d>(u.end, new Vector3d(off)));
+
+ sp = new Vector3d(start);
+ ep = new Vector3d(end);
+ ep.sub(u.offset);
+
+ updateFixedLengths(fixedLengthPoints, sp, ep, u.dir);
+
+ for (int i = 0; i < pathLegPoints.size(); i++) {
+ PipeControlPoint icp = pathLegPoints.get(i);
- for (PipeControlPoint icp : u.list) {
- 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;
+ PipeControlPoint prev = i > 0 ? pathLegPoints.get(i - 1) : null;
+ PipeControlPoint next = i < pathLegPoints.size() - 1 ? pathLegPoints.get(i + 1) : null;
- 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);
+ if (prev != null && prev.isDualInline())
+ prev = prev.getDualSub();
- 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 (prev != null && next != null) {
- recalcline = recalcline | updateVariableLength(icp, prev, next);
+ 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
- Vector3d offset = icp.getSizeChangeOffsetVector(u.dir);
- sp.add(offset);
- ep.add(offset);
+ } 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
+ Vector3d offset = icp.getSizeChangeOffsetVector(u.dir);
+ sp.add(offset);
+ ep.add(offset);
}
}
+
if (recalcline) {
u.list.clear();
u.start.findNextEnd(u.list);
+ }
+ if (checkSizes) {
+ sp = new Vector3d(u.startPoint);
+ ep = new Vector3d(u.endPoint);
+ ep.sub(u.offset);
+ double pathLegLength = MathTools.distance(sp, ep);
+ 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) {
+ setError(u.start, "Not enough available space");
+ setError(u.end, "Not enough available space");
+ for (PipeControlPoint pcp : u.list)
+ setError(pcp, "Not enough available space");
+ }
+// System.out.println(u.start.getPipelineComponent().toString() + " " + pathLegLength + " " + availableLength + " " + u.end.getPipelineComponent().toString() + " " + u.start.getInlineLength() + " " + u.end.getInlineLength());
}
}
+ private enum Gap{ATTACHED,OVERLAP,SPACE};
+
+ private static class GapObj {
+ Gap gap;
+ double d;
+
+ Pair<PipeControlPoint,Vector3d> pcp1;
+ Pair<PipeControlPoint,Vector3d> pcp2;
+ }
+
+ private static void updateFixedLengths(List<Pair<PipeControlPoint,Vector3d>> fixedLengthPoints, Vector3d s, Vector3d e, Vector3d dir) {
+ double totalLength = MathTools.distance(s, e);
+ double reservedLength = 0.0;
+ List<Double> distances = new ArrayList<>(fixedLengthPoints.size());
+ distances.add(0.0);
+ for (int i = 1; i < fixedLengthPoints.size()-1; i++) {
+ Pair<PipeControlPoint,Vector3d> pcp = fixedLengthPoints.get(i);
+ reservedLength += pcp.first.getLength();
+ Vector3d p = pcp.first.getWorldPosition();
+ p.sub(pcp.second);
+ double d= MathTools.distance(s, p);
+ distances.add(d);
+ }
+ distances.add(totalLength);
+
+ if (totalLength >= reservedLength) {
+ // There is enough space for all fixed length components.
+ List<GapObj> gaps = new ArrayList<>(fixedLengthPoints.size()-1);
+ int overlaps = 0;
+ // Analyze gaps between components
+ for (int i = 0; i < fixedLengthPoints.size()-1; i++) {
+ Pair<PipeControlPoint,Vector3d> pcp1 = fixedLengthPoints.get(i);
+ Pair<PipeControlPoint,Vector3d> pcp2 = fixedLengthPoints.get(i+1);
+ double d1 = distances.get(i);
+ double d2 = distances.get(i+1);
+ double ld1 = i == 0 ? 0.0 :pcp1.first.getInlineLength();
+ double ld2 = i == fixedLengthPoints.size()-2 ? 0.0 : pcp2.first.getInlineLength();
+
+ double e1 = d1 + ld1; // End of comp1
+ double s2 = d2 - ld2; // Start of comp2
+ double diff =s2 - e1;
+ GapObj obj = new GapObj();
+ obj.pcp1 = pcp1;
+ obj.pcp2 = pcp2;
+ obj.d = diff;
+ if (diff < -MIN_INLINE_LENGTH) {
+ obj.gap = Gap.OVERLAP;
+ overlaps++;
+ } else if (diff > MIN_INLINE_LENGTH) {
+ obj.gap = Gap.SPACE;
+ } else {
+ obj.gap = Gap.ATTACHED;
+ }
+ gaps.add(obj);
+ }
+ // If there are no overlaps, there is nothing to do.
+ if (overlaps == 0)
+ return;
+ // Get rid of overlapping components by using closest available free spaces.
+ for (int i = 0; i < gaps.size(); i++) {
+ GapObj gapObj = gaps.get(i);
+ if (gapObj.gap != Gap.OVERLAP)
+ continue;
+ double curr = gapObj.d;
+ int d = 1;
+ while (curr < -MIN_INLINE_LENGTH) {
+ GapObj next = i+d >= 0 ? gaps.get(i+d) : null;
+ GapObj prev = i-d >= 0 ? gaps.get(i-d) : null;
+ if (next != null && next.gap == Gap.SPACE) {
+ double move = Math.min(-curr, next.d);
+ curr+= move;
+ next.d -= move;
+ if (next.d < MIN_INLINE_LENGTH)
+ next.gap = Gap.ATTACHED;
+ Vector3d mv = new Vector3d(dir);
+ mv.normalize();
+ mv.scale(move);
+ for (int j = i ; j < i+d; j++) {
+ Pair<PipeControlPoint,Vector3d> pcp = gaps.get(j).pcp2;
+ Vector3d p = new Vector3d(pcp.first.getWorldPosition());
+ p.add(mv);
+ pcp.first.setWorldPosition(p);
+ }
+ }
+ if (curr < -MIN_INLINE_LENGTH && prev != null && prev.gap == Gap.SPACE) {
+ double move = Math.min(-curr, prev.d);
+ curr+= move;
+ next.d -= move;
+ if (next.d < MIN_INLINE_LENGTH)
+ next.gap = Gap.ATTACHED;
+ Vector3d mv = new Vector3d(dir);
+ mv.normalize();
+ mv.scale(-move);
+ for (int j = i ; j > i-d; j--) {
+ Pair<PipeControlPoint,Vector3d> pcp = gaps.get(j).pcp1;
+ Vector3d p = new Vector3d(pcp.first.getWorldPosition());
+ p.add(mv);
+ pcp.first.setWorldPosition(p);
+ }
+ }
+ }
+ }
+ } else {
+ for (int i = 1; i < fixedLengthPoints.size()-1; i++) {
+ Pair<PipeControlPoint,Vector3d> prev = i == 0 ? null : fixedLengthPoints.get(i-1);
+ Pair<PipeControlPoint,Vector3d> curr = fixedLengthPoints.get(i);
+ Pair<PipeControlPoint,Vector3d> next = i == fixedLengthPoints.size() -1 ? null : fixedLengthPoints.get(i+1);
+ updateFixedLength(curr, prev, next, s,e, dir);
+ }
+ }
+ }
+
+ private static void updateFixedLength(Pair<PipeControlPoint,Vector3d> icp, Pair<PipeControlPoint,Vector3d> prev, Pair<PipeControlPoint,Vector3d> next, Vector3d s, Vector3d e, Vector3d dir) {
+ if (prev != null) {
+ checkOverlap(prev, icp, dir,true);
+ }
+ if (next != null)
+ checkOverlap(icp, next, dir,true);
+ }
+
+ private static boolean checkOverlap(Pair<PipeControlPoint,Vector3d> icp, Pair<PipeControlPoint,Vector3d> icp2, Vector3d dir, boolean se) {
+ Vector3d p1 = icp.first.getWorldPosition();
+ Vector3d p2 = icp2.first.getWorldPosition();
+ p1.add(icp.second);
+ p2.add(icp2.second);
+ double u[] = new double[1];
+ MathTools.closestPointOnStraight(p2, p1, dir, u);
+ if (u[0] < 0.0) {
+ p2.set(p1);
+ p2.sub(icp.second);
+ p2.add(icp2.second);
+ MathTools.mad(p2, dir, MIN_INLINE_LENGTH);
+ icp2.first.setWorldPosition(p2);
+ }
+ double d = MathTools.distance(p1, p2);
+ double r = icp.first.getInlineLength() + icp2.first.getInlineLength();
+
+ if ((d-r) < - MIN_INLINE_LENGTH) {
+ if (se) {
+ setError(icp.first, "Overlapping");
+ setError(icp2.first, "Overlapping");
+ }
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Overrides current error of a component
+ * @param pcp
+ * @param error
+ */
+ private static void setErrorForce(PipeControlPoint pcp, String error) {
+ PipelineComponent comp = pcp.getPipelineComponent();
+ if (comp == null)
+ return;
+ comp.setError(error);
+ }
+
+ /**
+ * Sets error for a component, if there is no existing error.
+ * @param pcp
+ * @param error
+ */
+ private static void setError(PipeControlPoint pcp, String error) {
+ PipelineComponent comp = pcp.getPipelineComponent();
+ if (comp == null)
+ return;
+ if (comp.getError() != null)
+ return;
+ comp.setError(error);
+ }
+
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(MIN_INLINE_LENGTH);
+ setError(icp, "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;
}
double l2next = icp.getInlineLength();
double l2 = l2prev + l2next;
double l2s = l2 * l2;
- if (l > l2s) {
+ double diff = l - l2s;
+ if (diff >= MIN_INLINE_LENGTH) {
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);
- PipeControlPoint scp = insertStraight(prev, icp, dir, length);
+ insertStraight(prev, icp, dir, length);
return true;
} else {
triedIR = true;
}
}
- private static void ppNoOffset(UpdateStruct2 u) throws Exception {
+ /**
+ * Recalculates offset vector based on current direction, and calls checkExpandPathLeg
+ * @param u
+ * @param updateEnds
+ * @throws Exception
+ */
+ private static void ppNoOffset(UpdateStruct2 u, boolean updateEnds) throws Exception {
if (DEBUG)
System.out.println("PipingRules.ppNoOffset() " + u);
Vector3d offset = new Vector3d();
if (u.hasOffsets) {
- u.dir.normalize();
for (PipeControlPoint icp : u.list) {
if (icp.isOffset()) {
offset.add(icp.getSizeChangeOffsetVector(u.dir));
}
}
u.offset = offset;
- checkExpandPathLeg(u, PathLegUpdateType.NONE);
+ checkExpandPathLeg(u, PathLegUpdateType.NONE, updateEnds);
}
private static void ppNoDir(PipeControlPoint start, Vector3d startPoint, ArrayList<PipeControlPoint> list, PipeControlPoint end, Vector3d endPoint, boolean hasOffsets, int iter, boolean reversed, ArrayList<ExpandIterInfo> toRemove, PipeControlPoint updated) throws Exception {
// FIXME : extra loop (dir should be calculated here)
Vector3d dir = new Vector3d();
Vector3d offset = new Vector3d();
- hasOffsets = calculateOffset(startPoint, endPoint, list, dir, offset);
- ppNoOffset(new UpdateStruct2(start, startPoint, list, end, endPoint, dir, null, hasOffsets, iter, reversed, toRemove, updated));
+ hasOffsets = calculateOffset(startPoint, endPoint, start, list, end, dir, offset);
+ ppNoOffset(new UpdateStruct2(start, startPoint, list, end, endPoint, dir, null, hasOffsets, iter, reversed, toRemove, updated),true);
}
private static void checkExpandPathLeg(UpdateStruct2 u, PathLegUpdateType lengthChange) throws Exception {
position = u.startPoint;
dcpStart = true;
if (!u.reversed)
- canMoveOther = true;
+ canMoveOther = true;
inlineEnd = u.end.isInline();
} else {
other = u.start;
position = u.endPoint;
if (u.reversed)
- canMoveOther = true;
+ canMoveOther = true;
inlineEnd = u.start.isInline();
}
-
+
Vector3d directedDirection = direction(dcp, dcpStart ? Direction.NEXT : Direction.PREVIOUS);
if (directedDirection == null) {
//updateTurnControlPointTurn(dcp, dcp.getPrevious(), dcp.getNext());
}
Point3d directedEndPoint = new Point3d(u.endPoint);
if (u.hasOffsets)
- directedEndPoint.add(u.offset);
+ directedEndPoint.sub(u.offset);
double mu[] = new double[2];
double distance = t.length();
boolean aligned = (distance < ALLOWED_OFFSET);
+ double requiredSpace = 0.0;
+ if (other.isVariableAngle()) {
+ requiredSpace = spaceForTurn(other, dcp);
+ }
+ if (mu[0] < requiredSpace) {
+ // At the moment, if next component is directly behind the nozzle, we must force moving the other component.
+ // Trying to solve the situation by adding new turn creates infinite loop...
+ aligned = false;
+ canMoveOther = true;
+ }
if (aligned) {
- if (u.start.isInline() || u.end.isInline() || u.start.isFixed() || u.end.isFixed())
- processPathLeg(u, true, false);
- checkExpandPathLeg(u, lengthChange, inlineEnd);
-
+ //if (u.start.isInline() || u.end.isInline() || u.start.asFixedAngle() || u.end.asFixedAngle())
+ // processPathLeg(u, true, false);
+ checkExpandPathLeg(u, lengthChange, inlineEnd || u.start.isInline() || u.end.isInline() || u.start.asFixedAngle() || u.end.asFixedAngle());
} else {
if (u.iter > 0) {
backIter(u);
if (other.isVariableAngle()) {
// TODO calculate needed space from next run end.
- if (mu[0] < 1.0) {
+ if (mu[0] < requiredSpace) {
if (dcpStart) {
closest.set(u.startPoint);
} else {
closest.set(u.endPoint);
}
Vector3d v = new Vector3d(directedDirection);
- v.scale(spaceForTurn(other));
+ v.scale(requiredSpace);
closest.add(v);
}
if (canMoveOther) {
if (DEBUG)
System.out.println("PipingRules.updateDirectedPipeRun() moved end " + other + " to " + closest);
+
+ // Not aligned - we need to recalculate the offset to reflect new end points.
+ Vector3d offset;
+ if (u.hasOffsets) {
+ offset = new Vector3d();
+ Vector3d newDir = new Vector3d();
+ calculateDirectedOffset(position, closest, u.start, u.list, u.end, newDir, offset);
+ closest.add(offset);
+ } else {
+ offset = new Vector3d();
+ }
+
other.setWorldPosition(closest);
+
if (dcpStart) {
- ppNoOffset(new UpdateStruct2(u.start, u.startPoint, u.list, u.end, new Vector3d(closest), directedDirection, null, u.hasOffsets, u.iter, u.reversed, u.toRemove, u.updated));
+ checkExpandPathLeg(new UpdateStruct2(u.start, u.startPoint, u.list, u.end, new Vector3d(closest), directedDirection, offset, u.hasOffsets, u.iter, u.reversed, u.toRemove, u.updated), PathLegUpdateType.NONE, true);
if (u.end.getNext() != null)
updatePathLegNext(u.end, u.updated, PathLegUpdateType.NEXT);
} else {
- ppNoOffset(new UpdateStruct2(u.start, new Vector3d(closest), u.list, u.end, u.endPoint, directedDirection, null, u.hasOffsets, u.iter, u.reversed, u.toRemove, u.updated));
+ checkExpandPathLeg(new UpdateStruct2(u.start, new Vector3d(closest), u.list, u.end, u.endPoint, directedDirection, offset, u.hasOffsets, u.iter, u.reversed, u.toRemove, u.updated), PathLegUpdateType.NONE, true);
if (u.start.getPrevious() != null)
updatePathLegPrev(u.start, u.updated, PathLegUpdateType.PREV);
}
}
- 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 tcp.getPipeRun().getTurnRadius();
+ private static double spaceForTurn(PipeControlPoint tcp, PipeControlPoint dcp) {
+ // TODO : if the path legs contain offset, using just positions of opposite path leg ends is not enough.
+ // TODO : current iterative way for calculating required space may return longer length that is required.
+ double tr = ((TurnComponent)tcp.getPipelineComponent()).getTurnRadius();
+ if (dcp == null)
+ return tr; // space for 90 deg
+ PipeControlPoint ne = tcp.findNextEnd();
+ PipeControlPoint pe = tcp.findPreviousEnd();
+ PipeControlPoint other = null;
+ if (dcp == ne)
+ other = pe;
+ else if (dcp == pe)
+ other = ne;
+ else
+ return tr; // space for 90 deg
+ if (other == null)
+ return tr; // space for 90 deg
+ Vector3d dir = dcp.getDirectedControlPointDirection();
+ Vector3d dp = dcp.getWorldPosition();
+ Vector3d op = other.getWorldPosition();
+ double u[] = new double[1];
+ Vector3d closest = MathTools.closestPointOnStraight(op, dp, dir,u);
+ if (MathTools.distanceSquared(closest, op) <= MIN_INLINE_LENGTH) {
+ if (u[0] > -MIN_INLINE_LENGTH)
+ return 0.0; // point following turn is directly in the front of the nozzle.
+ else
+ return tr*2.0; // point following turn is directly behind the nozzle, in theory, we should return Double.Inf...
+ }
+ double curr = tr*0.1;
+ int iter = 10;
+ Vector3d v1 = new Vector3d();
+ Vector3d v2 = new Vector3d();
+ while (iter > 0) {
+ Vector3d tp = new Vector3d(dp);
+ MathTools.mad(tp, dir, curr);
+ v1.sub(tp, dp); // Vector from nozzle to turn
+ v2.sub(op,tp); // Vector from turn to other
+ double a = v1.angle(v2);
+ double t = Math.tan((Math.PI - a) * 0.5);
+ double R = 0.0;
+ if (t > MathTools.NEAR_ZERO)
+ R = tr / t;
+ if (R <= curr)
+ break;
+ curr = R*1.001;
+ iter--;
+ }
+ return curr;
}
private static void insertElbowUpdate(UpdateStruct2 u, PipeControlPoint dcp, PipeControlPoint next, boolean dcpStart, Vector3d position, Vector3d directedDirection) throws Exception{
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);
+ double s = spaceForTurn(tcp,dcp);
if (d < s) {
d = s - d;
Vector3d p = new Vector3d(directedDirection);
updateTurnControlPointTurn(u.start, null, null);
// updatePathLegPrev(u.start, u.start, PathLegUpdateType.NONE);
} else if (u.start.isEnd()) {
- updateEndComponentControlPoint(u.start, u.startPoint, u.endPoint);
+ updateEndComponentControlPoint(u.start, u.dir);
} else if (u.start.isInline()) {
- updateControlPointOrientation(u.start);
+ updateControlPointOrientation(u.start, u.dir);
}
if (u.end.isTurn()) {
//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);
+ updateEndComponentControlPoint(u.end, u.dir);
} else if (u.end.isInline()) {
- updateControlPointOrientation(u.end);
+ updateControlPointOrientation(u.end, u.dir);
}
} else {
if (u.start.isEnd()) {
- updateEndComponentControlPoint(u.start, u.startPoint, u.endPoint);
+ updateEndComponentControlPoint(u.start, u.dir);
}
if (u.end.isEnd()) {
- updateEndComponentControlPoint(u.end, u.startPoint, u.endPoint);
+ updateEndComponentControlPoint(u.end, u.dir);
}
}
if (updateInline)
// 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);
}
if (canCalc) {
boolean branchUpdate = false;
PipeControlPoint becp = null;
- for (PipeControlPoint pcp : icp.getSubPoint())
+ for (PipeControlPoint pcp : icp.getChildPoints())
if (pcp.isNonDirected()) {
branchUpdate = true;
becp = pcp;
System.out.println(" " + newInlinePoint);
icp.setWorldPosition(newInlinePoint);
- updateControlPointOrientation(icp);
+ updateControlPointOrientation(icp, dir);
}
/**
* @param nextPoint
* @param prevPoint
*/
- private static void updateEndComponentControlPoint(PipeControlPoint ecp, Vector3d start, Vector3d end) throws Exception {
+ private static void updateEndComponentControlPoint(PipeControlPoint ecp, Vector3d dir) 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()) {
+
+ if (!ecp.isFixed()) // prevent overriding nozzle orientations..
+ updateControlPointOrientation(ecp, dir);
+
+ for (PipeControlPoint pcp : ecp.getChildPoints()) {
// TODO update position
updatePathLegEndControlPoint(pcp);
}
}
- private static void updateControlPointOrientation(PipeControlPoint pcp) {
- // FIXME : hack to bypass variable length components orientation
-// if (pcp.getAtMostOneRelatedObject(ProcessResource.g3dResource.HasWorldOrientation) == null)
-// return;
-// if (pcp.rotationAngle == null)
-// return;
+ private static void updateControlPointOrientation(PipeControlPoint pcp, Vector3d dir) {
Double angleO = pcp.getRotationAngle();
double angle = 0.0;
if (angleO != null)
angle = angleO;
- Boolean reversedO = pcp.getReversed();
- boolean reversed = false;
- if (reversedO != null)
- reversed = reversedO;
- Quat4d q = pcp.getControlPointOrientationQuat(angle, reversed);
+ boolean reversed = pcp._getReversed();
+ Quat4d q = null;
+ if (dir != null) {
+ q = pcp.getControlPointOrientationQuat(dir, angle, reversed);
+ } else {
+ 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");
}
}
- if (!tcp.isFixed()) {
+ if (!tcp.asFixedAngle()) {
if (next == null || prev == null) {
Vector3d turnAxis = new Vector3d();
turnAxis.cross(prev, next);
if (turnAxis.lengthSquared() > MathTools.NEAR_ZERO) {
- double elbowRadius = tcp.getPipelineComponent().getPipeRun().getTurnRadius();
+ double elbowRadius = ((TurnComponent)tcp.getPipelineComponent()).getTurnRadius();
double R = elbowRadius / Math.tan(angle * 0.5);
turnAxis.normalize();
tcp.setTurnAxis(new Vector3d(MathTools.Y_AXIS));
}
- updateControlPointOrientation(tcp);
+ updateControlPointOrientation(tcp,prev);
if (DEBUG)
System.out.println("PipingTools.updateTurnControlPointTurn " + prev + " " + next + " " + turnAngle + " " + turnAxis);
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()) {
while (true) {
List<PipeControlPoint> points = getControlPoints(pipeRun);
PipeControlPoint pcp = points.get(0);
- if (pcp.isSizeChange() && pcp.getSubPoint().size() > 0) {
- pipeRun = pcp.getPipeRun();
+ if (pcp.isSizeChange() && pcp.getChildPoints().size() > 0) {
+ PipeRun pr = pcp.getPipeRun();
+ if (pr != pipeRun)
+ pipeRun = pr;
+ else break;
} else {
break;
}
List<PipeControlPoint> points = getControlPoints(pipeRun);
pcps.add(points);
PipeControlPoint pcp = points.get(points.size()-1);
- if (pcp.getSubPoint().size() > 0) {
- pipeRun = pcp.getSubPoint().get(0).getPipeRun();
+ if (pcp.getChildPoints().size() > 0) {
+ PipeRun pipeRun2 = pcp.getChildPoints().get(0).getPipeRun();
+ if (pipeRun == pipeRun2)
+ break;
+ else
+ pipeRun = pipeRun2;
} else {
break;
}
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();
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);
+ next = next.getDualSub();
if (current.getNext() == next)
current.setNext(null);
current.setPrevious(next);
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 (current.isTurn() && current.isFixed()) {
+ //if (current.isTurn() && current.isFixed()) {
+ if (current.asFixedAngle()) {
current.setReversed(!current._getReversed());
}
if (current.isInline() && current.isReverse()) {
}
}
- 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);
- }
- }
- }
- r2.remove();
-
- }
+
public static void validate(PipeRun pipeRun) {
if (pipeRun == null)
}
List<PipeControlPoint> runPcps = getControlPoints(pipeRun);
if (runPcps.size() != count) {
- System.out.println("Run " + pipeRun.getName() + " contains unconnected control points");
+ 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);
+ 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();
// 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);