1 package org.simantics.plant3d.scenegraph.controlpoint;
3 import java.util.ArrayList;
4 import java.util.Collection;
7 import javax.vecmath.AxisAngle4d;
8 import javax.vecmath.Matrix3d;
9 import javax.vecmath.Quat4d;
10 import javax.vecmath.Tuple3d;
11 import javax.vecmath.Vector3d;
13 import org.simantics.g3d.math.MathTools;
14 import org.simantics.g3d.property.annotations.GetPropertyValue;
15 import org.simantics.g3d.scenegraph.G3DNode;
16 import org.simantics.plant3d.scenegraph.IP3DNode;
17 import org.simantics.plant3d.scenegraph.PipeRun;
18 import org.simantics.plant3d.scenegraph.PipelineComponent;
20 import vtk.vtkRenderer;
23 public class PipeControlPoint extends G3DNode implements IP3DNode {
25 public enum Type{INLINE,TURN,END};
26 public enum Direction{NEXT,PREVIOUS};
27 public enum PositionType {SPLIT,NEXT,PREVIOUS,PORT}
29 private PipelineComponent component;
32 private boolean fixed = true;
33 private boolean rotate = false;
34 private boolean deletable = true;
35 private boolean sub = false;
37 public PipeControlPoint(PipelineComponent component) {
38 this.component = component;
39 if (component.getPipeRun() != null)
40 component.getPipeRun().addChild(this);
44 public PipeControlPoint(PipelineComponent component, PipeRun piperun) {
45 this.component = component;
46 piperun.addChild(this);
50 public void update(vtkRenderer ren) {
52 PipingRules.requestUpdate(this);
53 } catch (Exception e) {
59 public PipeRun getPipeRun() {
60 return (PipeRun)getParent();
63 public PipelineComponent getPipelineComponent() {
67 public Type getType() {
71 public void setType(Type type) {
75 @GetPropertyValue(name="Fixed",tabId="Debug",value="fixed")
76 public boolean isFixed() {
81 public void setFixed(boolean fixed) {
85 @GetPropertyValue(name="Rotate",tabId="Debug",value="rotate")
86 public boolean isRotate() {
91 public void setRotate(boolean rotate) {
95 public void setSub(boolean sub) {
99 @GetPropertyValue(name="Deletable",tabId="Debug",value="deletable")
100 public boolean isDeletable() {
104 public void setDeletable(boolean deletable) {
105 this.deletable = deletable;
108 public boolean isPathLegEnd() {
109 return type != Type.INLINE;
112 public boolean isEnd() {
113 return type == Type.END;
116 public boolean isTurn() {
117 return type == Type.TURN;
120 public boolean isInline() {
121 return type == Type.INLINE;
124 public boolean isDirected() {
125 return fixed && isEnd();
128 public boolean isNonDirected() {
129 return !fixed && isEnd();
132 public boolean isVariableLength() {
133 return !fixed && isInline();
136 public boolean isVariableAngle() {
137 return !fixed && isTurn();
140 public boolean isBranchEnd() {
141 return deletable && isEnd();
144 public boolean isOffset() {
145 return offset != null;
148 public boolean isDualSub() {
149 return parent != null && sub;
152 public boolean isDualInline() {
153 return children.size() == 1 && children.get(0).isDualSub();
156 public boolean isSizeChange() {
157 if (children.size() == 0)
161 return getPipeRun() != children.get(0).getPipeRun();
165 private PipeControlPoint next;
166 private PipeControlPoint previous;
168 public PipeControlPoint getNext() {
172 public PipeControlPoint getPrevious() {
176 public void setNext(PipeControlPoint next) {
177 if (isEnd() && previous != null && next != null)
178 throw new RuntimeException("End control points are allowed to have only one connection");
179 // if (next != null && getPipeRun() == null)
180 // throw new RuntimeException("Cannot connect control point befor piperun has been set");
182 if (component != null) {
183 if (parent == null || sub)
184 component.setNext(next != null ? next.component : null);
186 component.setBranch0(next != null ? next.component : null);
192 public void setPrevious(PipeControlPoint previous) {
193 if (isEnd() && next != null && previous != null)
194 throw new RuntimeException("End control points are allowed to have only one connection");
195 // if (previous != null && getPipeRun() == null)
196 // throw new RuntimeException("Cannot connect control point befor piperun has been set");
197 this.previous = previous;
198 if (component != null) {
199 if (parent == null || sub)
200 component.setPrevious(previous != null ? previous.component : null);
202 component.setBranch0(previous != null ? previous.component : null);
208 public PipeControlPoint parent;
209 public List<PipeControlPoint> children = new ArrayList<PipeControlPoint>();
211 public List<PipeControlPoint> getSubPoint() {
215 public PipeControlPoint getParentPoint() {
226 private double length;
227 private Double turnAngle;
228 private Vector3d turnAxis;
230 private Double offset;
231 private Double rotationAngle;
233 @GetPropertyValue(name="Length",tabId="Debug",value="length")
234 public double getLength() {
238 public void setLength(double l) {
239 if (Double.isInfinite(l) || Double.isNaN(l)) {
242 if (Math.abs(this.length-l) < MathTools.NEAR_ZERO)
245 firePropertyChanged("length");
247 getSubPoint().get(0).setLength(l);
250 @GetPropertyValue(name="Turn Angle",tabId="Debug",value="turnAngle")
251 public Double getTurnAngle() {
255 @GetPropertyValue(name="Turn Axis",tabId="Debug",value="turnAxis")
256 public Vector3d getTurnAxis() {
260 @GetPropertyValue(name="Offset",tabId="Debug",value="offset")
261 public Double getOffset() {
265 @GetPropertyValue(name="Rotation Angle",tabId="Debug",value="rotationAngle")
266 public Double getRotationAngle() {
267 return rotationAngle;
270 public void setTurnAngle(Double turnAngle) {
271 if (Double.isInfinite(turnAngle) || Double.isNaN(turnAngle)) {
274 if (this.turnAngle != null && Math.abs(this.turnAngle-turnAngle) < MathTools.NEAR_ZERO)
276 this.turnAngle = turnAngle;
277 firePropertyChanged("turnAngle");
280 public void setTurnAxis(Vector3d turnAxis) {
281 this.turnAxis = turnAxis;
282 firePropertyChanged("turnAxis");
285 public void setOffset(Double offset) {
286 if (Double.isInfinite(offset) || Double.isNaN(offset)) {
289 if (this.offset != null && Math.abs(this.offset-offset) < MathTools.NEAR_ZERO)
291 this.offset = offset;
292 firePropertyChanged("offset");
295 public void setRotationAngle(Double rotationAngle) {
296 if (Double.isInfinite(rotationAngle) || Double.isNaN(rotationAngle)) {
299 if (this.rotationAngle != null && Math.abs(this.rotationAngle-rotationAngle) < MathTools.NEAR_ZERO)
301 this.rotationAngle = rotationAngle;
302 firePropertyChanged("rotationAngle");
305 public Vector3d getSizeChangeOffsetVector(Vector3d dir) {
307 if (rotationAngle == null)
308 q = getControlPointOrientationQuat(dir, 0.0);
310 q = getControlPointOrientationQuat(dir, rotationAngle);
311 Vector3d v = new Vector3d(0.0,offset,0.0);
312 Vector3d offset = new Vector3d();
313 MathTools.rotate(q, v, offset);
317 public Vector3d getSizeChangeOffsetVector() {
319 if (rotationAngle == null)
320 q = getControlPointOrientationQuat(0.0);
322 q = getControlPointOrientationQuat(rotationAngle);
323 Vector3d v = new Vector3d(0.0,offset,0.0);
324 Vector3d offset = new Vector3d();
325 MathTools.rotate(q, v, offset);
329 @GetPropertyValue(name="Next",tabId="Debug",value="next")
330 private String getNextString() {
333 return next.toString();
336 @GetPropertyValue(name="Previous",tabId="Debug",value="previous")
337 private String getPrevString() {
338 if (previous == null)
340 return previous.toString();
343 public Quat4d getControlPointOrientationQuat(double angle) {
345 if (turnAxis == null) {
346 Vector3d dir = getPathLegDirection(Direction.NEXT);
347 if (dir.lengthSquared() > MathTools.NEAR_ZERO)
349 return getControlPointOrientationQuat(dir, angle);
351 Vector3d dir = getPathLegDirection(Direction.PREVIOUS);
353 if (dir.lengthSquared() > MathTools.NEAR_ZERO)
355 return getControlPointOrientationQuat(dir, turnAxis, angle);
361 public static Quat4d getControlPointOrientationQuat(Vector3d dir, double angle) {
362 if (dir.lengthSquared() < MathTools.NEAR_ZERO)
363 return MathTools.getIdentityQuat();
366 Vector3d up = new Vector3d(0.0, 1.0, 0.0);
367 double a = up.angle(dir);
368 if (a < 0.1 || (Math.PI - a) < 0.1) {
369 up.set(1.0, 0.0, 0.0);
373 return getControlPointOrientationQuat(dir, up, angle);
376 public static Quat4d getControlPointOrientationQuat(Vector3d dir, Vector3d up, double angle) {
377 if (dir.lengthSquared() < MathTools.NEAR_ZERO)
378 return MathTools.getIdentityQuat();
380 final Vector3d front = new Vector3d(1.0,0.0,0.0);
382 Quat4d q1 = new Quat4d();
385 Vector3d right = new Vector3d();
387 right.cross(dir, up);
388 up.cross(right, dir);
392 Matrix3d m = new Matrix3d();
403 //q1.set(m); MathTools contains more stable conversion
404 MathTools.getQuat(m, q1);
406 // if (DEBUG) System.out.println("PipingTools.getPipeComponentOrientationQuat() " + dir+ " " + up + " " + right);
408 Quat4d q2 = new Quat4d();
409 q2.set(new AxisAngle4d(front, angle));
414 public Vector3d getDirection() {
415 return getDirectedControlPointDirection();
424 public void insert(PipeControlPoint previous, PipeControlPoint next) {
425 // inserting an offsetpoint is error,
427 throw new RuntimeException();
428 // size change control point cannot be inserted this way, because it ends PipeRun
430 throw new RuntimeException();
431 PipeRun piperun = previous.getPipeRun();
432 // and just to make sure that control point structure is not corrupted
433 if (getPipeRun() != null) {
434 if (piperun != getPipeRun() || piperun != next.getPipeRun())
435 throw new RuntimeException();
437 piperun.addChild(this);
440 // insert new BranchControlPoint between straight's control points
441 PipeControlPoint previousNext = previous.getNext();
442 PipeControlPoint previousPrevious = previous.getPrevious();
444 PipeControlPoint offsetCP = null;
446 offsetCP = getSubPoint().get(0);
448 if (previousNext != null && previousNext == next) {
449 if (previous.isDualInline()) {
450 throw new RuntimeException();
452 if (next.isDualSub()) {
453 throw new RuntimeException();
455 previous.setNext(this);
456 this.setPrevious(previous);
457 if (previous.isDualSub()) {
458 previous.getParentPoint().setNext(this);
462 if (offsetCP == null) {
463 next.setPrevious(this);
465 next.setPrevious(offsetCP);
466 offsetCP.setNext(next);
467 offsetCP.setPrevious(previous);
470 if (next.isDualInline()) {
471 next.getSubPoint().get(0).setPrevious(this);
473 } else if (previousPrevious != null && previousPrevious == next) {
474 // control point were given in reverse order
475 if (next.isDualInline())
476 throw new RuntimeException();
477 if (previous.isDualSub())
478 throw new RuntimeException();
480 this.setNext(previous);
481 if (offsetCP == null) {
482 previous.setNext(this);
484 previous.setPrevious(offsetCP);
485 offsetCP.setNext(previous);
486 offsetCP.setPrevious(next);
488 if (previous.isDualInline()) {
489 previous.getSubPoint().get(0).setPrevious(this);
491 this.setPrevious(next);
493 if (next.isDualSub()) {
494 next.getParentPoint().setNext(this);
498 throw new RuntimeException();
501 PipingRules.validate(piperun);
506 public void insert(PipeControlPoint pcp, Direction direction) {
508 throw new RuntimeException();
509 if (direction == Direction.NEXT) {
510 // if direction is next, user must have given OffsetPoint
511 if (pcp.isDualInline())
512 throw new RuntimeException();
513 // basic next/prev links
515 this.setPrevious(pcp);
516 // and last take care of sizechange / offset points
517 if (pcp.isDualSub()) {
518 pcp.getParentPoint().setNext(this);
520 if (isDualInline()) {
521 getSubPoint().get(0).setPrevious(this);
524 // if direction is previous, user must have given sizechange
526 throw new RuntimeException();
527 // previous direction is more complicated, since if newCP is SizeChangeControlPoint,
528 // we must link pcp to newCP's OffsetPoint
529 PipeControlPoint nocp = null;
530 if (isDualInline()) {
531 nocp = getSubPoint().get(0);
535 pcp.setPrevious(this);
537 pcp.setPrevious(nocp);
540 if (pcp.isDualInline()) {
541 PipeControlPoint ocp = pcp.getSubPoint().get(0);
543 ocp.setPrevious(this);
545 ocp.setPrevious(nocp);
549 PipingRules.validate(getPipeRun());
552 public Vector3d getDirectedControlPointDirection() {
553 assert (isDirected());
554 Vector3d dir = new Vector3d();
555 MathTools.rotate(getWorldOrientation(), new Vector3d(1.0, 0.0, 0.0), dir);
560 public Vector3d getPathLegDirection(Direction direction) {
561 if (direction == Direction.NEXT) {
563 PipeControlPoint pcp = this;
564 if (pcp.isDualInline()) {
565 pcp = pcp.getSubPoint().get(0);
567 Vector3d v = new Vector3d();
568 v.sub(next.getWorldPosition(),pcp.getWorldPosition());
571 if (isVariableAngle())
572 throw new RuntimeException("Cannot calculate path leg direction for unconnected variable angle control point");
573 if (previous == null) {
575 throw new RuntimeException("Cannot calculate path leg direction for unconnected control point");
576 return getDirectedControlPointDirection();
580 PipeControlPoint pcp = this;
581 if (pcp.isDualSub()) {
582 pcp = pcp.getParentPoint();
584 Vector3d v = new Vector3d();
585 v.sub(pcp.getWorldPosition(),previous.getWorldPosition());
587 } else if (isDirected()) {
588 return getDirectedControlPointDirection();
589 } else if (isEnd()) {
590 Vector3d v = new Vector3d();
591 v.sub(getWorldPosition(),previous.getWorldPosition());
594 throw new RuntimeException("Missing implementation");
598 if (previous != null) {
599 PipeControlPoint pcp = this;
601 pcp = getParentPoint();
602 Vector3d v = new Vector3d();
603 v.sub(previous.getWorldPosition(),pcp.getWorldPosition());
606 if (isVariableAngle())
607 throw new RuntimeException("Cannot calculate path leg direction for unconnected variable angle control point");
610 throw new RuntimeException("Cannot calculate path leg direction for unconnected control point");
611 Vector3d v = getDirectedControlPointDirection();
616 PipeControlPoint pcp = this;
617 if (pcp.isDualInline()) {
618 pcp = pcp.getSubPoint().get(0);
620 Vector3d v = new Vector3d();
621 v.sub(pcp.getWorldPosition(),next.getWorldPosition());
623 } else if (isDirected()) {
624 Vector3d v = getDirectedControlPointDirection();
627 } else if (isEnd()) {
628 Vector3d v = new Vector3d();
629 v.sub(getWorldPosition(),next.getWorldPosition());
632 throw new RuntimeException("Missing implementation");
638 public void getInlineControlPointEnds(Tuple3d p1, Tuple3d p2) {
641 Vector3d pos = getWorldPosition();
642 Vector3d dir = getPathLegDirection(Direction.NEXT);
644 dir.scale(length * 0.5);
651 public void getControlPointEnds(Tuple3d p1, Tuple3d p2) {
652 Vector3d pos = getWorldPosition();
653 Vector3d dir1 = getPathLegDirection(Direction.PREVIOUS);
655 Vector3d dir2 = getPathLegDirection(Direction.NEXT);
658 dir1.scale(length * 0.5);
659 dir2.scale(length * 0.5);
670 public void getInlineControlPointEnds(Tuple3d p1, Tuple3d p2, Vector3d dir) {
673 Vector3d pos = getWorldPosition();
674 dir.set(getPathLegDirection(Direction.NEXT));
676 dir.scale(length * 0.5);
683 public void getInlineControlPointEnds(Tuple3d center, Tuple3d p1, Tuple3d p2, Vector3d dir) {
686 Vector3d pos = getWorldPosition();
688 dir.set(getPathLegDirection(Direction.NEXT));
690 dir.scale(length * 0.5);
697 public double getInlineLength() {
698 if (type == Type.TURN)
700 else if (type == Type.INLINE)
705 public Vector3d getRealPosition(PositionType type) {
706 Vector3d pos = getWorldPosition();
709 Vector3d dir = getPathLegDirection(Direction.NEXT);
710 double length = getInlineLength();
717 Vector3d dir = getPathLegDirection(Direction.PREVIOUS);
718 double length = getInlineLength();
725 // IEntity portDir = pcp.getSingleRelatedObject(ProcessResource.plant3Dresource.HasDirection);
726 // TODO : how we calculated needed space for a port; does it has an offset from control point's position or not?
736 public void getInlineMovement(Tuple3d start, Tuple3d end) {
737 // FIXME : check type of neighbor components and allow movement on top of variable length components,
738 // find proper range for movement (pcp's position is not)
739 PipeControlPoint p = previous.getPrevious();
740 PipeControlPoint n = next.getNext();
741 start.set(p.getWorldPosition());
742 end.set(n.getWorldPosition());
745 public PipeControlPoint findNextEnd() {
746 ArrayList<PipeControlPoint> t = new ArrayList<PipeControlPoint>();
747 return findNextEnd( t);
750 public PipeControlPoint findPreviousEnd() {
751 ArrayList<PipeControlPoint> t = new ArrayList<PipeControlPoint>();
752 return findPreviousEnd(t);
755 public PipeControlPoint findNextEnd(List<PipeControlPoint> nextList) {
757 PipeControlPoint pcp = null;
758 PipeControlPoint p = null;
759 if (nextList.size() == 0)
763 p = nextList.get(nextList.size() - 1);
768 if (nextList.size() > 0)
769 nextList.remove(nextList.size() - 1);
770 // if (DEBUG) System.out.println(" " + pcp.getResource() + " not full");
774 if (pcp.isPathLegEnd()) {
775 //if (DEBUG) System.out.println(" " + pcp.getResource());
779 // if (DEBUG) System.out.print(" " + pcp.getResource());
784 public PipeControlPoint findPreviousEnd(List<PipeControlPoint> prevList) {
786 PipeControlPoint pcp = null;
787 PipeControlPoint p = null;
788 if (prevList.size() == 0)
792 p = prevList.get(prevList.size() - 1);
794 pcp = p.getPrevious();
797 if (prevList.size() > 0)
798 prevList.remove(prevList.size() - 1);
799 // if (DEBUG) System.out.println(" " + pcp.getResource() + " not full");
802 if (pcp.isPathLegEnd()) {
803 // if (DEBUG) System.out.println(" " + pcp.getResource());
807 // if (DEBUG)System.out.print(" " + pcp.getResource());
812 public void _remove() {
813 if (component == null && next == null && previous == null)
815 if (isDualInline() || isDualSub()) {
819 PipeRun pipeRun = getPipeRun();
823 PipeControlPoint additionalRemove = null;
824 if (!PipingRules.isEnabled()) {
829 PipeControlPoint currentPrev = previous;
830 PipeControlPoint currentNext = next;
831 if (currentNext == null && currentPrev == null) {
833 pipeRun.remChild(this);
836 if (currentNext != null && currentPrev != null) {
838 if (currentNext.isBranchEnd()) {
840 // currentNext.setPrevious(null);
841 // currentNext.setNext(null);
842 currentNext.remove();
846 if (currentPrev.isBranchEnd()) {
848 // currentPrev.setPrevious(null);
849 // currentPrev.setNext(null);
850 currentPrev.remove();
854 if (link && currentPrev.isDirected() && currentNext.isDirected()) {
857 if (currentNext == null) {
859 } else if (currentNext.isDualInline()) {
860 PipeControlPoint sccp = currentNext;
861 PipeControlPoint ocp = sccp.getSubPoint().get(0);
863 throw new RuntimeException("Removing PipeControlPoint " + this+ " structure damaged, no offset control point");
866 sccp.setPrevious(currentPrev);
867 ocp.setPrevious(currentPrev);
869 sccp.setPrevious(null);
870 ocp.setPrevious(null);
873 } else if (currentNext.isDualSub()) {
874 throw new RuntimeException("Removing PipeControlPoint " + this + " structure damaged, next control point is offset control point");
875 } else if (currentNext.previous == this) {
877 currentNext.setPrevious(currentPrev);
879 currentNext.setPrevious(null);
883 throw new RuntimeException("Removing PipeControlPoint "+ this+ " structure damaged");
885 if (currentPrev == null) {
887 } else if (currentPrev.isDualInline()) {
888 throw new RuntimeException("Removing PipeControlPoint " + this + " structure damaged, previous control point is size change control point");
889 } else if (currentPrev.isDualSub()) {
890 PipeControlPoint ocp = currentPrev;
891 PipeControlPoint sccp = ocp.getParentPoint();
893 throw new RuntimeException("Removing PipeControlPoint " + this + " structure damaged, no size change control point");
895 ocp.setNext(currentNext);
896 sccp.setNext(currentNext);
902 } else if (currentPrev.next == this) {
904 currentPrev.setNext(currentNext);
906 currentPrev.setNext(null);
910 throw new RuntimeException("Removing PipeControlPoint " + this + " structure damaged");
913 if (currentNext.isVariableLength() && currentPrev.isVariableLength()) {
914 // we have to join them into single variable length component.
915 additionalRemove = currentPrev;
916 //currentPrev.remove();
919 // FIXME : pipe run must be split into two parts, since the control point structure is no more continuous.
921 } else if (next != null) {
922 if (next.isDualInline()) {
923 PipeControlPoint sccp = next;
924 PipeControlPoint ocp = sccp.getSubPoint().get(0);
926 throw new RuntimeException("Removing PipeControlPoint " + this+ " structure damaged, no offset control point");
928 sccp.setPrevious(null);
929 ocp.setPrevious(null);
930 } else if (next.isDualSub()) {
931 throw new RuntimeException("Removing PipeControlPoint " + this + " structure damaged, next control point is offset control point");
932 } else if (next.previous == this) {
933 next.setPrevious(null);
935 throw new RuntimeException("Removing PipeControlPoint "+ this+ " structure damaged");
938 } else { //(previous != null)
939 if(previous.isDualInline()) {
940 throw new RuntimeException("Removing PipeControlPoint " + this + " structure damaged, previous control point is size change control point");
941 } else if (previous.isDualSub()) {
942 PipeControlPoint ocp = previous;
943 PipeControlPoint sccp = ocp.getParentPoint();
945 throw new RuntimeException("Removing PipeControlPoint " + this + " structure damaged, no size change control point");
949 } else if (previous.next == this) {
950 previous.setNext(null);
952 throw new RuntimeException("Removing PipeControlPoint "+ this+ " structure damaged");
956 if (children.size() > 0 ) {
958 } else if (parent!= null) {
965 pipeRun.remChild(this);
966 checkRemove(pipeRun);
967 if (PipingRules.isEnabled() && pipeRun.getParent() != null && pipeRun.getControlPoints().size() > 0)
968 PipingRules.validate(pipeRun);
969 if (additionalRemove != null)
970 additionalRemove.remove();
973 public void remove() {
974 PipeControlPoint currentPrev = previous;
975 PipeControlPoint currentNext = next;
978 if (currentNext != null)
979 PipingRules.requestUpdate(currentNext);
980 if (currentPrev != null)
981 PipingRules.requestUpdate(currentPrev);
982 } catch (Exception e) {
987 private void checkRemove(PipeRun pipeRun) {
988 Collection<PipeControlPoint> points = pipeRun.getControlPoints();
989 if (points.size() == 0) {
991 } else if (points.size() == 1) {
992 PipeControlPoint pcp = points.iterator().next();
993 if (pcp.isDeletable())
998 private void removeDualPoint() {
999 if (previous != null)
1000 previous.setNext(null);
1002 next.setPrevious(null);
1003 PipeControlPoint ocp;
1004 PipeControlPoint sccp;
1005 if (isDualInline()) {
1007 ocp = getSubPoint().get(0);
1010 sccp = getParentPoint();
1012 PipeRun p1 = ocp.getPipeRun();
1013 PipeRun p2 = sccp.getPipeRun();
1015 ocp.removeComponent();
1016 sccp.removeComponent();
1022 ocp.setPrevious(null);
1024 sccp.setPrevious(null);
1030 private void removeSubPoints() {
1031 for (PipeControlPoint p : children) {
1032 // TODO : this may affect delete routine, since classification of the point changes.
1039 private void removeParentPoint() {
1040 throw new RuntimeException("Child points cannot be removed directly");
1043 private void removeComponent() {
1044 if (component == null)
1046 PipelineComponent next = component.getNext();
1047 PipelineComponent prev = component.getNext();
1049 if (next.getNext() == component)
1051 else if (next.getPrevious() == component)
1052 next.setPrevious(null);
1055 if (prev.getNext() == component)
1057 else if (prev.getPrevious() == component)
1058 prev.setPrevious(null);
1060 PipelineComponent comp = component;
1066 public void setOrientation(Quat4d orientation) {
1067 if (MathTools.equals(orientation, getOrientation()))
1069 super.setOrientation(orientation);
1070 if (getParentPoint() == null && component != null)
1071 component._setWorldOrientation(getWorldOrientation());
1076 public void setPosition(Vector3d position) {
1077 if (MathTools.equals(position, getPosition()))
1079 super.setPosition(position);
1080 if (getParentPoint() == null && component != null)
1081 component._setWorldPosition(getWorldPosition());
1083 System.out.println();
1087 private void updateSubPoint() {
1089 if (next == null && previous == null) {
1090 for (PipeControlPoint sub : getSubPoint()) {
1091 sub.setWorldPosition(getWorldPosition());
1092 sub.setWorldOrientation(getWorldOrientation());
1096 for (PipeControlPoint sub : getSubPoint()) {
1097 Vector3d wp = getWorldPosition();
1098 wp.add(getSizeChangeOffsetVector());
1099 sub.setWorldPosition(wp);
1100 sub.setWorldOrientation(getWorldOrientation());
1103 for (PipeControlPoint sub : getSubPoint()) {
1104 sub.setWorldPosition(getWorldPosition());
1105 sub.setWorldOrientation(getWorldOrientation());
1111 public void _setWorldPosition(Vector3d position) {
1112 Vector3d localPos = getLocalPosition(position);
1113 super.setPosition(localPos);
1117 public void _setWorldOrientation(Quat4d orientation) {
1118 Quat4d localOr = getLocalOrientation(orientation);
1119 super.setOrientation(localOr);
1124 public String toString() {
1125 return getClass().getName() + "@" + Integer.toHexString(hashCode());