1 package org.simantics.plant3d.scenegraph.controlpoint;
3 import java.util.ArrayList;
4 import java.util.Arrays;
5 import java.util.Collection;
8 import javax.vecmath.AxisAngle4d;
9 import javax.vecmath.Matrix3d;
10 import javax.vecmath.Quat4d;
11 import javax.vecmath.Tuple3d;
12 import javax.vecmath.Vector3d;
14 import org.simantics.g3d.math.MathTools;
15 import org.simantics.g3d.property.annotations.GetPropertyValue;
16 import org.simantics.g3d.scenegraph.G3DNode;
17 import org.simantics.plant3d.scenegraph.IP3DNode;
18 import org.simantics.plant3d.scenegraph.PipeRun;
19 import org.simantics.plant3d.scenegraph.PipelineComponent;
21 import vtk.vtkRenderer;
24 public class PipeControlPoint extends G3DNode implements IP3DNode {
26 public enum Type{INLINE,TURN,END};
27 public enum Direction{NEXT,PREVIOUS};
28 public enum PositionType {SPLIT,NEXT,PREVIOUS,PORT}
30 private PipelineComponent component;
33 private boolean fixed = true;
34 private boolean rotate = false;
35 private boolean reverse = false;
36 private boolean deletable = true;
37 private boolean sub = false;
39 public PipeControlPoint(PipelineComponent component) {
40 this.component = component;
41 if (component.getPipeRun() != null)
42 component.getPipeRun().addChild(this);
46 public PipeControlPoint(PipelineComponent component, PipeRun piperun) {
47 this.component = component;
48 piperun.addChild(this);
52 public void update(vtkRenderer ren) {
54 PipingRules.requestUpdate(this);
55 } catch (Exception e) {
61 public PipeRun getPipeRun() {
62 return (PipeRun)getParent();
65 public PipelineComponent getPipelineComponent() {
69 public Type getType() {
73 public void setType(Type type) {
77 @GetPropertyValue(name="Fixed",tabId="Debug",value="fixed")
78 public boolean isFixed() {
83 public void setFixed(boolean fixed) {
87 @GetPropertyValue(name="Rotate",tabId="Debug",value="rotate")
88 public boolean isRotate() {
92 public void setRotate(boolean rotate) {
96 @GetPropertyValue(name="Reverse",tabId="Debug",value="reverse")
97 public boolean isReverse() {
101 public void setReverse(boolean reverse) {
102 this.reverse = reverse;
105 public void setSub(boolean sub) {
109 @GetPropertyValue(name="Deletable",tabId="Debug",value="deletable")
110 public boolean isDeletable() {
114 public void setDeletable(boolean deletable) {
115 this.deletable = deletable;
118 public boolean isPathLegEnd() {
119 return type != Type.INLINE;
122 public boolean isEnd() {
123 return type == Type.END;
126 public boolean isTurn() {
127 return type == Type.TURN;
130 public boolean isInline() {
131 return type == Type.INLINE;
134 public boolean isDirected() {
135 return fixed && isEnd();
138 public boolean isNonDirected() {
139 return !fixed && isEnd();
142 public boolean isVariableLength() {
143 return !fixed && isInline();
146 public boolean isVariableAngle() {
147 return !fixed && isTurn();
150 public boolean isBranchEnd() {
151 return deletable && isEnd();
154 public boolean isOffset() {
155 return offset != null;
158 public boolean isDualSub() {
159 return parent != null && sub;
162 public boolean isDualInline() {
163 return children.size() == 1 && children.get(0).isDualSub();
166 public boolean isSizeChange() {
167 if (children.size() == 0)
171 return getPipeRun() != children.get(0).getPipeRun();
175 private PipeControlPoint next;
176 private PipeControlPoint previous;
178 public PipeControlPoint getNext() {
182 public PipeControlPoint getPrevious() {
186 public void setNext(PipeControlPoint next) {
187 if (isEnd() && previous != null && next != null)
188 throw new RuntimeException("End control points are allowed to have only one connection");
189 // if (next != null && getPipeRun() == null)
190 // throw new RuntimeException("Cannot connect control point befor piperun has been set");
192 if (component != null) {
193 if (parent == null || sub)
194 component.setNext(next != null ? next.component : null);
196 component.setBranch0(next != null ? next.component : null);
202 public void setPrevious(PipeControlPoint previous) {
203 if (isEnd() && next != null && previous != null)
204 throw new RuntimeException("End control points are allowed to have only one connection");
205 // if (previous != null && getPipeRun() == null)
206 // throw new RuntimeException("Cannot connect control point befor piperun has been set");
207 this.previous = previous;
208 if (component != null) {
209 if (parent == null || sub)
210 component.setPrevious(previous != null ? previous.component : null);
212 component.setBranch0(previous != null ? previous.component : null);
218 public PipeControlPoint parent;
219 public List<PipeControlPoint> children = new ArrayList<PipeControlPoint>();
221 public List<PipeControlPoint> getSubPoint() {
225 public PipeControlPoint getParentPoint() {
236 private double length;
237 private Double turnAngle;
238 private Vector3d turnAxis;
240 private Double offset;
241 private Double rotationAngle;
242 private Boolean reversed;
244 @GetPropertyValue(name="Length",tabId="Debug",value="length")
245 public double getLength() {
249 public void setLength(double l) {
250 if (Double.isInfinite(l) || Double.isNaN(l)) {
253 if (Math.abs(this.length-l) < MathTools.NEAR_ZERO)
256 firePropertyChanged("length");
258 getSubPoint().get(0).setLength(l);
261 @GetPropertyValue(name="Turn Angle",tabId="Debug",value="turnAngle")
262 public Double getTurnAngle() {
266 @GetPropertyValue(name="Turn Axis",tabId="Debug",value="turnAxis")
267 public Vector3d getTurnAxis() {
271 @GetPropertyValue(name="Offset",tabId="Debug",value="offset")
272 public Double getOffset() {
276 @GetPropertyValue(name="Rotation Angle",tabId="Debug",value="rotationAngle")
277 public Double getRotationAngle() {
278 return rotationAngle;
281 @GetPropertyValue(name="Reversed",tabId="Debug",value="reversed")
282 public Boolean getReversed() {
286 public boolean _getReversed() {
287 if (reversed == null)
292 public void setTurnAngle(Double turnAngle) {
293 if (Double.isInfinite(turnAngle) || Double.isNaN(turnAngle)) {
296 if (this.turnAngle != null && Math.abs(this.turnAngle-turnAngle) < MathTools.NEAR_ZERO)
298 this.turnAngle = turnAngle;
299 firePropertyChanged("turnAngle");
302 public void setTurnAxis(Vector3d turnAxis) {
303 this.turnAxis = turnAxis;
304 firePropertyChanged("turnAxis");
307 public void setOffset(Double offset) {
308 if (Double.isInfinite(offset) || Double.isNaN(offset)) {
311 if (this.offset != null && Math.abs(this.offset-offset) < MathTools.NEAR_ZERO)
313 this.offset = offset;
314 firePropertyChanged("offset");
317 public void setRotationAngle(Double rotationAngle) {
318 if (Double.isInfinite(rotationAngle) || Double.isNaN(rotationAngle)) {
321 if (this.rotationAngle != null && Math.abs(this.rotationAngle-rotationAngle) < MathTools.NEAR_ZERO)
323 this.rotationAngle = rotationAngle;
324 firePropertyChanged("rotationAngle");
327 public void setReversed(Boolean reversed) {
328 this.reversed = reversed;
329 firePropertyChanged("reversed");
332 public Vector3d getSizeChangeOffsetVector(Vector3d dir) {
334 if (rotationAngle == null)
335 q = getControlPointOrientationQuat(dir, 0.0);
337 q = getControlPointOrientationQuat(dir, rotationAngle);
338 Vector3d v = new Vector3d(0.0,offset,0.0);
339 Vector3d offset = new Vector3d();
340 MathTools.rotate(q, v, offset);
344 public Vector3d getSizeChangeOffsetVector() {
346 if (rotationAngle == null)
347 q = getControlPointOrientationQuat(0.0);
349 q = getControlPointOrientationQuat(rotationAngle);
350 Vector3d v = new Vector3d(0.0,offset,0.0);
351 Vector3d offset = new Vector3d();
352 MathTools.rotate(q, v, offset);
356 @GetPropertyValue(name="Next",tabId="Debug",value="next")
357 private String getNextString() {
360 return next.toString();
363 @GetPropertyValue(name="Previous",tabId="Debug",value="previous")
364 private String getPrevString() {
365 if (previous == null)
367 return previous.toString();
370 @GetPropertyValue(name="Sub",tabId="Debug",value="sub")
371 private String getSubString() {
372 if (children.size() == 0)
374 return Arrays.toString(children.toArray());
377 @GetPropertyValue(name="Type",tabId="Debug",value="type")
378 public String getTypeString() {
382 public Quat4d getControlPointOrientationQuat(double angle) {
384 if (turnAxis == null) {
385 Vector3d dir = getPathLegDirection(Direction.NEXT);
386 if (dir.lengthSquared() > MathTools.NEAR_ZERO)
388 return getControlPointOrientationQuat(dir, angle);
390 Vector3d dir = getPathLegDirection(Direction.PREVIOUS);
392 if (dir.lengthSquared() > MathTools.NEAR_ZERO)
394 return getControlPointOrientationQuat(dir, turnAxis, angle);
398 public Quat4d getControlPointOrientationQuat(double angle, boolean reversed) {
400 if (turnAxis == null) {
401 Vector3d dir = getPathLegDirection(Direction.NEXT);
402 if (dir.lengthSquared() > MathTools.NEAR_ZERO)
404 Quat4d q = getControlPointOrientationQuat(dir, angle);
406 Quat4d q2 = new Quat4d();
407 q2.set(new AxisAngle4d(MathTools.Y_AXIS, Math.PI));
412 Vector3d dir = getPathLegDirection(Direction.PREVIOUS);
414 if (dir.lengthSquared() > MathTools.NEAR_ZERO)
416 return getControlPointOrientationQuat(dir, turnAxis, angle);
422 public static Quat4d getControlPointOrientationQuat(Vector3d dir, double angle) {
423 if (dir.lengthSquared() < MathTools.NEAR_ZERO)
424 return MathTools.getIdentityQuat();
427 Vector3d up = new Vector3d(0.0, 1.0, 0.0);
428 double a = up.angle(dir);
429 if (a < 0.1 || (Math.PI - a) < 0.1) {
430 up.set(1.0, 0.0, 0.0);
434 return getControlPointOrientationQuat(dir, up, angle);
437 public static Quat4d getControlPointOrientationQuat(Vector3d dir, Vector3d up, double angle) {
438 if (dir.lengthSquared() < MathTools.NEAR_ZERO)
439 return MathTools.getIdentityQuat();
441 final Vector3d front = new Vector3d(1.0,0.0,0.0);
443 Quat4d q1 = new Quat4d();
446 Vector3d right = new Vector3d();
448 right.cross(dir, up);
449 up.cross(right, dir);
453 Matrix3d m = new Matrix3d();
464 //q1.set(m); MathTools contains more stable conversion
465 MathTools.getQuat(m, q1);
467 // if (DEBUG) System.out.println("PipingTools.getPipeComponentOrientationQuat() " + dir+ " " + up + " " + right);
469 Quat4d q2 = new Quat4d();
470 q2.set(new AxisAngle4d(front, angle));
475 public Vector3d getDirection(Direction direction) {
477 return getDirectedControlPointDirection();
478 if (isTurn() && isFixed()) {
479 if (direction == Direction.NEXT) {
480 if (previous != null) {
481 PipeControlPoint pcp = this;
482 Vector3d dir = new Vector3d();
483 dir.sub(pcp.getWorldPosition(),previous.getWorldPosition());
484 if (dir.lengthSquared() > MathTools.NEAR_ZERO)
486 Quat4d q = getControlPointOrientationQuat(dir, pcp.getRotationAngle() != null ? pcp.getRotationAngle() : 0.0);
487 AxisAngle4d aa = new AxisAngle4d(MathTools.Y_AXIS,pcp.getTurnAngle() == null ? 0.0 : pcp.getTurnAngle());
488 Quat4d q2 = MathTools.getQuat(aa);
489 Vector3d v = new Vector3d(1.,0.,0.);
490 Vector3d offset = new Vector3d();
491 MathTools.rotate(q2, v, offset);
492 MathTools.rotate(q, offset, dir);
497 PipeControlPoint pcp = this;
498 Vector3d dir = new Vector3d();
499 dir.sub(next.getWorldPosition(),pcp.getWorldPosition());
500 if (dir.lengthSquared() > MathTools.NEAR_ZERO)
502 Quat4d q = getControlPointOrientationQuat(dir, pcp.getRotationAngle() != null ? pcp.getRotationAngle() : 0.0);
503 AxisAngle4d aa = new AxisAngle4d(MathTools.Y_AXIS,pcp.getTurnAngle() == null ? 0.0 : pcp.getTurnAngle());
504 Quat4d q2 = MathTools.getQuat(aa);
505 Vector3d v = new Vector3d(1.,0.,0.);
506 Vector3d offset = new Vector3d();
507 MathTools.rotate(q2, v, offset);
508 MathTools.rotate(q, offset, dir);
516 public void insert(PipeControlPoint previous, PipeControlPoint next) {
517 // inserting an offsetpoint is error,
519 throw new RuntimeException("Dual sub points cannot be inserted.");
520 // size change control point cannot be inserted this way, because it ends PipeRun
522 throw new RuntimeException("Size change points cannot be inserted.");
523 PipeRun piperun = previous.getPipeRun();
524 // and just to make sure that control point structure is not corrupted
525 if (getPipeRun() != null) {
526 if (piperun != getPipeRun() || piperun != next.getPipeRun())
527 throw new RuntimeException("All controls points must be located on the same pipe run");
529 piperun.addChild(this);
532 // insert new BranchControlPoint between straight's control points
533 PipeControlPoint previousNext = previous.getNext();
534 PipeControlPoint previousPrevious = previous.getPrevious();
536 PipeControlPoint offsetCP = null;
538 offsetCP = getSubPoint().get(0);
540 if (previousNext != null && previousNext == next) {
541 if (previous.isDualInline()) {
542 throw new RuntimeException();
544 if (next.isDualSub()) {
545 throw new RuntimeException();
547 previous.setNext(this);
548 this.setPrevious(previous);
549 if (previous.isDualSub()) {
550 previous.getParentPoint().setNext(this);
554 if (offsetCP == null) {
555 next.setPrevious(this);
557 next.setPrevious(offsetCP);
558 offsetCP.setNext(next);
559 offsetCP.setPrevious(previous);
562 if (next.isDualInline()) {
563 next.getSubPoint().get(0).setPrevious(this);
565 } else if (previousPrevious != null && previousPrevious == next) {
566 // control point were given in reverse order
567 if (next.isDualInline())
568 throw new RuntimeException();
569 if (previous.isDualSub())
570 throw new RuntimeException();
572 this.setNext(previous);
573 if (offsetCP == null) {
574 previous.setNext(this);
576 previous.setPrevious(offsetCP);
577 offsetCP.setNext(previous);
578 offsetCP.setPrevious(next);
580 if (previous.isDualInline()) {
581 previous.getSubPoint().get(0).setPrevious(this);
583 this.setPrevious(next);
585 if (next.isDualSub()) {
586 next.getParentPoint().setNext(this);
590 throw new RuntimeException();
593 PipingRules.validate(piperun);
598 public void insert(PipeControlPoint pcp, Direction direction) {
600 throw new RuntimeException();
601 if (direction == Direction.NEXT) {
602 // if direction is next, user must have given OffsetPoint
603 if (pcp.isDualInline())
604 throw new RuntimeException();
605 // basic next/prev links
607 this.setPrevious(pcp);
608 // and last take care of sizechange / offset points
609 if (pcp.isDualSub()) {
610 pcp.getParentPoint().setNext(this);
612 if (isDualInline()) {
613 getSubPoint().get(0).setPrevious(this);
616 // if direction is previous, user must have given sizechange
618 throw new RuntimeException();
619 // previous direction is more complicated, since if newCP is SizeChangeControlPoint,
620 // we must link pcp to newCP's OffsetPoint
621 PipeControlPoint nocp = null;
622 if (isDualInline()) {
623 nocp = getSubPoint().get(0);
627 pcp.setPrevious(this);
629 pcp.setPrevious(nocp);
632 if (pcp.isDualInline()) {
633 PipeControlPoint ocp = pcp.getSubPoint().get(0);
635 ocp.setPrevious(this);
637 ocp.setPrevious(nocp);
641 PipingRules.validate(getPipeRun());
644 public Vector3d getDirectedControlPointDirection() {
645 assert (isDirected());
646 Vector3d dir = new Vector3d();
647 MathTools.rotate(getWorldOrientation(), new Vector3d(1.0, 0.0, 0.0), dir);
652 public Vector3d getPathLegDirection(Direction direction) {
653 if (direction == Direction.NEXT) {
655 PipeControlPoint pcp = this;
656 if (pcp.isDualInline()) {
657 pcp = pcp.getSubPoint().get(0);
659 Vector3d v = new Vector3d();
660 v.sub(next.getWorldPosition(),pcp.getWorldPosition());
663 if (previous == null) {
665 throw new RuntimeException("Cannot calculate path leg direction for unconnected control point");
666 return getDirectedControlPointDirection();
669 if (isVariableAngle())
670 throw new RuntimeException("Cannot calculate path leg direction for unconnected variable angle control point");
672 PipeControlPoint pcp = this;
673 if (pcp.isDualSub()) {
674 pcp = pcp.getParentPoint();
676 Vector3d v = new Vector3d();
677 v.sub(pcp.getWorldPosition(),previous.getWorldPosition());
679 } else if (isDirected()) {
680 return getDirectedControlPointDirection();
681 } else if (isEnd()) {
682 Vector3d v = new Vector3d();
683 v.sub(getWorldPosition(),previous.getWorldPosition());
685 } else if (isTurn() && isFixed() && !_getReversed()) {
686 return getDirection(Direction.NEXT);
688 throw new RuntimeException("Missing implementation");
692 if (previous != null) {
693 PipeControlPoint pcp = this;
695 pcp = getParentPoint();
696 Vector3d v = new Vector3d();
697 v.sub(previous.getWorldPosition(),pcp.getWorldPosition());
702 throw new RuntimeException("Cannot calculate path leg direction for unconnected control point");
703 Vector3d v = getDirectedControlPointDirection();
707 if (isVariableAngle())
708 throw new RuntimeException("Cannot calculate path leg direction for unconnected variable angle control point");
710 PipeControlPoint pcp = this;
711 if (pcp.isDualInline()) {
712 pcp = pcp.getSubPoint().get(0);
714 Vector3d v = new Vector3d();
715 v.sub(pcp.getWorldPosition(),next.getWorldPosition());
717 } else if (isDirected()) {
718 Vector3d v = getDirectedControlPointDirection();
721 } else if (isEnd()) {
722 Vector3d v = new Vector3d();
723 v.sub(getWorldPosition(),next.getWorldPosition());
725 } else if (isTurn() && isFixed() && _getReversed()) {
726 return getDirection(Direction.PREVIOUS);
728 throw new RuntimeException("Missing implementation");
734 public void getInlineControlPointEnds(Tuple3d p1, Tuple3d p2) {
737 Vector3d pos = getWorldPosition();
738 Vector3d dir = getPathLegDirection(Direction.NEXT);
740 dir.scale(length * 0.5);
747 public void getControlPointEnds(Tuple3d p1, Tuple3d p2) {
748 Vector3d pos = getWorldPosition();
749 Vector3d dir1 = getPathLegDirection(Direction.PREVIOUS);
751 Vector3d dir2 = getPathLegDirection(Direction.NEXT);
754 dir1.scale(length * 0.5);
755 dir2.scale(length * 0.5);
766 public void getInlineControlPointEnds(Tuple3d p1, Tuple3d p2, Vector3d dir) {
769 Vector3d pos = getWorldPosition();
770 dir.set(getPathLegDirection(Direction.NEXT));
772 dir.scale(length * 0.5);
779 public void getInlineControlPointEnds(Tuple3d center, Tuple3d p1, Tuple3d p2, Vector3d dir) {
782 Vector3d pos = getWorldPosition();
784 dir.set(getPathLegDirection(Direction.NEXT));
786 dir.scale(length * 0.5);
793 public double getInlineLength() {
794 if (type == Type.TURN)
796 else if (type == Type.INLINE)
801 public Vector3d getRealPosition(PositionType type) {
802 Vector3d pos = getWorldPosition();
805 Vector3d dir = getPathLegDirection(Direction.NEXT);
806 double length = getInlineLength();
813 Vector3d dir = getPathLegDirection(Direction.PREVIOUS);
814 double length = getInlineLength();
821 // IEntity portDir = pcp.getSingleRelatedObject(ProcessResource.plant3Dresource.HasDirection);
822 // TODO : how we calculated needed space for a port; does it has an offset from control point's position or not?
832 public void getInlineMovement(Tuple3d start, Tuple3d end) {
833 // FIXME : check type of neighbor components and allow movement on top of variable length components,
834 // find proper range for movement (pcp's position is not)
835 PipeControlPoint p = previous.getPrevious();
836 PipeControlPoint n = next.getNext();
837 start.set(p.getWorldPosition());
838 end.set(n.getWorldPosition());
841 public PipeControlPoint findNextEnd() {
842 ArrayList<PipeControlPoint> t = new ArrayList<PipeControlPoint>();
843 return findNextEnd( t);
846 public PipeControlPoint findPreviousEnd() {
847 ArrayList<PipeControlPoint> t = new ArrayList<PipeControlPoint>();
848 return findPreviousEnd(t);
851 public PipeControlPoint findNextEnd(List<PipeControlPoint> nextList) {
853 PipeControlPoint pcp = null;
854 PipeControlPoint p = null;
855 if (nextList.size() == 0)
859 p = nextList.get(nextList.size() - 1);
864 if (nextList.size() > 0)
865 nextList.remove(nextList.size() - 1);
866 // if (DEBUG) System.out.println(" " + pcp.getResource() + " not full");
870 if (pcp.isPathLegEnd()) {
871 //if (DEBUG) System.out.println(" " + pcp.getResource());
875 // if (DEBUG) System.out.print(" " + pcp.getResource());
880 public PipeControlPoint findPreviousEnd(List<PipeControlPoint> prevList) {
882 PipeControlPoint pcp = null;
883 PipeControlPoint p = null;
884 if (prevList.size() == 0)
888 p = prevList.get(prevList.size() - 1);
890 pcp = p.getPrevious();
893 if (prevList.size() > 0)
894 prevList.remove(prevList.size() - 1);
895 // if (DEBUG) System.out.println(" " + pcp.getResource() + " not full");
898 if (pcp.isPathLegEnd()) {
899 // if (DEBUG) System.out.println(" " + pcp.getResource());
903 // if (DEBUG)System.out.print(" " + pcp.getResource());
908 public void _remove() {
909 if (component == null && next == null && previous == null)
911 if (isDualInline() || isDualSub()) {
915 PipeRun pipeRun = getPipeRun();
919 PipeControlPoint additionalRemove = null;
920 if (!PipingRules.isEnabled()) {
925 PipeControlPoint currentPrev = previous;
926 PipeControlPoint currentNext = next;
927 if (currentNext == null && currentPrev == null) {
929 pipeRun.remChild(this);
932 if (currentNext != null && currentPrev != null) {
934 if (currentNext.isBranchEnd()) {
936 // currentNext.setPrevious(null);
937 // currentNext.setNext(null);
938 currentNext.remove();
942 if (currentPrev.isBranchEnd()) {
944 // currentPrev.setPrevious(null);
945 // currentPrev.setNext(null);
946 currentPrev.remove();
950 if (link && currentPrev.isDirected() && currentNext.isDirected()) {
953 if (currentNext == null) {
955 } else if (currentNext.isDualInline()) {
956 PipeControlPoint sccp = currentNext;
957 PipeControlPoint ocp = sccp.getSubPoint().get(0);
959 throw new RuntimeException("Removing PipeControlPoint " + this+ " structure damaged, no offset control point");
962 sccp.setPrevious(currentPrev);
963 ocp.setPrevious(currentPrev);
965 sccp.setPrevious(null);
966 ocp.setPrevious(null);
969 } else if (currentNext.isDualSub()) {
970 throw new RuntimeException("Removing PipeControlPoint " + this + " structure damaged, next control point is offset control point");
971 } else if (currentNext.previous == this) {
973 currentNext.setPrevious(currentPrev);
975 currentNext.setPrevious(null);
979 throw new RuntimeException("Removing PipeControlPoint "+ this+ " structure damaged");
981 if (currentPrev == null) {
983 } else if (currentPrev.isDualInline()) {
984 throw new RuntimeException("Removing PipeControlPoint " + this + " structure damaged, previous control point is size change control point");
985 } else if (currentPrev.isDualSub()) {
986 PipeControlPoint ocp = currentPrev;
987 PipeControlPoint sccp = ocp.getParentPoint();
989 throw new RuntimeException("Removing PipeControlPoint " + this + " structure damaged, no size change control point");
991 ocp.setNext(currentNext);
992 sccp.setNext(currentNext);
998 } else if (currentPrev.next == this) {
1000 currentPrev.setNext(currentNext);
1002 currentPrev.setNext(null);
1006 throw new RuntimeException("Removing PipeControlPoint " + this + " structure damaged");
1009 if (currentNext.isVariableLength() && currentPrev.isVariableLength()) {
1010 // we have to join them into single variable length component.
1011 additionalRemove = currentPrev;
1012 //currentPrev.remove();
1015 // FIXME : pipe run must be split into two parts, since the control point structure is no more continuous.
1017 } else if (next != null) {
1018 if (next.isDualInline()) {
1019 PipeControlPoint sccp = next;
1020 PipeControlPoint ocp = sccp.getSubPoint().get(0);
1022 throw new RuntimeException("Removing PipeControlPoint " + this+ " structure damaged, no offset control point");
1024 sccp.setPrevious(null);
1025 ocp.setPrevious(null);
1026 } else if (next.isDualSub()) {
1027 throw new RuntimeException("Removing PipeControlPoint " + this + " structure damaged, next control point is offset control point");
1028 } else if (next.previous == this) {
1029 next.setPrevious(null);
1031 throw new RuntimeException("Removing PipeControlPoint "+ this+ " structure damaged");
1034 } else { //(previous != null)
1035 if(previous.isDualInline()) {
1036 throw new RuntimeException("Removing PipeControlPoint " + this + " structure damaged, previous control point is size change control point");
1037 } else if (previous.isDualSub()) {
1038 PipeControlPoint ocp = previous;
1039 PipeControlPoint sccp = ocp.getParentPoint();
1041 throw new RuntimeException("Removing PipeControlPoint " + this + " structure damaged, no size change control point");
1045 } else if (previous.next == this) {
1046 previous.setNext(null);
1048 throw new RuntimeException("Removing PipeControlPoint "+ this+ " structure damaged");
1052 if (children.size() > 0 ) {
1054 } else if (parent!= null) {
1055 removeParentPoint();
1061 pipeRun.remChild(this);
1062 checkRemove(pipeRun);
1063 if (PipingRules.isEnabled() && pipeRun.getParent() != null && pipeRun.getControlPoints().size() > 0)
1064 PipingRules.validate(pipeRun);
1065 if (additionalRemove != null)
1066 additionalRemove.remove();
1069 public void remove() {
1070 PipeControlPoint currentPrev = previous;
1071 PipeControlPoint currentNext = next;
1074 if (currentNext != null)
1075 PipingRules.requestUpdate(currentNext);
1076 if (currentPrev != null)
1077 PipingRules.requestUpdate(currentPrev);
1078 } catch (Exception e) {
1079 e.printStackTrace();
1083 private void checkRemove(PipeRun pipeRun) {
1084 Collection<PipeControlPoint> points = pipeRun.getControlPoints();
1085 if (points.size() == 0) {
1087 } else if (points.size() == 1) {
1088 PipeControlPoint pcp = points.iterator().next();
1089 if (pcp.isDeletable())
1094 private void removeDualPoint() {
1095 if (previous != null)
1096 previous.setNext(null);
1098 next.setPrevious(null);
1099 PipeControlPoint ocp;
1100 PipeControlPoint sccp;
1101 if (isDualInline()) {
1103 ocp = getSubPoint().get(0);
1106 sccp = getParentPoint();
1108 PipeRun p1 = ocp.getPipeRun();
1109 PipeRun p2 = sccp.getPipeRun();
1111 ocp.removeComponent();
1112 sccp.removeComponent();
1117 // TODO : now we assume that this is size change, and we do
1118 if (ocp.next != null)
1119 ocp.next.setPrevious(null);
1120 if (ocp.previous != null)
1121 ocp.previous.setNext(null);
1122 if (sccp.next != null)
1123 sccp.next.setPrevious(null);
1124 if (sccp.previous != null)
1125 sccp.previous.setNext(null);
1127 ocp.setPrevious(null);
1129 sccp.setPrevious(null);
1135 private void removeSubPoints() {
1136 for (PipeControlPoint p : children) {
1137 // TODO : this may affect delete routine, since classification of the point changes.
1144 private void removeParentPoint() {
1145 throw new RuntimeException("Child points cannot be removed directly");
1148 private void removeComponent() {
1149 if (component == null)
1151 PipelineComponent next = component.getNext();
1152 PipelineComponent prev = component.getNext();
1154 if (next.getNext() == component)
1156 else if (next.getPrevious() == component)
1157 next.setPrevious(null);
1160 if (prev.getNext() == component)
1162 else if (prev.getPrevious() == component)
1163 prev.setPrevious(null);
1165 PipelineComponent comp = component;
1172 public void setOrientation(Quat4d orientation) {
1173 if (MathTools.equals(orientation, getOrientation()))
1175 super.setOrientation(orientation);
1176 if (getParentPoint() == null && component != null)
1177 component._setWorldOrientation(getWorldOrientation());
1182 public void setPosition(Vector3d position) {
1183 if (MathTools.equals(position, getPosition()))
1185 if (Double.isNaN(position.x) || Double.isNaN(position.y) || Double.isNaN(position.z))
1186 throw new IllegalArgumentException("NaN is not supported");
1187 super.setPosition(position);
1188 if (getParentPoint() == null && component != null)
1189 component._setWorldPosition(getWorldPosition());
1193 private void updateSubPoint() {
1195 if (next == null && previous == null) {
1196 for (PipeControlPoint sub : getSubPoint()) {
1197 sub.setWorldPosition(getWorldPosition());
1198 sub.setWorldOrientation(getWorldOrientation());
1202 for (PipeControlPoint sub : getSubPoint()) {
1203 Vector3d wp = getWorldPosition();
1204 wp.add(getSizeChangeOffsetVector());
1205 sub.setWorldPosition(wp);
1206 sub.setWorldOrientation(getWorldOrientation());
1209 for (PipeControlPoint sub : getSubPoint()) {
1210 sub.setWorldPosition(getWorldPosition());
1211 sub.setWorldOrientation(getWorldOrientation());
1217 public void _setWorldPosition(Vector3d position) {
1218 Vector3d localPos = getLocalPosition(position);
1219 super.setPosition(localPos);
1223 public void _setWorldOrientation(Quat4d orientation) {
1224 Quat4d localOr = getLocalOrientation(orientation);
1225 super.setOrientation(localOr);
1230 public String toString() {
1231 return getClass().getName() + "@" + Integer.toHexString(hashCode());