X-Git-Url: https://gerrit.simantics.org/r/gitweb?a=blobdiff_plain;f=org.simantics.plant3d%2Fsrc%2Forg%2Fsimantics%2Fplant3d%2Fscenegraph%2Fcontrolpoint%2FPipeControlPoint.java;fp=org.simantics.plant3d%2Fsrc%2Forg%2Fsimantics%2Fplant3d%2Fscenegraph%2Fcontrolpoint%2FPipeControlPoint.java;h=02bce62246e8748612ac72f7e2b64afae4da06de;hb=22bb24d2a7e26c70b0dd4c57080f2c25ac3d40a8;hp=0000000000000000000000000000000000000000;hpb=16ec8075f708c6589937f8e760f8074ba27d86c4;p=simantics%2F3d.git diff --git a/org.simantics.plant3d/src/org/simantics/plant3d/scenegraph/controlpoint/PipeControlPoint.java b/org.simantics.plant3d/src/org/simantics/plant3d/scenegraph/controlpoint/PipeControlPoint.java new file mode 100644 index 00000000..02bce622 --- /dev/null +++ b/org.simantics.plant3d/src/org/simantics/plant3d/scenegraph/controlpoint/PipeControlPoint.java @@ -0,0 +1,1077 @@ +package org.simantics.plant3d.scenegraph.controlpoint; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +import javax.vecmath.AxisAngle4d; +import javax.vecmath.Matrix3d; +import javax.vecmath.Quat4d; +import javax.vecmath.Tuple3d; +import javax.vecmath.Vector3d; + +import org.simantics.g3d.math.MathTools; +import org.simantics.g3d.property.annotations.GetPropertyValue; +import org.simantics.g3d.scenegraph.G3DNode; +import org.simantics.plant3d.scenegraph.IP3DNode; +import org.simantics.plant3d.scenegraph.PipeRun; +import org.simantics.plant3d.scenegraph.PipelineComponent; + +import vtk.vtkRenderer; + + +public class PipeControlPoint extends G3DNode implements IP3DNode { + + public enum Type{INLINE,TURN,END}; + public enum Direction{NEXT,PREVIOUS}; + public enum PositionType {SPLIT,NEXT,PREVIOUS,PORT} + + private PipelineComponent component; + + private Type type; + private boolean fixed = true; + private boolean deletable = true; + private boolean sub = false; + + public PipeControlPoint(PipelineComponent component) { + this.component = component; + if (component.getPipeRun() != null) + component.getPipeRun().addChild(this); + + } + + public PipeControlPoint(PipelineComponent component, PipeRun piperun) { + this.component = component; + piperun.addChild(this); + } + + @Override + public void update(vtkRenderer ren) { + try { + PipingRules.requestUpdate(this); + } catch (Exception e) { + e.printStackTrace(); + } + + } + + public PipeRun getPipeRun() { + return (PipeRun)getParent(); + } + + public PipelineComponent getPipelineComponent() { + return component; + } + + public Type getType() { + return type; + } + + public void setType(Type type) { + this.type = type; + } + + @GetPropertyValue(name="Fixed",tabId="Debug",value="fixed") + public boolean isFixed() { + return fixed; + } + + + public void setFixed(boolean fixed) { + this.fixed = fixed; + } + + public void setSub(boolean sub) { + this.sub = sub; + } + + @GetPropertyValue(name="Deletable",tabId="Debug",value="deletable") + public boolean isDeletable() { + return deletable; + } + + public void setDeletable(boolean deletable) { + this.deletable = deletable; + } + + public boolean isPathLegEnd() { + return type != Type.INLINE; + } + + public boolean isEnd() { + return type == Type.END; + } + + public boolean isTurn() { + return type == Type.TURN; + } + + public boolean isInline() { + return type == Type.INLINE; + } + + public boolean isDirected() { + return fixed && isEnd(); + } + + public boolean isNonDirected() { + return !fixed && isEnd(); + } + + public boolean isVariableLength() { + return !fixed && isInline(); + } + + public boolean isVariableAngle() { + return !fixed && isTurn(); + } + + public boolean isBranchEnd() { + return deletable && isEnd(); + } + + public boolean isOffset() { + return offset != null; + } + + public boolean isDualSub() { + return parent != null && sub; + } + + public boolean isDualInline() { + return children.size() == 1 && children.get(0).isDualSub(); + } + + public boolean isSizeChange() { + if (children.size() == 0) + return false; + if (!isDualInline()) + return false; + return getPipeRun() != children.get(0).getPipeRun(); + } + + + private PipeControlPoint next; + private PipeControlPoint previous; + + public PipeControlPoint getNext() { + return next; + } + + public PipeControlPoint getPrevious() { + return previous; + } + + public void setNext(PipeControlPoint next) { + if (isEnd() && previous != null && next != null) + throw new RuntimeException("End control points are allowed to have only one connection"); +// if (next != null && getPipeRun() == null) +// throw new RuntimeException("Cannot connect control point befor piperun has been set"); + this.next = next; + if (component != null) { + if (parent == null || sub) + component.setNext(next != null ? next.component : null); + else + component.setBranch0(next != null ? next.component : null); + } + } + + public void setPrevious(PipeControlPoint previous) { + if (isEnd() && next != null && previous != null) + throw new RuntimeException("End control points are allowed to have only one connection"); +// if (previous != null && getPipeRun() == null) +// throw new RuntimeException("Cannot connect control point befor piperun has been set"); + this.previous = previous; + if (component != null) + if (parent == null || sub) + component.setPrevious(previous != null ? previous.component : null); + else + component.setBranch0(previous != null ? previous.component : null); + } + + public PipeControlPoint parent; + public List children = new ArrayList(); + + public List getSubPoint() { + return children; + } + + public PipeControlPoint getParentPoint() { + return parent; + } + + + + + + + + + private double length; + private Double turnAngle; + private Vector3d turnAxis; + + private Double offset; + private Double rotationAngle; + + @GetPropertyValue(name="Length",tabId="Debug",value="length") + public double getLength() { + return length; + } + + public void setLength(double l) { + if (Double.isInfinite(l) || Double.isNaN(l)) { + return; + } + if (Math.abs(this.length-l) < MathTools.NEAR_ZERO) + return; + this.length = l; + firePropertyChanged("length"); + if (isDualInline()) + getSubPoint().get(0).setLength(l); + } + + @GetPropertyValue(name="Turn Angle",tabId="Debug",value="turnAngle") + public Double getTurnAngle() { + return turnAngle; + } + + @GetPropertyValue(name="Turn Axis",tabId="Debug",value="turnAxis") + public Vector3d getTurnAxis() { + return turnAxis; + } + + @GetPropertyValue(name="Offset",tabId="Debug",value="offset") + public Double getOffset() { + return offset; + } + + @GetPropertyValue(name="Rotation Angle",tabId="Debug",value="rotationAngle") + public Double getRotationAngle() { + return rotationAngle; + } + + public void setTurnAngle(Double turnAngle) { + if (Double.isInfinite(turnAngle) || Double.isNaN(turnAngle)) { + return; + } + if (this.turnAngle != null && Math.abs(this.turnAngle-turnAngle) < MathTools.NEAR_ZERO) + return; + this.turnAngle = turnAngle; + firePropertyChanged("turnAngle"); + } + + public void setTurnAxis(Vector3d turnAxis) { + this.turnAxis = turnAxis; + firePropertyChanged("turnAxis"); + } + + public void setOffset(Double offset) { + if (Double.isInfinite(offset) || Double.isNaN(offset)) { + return; + } + if (this.offset != null && Math.abs(this.offset-offset) < MathTools.NEAR_ZERO) + return; + this.offset = offset; + firePropertyChanged("offset"); + } + + public void setRotationAngle(Double rotationAngle) { + if (Double.isInfinite(rotationAngle) || Double.isNaN(rotationAngle)) { + return; + } + if (this.rotationAngle != null && Math.abs(this.rotationAngle-rotationAngle) < MathTools.NEAR_ZERO) + return; + this.rotationAngle = rotationAngle; + firePropertyChanged("rotationAngle"); + } + + public Vector3d getSizeChangeOffsetVector(Vector3d dir) { + if (rotationAngle == null) + rotationAngle = 0.0; + Quat4d q = getControlPointOrientationQuat(dir, rotationAngle); + Vector3d v = new Vector3d(0.0,0.0,offset); + Vector3d offset = new Vector3d(); + MathTools.rotate(q, v, offset); + return offset; + } + + @GetPropertyValue(name="Next",tabId="Debug",value="next") + private String getNextString() { + if (next == null) + return null; + return next.toString(); + } + + @GetPropertyValue(name="Previous",tabId="Debug",value="previous") + private String getPrevString() { + if (previous == null) + return null; + return previous.toString(); + } + + public Quat4d getControlPointOrientationQuat(double angle) { + + if (turnAxis == null) { + Vector3d dir = getPathLegDirection(Direction.NEXT); + if (dir.lengthSquared() > MathTools.NEAR_ZERO) + dir.normalize(); + 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 static Quat4d getControlPointOrientationQuat(Vector3d dir, double angle) { + if (dir.lengthSquared() < MathTools.NEAR_ZERO) + return MathTools.getIdentityQuat(); + + + Vector3d up = new Vector3d(0.0, 1.0, 0.0); + double a = up.angle(dir); + if (a < 0.1 || (Math.PI - a) < 0.1) { + up.set(1.0, 0.0, 0.0); + } + + + return getControlPointOrientationQuat(dir, up, angle); + } + + public static Quat4d getControlPointOrientationQuat(Vector3d dir, Vector3d up, double angle) { + if (dir.lengthSquared() < MathTools.NEAR_ZERO) + return MathTools.getIdentityQuat(); + + final Vector3d front = new Vector3d(1.0,0.0,0.0); + + Quat4d q1 = new Quat4d(); + + + Vector3d right = new Vector3d(); + + right.cross(dir, up); + up.cross(right, dir); + right.normalize(); + up.normalize(); + + Matrix3d m = new Matrix3d(); + m.m00 = dir.x; + m.m10 = dir.y; + m.m20 = dir.z; + m.m01 = up.x; + m.m11 = up.y; + m.m21 = up.z; + m.m02 = right.x; + m.m12 = right.y; + m.m22 = right.z; + + //q1.set(m); MathTools contains more stable conversion + MathTools.getQuat(m, q1); + +// if (DEBUG) System.out.println("PipingTools.getPipeComponentOrientationQuat() " + dir+ " " + up + " " + right); + + Quat4d q2 = new Quat4d(); + q2.set(new AxisAngle4d(front, angle)); + q1.mul(q2); + return q1; + } + + public Vector3d getDirection() { + return getDirectedControlPointDirection(); + } + + + + + + + + public void insert(PipeControlPoint previous, PipeControlPoint next) { + // inserting an offsetpoint is error, + if (isDualSub()) + throw new RuntimeException(); + // size change control point cannot be inserted this way, because it ends PipeRun + if (isSizeChange()) + throw new RuntimeException(); + PipeRun piperun = previous.getPipeRun(); + // and just to make sure that control point structure is not corrupted + if (getPipeRun() != null) { + if (piperun != getPipeRun() || piperun != next.getPipeRun()) + throw new RuntimeException(); + } else { + piperun.addChild(this); + } + + // insert new BranchControlPoint between straight's control points + PipeControlPoint previousNext = previous.getNext(); + PipeControlPoint previousPrevious = previous.getPrevious(); + + PipeControlPoint offsetCP = null; + if (isOffset()) { + offsetCP = getSubPoint().get(0); + } + if (previousNext != null && previousNext == next) { + if (previous.isDualInline()) { + throw new RuntimeException(); + } + if (next.isDualSub()) { + throw new RuntimeException(); + } + previous.setNext(this); + this.setPrevious(previous); + if (previous.isDualSub()) { + previous.getParentPoint().setNext(this); + } + this.setNext(next); + + if (offsetCP == null) { + next.setPrevious(this); + } else { + next.setPrevious(offsetCP); + offsetCP.setNext(next); + offsetCP.setPrevious(previous); + } + + if (next.isDualInline()) { + next.getSubPoint().get(0).setPrevious(this); + } + } else if (previousPrevious != null && previousPrevious == next) { + // control point were given in reverse order + if (next.isDualInline()) + throw new RuntimeException(); + if (previous.isDualSub()) + throw new RuntimeException(); + + this.setNext(previous); + if (offsetCP == null) { + previous.setNext(this); + } else { + previous.setPrevious(offsetCP); + offsetCP.setNext(previous); + offsetCP.setPrevious(next); + } + if (previous.isDualInline()) { + previous.getSubPoint().get(0).setPrevious(this); + } + this.setPrevious(next); + next.setNext(this); + if (next.isDualSub()) { + next.getParentPoint().setNext(this); + } + + } else { + throw new RuntimeException(); + } + + PipingRules.validate(piperun); + } + + + + public void insert(PipeControlPoint pcp, Direction direction) { + if (isDualSub()) + throw new RuntimeException(); + if (direction == Direction.NEXT) { + // if direction is next, user must have given OffsetPoint + if (pcp.isDualInline()) + throw new RuntimeException(); + // basic next/prev links + pcp.setNext(this); + this.setPrevious(pcp); + // and last take care of sizechange / offset points + if (pcp.isDualSub()) { + pcp.getParentPoint().setNext(this); + } + if (isDualInline()) { + getSubPoint().get(0).setPrevious(this); + } + } else { + // if direction is previous, user must have given sizechange + if (pcp.isDualSub()) + throw new RuntimeException(); + // previous direction is more complicated, since if newCP is SizeChangeControlPoint, + // we must link pcp to newCP's OffsetPoint + PipeControlPoint nocp = null; + if (isDualInline()) { + nocp = getSubPoint().get(0); + nocp.setNext(pcp); + } + if (nocp == null) { + pcp.setPrevious(this); + } else { + pcp.setPrevious(nocp); + } + this.setNext(pcp); + if (pcp.isDualInline()) { + PipeControlPoint ocp = pcp.getSubPoint().get(0); + if (nocp == null) + ocp.setPrevious(this); + else + ocp.setPrevious(nocp); + } + + } + PipingRules.validate(getPipeRun()); + } + + public Vector3d getDirectedControlPointDirection() { + assert (isDirected()); + Vector3d dir = new Vector3d(); + MathTools.rotate(getWorldOrientation(), new Vector3d(1.0, 0.0, 0.0), dir); + dir.normalize(); + return dir; + } + + public Vector3d getPathLegDirection(Direction direction) { + if (direction == Direction.NEXT) { + if (next != null) { + PipeControlPoint pcp = this; + if (pcp.isDualInline()) { + pcp = pcp.getSubPoint().get(0); + } + Vector3d v = new Vector3d(); + v.sub(next.getWorldPosition(),pcp.getWorldPosition()); + return v; + } else { + if (isVariableAngle()) + throw new RuntimeException("Cannot calculate path leg direction for unconnected variable angle control point"); + if (previous == null) { + if (!isDirected()) + throw new RuntimeException("Cannot calculate path leg direction for unconnected control point"); + return getDirectedControlPointDirection(); + + } else { + if (isInline()) { + Vector3d v = new Vector3d(); + v.sub(getWorldPosition(),previous.getWorldPosition()); + return v; + } else if (isDirected()) { + return getDirectedControlPointDirection(); + } else if (isEnd()) { + Vector3d v = new Vector3d(); + v.sub(getWorldPosition(),previous.getWorldPosition()); + return v; + } + throw new RuntimeException("Missing implementation"); + } + } + } 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 (isVariableAngle()) + throw new RuntimeException("Cannot calculate path leg direction for unconnected variable angle control point"); + if (next == null) { + if (!isDirected()) + throw new RuntimeException("Cannot calculate path leg direction for unconnected control point"); + Vector3d v = getDirectedControlPointDirection(); + v.negate(); + return v; + } else { + if (isInline()) { + Vector3d v = new Vector3d(); + v.sub(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; + } + throw new RuntimeException("Missing implementation"); + } + } + } + } + + public void getInlineControlPointEnds(Tuple3d p1, Tuple3d p2) { + assert (isInline()); + + Vector3d pos = getWorldPosition(); + Vector3d dir = getPathLegDirection(Direction.NEXT); + dir.normalize(); + dir.scale(length * 0.5); + p1.set(pos); + p2.set(pos); + p1.sub(dir); + p2.add(dir); + } + + public void getControlPointEnds(Tuple3d p1, Tuple3d p2) { + Vector3d pos = getWorldPosition(); + Vector3d dir1 = getPathLegDirection(Direction.PREVIOUS); + dir1.normalize(); + Vector3d dir2 = getPathLegDirection(Direction.NEXT); + dir2.normalize(); + if (isInline()) { + dir1.scale(length * 0.5); + dir2.scale(length * 0.5); + } else { + dir1.scale(length); + dir2.scale(length); + } + p1.set(pos); + p2.set(pos); + p1.add(dir1); + p2.add(dir2); + } + + public void getInlineControlPointEnds(Tuple3d p1, Tuple3d p2, Vector3d dir) { + assert (isInline()); + + Vector3d pos = getWorldPosition(); + dir.set(getPathLegDirection(Direction.NEXT)); + dir.normalize(); + dir.scale(length * 0.5); + p1.set(pos); + p2.set(pos); + p1.sub(dir); + p2.add(dir); + } + + public void getInlineControlPointEnds(Tuple3d center, Tuple3d p1, Tuple3d p2, Vector3d dir) { + assert (isInline()); + + Vector3d pos = getWorldPosition(); + center.set(pos); + dir.set(getPathLegDirection(Direction.NEXT)); + dir.normalize(); + dir.scale(length * 0.5); + p1.set(pos); + p2.set(pos); + p1.sub(dir); + p2.add(dir); + } + + public double getInlineLength() { + if (type == Type.TURN) + return length; + else if (type == Type.INLINE) + return length * 0.5; + return 0; + } + + public Vector3d getRealPosition(PositionType type) { + Vector3d pos = getWorldPosition(); + switch (type) { + case NEXT: { + Vector3d dir = getPathLegDirection(Direction.NEXT); + double length = getInlineLength(); + dir.normalize(); + dir.scale(length); + pos.add(dir); + break; + } + case PREVIOUS: { + Vector3d dir = getPathLegDirection(Direction.PREVIOUS); + double length = getInlineLength(); + dir.normalize(); + dir.scale(length); + pos.add(dir); + break; + } + case PORT: + // IEntity portDir = pcp.getSingleRelatedObject(ProcessResource.plant3Dresource.HasDirection); + // TODO : how we calculated needed space for a port; does it has an offset from control point's position or not? + break; + case SPLIT: + // do nothing + break; + + } + return pos; + } + + public void getInlineMovement(Tuple3d start, Tuple3d end) { + // FIXME : check type of neighbor components and allow movement on top of variable length components, + // find proper range for movement (pcp's position is not) + PipeControlPoint p = previous.getPrevious(); + PipeControlPoint n = next.getNext(); + start.set(p.getWorldPosition()); + end.set(n.getWorldPosition()); + } + + public PipeControlPoint findNextEnd() { + ArrayList t = new ArrayList(); + return findNextEnd( t); + } + + public PipeControlPoint findPreviousEnd() { + ArrayList t = new ArrayList(); + return findPreviousEnd(t); + } + + public PipeControlPoint findNextEnd(List nextList) { + while (true) { + PipeControlPoint pcp = null; + PipeControlPoint p = null; + if (nextList.size() == 0) + p = this; + + else + p = nextList.get(nextList.size() - 1); + + pcp = p.getNext(); + if (pcp == null) { + pcp = p; + if (nextList.size() > 0) + nextList.remove(nextList.size() - 1); +// if (DEBUG) System.out.println(" " + pcp.getResource() + " not full"); + return pcp; + //break; + } + if (pcp.isPathLegEnd()) { + //if (DEBUG) System.out.println(" " + pcp.getResource()); + return pcp; + } else { + nextList.add(pcp); + // if (DEBUG) System.out.print(" " + pcp.getResource()); + } + } + } + + public PipeControlPoint findPreviousEnd(List prevList) { + while (true) { + PipeControlPoint pcp = null; + PipeControlPoint p = null; + if (prevList.size() == 0) + p = this; + + else + p = prevList.get(prevList.size() - 1); + + pcp = p.getPrevious(); + if (pcp == null) { + pcp = p; + if (prevList.size() > 0) + prevList.remove(prevList.size() - 1); +// if (DEBUG) System.out.println(" " + pcp.getResource() + " not full"); + return pcp; + } + if (pcp.isPathLegEnd()) { +// if (DEBUG) System.out.println(" " + pcp.getResource()); + return pcp; + } else { + prevList.add(pcp); +// if (DEBUG)System.out.print(" " + pcp.getResource()); + } + } + } + + public void _remove() { + if (component == null && next == null && previous == null) + return; + if (isDualInline() || isDualSub()) { + removeDualPoint(); + return; + } + PipeRun pipeRun = getPipeRun(); + if (pipeRun == null) + return; + + PipeControlPoint additionalRemove = null; + if (!PipingRules.isEnabled()) { + setPrevious(null); + setNext(null); + } else { + + PipeControlPoint currentPrev = previous; + PipeControlPoint currentNext = next; + if (currentNext == null && currentPrev == null) { + removeComponent(); + pipeRun.remChild(this); + return; + } + if (currentNext != null && currentPrev != null) { + boolean link = true; + if (currentNext.isBranchEnd()) { + link = false; +// currentNext.setPrevious(null); +// currentNext.setNext(null); + currentNext.remove(); + currentNext = null; + setNext(null); + } + if (currentPrev.isBranchEnd()) { + link = false; +// currentPrev.setPrevious(null); +// currentPrev.setNext(null); + currentPrev.remove(); + currentPrev = null; + setPrevious(null); + } + if (link && currentPrev.isDirected() && currentNext.isDirected()) { + link = false; + } + if (currentNext == null) { + // Nothing to do + } else if (currentNext.isDualInline()) { + PipeControlPoint sccp = currentNext; + PipeControlPoint ocp = sccp.getSubPoint().get(0); + if (ocp == null) { + throw new RuntimeException("Removing PipeControlPoint " + this+ " structure damaged, no offset control point"); + } + if (link) { + sccp.setPrevious(currentPrev); + ocp.setPrevious(currentPrev); + } else { + sccp.setPrevious(null); + ocp.setPrevious(null); + } + setNext(null); + } else if (currentNext.isDualSub()) { + throw new RuntimeException("Removing PipeControlPoint " + this + " structure damaged, next control point is offset control point"); + } else if (currentNext.previous == this) { + if (link) { + currentNext.setPrevious(currentPrev); + } else { + currentNext.setPrevious(null); + } + setNext(null); + } else { + throw new RuntimeException("Removing PipeControlPoint "+ this+ " structure damaged"); + } + if (currentPrev == null) { + // Nothing to do + } else if (currentPrev.isDualInline()) { + throw new RuntimeException("Removing PipeControlPoint " + this + " structure damaged, previous control point is size change control point"); + } else if (currentPrev.isDualSub()) { + PipeControlPoint ocp = currentPrev; + PipeControlPoint sccp = ocp.getParentPoint(); + if (sccp == null) + throw new RuntimeException("Removing PipeControlPoint " + this + " structure damaged, no size change control point"); + if (link) { + ocp.setNext(currentNext); + sccp.setNext(currentNext); + } else { + ocp.setNext(null); + sccp.setNext(null); + } + setPrevious(null); + } else if (currentPrev.next == this) { + if (link) + currentPrev.setNext(currentNext); + else + currentPrev.setNext(null); + + setPrevious(null); + } else { + throw new RuntimeException("Removing PipeControlPoint " + this + " structure damaged"); + } + if (link) { + if (currentNext.isVariableLength() && currentPrev.isVariableLength()) { + // we have to join them into single variable length component. + additionalRemove = currentPrev; + //currentPrev.remove(); + } + } else { + // FIXME : pipe run must be split into two parts, since the control point structure is no more continuous. + } + } else if (next != null) { + if (next.isDualInline()) { + PipeControlPoint sccp = next; + PipeControlPoint ocp = sccp.getSubPoint().get(0); + if (ocp == null) { + throw new RuntimeException("Removing PipeControlPoint " + this+ " structure damaged, no offset control point"); + } + sccp.setPrevious(null); + ocp.setPrevious(null); + } else if (next.isDualSub()) { + throw new RuntimeException("Removing PipeControlPoint " + this + " structure damaged, next control point is offset control point"); + } else if (next.previous == this) { + next.setPrevious(null); + } else { + throw new RuntimeException("Removing PipeControlPoint "+ this+ " structure damaged"); + } + setNext(null); + } else { //(previous != null) + if(previous.isDualInline()) { + throw new RuntimeException("Removing PipeControlPoint " + this + " structure damaged, previous control point is size change control point"); + } else if (previous.isDualSub()) { + PipeControlPoint ocp = previous; + PipeControlPoint sccp = ocp.getParentPoint(); + if (sccp == null) { + throw new RuntimeException("Removing PipeControlPoint " + this + " structure damaged, no size change control point"); + } + ocp.setNext(null); + sccp.setNext(null); + } else if (previous.next == this) { + previous.setNext(null); + } else { + throw new RuntimeException("Removing PipeControlPoint "+ this+ " structure damaged"); + } + setPrevious(null); + } + if (children.size() > 0 ) { + removeSubPoints(); + } else if (parent!= null) { + removeParentPoint(); + } + + } + + removeComponent(); + pipeRun.remChild(this); + checkRemove(pipeRun); + if (PipingRules.isEnabled() && pipeRun.getParent() != null && pipeRun.getControlPoints().size() > 0) + PipingRules.validate(pipeRun); + if (additionalRemove != null) + additionalRemove.remove(); + } + + public void remove() { + PipeControlPoint currentPrev = previous; + PipeControlPoint currentNext = next; + _remove(); + try { + if (currentNext != null) + PipingRules.requestUpdate(currentNext); + if (currentPrev != null) + PipingRules.requestUpdate(currentPrev); + } catch (Exception e) { + e.printStackTrace(); + } + } + + private void checkRemove(PipeRun pipeRun) { + Collection points = pipeRun.getControlPoints(); + if (points.size() == 0) { + pipeRun.remove(); + } else if (points.size() == 1) { + PipeControlPoint pcp = points.iterator().next(); + if (pcp.isDeletable()) + pcp._remove(); + } + } + + private void removeDualPoint() { + if (previous != null) + previous.setNext(null); + if (next != null) + next.setPrevious(null); + PipeControlPoint ocp; + PipeControlPoint sccp; + if (isDualInline()) { + sccp = this; + ocp = getSubPoint().get(0); + } else { + ocp = this; + sccp = getParentPoint(); + } + PipeRun p1 = ocp.getPipeRun(); + PipeRun p2 = sccp.getPipeRun(); + + ocp.removeComponent(); + sccp.removeComponent(); + + p1.remChild(ocp); + p2.remChild(sccp); + + ocp.setNext(null); + ocp.setPrevious(null); + sccp.setNext(null); + sccp.setPrevious(null); + + checkRemove(p1); + checkRemove(p2); + } + + private void removeSubPoints() { + for (PipeControlPoint p : children) { + // TODO : this may affect delete routine, since classification of the point changes. + p.parent = null; + p._remove(); + } + children.clear(); + } + + private void removeParentPoint() { + throw new RuntimeException("Child points cannot be removed directly"); + } + + private void removeComponent() { + if (component == null) + return; + PipelineComponent next = component.getNext(); + PipelineComponent prev = component.getNext(); + if (next != null) { + if (next.getNext() == component) + next.setNext(null); + else if (next.getPrevious() == component) + next.setPrevious(null); + } + if (prev != null) { + if (prev.getNext() == component) + prev.setNext(null); + else if (prev.getPrevious() == component) + prev.setPrevious(null); + } + PipelineComponent comp = component; + component = null; + comp.remove(); + } + + @Override + public void setOrientation(Quat4d orientation) { + if (MathTools.equals(orientation, getOrientation())) + return; + super.setOrientation(orientation); + if (getParentPoint() == null && component != null) + component._setWorldOrientation(getWorldOrientation()); + for (PipeControlPoint sub : getSubPoint()) { + sub.setWorldPosition(getWorldPosition()); + sub.setWorldOrientation(getWorldOrientation()); + } + } + + @Override + public void setPosition(Vector3d position) { + if (MathTools.equals(position, getPosition())) + return; + super.setPosition(position); + if (getParentPoint() == null && component != null) + component._setWorldPosition(getWorldPosition()); + for (PipeControlPoint sub : getSubPoint()) { + sub.setWorldPosition(getWorldPosition()); + sub.setWorldOrientation(getWorldOrientation()); + } + } + + + public void _setWorldPosition(Vector3d position) { + Vector3d localPos = getLocalPosition(position); + super.setPosition(localPos); + for (PipeControlPoint sub : getSubPoint()) { + sub.setWorldPosition(getWorldPosition()); + sub.setWorldOrientation(getWorldOrientation()); + } + } + + public void _setWorldOrientation(Quat4d orientation) { + Quat4d localOr = getLocalOrientation(orientation); + super.setOrientation(localOr); + for (PipeControlPoint sub : getSubPoint()) { + sub.setWorldPosition(getWorldPosition()); + sub.setWorldOrientation(getWorldOrientation()); + } + } + + @Override + public String toString() { + return getClass().getName() + "@" + Integer.toHexString(hashCode()); + } + +}