import java.util.Arrays;
import java.util.Collection;
import java.util.List;
+import java.util.Objects;
import javax.vecmath.AxisAngle4d;
import javax.vecmath.Matrix3d;
import org.simantics.g3d.math.MathTools;
import org.simantics.g3d.property.annotations.GetPropertyValue;
import org.simantics.g3d.scenegraph.G3DNode;
+import org.simantics.g3d.scenegraph.base.INode;
import org.simantics.plant3d.scenegraph.IP3DNode;
import org.simantics.plant3d.scenegraph.Nozzle;
import org.simantics.plant3d.scenegraph.P3DRootNode;
// We need to calculate turnAngle and rotationAngle
Vector3d dirOut = getPathLegDirection(direction == Direction.NEXT ? Direction.NEXT : Direction.PREVIOUS);
Vector3d dir = getPathLegDirection(direction == Direction.NEXT ? Direction.PREVIOUS : Direction.NEXT);
+ if (dir == null || dirOut == null)
+ return;
dir.negate();
- dirOut.normalize();
- dir.normalize();
double angle = dir.angle(dirOut);
//super._setNext(null);
if (direction == Direction.NEXT)
}
public void setLength(double l) {
- if (Double.isInfinite(l) || Double.isNaN(l)) {
+ if (this.length == l)
+ return;
+ if (Double.isInfinite(l) || Double.isNaN(l))
return;
- }
if (Math.abs(this.length-l) < MathTools.NEAR_ZERO)
return;
this.length = l;
}
if (this.turnAngle != null && Math.abs(this.turnAngle-turnAngle) < MathTools.NEAR_ZERO)
return;
+ if (Objects.equals(this.turnAngle, turnAngle))
+ return;
this.turnAngle = turnAngle;
firePropertyChanged("turnAngle");
}
}
if (this.offset != null && Math.abs(this.offset-offset) < MathTools.NEAR_ZERO)
return;
+ if (Objects.equals(this.offset, offset))
+ return;
this.offset = offset;
firePropertyChanged("offset");
}
}
if (this.rotationAngle != null && Math.abs(this.rotationAngle-rotationAngle) < MathTools.NEAR_ZERO)
return;
+ if (Objects.equals(this.rotationAngle, rotationAngle))
+ return;
this.rotationAngle = rotationAngle;
firePropertyChanged("rotationAngle");
}
public void setReversed(Boolean reversed) {
+ if (this.reversed == reversed)
+ return;
this.reversed = reversed;
firePropertyChanged("reversed");
}
q = getControlPointOrientationQuat(dir, 0.0);
else
q = getControlPointOrientationQuat(dir, rotationAngle);
- Vector3d v = new Vector3d(0.0,offset,0.0);
+ Vector3d v = new Vector3d(0.0,-offset,0.0);
Vector3d offset = new Vector3d();
MathTools.rotate(q, v, offset);
return offset;
q = getControlPointOrientationQuat(0.0);
else
q = getControlPointOrientationQuat(rotationAngle);
- Vector3d v = new Vector3d(0.0,offset,0.0);
+ Vector3d v = new Vector3d(0.0,-offset,0.0);
Vector3d offset = new Vector3d();
MathTools.rotate(q, v, offset);
return offset;
return type.name();
}
- public Quat4d getControlPointOrientationQuat(double angle) {
+ public Vector3d getPathLegEndpointVector() {
+ PipeControlPoint a = findPreviousEnd();
+ PipeControlPoint b = findNextEnd();
+
+ if (a == null || b == null) {
+ return getPathLegDirection();
+ }
+
+ Vector3d p1 = a.getWorldPosition();
+ Vector3d p2 = b.getWorldPosition();
+ p2.sub(p1);
+ double l = p2.length();
+ if (l != 0.0) {
+ p2.scale(1.0 / l);
+ return p2;
+ }
+ else {
+ return getPathLegDirection();
+ }
+ }
+ public Vector3d getPathLegDirection() {
if (turnAxis == null) {
- Vector3d dir = getPathLegDirection(Direction.NEXT);
- if (dir.lengthSquared() > MathTools.NEAR_ZERO)
- dir.normalize();
- return getControlPointOrientationQuat(dir, angle);
+ return getPathLegDirection(Direction.NEXT);
} else {
Vector3d dir = getPathLegDirection(Direction.PREVIOUS);
- dir.negate();
- if (dir.lengthSquared() > MathTools.NEAR_ZERO)
- dir.normalize();
- return getControlPointOrientationQuat(dir, turnAxis, angle);
+ if (dir != null) dir.negate();
+ return dir;
}
}
-
- public Quat4d getControlPointOrientationQuat(double angle, boolean reversed) {
-
+
+ public Quat4d getControlPointOrientationQuat(double angle) {
+ Vector3d dir = getPathLegDirection();
if (turnAxis == null) {
- Vector3d dir = getPathLegDirection(Direction.NEXT);
- if (dir.lengthSquared() > MathTools.NEAR_ZERO)
- dir.normalize();
- Quat4d q = getControlPointOrientationQuat(dir, angle);
- if (reversed) {
- Quat4d q2 = new Quat4d();
- q2.set(new AxisAngle4d(MathTools.Y_AXIS, Math.PI));
- q.mulInverse(q2);
- }
- return q;
+ return getControlPointOrientationQuat(dir, angle);
} else {
- Vector3d dir = getPathLegDirection(Direction.PREVIOUS);
- dir.negate();
- if (dir.lengthSquared() > MathTools.NEAR_ZERO)
- dir.normalize();
return getControlPointOrientationQuat(dir, turnAxis, angle);
}
}
+
+ public Quat4d getControlPointOrientationQuat(Vector3d dir, double angle, boolean reversed) {
+ if (turnAxis == null) {
+ if (dir.lengthSquared() > MathTools.NEAR_ZERO)
+ dir.normalize();
+ Quat4d q = getControlPointOrientationQuat(dir, angle);
+ if (reversed) {
+ Quat4d q2 = new Quat4d();
+ q2.set(new AxisAngle4d(MathTools.Y_AXIS, Math.PI));
+ q.mulInverse(q2);
+ }
+ return q;
+ } else {
+ if (dir.lengthSquared() > MathTools.NEAR_ZERO)
+ dir.normalize();
+ return getControlPointOrientationQuat(dir, turnAxis, angle);
+ }
+ }
+ public Quat4d getControlPointOrientationQuat(double angle, boolean reversed) {
+ Vector3d dir = getPathLegDirection();
+ return getControlPointOrientationQuat(dir, angle, reversed);
+ }
-
- public static Quat4d getControlPointOrientationQuat(Vector3d dir, double angle) {
- if (dir.lengthSquared() < MathTools.NEAR_ZERO)
+ public Quat4d getControlPointOrientationQuat(Vector3d dir, double angle) {
+ if (dir == null || dir.lengthSquared() < MathTools.NEAR_ZERO)
return MathTools.getIdentityQuat();
-
- Vector3d up = new Vector3d(0.0, 1.0, 0.0);
- double a = up.angle(dir);
+ final P3DRootNode root = getRoot();
+ Vector3d up = root != null ? new Vector3d(root.getUpVector()) : new Vector3d(0.0, 1.0, 0.0);
+ final Vector3d legDir = getPathLegEndpointVector();
+ double a = up.angle(legDir);
if (a < 0.1 || (Math.PI - a) < 0.1) {
- up.set(1.0, 0.0, 0.0);
+ // Rotate components
+ up.set(up.getY(), up.getZ(), up.getX());
}
-
+
+ // Project up vector into a normal of the leg direction before applying to 'dir'
+ MathTools.mad(up, legDir, -legDir.dot(up)/legDir.lengthSquared());
+ up.normalize();
return getControlPointOrientationQuat(dir, up, angle);
}
+ public P3DRootNode getRoot() {
+ INode n = getParent();
+ while (n != null && !(n instanceof P3DRootNode))
+ n = n.getParent();
+ return (P3DRootNode) n;
+ }
+
public static Quat4d getControlPointOrientationQuat(Vector3d dir, Vector3d up, double angle) {
- if (dir.lengthSquared() < MathTools.NEAR_ZERO)
+ if (dir == null || dir.lengthSquared() < MathTools.NEAR_ZERO)
return MathTools.getIdentityQuat();
final Vector3d front = new Vector3d(1.0,0.0,0.0);
Vector3d right = new Vector3d();
-
+
+ up = new Vector3d(up);
right.cross(dir, up);
up.cross(right, dir);
right.normalize();
if (isDualSub())
throw new RuntimeException("Dual sub points cannot be inserted.");
// size change control point cannot be inserted this way, because it ends PipeRun
- if (isSizeChange())
- throw new RuntimeException("Size change points cannot be inserted.");
+// if (isSizeChange())
+// throw new RuntimeException("Size change points cannot be inserted.");
PipeRun piperun = previous.getPipeRun();
// and just to make sure that control point structure is not corrupted
if (getPipeRun() != null) {
if (pcp.isDualSub()) {
pcp.getParentPoint().setNext(this);
}
- if (isDualInline()) {
- getDualSub().setPrevious(this);
- }
} else {
// if direction is previous, user must have given sizechange
if (pcp.isDualSub())
return dir;
}
+ /**
+ * Returns direction vector pointing towards an adjacent component for
+ * directed control points or turn control points with one open end.
+ *
+ * Always returns an outwards pointing vector.
+ *
+ * For any other type of component, the return value is null.
+ *
+ * For turn components this only return a non-null value for the unconnected
+ * end of the component.
+ *
+ * @param direction
+ * @return normalized vector, or null
+ */
public Vector3d getDirection(Direction direction) {
if (isDirected())
return getDirectedControlPointDirection();
Vector3d offset = new Vector3d();
MathTools.rotate(q2, v, offset);
MathTools.rotate(q, offset, dir);
+ dir.normalize();
return dir;
}
} else {
Vector3d offset = new Vector3d();
MathTools.rotate(q2, v, offset);
MathTools.rotate(q, offset, dir);
+ dir.negate();
+ dir.normalize();
return dir;
}
}
return null;
}
+ /**
+ * Returns path leg direction of the control point.
+ *
+ * This method differs from getDirection by also returning inward pointing vectors for directed control points.
+ *
+ * @param direction
+ * @return
+ */
public Vector3d getPathLegDirection(Direction direction) {
if (direction == Direction.NEXT) {
- if (next != null) {
- PipeControlPoint pcp = this;
- if (pcp.isDualInline()) {
- pcp = pcp.getDualSub();
- }
- Vector3d v = new Vector3d();
- v.sub(next.getWorldPosition(),pcp.getWorldPosition());
- return v;
- } else {
- if (previous == null) {
- if (!isDirected())
- throw new RuntimeException("Cannot calculate path leg direction for unconnected control point " + this);
- return getDirectedControlPointDirection();
+ return getPathLegDirectionNext();
+ } else {
+ return getPathLegDirectionPrevious();
+ }
+ }
- } else {
- if (isVariableAngle() && !asFixedAngle())
- throw new RuntimeException("Cannot calculate path leg direction for unconnected variable angle control point " + this);
- if (isInline()) {
- PipeControlPoint pcp = this;
- if (pcp.isDualSub()) {
- pcp = pcp.getParentPoint();
- }
- Vector3d v = new Vector3d();
- v.sub(pcp.getWorldPosition(),previous.getWorldPosition());
- return v;
- } else if (isDirected()) {
- return getDirectedControlPointDirection();
- } else if (isEnd()) {
- Vector3d v = new Vector3d();
- v.sub(getWorldPosition(),previous.getWorldPosition());
- return v;
- } else if (isTurn() && asFixedAngle() && !_getReversed()) {
- return getDirection(Direction.NEXT);
- }
- throw new RuntimeException("Missing implementation " + this);
- }
- }
+ public Vector3d getPathLegDirectionPrevious() {
+ if (previous != null) {
+ PipeControlPoint pcp = this;
+ if (isDualSub())
+ pcp = getParentPoint();
+ Vector3d v = new Vector3d();
+ v.sub(previous.getWorldPosition(),pcp.getWorldPosition());
+ if (v.lengthSquared() > MathTools.NEAR_ZERO)
+ v.normalize();
+ else
+ return null;
+ return v;
+ } else if (isDirected()) {
+ Vector3d v = getDirectedControlPointDirection();
+ v.negate();
+ return v;
+ } else if (next == null) {
+ throw new RuntimeException("Cannot calculate path leg direction for unconnected control point " + this);
+ } else if (isVariableAngle() && !asFixedAngle()) {
+ throw new RuntimeException("Cannot calculate path leg direction for unconnected variable angle control point " + this);
+ } else if (isInline() || isEnd()) {
+ Vector3d v = getPathLegDirectionNext();
+ if (v != null) v.negate();
+ return v;
+ } else if (isTurn() && asFixedAngle() && _getReversed()) {
+ return getDirection(Direction.PREVIOUS);
} else {
- if (previous != null) {
- PipeControlPoint pcp = this;
- if (isDualSub())
- pcp = getParentPoint();
- Vector3d v = new Vector3d();
- v.sub(previous.getWorldPosition(),pcp.getWorldPosition());
- return v;
- } else {
- if (next == null) {
- if (!isDirected())
- throw new RuntimeException("Cannot calculate path leg direction for unconnected control point " + this);
- Vector3d v = getDirectedControlPointDirection();
- v.negate();
- return v;
- } else {
- if (isVariableAngle() && !asFixedAngle())
- throw new RuntimeException("Cannot calculate path leg direction for unconnected variable angle control point " + this);
- if (isInline()) {
- PipeControlPoint pcp = this;
- if (pcp.isDualInline()) {
- pcp = pcp.getDualSub();
- }
- Vector3d v = new Vector3d();
- v.sub(pcp.getWorldPosition(),next.getWorldPosition());
- return v;
- } else if (isDirected()) {
- Vector3d v = getDirectedControlPointDirection();
- v.negate();
- return v;
- } else if (isEnd()) {
- Vector3d v = new Vector3d();
- v.sub(getWorldPosition(),next.getWorldPosition());
- return v;
- } else if (isTurn() && asFixedAngle() && _getReversed()) {
- return getDirection(Direction.PREVIOUS);
- }
- throw new RuntimeException("Missing implementation " + this);
- }
+ throw new RuntimeException("Missing implementation " + this);
+ }
+ }
+
+ public Vector3d getPathLegDirectionNext() {
+ if (next != null) {
+ PipeControlPoint pcp = this;
+ if (pcp.isDualInline()) {
+ pcp = pcp.getDualSub();
}
+ Vector3d v = new Vector3d();
+ v.sub(next.getWorldPosition(),pcp.getWorldPosition());
+ if (v.lengthSquared() > MathTools.NEAR_ZERO)
+ v.normalize();
+ else
+ return null;
+ return v;
+ } else if (isDirected()) {
+ return getDirectedControlPointDirection();
+ } else if (previous == null) {
+ throw new RuntimeException("Cannot calculate path leg direction for unconnected control point " + this);
+ } else if (isVariableAngle() && !asFixedAngle()) {
+ throw new RuntimeException("Cannot calculate path leg direction for unconnected variable angle control point " + this);
+ } else if (isInline() || isEnd()) {
+ Vector3d v = getPathLegDirectionPrevious();
+ if (v != null) v.negate();
+ return v;
+ } else if (isTurn() && asFixedAngle() && !_getReversed()) {
+ return getDirection(Direction.NEXT);
+ } else {
+ throw new RuntimeException("Missing implementation " + this);
}
}
PipeControlPoint sub = isAxial() ? this : getDualSub();
Vector3d pos = getWorldPosition(), pos2 = sub == this ? pos : sub.getWorldPosition();
- Vector3d dir = sub.getPathLegDirection(Direction.NEXT);
+ Vector3d dir = sub.getInlineDir();
- dir.normalize();
dir.scale(length * 0.5);
p1.set(pos);
p2.set(pos2);
PipeControlPoint sub = isAxial() || isDirected() || isTurn() ? this : getChildPoints().get(0);
Vector3d pos = getWorldPosition(), pos2 = sub == this ? pos : sub.getWorldPosition();
- Vector3d dir1 = getPathLegDirection(Direction.PREVIOUS);
- dir1.normalize();
- Vector3d dir2 = sub.getPathLegDirection(Direction.NEXT);
- dir2.normalize();
+ Vector3d dir1;
+ Vector3d dir2;
if (isInline()) {
- dir1.scale(length * 0.5);
+ dir2 = getInlineDir();
dir2.scale(length * 0.5);
+ dir1 = new Vector3d(dir2);
+ dir1.negate();
+ } else if (isEnd()) {
+ dir2 = dir1 = new Vector3d();
} else {
+ dir1 = getPathLegDirection(Direction.PREVIOUS);
+ dir2 = sub.getPathLegDirection(Direction.NEXT);
dir1.scale(length);
dir2.scale(length);
}
p2.add(dir2);
}
+ /**
+ * Get both path leg directions, with (0,0,0) if no connection exists. The returned vectors are not normalized.
+ *
+ * @param v1 Set to the direction towards the previous control point on output
+ * @param v2 Set to the direction towards the next control point on output
+ */
public void getEndDirections(Tuple3d v1, Tuple3d v2) {
PipeControlPoint sub = isAxial() ? this : getDualSub();
Vector3d dir1 = getPathLegDirection(Direction.PREVIOUS);
- dir1.normalize();
Vector3d dir2 = sub.getPathLegDirection(Direction.NEXT);
- dir2.normalize();
- v1.set(dir1);
- v2.set(dir2);
+
+ if (dir1 != null)
+ v1.set(dir1);
+ else
+ v1.set(0,0,0);
+
+ if (dir2 != null)
+ v2.set(dir2);
+ else
+ v2.set(0,0,0);
}
public void getInlineControlPointEnds(Tuple3d p1, Tuple3d p2, Vector3d dir) {
assert (isInline());
Vector3d pos = getWorldPosition();
- dir.set(getPathLegDirection(Direction.NEXT));
+ dir.set(getInlineDir());
dir.normalize();
dir.scale(length * 0.5);
p1.set(pos);
Vector3d pos = getWorldPosition();
center.set(pos);
- dir.set(getPathLegDirection(Direction.NEXT));
+ dir.set(getInlineDir());
dir.normalize();
dir.scale(length * 0.5);
p1.set(pos);
p2.add(dir);
}
+ public Vector3d getInlineDir() {
+ Vector3d dir = getPathLegDirection(Direction.NEXT);
+ if (dir == null) {
+ dir = getPathLegDirection(Direction.PREVIOUS);
+ if (dir != null) {
+ // Use reverse direction
+ dir.scale(-1.0);
+ } else {
+ // Control point is not connected at all, use current orientation
+ dir = new Vector3d(1,0,0);
+ MathTools.rotate(getWorldOrientation(), dir, dir);
+ }
+ }
+ return dir;
+ }
+
public double getInlineLength() {
if (type == PointType.TURN)
return length;
return 0;
}
+ /**
+ * Return the position indicated by the argument. If the indicated direction is not connected, the
+ * control point's wolrd position is returned instead.
+ *
+ * @param type A selector for the position to be returned
+ * @return The selected position
+ */
public Vector3d getRealPosition(PositionType type) {
Vector3d pos = getWorldPosition();
switch (type) {
case NEXT: {
- Vector3d dir = getPathLegDirection(Direction.NEXT);
double length = getInlineLength();
- dir.normalize();
+ Vector3d dir;
+ if (isInline()) {
+ dir = getInlineDir();
+ } else {
+ dir = getPathLegDirection(Direction.NEXT);
+ }
dir.scale(length);
pos.add(dir);
break;
}
case PREVIOUS: {
- Vector3d dir = getPathLegDirection(Direction.PREVIOUS);
double length = getInlineLength();
- dir.normalize();
+ Vector3d dir;
+ if (isInline()) {
+ dir = getInlineDir();
+ dir.negate();
+ } else {
+ dir = getPathLegDirection(Direction.PREVIOUS);
+ }
dir.scale(length);
pos.add(dir);
break;
if (link) {
if (currentPrev.isDirected() && currentNext.isDirected())
link = false;
- else if (this.isDualInline()) {
- link = false;
- } else if (this.isDualSub()) {
+ else if (this.isDualSub()) {
throw new RuntimeException("_remove() is called for parent point, somehow got to child point. " + this);
}
}
} else if (currentNext != null) {
if (currentNext.isDualInline()) {
PipeControlPoint sccp = currentNext;
- PipeControlPoint ocp = getDualSub();
+ PipeControlPoint ocp = currentNext.getDualSub();
if (ocp == null) {
throw new RuntimeException("Removing PipeControlPoint " + this+ " structure damaged, no offset control point");
}
PipeRun previousRun = previous.getPipeRun();
nextPipeRun.setPipeDiameter(previousRun.getPipeDiameter());
+ nextPipeRun.setPipeThickness(previousRun.getPipeThickness());
nextPipeRun.setTurnRadiusArray(previousRun.getTurnRadiusArray());
PipelineComponent n = next.getPipelineComponent();
public void setOrientation(Quat4d orientation) {
if (MathTools.equals(orientation, getOrientation()))
return;
+ if (getPipelineComponent() != null && (getPipelineComponent() instanceof Nozzle))
+ System.out.println();
super.setOrientation(orientation);
if (getParentPoint() == null && component != null)
component._setWorldOrientation(getWorldOrientation());
component._setWorldPosition(getWorldPosition());
updateSubPoint();
}
-
+
private void updateSubPoint() {
if (isOffset()) {
if (next == null && previous == null) {
updateSubPoint();
}
+ public void orientToDirection(Vector3d dir) {
+ Double angleO = getRotationAngle();
+ double angle = 0.0;
+ if (angleO != null)
+ angle = angleO;
+ boolean reversed = _getReversed();
+ Quat4d q = null;
+ if (dir != null) {
+ q = getControlPointOrientationQuat(dir, angle, reversed);
+ } else {
+ q = getControlPointOrientationQuat(angle, reversed);
+ }
+ setWorldOrientation(q);
+ }
+
@Override
public String toString() {
return getClass().getName() + "@" + Integer.toHexString(hashCode());