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 deletable = true;
34 private boolean sub = false;
36 public PipeControlPoint(PipelineComponent component) {
37 this.component = component;
38 if (component.getPipeRun() != null)
39 component.getPipeRun().addChild(this);
43 public PipeControlPoint(PipelineComponent component, PipeRun piperun) {
44 this.component = component;
45 piperun.addChild(this);
49 public void update(vtkRenderer ren) {
51 PipingRules.requestUpdate(this);
52 } catch (Exception e) {
58 public PipeRun getPipeRun() {
59 return (PipeRun)getParent();
62 public PipelineComponent getPipelineComponent() {
66 public Type getType() {
70 public void setType(Type type) {
74 @GetPropertyValue(name="Fixed",tabId="Debug",value="fixed")
75 public boolean isFixed() {
80 public void setFixed(boolean fixed) {
84 public void setSub(boolean sub) {
88 @GetPropertyValue(name="Deletable",tabId="Debug",value="deletable")
89 public boolean isDeletable() {
93 public void setDeletable(boolean deletable) {
94 this.deletable = deletable;
97 public boolean isPathLegEnd() {
98 return type != Type.INLINE;
101 public boolean isEnd() {
102 return type == Type.END;
105 public boolean isTurn() {
106 return type == Type.TURN;
109 public boolean isInline() {
110 return type == Type.INLINE;
113 public boolean isDirected() {
114 return fixed && isEnd();
117 public boolean isNonDirected() {
118 return !fixed && isEnd();
121 public boolean isVariableLength() {
122 return !fixed && isInline();
125 public boolean isVariableAngle() {
126 return !fixed && isTurn();
129 public boolean isBranchEnd() {
130 return deletable && isEnd();
133 public boolean isOffset() {
134 return offset != null;
137 public boolean isDualSub() {
138 return parent != null && sub;
141 public boolean isDualInline() {
142 return children.size() == 1 && children.get(0).isDualSub();
145 public boolean isSizeChange() {
146 if (children.size() == 0)
150 return getPipeRun() != children.get(0).getPipeRun();
154 private PipeControlPoint next;
155 private PipeControlPoint previous;
157 public PipeControlPoint getNext() {
161 public PipeControlPoint getPrevious() {
165 public void setNext(PipeControlPoint next) {
166 if (isEnd() && previous != null && next != null)
167 throw new RuntimeException("End control points are allowed to have only one connection");
168 // if (next != null && getPipeRun() == null)
169 // throw new RuntimeException("Cannot connect control point befor piperun has been set");
171 if (component != null) {
172 if (parent == null || sub)
173 component.setNext(next != null ? next.component : null);
175 component.setBranch0(next != null ? next.component : null);
179 public void setPrevious(PipeControlPoint previous) {
180 if (isEnd() && next != null && previous != null)
181 throw new RuntimeException("End control points are allowed to have only one connection");
182 // if (previous != null && getPipeRun() == null)
183 // throw new RuntimeException("Cannot connect control point befor piperun has been set");
184 this.previous = previous;
185 if (component != null)
186 if (parent == null || sub)
187 component.setPrevious(previous != null ? previous.component : null);
189 component.setBranch0(previous != null ? previous.component : null);
192 public PipeControlPoint parent;
193 public List<PipeControlPoint> children = new ArrayList<PipeControlPoint>();
195 public List<PipeControlPoint> getSubPoint() {
199 public PipeControlPoint getParentPoint() {
210 private double length;
211 private Double turnAngle;
212 private Vector3d turnAxis;
214 private Double offset;
215 private Double rotationAngle;
217 @GetPropertyValue(name="Length",tabId="Debug",value="length")
218 public double getLength() {
222 public void setLength(double l) {
223 if (Double.isInfinite(l) || Double.isNaN(l)) {
226 if (Math.abs(this.length-l) < MathTools.NEAR_ZERO)
229 firePropertyChanged("length");
231 getSubPoint().get(0).setLength(l);
234 @GetPropertyValue(name="Turn Angle",tabId="Debug",value="turnAngle")
235 public Double getTurnAngle() {
239 @GetPropertyValue(name="Turn Axis",tabId="Debug",value="turnAxis")
240 public Vector3d getTurnAxis() {
244 @GetPropertyValue(name="Offset",tabId="Debug",value="offset")
245 public Double getOffset() {
249 @GetPropertyValue(name="Rotation Angle",tabId="Debug",value="rotationAngle")
250 public Double getRotationAngle() {
251 return rotationAngle;
254 public void setTurnAngle(Double turnAngle) {
255 if (Double.isInfinite(turnAngle) || Double.isNaN(turnAngle)) {
258 if (this.turnAngle != null && Math.abs(this.turnAngle-turnAngle) < MathTools.NEAR_ZERO)
260 this.turnAngle = turnAngle;
261 firePropertyChanged("turnAngle");
264 public void setTurnAxis(Vector3d turnAxis) {
265 this.turnAxis = turnAxis;
266 firePropertyChanged("turnAxis");
269 public void setOffset(Double offset) {
270 if (Double.isInfinite(offset) || Double.isNaN(offset)) {
273 if (this.offset != null && Math.abs(this.offset-offset) < MathTools.NEAR_ZERO)
275 this.offset = offset;
276 firePropertyChanged("offset");
279 public void setRotationAngle(Double rotationAngle) {
280 if (Double.isInfinite(rotationAngle) || Double.isNaN(rotationAngle)) {
283 if (this.rotationAngle != null && Math.abs(this.rotationAngle-rotationAngle) < MathTools.NEAR_ZERO)
285 this.rotationAngle = rotationAngle;
286 firePropertyChanged("rotationAngle");
289 public Vector3d getSizeChangeOffsetVector(Vector3d dir) {
290 if (rotationAngle == null)
292 Quat4d q = getControlPointOrientationQuat(dir, rotationAngle);
293 Vector3d v = new Vector3d(0.0,0.0,offset);
294 Vector3d offset = new Vector3d();
295 MathTools.rotate(q, v, offset);
299 @GetPropertyValue(name="Next",tabId="Debug",value="next")
300 private String getNextString() {
303 return next.toString();
306 @GetPropertyValue(name="Previous",tabId="Debug",value="previous")
307 private String getPrevString() {
308 if (previous == null)
310 return previous.toString();
313 public Quat4d getControlPointOrientationQuat(double angle) {
315 if (turnAxis == null) {
316 Vector3d dir = getPathLegDirection(Direction.NEXT);
317 if (dir.lengthSquared() > MathTools.NEAR_ZERO)
319 return getControlPointOrientationQuat(dir, angle);
321 Vector3d dir = getPathLegDirection(Direction.PREVIOUS);
323 if (dir.lengthSquared() > MathTools.NEAR_ZERO)
325 return getControlPointOrientationQuat(dir, turnAxis, angle);
331 public static Quat4d getControlPointOrientationQuat(Vector3d dir, double angle) {
332 if (dir.lengthSquared() < MathTools.NEAR_ZERO)
333 return MathTools.getIdentityQuat();
336 Vector3d up = new Vector3d(0.0, 1.0, 0.0);
337 double a = up.angle(dir);
338 if (a < 0.1 || (Math.PI - a) < 0.1) {
339 up.set(1.0, 0.0, 0.0);
343 return getControlPointOrientationQuat(dir, up, angle);
346 public static Quat4d getControlPointOrientationQuat(Vector3d dir, Vector3d up, double angle) {
347 if (dir.lengthSquared() < MathTools.NEAR_ZERO)
348 return MathTools.getIdentityQuat();
350 final Vector3d front = new Vector3d(1.0,0.0,0.0);
352 Quat4d q1 = new Quat4d();
355 Vector3d right = new Vector3d();
357 right.cross(dir, up);
358 up.cross(right, dir);
362 Matrix3d m = new Matrix3d();
373 //q1.set(m); MathTools contains more stable conversion
374 MathTools.getQuat(m, q1);
376 // if (DEBUG) System.out.println("PipingTools.getPipeComponentOrientationQuat() " + dir+ " " + up + " " + right);
378 Quat4d q2 = new Quat4d();
379 q2.set(new AxisAngle4d(front, angle));
384 public Vector3d getDirection() {
385 return getDirectedControlPointDirection();
394 public void insert(PipeControlPoint previous, PipeControlPoint next) {
395 // inserting an offsetpoint is error,
397 throw new RuntimeException();
398 // size change control point cannot be inserted this way, because it ends PipeRun
400 throw new RuntimeException();
401 PipeRun piperun = previous.getPipeRun();
402 // and just to make sure that control point structure is not corrupted
403 if (getPipeRun() != null) {
404 if (piperun != getPipeRun() || piperun != next.getPipeRun())
405 throw new RuntimeException();
407 piperun.addChild(this);
410 // insert new BranchControlPoint between straight's control points
411 PipeControlPoint previousNext = previous.getNext();
412 PipeControlPoint previousPrevious = previous.getPrevious();
414 PipeControlPoint offsetCP = null;
416 offsetCP = getSubPoint().get(0);
418 if (previousNext != null && previousNext == next) {
419 if (previous.isDualInline()) {
420 throw new RuntimeException();
422 if (next.isDualSub()) {
423 throw new RuntimeException();
425 previous.setNext(this);
426 this.setPrevious(previous);
427 if (previous.isDualSub()) {
428 previous.getParentPoint().setNext(this);
432 if (offsetCP == null) {
433 next.setPrevious(this);
435 next.setPrevious(offsetCP);
436 offsetCP.setNext(next);
437 offsetCP.setPrevious(previous);
440 if (next.isDualInline()) {
441 next.getSubPoint().get(0).setPrevious(this);
443 } else if (previousPrevious != null && previousPrevious == next) {
444 // control point were given in reverse order
445 if (next.isDualInline())
446 throw new RuntimeException();
447 if (previous.isDualSub())
448 throw new RuntimeException();
450 this.setNext(previous);
451 if (offsetCP == null) {
452 previous.setNext(this);
454 previous.setPrevious(offsetCP);
455 offsetCP.setNext(previous);
456 offsetCP.setPrevious(next);
458 if (previous.isDualInline()) {
459 previous.getSubPoint().get(0).setPrevious(this);
461 this.setPrevious(next);
463 if (next.isDualSub()) {
464 next.getParentPoint().setNext(this);
468 throw new RuntimeException();
471 PipingRules.validate(piperun);
476 public void insert(PipeControlPoint pcp, Direction direction) {
478 throw new RuntimeException();
479 if (direction == Direction.NEXT) {
480 // if direction is next, user must have given OffsetPoint
481 if (pcp.isDualInline())
482 throw new RuntimeException();
483 // basic next/prev links
485 this.setPrevious(pcp);
486 // and last take care of sizechange / offset points
487 if (pcp.isDualSub()) {
488 pcp.getParentPoint().setNext(this);
490 if (isDualInline()) {
491 getSubPoint().get(0).setPrevious(this);
494 // if direction is previous, user must have given sizechange
496 throw new RuntimeException();
497 // previous direction is more complicated, since if newCP is SizeChangeControlPoint,
498 // we must link pcp to newCP's OffsetPoint
499 PipeControlPoint nocp = null;
500 if (isDualInline()) {
501 nocp = getSubPoint().get(0);
505 pcp.setPrevious(this);
507 pcp.setPrevious(nocp);
510 if (pcp.isDualInline()) {
511 PipeControlPoint ocp = pcp.getSubPoint().get(0);
513 ocp.setPrevious(this);
515 ocp.setPrevious(nocp);
519 PipingRules.validate(getPipeRun());
522 public Vector3d getDirectedControlPointDirection() {
523 assert (isDirected());
524 Vector3d dir = new Vector3d();
525 MathTools.rotate(getWorldOrientation(), new Vector3d(1.0, 0.0, 0.0), dir);
530 public Vector3d getPathLegDirection(Direction direction) {
531 if (direction == Direction.NEXT) {
533 PipeControlPoint pcp = this;
534 if (pcp.isDualInline()) {
535 pcp = pcp.getSubPoint().get(0);
537 Vector3d v = new Vector3d();
538 v.sub(next.getWorldPosition(),pcp.getWorldPosition());
541 if (isVariableAngle())
542 throw new RuntimeException("Cannot calculate path leg direction for unconnected variable angle control point");
543 if (previous == null) {
545 throw new RuntimeException("Cannot calculate path leg direction for unconnected control point");
546 return getDirectedControlPointDirection();
550 Vector3d v = new Vector3d();
551 v.sub(getWorldPosition(),previous.getWorldPosition());
553 } else if (isDirected()) {
554 return getDirectedControlPointDirection();
555 } else if (isEnd()) {
556 Vector3d v = new Vector3d();
557 v.sub(getWorldPosition(),previous.getWorldPosition());
560 throw new RuntimeException("Missing implementation");
564 if (previous != null) {
565 PipeControlPoint pcp = this;
567 pcp = getParentPoint();
568 Vector3d v = new Vector3d();
569 v.sub(previous.getWorldPosition(),pcp.getWorldPosition());
572 if (isVariableAngle())
573 throw new RuntimeException("Cannot calculate path leg direction for unconnected variable angle control point");
576 throw new RuntimeException("Cannot calculate path leg direction for unconnected control point");
577 Vector3d v = getDirectedControlPointDirection();
582 Vector3d v = new Vector3d();
583 v.sub(getWorldPosition(),next.getWorldPosition());
585 } else if (isDirected()) {
586 Vector3d v = getDirectedControlPointDirection();
589 } else if (isEnd()) {
590 Vector3d v = new Vector3d();
591 v.sub(getWorldPosition(),next.getWorldPosition());
594 throw new RuntimeException("Missing implementation");
600 public void getInlineControlPointEnds(Tuple3d p1, Tuple3d p2) {
603 Vector3d pos = getWorldPosition();
604 Vector3d dir = getPathLegDirection(Direction.NEXT);
606 dir.scale(length * 0.5);
613 public void getControlPointEnds(Tuple3d p1, Tuple3d p2) {
614 Vector3d pos = getWorldPosition();
615 Vector3d dir1 = getPathLegDirection(Direction.PREVIOUS);
617 Vector3d dir2 = getPathLegDirection(Direction.NEXT);
620 dir1.scale(length * 0.5);
621 dir2.scale(length * 0.5);
632 public void getInlineControlPointEnds(Tuple3d p1, Tuple3d p2, Vector3d dir) {
635 Vector3d pos = getWorldPosition();
636 dir.set(getPathLegDirection(Direction.NEXT));
638 dir.scale(length * 0.5);
645 public void getInlineControlPointEnds(Tuple3d center, Tuple3d p1, Tuple3d p2, Vector3d dir) {
648 Vector3d pos = getWorldPosition();
650 dir.set(getPathLegDirection(Direction.NEXT));
652 dir.scale(length * 0.5);
659 public double getInlineLength() {
660 if (type == Type.TURN)
662 else if (type == Type.INLINE)
667 public Vector3d getRealPosition(PositionType type) {
668 Vector3d pos = getWorldPosition();
671 Vector3d dir = getPathLegDirection(Direction.NEXT);
672 double length = getInlineLength();
679 Vector3d dir = getPathLegDirection(Direction.PREVIOUS);
680 double length = getInlineLength();
687 // IEntity portDir = pcp.getSingleRelatedObject(ProcessResource.plant3Dresource.HasDirection);
688 // TODO : how we calculated needed space for a port; does it has an offset from control point's position or not?
698 public void getInlineMovement(Tuple3d start, Tuple3d end) {
699 // FIXME : check type of neighbor components and allow movement on top of variable length components,
700 // find proper range for movement (pcp's position is not)
701 PipeControlPoint p = previous.getPrevious();
702 PipeControlPoint n = next.getNext();
703 start.set(p.getWorldPosition());
704 end.set(n.getWorldPosition());
707 public PipeControlPoint findNextEnd() {
708 ArrayList<PipeControlPoint> t = new ArrayList<PipeControlPoint>();
709 return findNextEnd( t);
712 public PipeControlPoint findPreviousEnd() {
713 ArrayList<PipeControlPoint> t = new ArrayList<PipeControlPoint>();
714 return findPreviousEnd(t);
717 public PipeControlPoint findNextEnd(List<PipeControlPoint> nextList) {
719 PipeControlPoint pcp = null;
720 PipeControlPoint p = null;
721 if (nextList.size() == 0)
725 p = nextList.get(nextList.size() - 1);
730 if (nextList.size() > 0)
731 nextList.remove(nextList.size() - 1);
732 // if (DEBUG) System.out.println(" " + pcp.getResource() + " not full");
736 if (pcp.isPathLegEnd()) {
737 //if (DEBUG) System.out.println(" " + pcp.getResource());
741 // if (DEBUG) System.out.print(" " + pcp.getResource());
746 public PipeControlPoint findPreviousEnd(List<PipeControlPoint> prevList) {
748 PipeControlPoint pcp = null;
749 PipeControlPoint p = null;
750 if (prevList.size() == 0)
754 p = prevList.get(prevList.size() - 1);
756 pcp = p.getPrevious();
759 if (prevList.size() > 0)
760 prevList.remove(prevList.size() - 1);
761 // if (DEBUG) System.out.println(" " + pcp.getResource() + " not full");
764 if (pcp.isPathLegEnd()) {
765 // if (DEBUG) System.out.println(" " + pcp.getResource());
769 // if (DEBUG)System.out.print(" " + pcp.getResource());
774 public void _remove() {
775 if (component == null && next == null && previous == null)
777 if (isDualInline() || isDualSub()) {
781 PipeRun pipeRun = getPipeRun();
785 PipeControlPoint additionalRemove = null;
786 if (!PipingRules.isEnabled()) {
791 PipeControlPoint currentPrev = previous;
792 PipeControlPoint currentNext = next;
793 if (currentNext == null && currentPrev == null) {
795 pipeRun.remChild(this);
798 if (currentNext != null && currentPrev != null) {
800 if (currentNext.isBranchEnd()) {
802 // currentNext.setPrevious(null);
803 // currentNext.setNext(null);
804 currentNext.remove();
808 if (currentPrev.isBranchEnd()) {
810 // currentPrev.setPrevious(null);
811 // currentPrev.setNext(null);
812 currentPrev.remove();
816 if (link && currentPrev.isDirected() && currentNext.isDirected()) {
819 if (currentNext == null) {
821 } else if (currentNext.isDualInline()) {
822 PipeControlPoint sccp = currentNext;
823 PipeControlPoint ocp = sccp.getSubPoint().get(0);
825 throw new RuntimeException("Removing PipeControlPoint " + this+ " structure damaged, no offset control point");
828 sccp.setPrevious(currentPrev);
829 ocp.setPrevious(currentPrev);
831 sccp.setPrevious(null);
832 ocp.setPrevious(null);
835 } else if (currentNext.isDualSub()) {
836 throw new RuntimeException("Removing PipeControlPoint " + this + " structure damaged, next control point is offset control point");
837 } else if (currentNext.previous == this) {
839 currentNext.setPrevious(currentPrev);
841 currentNext.setPrevious(null);
845 throw new RuntimeException("Removing PipeControlPoint "+ this+ " structure damaged");
847 if (currentPrev == null) {
849 } else if (currentPrev.isDualInline()) {
850 throw new RuntimeException("Removing PipeControlPoint " + this + " structure damaged, previous control point is size change control point");
851 } else if (currentPrev.isDualSub()) {
852 PipeControlPoint ocp = currentPrev;
853 PipeControlPoint sccp = ocp.getParentPoint();
855 throw new RuntimeException("Removing PipeControlPoint " + this + " structure damaged, no size change control point");
857 ocp.setNext(currentNext);
858 sccp.setNext(currentNext);
864 } else if (currentPrev.next == this) {
866 currentPrev.setNext(currentNext);
868 currentPrev.setNext(null);
872 throw new RuntimeException("Removing PipeControlPoint " + this + " structure damaged");
875 if (currentNext.isVariableLength() && currentPrev.isVariableLength()) {
876 // we have to join them into single variable length component.
877 additionalRemove = currentPrev;
878 //currentPrev.remove();
881 // FIXME : pipe run must be split into two parts, since the control point structure is no more continuous.
883 } else if (next != null) {
884 if (next.isDualInline()) {
885 PipeControlPoint sccp = next;
886 PipeControlPoint ocp = sccp.getSubPoint().get(0);
888 throw new RuntimeException("Removing PipeControlPoint " + this+ " structure damaged, no offset control point");
890 sccp.setPrevious(null);
891 ocp.setPrevious(null);
892 } else if (next.isDualSub()) {
893 throw new RuntimeException("Removing PipeControlPoint " + this + " structure damaged, next control point is offset control point");
894 } else if (next.previous == this) {
895 next.setPrevious(null);
897 throw new RuntimeException("Removing PipeControlPoint "+ this+ " structure damaged");
900 } else { //(previous != null)
901 if(previous.isDualInline()) {
902 throw new RuntimeException("Removing PipeControlPoint " + this + " structure damaged, previous control point is size change control point");
903 } else if (previous.isDualSub()) {
904 PipeControlPoint ocp = previous;
905 PipeControlPoint sccp = ocp.getParentPoint();
907 throw new RuntimeException("Removing PipeControlPoint " + this + " structure damaged, no size change control point");
911 } else if (previous.next == this) {
912 previous.setNext(null);
914 throw new RuntimeException("Removing PipeControlPoint "+ this+ " structure damaged");
918 if (children.size() > 0 ) {
920 } else if (parent!= null) {
927 pipeRun.remChild(this);
928 checkRemove(pipeRun);
929 if (PipingRules.isEnabled() && pipeRun.getParent() != null && pipeRun.getControlPoints().size() > 0)
930 PipingRules.validate(pipeRun);
931 if (additionalRemove != null)
932 additionalRemove.remove();
935 public void remove() {
936 PipeControlPoint currentPrev = previous;
937 PipeControlPoint currentNext = next;
940 if (currentNext != null)
941 PipingRules.requestUpdate(currentNext);
942 if (currentPrev != null)
943 PipingRules.requestUpdate(currentPrev);
944 } catch (Exception e) {
949 private void checkRemove(PipeRun pipeRun) {
950 Collection<PipeControlPoint> points = pipeRun.getControlPoints();
951 if (points.size() == 0) {
953 } else if (points.size() == 1) {
954 PipeControlPoint pcp = points.iterator().next();
955 if (pcp.isDeletable())
960 private void removeDualPoint() {
961 if (previous != null)
962 previous.setNext(null);
964 next.setPrevious(null);
965 PipeControlPoint ocp;
966 PipeControlPoint sccp;
967 if (isDualInline()) {
969 ocp = getSubPoint().get(0);
972 sccp = getParentPoint();
974 PipeRun p1 = ocp.getPipeRun();
975 PipeRun p2 = sccp.getPipeRun();
977 ocp.removeComponent();
978 sccp.removeComponent();
984 ocp.setPrevious(null);
986 sccp.setPrevious(null);
992 private void removeSubPoints() {
993 for (PipeControlPoint p : children) {
994 // TODO : this may affect delete routine, since classification of the point changes.
1001 private void removeParentPoint() {
1002 throw new RuntimeException("Child points cannot be removed directly");
1005 private void removeComponent() {
1006 if (component == null)
1008 PipelineComponent next = component.getNext();
1009 PipelineComponent prev = component.getNext();
1011 if (next.getNext() == component)
1013 else if (next.getPrevious() == component)
1014 next.setPrevious(null);
1017 if (prev.getNext() == component)
1019 else if (prev.getPrevious() == component)
1020 prev.setPrevious(null);
1022 PipelineComponent comp = component;
1028 public void setOrientation(Quat4d orientation) {
1029 if (MathTools.equals(orientation, getOrientation()))
1031 super.setOrientation(orientation);
1032 if (getParentPoint() == null && component != null)
1033 component._setWorldOrientation(getWorldOrientation());
1034 for (PipeControlPoint sub : getSubPoint()) {
1035 sub.setWorldPosition(getWorldPosition());
1036 sub.setWorldOrientation(getWorldOrientation());
1041 public void setPosition(Vector3d position) {
1042 if (MathTools.equals(position, getPosition()))
1044 super.setPosition(position);
1045 if (getParentPoint() == null && component != null)
1046 component._setWorldPosition(getWorldPosition());
1047 for (PipeControlPoint sub : getSubPoint()) {
1048 sub.setWorldPosition(getWorldPosition());
1049 sub.setWorldOrientation(getWorldOrientation());
1054 public void _setWorldPosition(Vector3d position) {
1055 Vector3d localPos = getLocalPosition(position);
1056 super.setPosition(localPos);
1057 for (PipeControlPoint sub : getSubPoint()) {
1058 sub.setWorldPosition(getWorldPosition());
1059 sub.setWorldOrientation(getWorldOrientation());
1063 public void _setWorldOrientation(Quat4d orientation) {
1064 Quat4d localOr = getLocalOrientation(orientation);
1065 super.setOrientation(localOr);
1066 for (PipeControlPoint sub : getSubPoint()) {
1067 sub.setWorldPosition(getWorldPosition());
1068 sub.setWorldOrientation(getWorldOrientation());
1073 public String toString() {
1074 return getClass().getName() + "@" + Integer.toHexString(hashCode());