1 /*******************************************************************************
\r
2 * Copyright (c) 2007 VTT Technical Research Centre of Finland and others.
\r
3 * All rights reserved. This program and the accompanying materials
\r
4 * are made available under the terms of the Eclipse Public License v1.0
\r
5 * which accompanies this distribution, and is available at
\r
6 * http://www.eclipse.org/legal/epl-v10.html
\r
9 * VTT Technical Research Centre of Finland - initial API and implementation
\r
10 *******************************************************************************/
\r
11 package fi.vtt.simantics.processeditor.common;
\r
13 import java.util.ArrayList;
\r
14 import java.util.Collection;
\r
16 import javax.vecmath.AxisAngle4d;
\r
17 import javax.vecmath.Point3d;
\r
18 import javax.vecmath.Vector3d;
\r
20 import org.simantics.db.Graph;
\r
21 import org.simantics.db.Resource;
\r
22 import org.simantics.proconf.g3d.base.G3DTools;
\r
23 import org.simantics.proconf.g3d.base.MathTools;
\r
24 import org.simantics.utils.ErrorLogger;
\r
26 import fi.vtt.simantics.processeditor.ProcessResource;
\r
27 import fi.vtt.simantics.processeditor.stubs.PipeControlPoint;
\r
28 import fi.vtt.simantics.processeditor.stubs.PipeRun;
\r
29 import fi.vtt.simantics.processeditor.stubs.PipelineComponent;
\r
32 * Rules that update pipeline.
\r
33 * TODO : optimize, remove stubs
\r
35 * FIXME : transformations
\r
37 * TODO : FixedAngleTurnComponents are handled like VariableAngleTurnComponents
\r
40 * @author Marko Luukkainen <Marko.Luukkainen@vtt.fi>
\r
43 public class PipingRules {
\r
45 private static final boolean DEBUG = false;
\r
46 private static final boolean DUMMY = false;
\r
48 private static final double MIN_TURN_ANGLE = 0.01;
\r
50 private static final int REMOVE_NONE = 0;
\r
51 private static final int REMOVE_START = 1;
\r
52 private static final int REMOVE_END = 2;
\r
53 private static final int REMOVE_BOTH = 3;
\r
55 private enum PathLegUpdateType {NONE,PREV,NEXT,PREV_S,NEXT_S};
\r
62 * @throws TransactionException
\r
64 public static void pipeControlPointPositionUpdate(Graph g, Resource pp) {
\r
66 PipeControlPoint pcp = new PipeControlPoint(g,pp);
\r
67 if (DEBUG) System.out.println("PipeControlPoint changed " + pp);
\r
69 boolean changed = ControlPointTools.isControlPointChanged(pcp);
\r
73 if (pcp.isInstanceOf(ProcessResource.plant3Dresource.PathLegEndControlPoint)) {
\r
74 updatePathLegEndControlPoint(pcp);
\r
76 updateInlineControlPoint(pcp);
\r
84 public static class ExpandIterInfo {
\r
85 // these two are turn control points
\r
86 private PipeControlPoint start;
\r
87 private PipeControlPoint end;
\r
90 public ExpandIterInfo() {
\r
94 public ExpandIterInfo(PipeControlPoint tcp, int type) {
\r
95 if (type == REMOVE_START)
\r
102 public ExpandIterInfo(PipeControlPoint start, PipeControlPoint end) {
\r
103 this.start = start;
\r
105 this.type = REMOVE_BOTH;
\r
108 public PipeControlPoint getEnd() {
\r
111 public void setEnd(PipeControlPoint end) {
\r
114 public PipeControlPoint getStart() {
\r
117 public void setStart(PipeControlPoint start) {
\r
118 this.start = start;
\r
120 public int getType() {
\r
123 public void setType(int type) {
\r
130 private static void updatePathLegEndControlPoint(PipeControlPoint pcp) {
\r
131 if (DEBUG) System.out.println("PipingTools.updateRunEndControlPoint() " + pcp.getResource());
\r
132 if (pcp.getNext() != null) {
\r
133 updatePathLegNext(pcp,pcp,PathLegUpdateType.NEXT_S);
\r
135 if (pcp.getPrevious() != null) {
\r
136 updatePathLegPrev(pcp,pcp,PathLegUpdateType.PREV_S);
\r
141 private static void updateInlineControlPoint(PipeControlPoint pcp) {
\r
142 if (DEBUG) System.out.println("PipingTools.updateInlineControlPoint() " + pcp.getResource());
\r
143 PipeControlPoint start = ControlPointTools.findPreviousEnd(pcp);
\r
144 updatePathLegNext(start,pcp,PathLegUpdateType.NONE);
\r
147 private static PipeControlPoint insertElbow(PipeControlPoint pcp1 , PipeControlPoint pcp2, Point3d pos) {
\r
148 if (DEBUG) System.out.println("PipingRules.insertElbow() " + pcp1.getResource() + " " + pcp2.getResource()+ " " + pos);
\r
149 PipelineComponent elbow = PipingTools2.instantiatePipelineComponent(pcp1.getGraph(), ControlPointTools.getPipeRun(pcp1).getResource(), ProcessResource.plant3Dresource.Elbow);
\r
150 PipeControlPoint pcp = elbow.getControlPoint();
\r
152 ControlPointTools.insertControlPoint(pcp, pcp1,pcp2);
\r
154 ControlPointTools.setWorldPosition(pcp, pos);
\r
159 private static void updatePathLegNext(PipeControlPoint start, PipeControlPoint updated, PathLegUpdateType lengthChange){
\r
160 ArrayList<PipeControlPoint> list = new ArrayList<PipeControlPoint>();
\r
161 PipeControlPoint end = ControlPointTools.findNextEnd(start,list);
\r
162 // this is for inline cp that is also path leg end
\r
163 if (start.equals(updated))
\r
164 lengthChange = PathLegUpdateType.NEXT;
\r
165 else if (end.equals(updated))
\r
166 lengthChange = PathLegUpdateType.PREV;
\r
167 updatePathLegNext(start, list, end, updated, lengthChange);
\r
170 private static void updatePathLegNext(PipeControlPoint start, ArrayList<PipeControlPoint> list, PipeControlPoint end, PipeControlPoint updated, PathLegUpdateType lengthChange) {
\r
171 updatePathLeg(start,list,end,false,0,new ArrayList<ExpandIterInfo>(),updated, lengthChange);
\r
174 private static class UpdateStruct2 {
\r
175 public PipeControlPoint start;
\r
176 public Point3d startPoint;
\r
177 public ArrayList<PipeControlPoint> list;
\r
178 public PipeControlPoint end;
\r
179 public Point3d endPoint;
\r
180 public Vector3d dir;
\r
181 public Vector3d offset;
\r
182 public boolean hasOffsets;
\r
184 public boolean reversed;
\r
185 public ArrayList<ExpandIterInfo> toRemove;
\r
186 public PipeControlPoint updated;
\r
187 public UpdateStruct2(PipeControlPoint start, Point3d startPoint, ArrayList<PipeControlPoint> list, PipeControlPoint end, Point3d endPoint, Vector3d dir, Vector3d offset, boolean hasOffsets, int iter, boolean reversed, ArrayList<ExpandIterInfo> toRemove, PipeControlPoint updated) {
\r
189 this.start = start;
\r
190 this.startPoint = startPoint;
\r
193 this.endPoint = endPoint;
\r
195 this.offset = offset;
\r
196 this.hasOffsets = hasOffsets;
\r
198 this.reversed = reversed;
\r
199 this.toRemove = toRemove;
\r
200 this.updated = updated;
\r
203 public String toString() {
\r
204 return start.getResource() + " " + end.getResource() + " " + dir + " " + hasOffsets + " " + offset + " " + iter + " " + toRemove.size();
\r
209 private static boolean calculateOffset(Point3d startPoint, Point3d endPoint, ArrayList<PipeControlPoint> list, Vector3d dir, Vector3d offset) {
\r
210 boolean hasOffsets = false;
\r
211 dir.set(startPoint);
\r
214 offset.set(0.0,0.0,0.0);
\r
215 for (PipeControlPoint icp : list) {
\r
216 if (icp.isInstanceOf(ProcessResource.plant3Dresource.OffsettingPoint)) {
\r
218 offset.add(ControlPointTools.getSizeChangeOffsetVector(icp,dir));
\r
220 else if (icp.isInstanceOf(ProcessResource.plant3Dresource.DualSubControlPoint))
\r
221 ErrorLogger.defaultLogError("Updating pipe run, found offset controlpoint " + icp.getResource(), new Exception("ASSERT!"));
\r
227 * @param start starting point of the pipe run
\r
228 * @param list list of inline control points in the pipe run
\r
229 * @param end ending point of the pipe run
\r
230 * @param reversed boolean flag indicating wether start or end control point was modified (if true then end point was modified)
\r
231 * @throws TransactionException
\r
233 private static void updatePathLeg(PipeControlPoint start, ArrayList<PipeControlPoint> list, PipeControlPoint end, boolean reversed, int iter, ArrayList<ExpandIterInfo> toRemove, PipeControlPoint updated, PathLegUpdateType lengthChange) {
\r
234 // FIXME: direction is calculated wrong way!
\r
235 boolean hasOffsets = false;
\r
236 Vector3d offset = new Vector3d();
\r
237 Point3d startPoint = G3DTools.getPoint(start.getWorldPosition());
\r
238 Point3d endPoint = G3DTools.getPoint(end.getWorldPosition());
\r
239 Vector3d dir = new Vector3d ();
\r
240 hasOffsets = calculateOffset(startPoint, endPoint, list, dir, offset);
\r
241 updatePathLeg(new UpdateStruct2(start, startPoint, list, end, endPoint, dir, offset, hasOffsets, iter, reversed, toRemove, updated), lengthChange);
\r
245 private static void updatePathLeg(UpdateStruct2 u, PathLegUpdateType lengthChange){
\r
247 if (u.start.isInstanceOf(ProcessResource.plant3Dresource.DirectedControlPoint))
\r
249 if (u.end.isInstanceOf(ProcessResource.plant3Dresource.DirectedControlPoint))
\r
251 switch (directed) {
\r
253 updateFreePathLeg(u,lengthChange);
\r
256 updateDirectedPathLeg(u,lengthChange);
\r
259 updateDualDirectedPathLeg(u,lengthChange);
\r
265 private static void updateFreePathLeg(UpdateStruct2 u, PathLegUpdateType lengthChange) {
\r
266 if (DEBUG) System.out.println("PipingRules.updateFreePipeRun " + u + " " + lengthChange);
\r
267 checkExpandPathLeg(u, lengthChange);
\r
270 private static void updateInlineControlPoints(UpdateStruct2 u, boolean checkSizes) {
\r
271 if (DEBUG) System.out.println("PipingTools.updateInlineControlPoints() " + u);
\r
273 if (!u.hasOffsets) {
\r
274 // FIXME : cache positions
\r
276 for (PipeControlPoint icp : u.list) {
\r
277 updateInlineControlPoint(icp, u.startPoint, u.endPoint,u.dir);
\r
282 ArrayList<PipeControlPoint> pathLegPoints = new ArrayList<PipeControlPoint>();
\r
283 pathLegPoints.add(u.start);
\r
284 for (PipeControlPoint icp : u.list) {
\r
285 //updateInlineControlPoint(icp, u.startPoint, u.endPoint,u.dir);
\r
286 updateBranchControlPointBranches(icp);
\r
287 pathLegPoints.add(icp);
\r
289 pathLegPoints.add(u.end);
\r
291 // TODO : values can be cached in the loop
\r
292 for (int i = 1; i < pathLegPoints.size(); i++) {
\r
293 PipeControlPoint icp = pathLegPoints.get(i);
\r
295 PipeControlPoint prev;
\r
297 prev = pathLegPoints.get(i-1);
\r
298 prevPos = G3DTools.getPoint(prev.getWorldPosition());
\r
299 Point3d currentPos = G3DTools.getPoint(icp.getWorldPosition());
\r
301 if (icp.isInstanceOf(ProcessResource.plant3Dresource.VariableLengthControlPoint)) {
\r
302 if (i != pathLegPoints.size() - 1) {
\r
303 PipeControlPoint next;
\r
305 next = pathLegPoints.get(i + 1);
\r
306 nextPos = G3DTools.getPoint(next.getWorldPosition());
\r
307 Vector3d dir = new Vector3d(nextPos);
\r
309 double l = dir.lengthSquared(); // distance between control points (square)
\r
310 double l2prev = ControlPointTools.getInlineLength(prev); // distance taken by components
\r
311 double l2next = ControlPointTools.getInlineLength(next);
\r
312 double l2 = l2prev + l2next;
\r
313 double l2s = MathTools.square(l2);
\r
314 if (l2s < l) { // check if there is enough space for variable length component.
\r
317 double length = Math.sqrt(l) - l2; // true length of the variable length component
\r
318 dir.scale(length*0.5 + l2prev); // calculate center position of the component
\r
320 ControlPointTools.setWorldPosition(icp,dir);
\r
321 icp.setRelatedScalarDouble(ProcessResource.plant3Dresource.HasLength, length);
\r
323 //components leave no space to the component and it must be removed
\r
324 ControlPointTools.removeControlPoint(icp);
\r
328 // this is variable length component at the end of the piperun.
\r
329 // the problem is that we want to keep unconnected end of the component in the same
\r
330 // place, but center of the component must be moved.
\r
331 double currentLength = icp.getSingleRelatedScalarDouble(ProcessResource.plant3Dresource.HasLength);
\r
332 Vector3d dir = new Vector3d();
\r
333 dir.sub(currentPos,prevPos);
\r
335 Point3d endPos = new Point3d(dir);
\r
336 endPos.scale(currentLength * 0.5);
\r
337 endPos.add(currentPos); //this is the free end of the component
\r
339 double offset = ControlPointTools.getInlineLength(prev);
\r
340 Point3d beginPos = new Point3d(dir);
\r
341 beginPos.scale(offset);
\r
342 beginPos.add(prevPos); //this is the connected end of the component
\r
344 double l = beginPos.distance(endPos);
\r
347 beginPos.add(dir); //center position
\r
349 if (DEBUG) System.out.println("PipingRules.updateInlineControlPoints() setting variable length to " + l);
\r
350 icp.setRelatedScalarDouble(ProcessResource.plant3Dresource.HasLength, l);
\r
352 ControlPointTools.setWorldPosition(icp, beginPos);
\r
356 } else if (!prev.isInstanceOf(ProcessResource.plant3Dresource.VariableLengthControlPoint)){
\r
357 // If this and previous control point are not variable length pcps, we'll have to check if there is no empty space between them.
\r
358 // I there is, we'll have to create new variable length component between them.
\r
359 Vector3d dir = new Vector3d(currentPos);
\r
361 double l = dir.lengthSquared();
\r
362 double l2prev = ControlPointTools.getInlineLength(prev);
\r
363 double l2next = ControlPointTools.getInlineLength(icp);
\r
364 double l2 = l2prev + l2next;
\r
365 double l2s = l2 * l2;
\r
367 PipelineComponent component = PipingTools2.instantiatePipelineComponent(prev.getGraph(), ControlPointTools.getPipeRun(prev).getResource(), ProcessResource.plant3Dresource.Straight);
\r
368 PipeControlPoint scp = component.getControlPoint();
\r
369 ControlPointTools.insertControlPoint(scp, prev, icp);
\r
372 double length = Math.sqrt(l) - l2; // true length of the variable length component
\r
373 dir.scale(length*0.5 + l2prev); // calculate center position of the component
\r
375 ControlPointTools.setWorldPosition(scp, dir);
\r
376 scp.setRelatedScalarDouble(ProcessResource.plant3Dresource.HasLength, length);
\r
381 u.endPoint.sub(u.offset);
\r
382 // FIXME : straights
\r
383 for (PipeControlPoint icp : u.list) {
\r
384 updateInlineControlPoint(icp, u.startPoint, u.endPoint,u.dir);
\r
385 updateBranchControlPointBranches(icp);
\r
386 if (icp.isInstanceOf(ProcessResource.plant3Dresource.OffsettingPoint)) {
\r
387 // TODO : offset vector is already calculated and should be
\r
389 u.offset = ControlPointTools.getSizeChangeOffsetVector(icp, u.dir);
\r
390 updateOffsetPoint( icp, u.offset);
\r
391 u.startPoint.add(u.offset);
\r
392 u.endPoint.add(u.offset);
\r
400 private static void ppNoOffset(UpdateStruct2 u) {
\r
401 if (DEBUG)System.out.println("PipingRules.ppNoOffset() " + u);
\r
402 Vector3d offset = new Vector3d();
\r
403 if (u.hasOffsets) {
\r
405 for (PipeControlPoint icp : u.list) {
\r
406 if (icp.isInstanceOf(ProcessResource.plant3Dresource.OffsettingPoint)) {
\r
407 offset.add(ControlPointTools.getSizeChangeOffsetVector(icp,u.dir));
\r
409 else if (icp.isInstanceOf(ProcessResource.plant3Dresource.DualSubControlPoint))
\r
410 ErrorLogger.defaultLogError("Updating pipe run, found offset controlpoint " + icp.getResource(), new Exception("ASSERT!"));
\r
414 checkExpandPathLeg(u,PathLegUpdateType.NONE);
\r
417 private static void ppNoDir(PipeControlPoint start, Point3d startPoint,ArrayList<PipeControlPoint> list, PipeControlPoint end,Point3d endPoint, boolean hasOffsets,int iter,boolean reversed, ArrayList<ExpandIterInfo> toRemove, PipeControlPoint updated) {
\r
418 if (DEBUG)System.out.println("PipingRules.ppNoDir() " + start.getResource() + " " + end.getResource() + " " + iter + " " + toRemove.size());
\r
419 // FIXME : extra loop (dir should be calculated here)
\r
420 Vector3d dir = new Vector3d();
\r
421 Vector3d offset = new Vector3d();
\r
422 hasOffsets = calculateOffset(startPoint, endPoint, list, dir, offset);
\r
423 ppNoOffset(new UpdateStruct2(start, startPoint, list, end, endPoint, dir, null, hasOffsets, iter, reversed, toRemove,updated));
\r
426 private static void checkExpandPathLeg(UpdateStruct2 u, PathLegUpdateType lengthChange) {
\r
427 if (DEBUG)System.out.println("PipingRules.checkExpandPathLeg() " + u + " " + lengthChange);
\r
428 if (lengthChange != PathLegUpdateType.NONE) {
\r
429 // FIXME : turns cannot be checked before inline cps are updated, since their position affects calculation of turns
\r
430 processPathLeg(u,false,false);
\r
431 int type = checkTurns(u,lengthChange);
\r
432 if (type == REMOVE_NONE) {
\r
433 processPathLeg(u,false,true);
\r
435 expandPathLeg(u, type);
\r
438 processPathLeg(u,false,true);
\r
442 private static void updateDirectedPathLeg(UpdateStruct2 u, PathLegUpdateType lengthChange) {
\r
443 if (DEBUG)System.out.println("PipingRules.updateDirectedPipeRun() " + u + " " + lengthChange);
\r
444 PipeControlPoint dcp;
\r
445 PipeControlPoint other;
\r
446 boolean canMoveOther = false;
\r
447 boolean dcpStart = false;
\r
449 if (u.start.isInstanceOf(ProcessResource.plant3Dresource.DirectedControlPoint)) {
\r
452 position = u.startPoint;
\r
455 canMoveOther = true;
\r
459 position = u.endPoint;
\r
461 canMoveOther = true;
\r
464 Vector3d directedDirection = ControlPointTools.getDirectedControlPointDirection(dcp);
\r
465 Point3d directedEndPoint = new Point3d(u.endPoint);
\r
467 directedEndPoint.add(u.offset);
\r
469 double mu[] = new double[2];
\r
472 Vector3d t = new Vector3d();
\r
475 closest = MathTools.closestPointOnStraight(directedEndPoint, u.startPoint, directedDirection, mu);
\r
476 t.sub(closest, directedEndPoint);
\r
478 closest = MathTools.closestPointOnStraight(u.startPoint, directedEndPoint, directedDirection, mu);
\r
479 t.sub(closest, u.startPoint);
\r
483 double distance = t.lengthSquared();
\r
484 boolean aligned = (distance < 0.001);
\r
486 checkExpandPathLeg(u,lengthChange);
\r
491 PipeControlPoint nextToMoved;
\r
493 if (u.list.size() > 0)
\r
495 nextToMoved = u.list.get(0);
\r
497 nextToMoved = u.list.get(u.list.size() - 1);
\r
499 nextToMoved = u.end;
\r
501 nextToMoved = u.start;
\r
502 if (other.isInstanceOf(ProcessResource.plant3Dresource.VariableAngleTurnControlPoint)) {
\r
504 // TODO calculate needed space from next run end.
\r
507 closest.set(u.startPoint);
\r
509 closest.set(u.endPoint);
\r
511 closest.add(directedDirection);
\r
514 if (canMoveOther) {
\r
515 if (DEBUG)System.out.println("PipingRules.updateDirectedPipeRun() moved end " + other.getResource() + " to " + closest);
\r
516 ControlPointTools.setWorldPosition(other, closest);
\r
518 ppNoOffset(new UpdateStruct2(u.start, u.startPoint, u.list, u.end, new Point3d(closest), directedDirection,null, u.hasOffsets, u.iter, u.reversed, u.toRemove,u.updated));
\r
519 if (u.end.getNext() != null)
\r
520 updatePathLegNext(u.end,u.updated,PathLegUpdateType.NEXT);
\r
522 ppNoOffset(new UpdateStruct2(u.start, new Point3d(closest), u.list, u.end, u.endPoint, directedDirection,null, u.hasOffsets, u.iter, u.reversed, u.toRemove,u.updated));
\r
523 if (u.start.getPrevious() != null)
\r
524 updatePathLegPrev(u.start,u.updated,PathLegUpdateType.PREV);
\r
527 // TODO : calculate needed space from next run end.
\r
528 insertElbowUpdate(u, dcp, nextToMoved, dcpStart, position, directedDirection);
\r
530 } else if (other.isInstanceOf(ProcessResource.plant3Dresource.UndirectedControlPoint) &&
\r
531 other.getSubPointOf() != null) {
\r
532 // FIXME : this code was for updating branches
\r
533 Vector3d bintersect = new Vector3d();
\r
534 PipeControlPoint bcp = other.getSubPointOf();
\r
535 if (bcp != null && canMoveOther) {
\r
536 Point3d bstart = new Point3d();
\r
537 Point3d bend = new Point3d();
\r
538 Vector3d bdir = new Vector3d();
\r
539 ControlPointTools.getInlineControlPointEnds(bcp, bstart, bend, bdir);
\r
540 Vector3d nintersect = new Vector3d();
\r
542 MathTools.intersectStraightStraight(position, directedDirection, bstart,
\r
543 bdir, nintersect, bintersect, mu);
\r
544 Vector3d dist = new Vector3d(nintersect);
\r
545 dist.sub(bintersect);
\r
546 canMoveOther = mu[1] > 0.0 && mu[1] < 1.0 && dist.lengthSquared() < 0.01;
\r
548 // TODO : endControlPoints are undirected: calculcate correct position for it
\r
549 throw new UnsupportedOperationException("not implemented");
\r
551 if (canMoveOther) {
\r
552 if (DEBUG) System.out.println("PipingRules.updateDirectedPipeRun() moved end " + other.getResource() + " to " + bintersect);
\r
553 // is required branch position is in possible range
\r
554 ControlPointTools.setWorldPosition(bcp, bintersect);
\r
556 checkExpandPathLeg(new UpdateStruct2(u.start, u.startPoint, u.list, u.end, new Point3d(bintersect),directedDirection, u.offset, u.hasOffsets, u.iter, u.reversed, u.toRemove,u.updated),lengthChange);
\r
558 checkExpandPathLeg(new UpdateStruct2(u.start, new Point3d(bintersect), u.list, u.end, u.endPoint,directedDirection, u.offset, u.hasOffsets, u.iter, u.reversed, u.toRemove,u.updated),lengthChange);
\r
561 // branch cannot be moved into right position, new turn
\r
562 // / elbow must be inserted
\r
563 insertElbowUpdate(u , dcp, nextToMoved, dcpStart, position, directedDirection);
\r
566 } else { // assume that control point cannot be moved, but can be rotated
\r
567 insertElbowUpdate(u, dcp, nextToMoved, dcpStart, position, directedDirection);
\r
575 private static void updateDualDirectedPathLeg(UpdateStruct2 u, PathLegUpdateType lengthChange) {
\r
576 if (DEBUG) System.out.println("PipingRules.updateDualDirectedPipeRun() " + u + " " + lengthChange);
\r
578 PipeControlPoint dcp1 = u.start;
\r
579 PipeControlPoint dcp2 = u.end;
\r
580 Point3d position1 = u.startPoint;
\r
581 Point3d position2 = u.endPoint;
\r
582 Point3d position1offset = new Point3d(position1);
\r
583 position1offset.sub(u.offset);
\r
584 Point3d position2offset = new Point3d(position2);
\r
585 position2offset.add(u.offset);
\r
586 Vector3d dir1 = ControlPointTools.getDirectedControlPointDirection(dcp1);
\r
587 Vector3d dir2 = ControlPointTools.getDirectedControlPointDirection(dcp2);
\r
588 Vector3d p1 = MathTools.closestPointOnStraight(position1offset, position2, dir2);
\r
589 Vector3d p2 = MathTools.closestPointOnStraight(position2offset, position1, dir1);
\r
590 double d1 = position1.distance(new Point3d(p1));
\r
591 double d2 = position2.distance(new Point3d(p2));
\r
593 boolean aligned = (d1 < 0.01 && d2 < 0.01);
\r
600 PipeControlPoint dcp;
\r
601 PipeControlPoint next;
\r
604 if (u.list.size() > 0)
\r
605 next = u.list.get(0);
\r
610 if (u.list.size() > 0)
\r
611 next = u.list.get(u.list.size() - 1);
\r
616 PipeRun pipeline = ControlPointTools.getPipeRun(dcp1);
\r
617 PipelineComponent elbow1 = PipingTools2.instantiatePipelineComponent(u.start.getGraph(), pipeline.getResource(), ProcessResource.plant3Dresource.Elbow);
\r
618 PipelineComponent elbow2 = PipingTools2.instantiatePipelineComponent(u.start.getGraph(), pipeline.getResource(), ProcessResource.plant3Dresource.Elbow);
\r
620 PipeControlPoint tcp1 = elbow1.getControlPoint();
\r
621 PipeControlPoint tcp2 = elbow2.getControlPoint();
\r
623 // Straight s1 = getStraight(dcp, next);
\r
624 ControlPointTools.insertControlPoint(tcp1, dcp, next);
\r
625 // s1 = getStraight(tcp1, next);
\r
626 ControlPointTools.insertControlPoint(tcp2, tcp1, next);
\r
627 p1 = G3DTools.getVector(dcp.getLocalPosition());
\r
634 p2 = MathTools.closestPointOnStraight(new Point3d(p1), position2, dir2);
\r
636 p2 = MathTools.closestPointOnStraight(new Point3d(p1), position1, dir1);
\r
638 ControlPointTools.setWorldPosition(tcp1, p1);
\r
639 ControlPointTools.setWorldPosition(tcp2, p2);
\r
641 if (DEBUG) System.out.println("PipingRules.updateDualDirectedPipeRun() created two turns " + tcp1.getResource() + " " + tcp2.getResource());
\r
644 Vector3d dd = new Vector3d(p2);
\r
647 processPathLeg(new UpdateStruct2(u.start, u.startPoint,new ArrayList<PipeControlPoint>(), tcp1, new Point3d(p1),dir1, new Vector3d(), false, 0, false,new ArrayList<ExpandIterInfo>(), u.updated));
\r
648 processPathLeg(new UpdateStruct2(tcp1,new Point3d(p1), new ArrayList<PipeControlPoint>(),tcp2, new Point3d(p2), dd,new Vector3d(), false, 0, false,new ArrayList<ExpandIterInfo>(), u.updated));
\r
649 // offset is recalculated
\r
650 processPathLegNoOffset(new UpdateStruct2(tcp2, new Point3d(p2), u.list,u.end, u.endPoint, dir2, null, u.hasOffsets,u.iter, u.reversed, u.toRemove, u.updated));
\r
652 Vector3d dd = new Vector3d(p1);
\r
655 processPathLeg(new UpdateStruct2(tcp1,new Point3d(p1), new ArrayList<PipeControlPoint>(),u.end, u.endPoint, dir2, new Vector3d(), false, 0,false, new ArrayList<ExpandIterInfo>(), u.updated));
\r
656 processPathLeg(new UpdateStruct2(tcp2,new Point3d(p2), new ArrayList<PipeControlPoint>(),tcp1, new Point3d(p1), dd,new Vector3d(), false, 0, false,new ArrayList<ExpandIterInfo>(), u.updated));
\r
657 // offset is recalculated
\r
658 processPathLegNoOffset(new UpdateStruct2(u.start, u.startPoint,u.list, tcp2, new Point3d(p2),dir1, null, u.hasOffsets, u.iter, u.reversed,u.toRemove, u.updated));
\r
664 private static void insertElbowUpdate(UpdateStruct2 u, PipeControlPoint dcp, PipeControlPoint next, boolean dcpStart, Point3d position, Vector3d directedDirection) {
\r
666 Vector3d closest = new Vector3d(position);
\r
667 closest.add(directedDirection);
\r
668 PipeControlPoint tcp = insertElbow(dcp, next, new Point3d(closest));
\r
670 if (DEBUG) System.out.println("PipingRules.updateDirectedPipeRun() inserted " + tcp.getResource());
\r
673 // update pipe run from new turn to other end
\r
674 ppNoDir(tcp, new Point3d(closest), u.list, u.end, u.endPoint, u.hasOffsets, u.iter, u.reversed, u.toRemove, u.updated);
\r
675 // update pipe run from directed to new turn
\r
676 processPathLeg(new UpdateStruct2(u.start, u.startPoint, new ArrayList<PipeControlPoint>(), tcp, new Point3d(closest), directedDirection, new Vector3d(), false, 0, false, new ArrayList<ExpandIterInfo>(),u.updated));
\r
678 // update pipe run from other end to new turn
\r
679 ppNoDir(u.start, u.startPoint, u.list, tcp, new Point3d(closest), u.hasOffsets, u.iter, u.reversed, u.toRemove,u.updated);
\r
680 // update pipe run from new turn to directed
\r
681 processPathLeg(new UpdateStruct2(tcp, new Point3d(closest), new ArrayList<PipeControlPoint>(), u.end, u.endPoint, directedDirection, new Vector3d(), false, 0, false, new ArrayList<ExpandIterInfo>(),u.updated));
\r
686 * Checks if turns can be removed (turn angle near zero)
\r
688 private static int checkTurns(UpdateStruct2 u, PathLegUpdateType lengthChange) {
\r
690 System.out.println("PipingRules.checkTurns() " + u.start.getResource()
\r
691 + " " + u.end.getResource());
\r
692 boolean startRemoved = false;
\r
693 boolean endRemoved = false;
\r
694 if (u.start.isInstanceOf(ProcessResource.plant3Dresource.VariableAngleTurnControlPoint)) {
\r
695 // this won't work properly if inline control points are not updated
\r
696 PipeControlPoint startPrev = u.start.getPrevious();
\r
697 if (startPrev != null) {
\r
699 if (!u.hasOffsets) {
\r
700 a = updateTurnControlPointTurn( u.start, startPrev, u.end);
\r
702 Point3d ep = new Point3d(u.endPoint);
\r
704 a = updateTurnControlPointTurn( u.start,u.startPoint, G3DTools.getPoint(startPrev.getLocalPosition()), ep);
\r
707 if (a < MIN_TURN_ANGLE)
\r
708 startRemoved = true;
\r
709 else if (lengthChange == PathLegUpdateType.PREV || lengthChange == PathLegUpdateType.PREV_S){
\r
710 PathLegUpdateType type;
\r
711 if (lengthChange == PathLegUpdateType.PREV_S)
\r
712 type = PathLegUpdateType.PREV;
\r
714 type = PathLegUpdateType.NONE;
\r
715 updatePathLegPrev(u.start, u.start, type);
\r
719 if (u.end.isInstanceOf(ProcessResource.plant3Dresource.VariableAngleTurnControlPoint)) {
\r
721 PipeControlPoint endNext = u.end.getNext();
\r
722 if (endNext != null) {
\r
724 if (!u.hasOffsets) {
\r
725 a = updateTurnControlPointTurn(u.end,u.start, endNext);
\r
727 Point3d sp = new Point3d(u.startPoint);
\r
729 a = updateTurnControlPointTurn(u.end, u.endPoint, sp, G3DTools.getPoint(endNext.getLocalPosition()));
\r
731 if (a < MIN_TURN_ANGLE)
\r
733 else if (lengthChange == PathLegUpdateType.NEXT || lengthChange == PathLegUpdateType.NEXT_S){
\r
734 PathLegUpdateType type;
\r
735 if (lengthChange == PathLegUpdateType.NEXT_S)
\r
736 type = PathLegUpdateType.NEXT;
\r
738 type = PathLegUpdateType.NONE;
\r
739 updatePathLegNext(u.end, u.end,type);
\r
744 System.out.println("PipingRules.checkTurns() res " + startRemoved + " " + endRemoved);
\r
745 if (!startRemoved && !endRemoved)
\r
746 return REMOVE_NONE;
\r
747 if (startRemoved && endRemoved)
\r
748 return REMOVE_BOTH;
\r
750 return REMOVE_START;
\r
755 * Expands piperun search over turns that are going to be removed
\r
758 private static void expandPathLeg(UpdateStruct2 u, int type) {
\r
759 if (DEBUG) System.out.println("PipingRules.expandPipeline " + u.start.getResource() + " " + u.end.getResource());
\r
760 ArrayList<PipeControlPoint> newList = new ArrayList<PipeControlPoint> ();
\r
763 throw new RuntimeException("Error in piping rules");
\r
764 case REMOVE_START :
\r
765 u.toRemove.add(new ExpandIterInfo(u.start,REMOVE_START));
\r
766 u.start = ControlPointTools.findPreviousEnd(u.start);
\r
767 u.startPoint = G3DTools.getPoint(u.start.getLocalPosition());
\r
768 ControlPointTools.findNextEnd(u.start,newList);
\r
769 newList.addAll(u.list);
\r
773 u.toRemove.add(new ExpandIterInfo(u.end,REMOVE_END));
\r
774 u.end = ControlPointTools.findNextEnd(u.end,newList);
\r
775 u.endPoint = G3DTools.getPoint(u.end.getLocalPosition());
\r
776 u.list.addAll(newList);
\r
779 u.toRemove.add(new ExpandIterInfo(u.start,u.end));
\r
780 u.start = ControlPointTools.findPreviousEnd(u.start);
\r
781 u.startPoint = G3DTools.getPoint(u.start.getLocalPosition());
\r
782 ControlPointTools.findNextEnd(u.start,newList);
\r
783 newList.addAll(u.list);
\r
785 newList = new ArrayList<PipeControlPoint> ();
\r
786 u.end = ControlPointTools.findNextEnd(u.end,newList);
\r
787 u.endPoint = G3DTools.getPoint(u.end.getLocalPosition());
\r
788 u.list.addAll(newList);
\r
791 throw new RuntimeException("Error in piping rules");
\r
794 u.offset = new Vector3d();
\r
795 if (u.hasOffsets) {
\r
797 for (PipeControlPoint icp : u.list) {
\r
798 if (icp.isInstanceOf(ProcessResource.plant3Dresource.OffsettingPoint)) {
\r
799 u.offset.add(ControlPointTools.getSizeChangeOffsetVector(icp,u.dir));
\r
801 else if (icp.isInstanceOf(ProcessResource.plant3Dresource.DualSubControlPoint))
\r
802 ErrorLogger.defaultLogError("Updating pipe run, found offset controlpoint " + icp.getResource(), new Exception("ASSERT!"));
\r
805 if (DEBUG) System.out.println("PipingRules.expandPipeline expanded " + u.start.getResource() + " " + u.end.getResource());
\r
807 updatePathLeg(u,PathLegUpdateType.NONE);
\r
811 * reverts one iteration of turn removing back)
\r
813 private static void backIter(UpdateStruct2 u) {
\r
815 if (DEBUG) System.out.println("PipingRules.backIter" + u.start.getResource() + " " + u.end.getResource());
\r
817 throw new RuntimeException("Error in piping rules");
\r
818 ExpandIterInfo info = u.toRemove.get(u.toRemove.size()-1);
\r
819 u.toRemove.remove(u.toRemove.size()-1);
\r
820 if (info.getType() == REMOVE_START || info.getType() == REMOVE_BOTH) {
\r
821 while (u.list.size() > 0) {
\r
822 PipeControlPoint icp = u.list.get(0);
\r
823 if (icp.getPrevious().getResource().equals(info.getStart().getResource()))
\r
825 u.list.remove(icp);
\r
827 u.start = info.getStart();
\r
829 if (info.getType() == REMOVE_END || info.getType() == REMOVE_BOTH) {
\r
830 while (u.list.size() > 0) {
\r
831 PipeControlPoint icp = u.list.get(u.list.size() - 1);
\r
832 if (icp.getNext().getResource().equals(info.getEnd().getResource()))
\r
834 u.list.remove(icp);
\r
836 u.end = info.getEnd();
\r
838 u.offset = new Vector3d();
\r
839 if (u.hasOffsets) {
\r
841 for (PipeControlPoint icp : u.list) {
\r
842 if (icp.isInstanceOf(ProcessResource.plant3Dresource.OffsettingPoint)) {
\r
843 u.offset.add(ControlPointTools.getSizeChangeOffsetVector(icp,u.dir));
\r
845 else if (icp.isInstanceOf(ProcessResource.plant3Dresource.DualSubControlPoint))
\r
846 ErrorLogger.defaultLogError("Updating pipe run, found offset controlpoint " + icp.getResource(), new Exception("ASSERT!"));
\r
854 * Processes pipe run (removes necessary turns and updates run ends)
\r
856 // private static void processPathLeg(PipeControlPoint start, Point3d startPoint,ArrayList<InlineControlPoint> list, PipeControlPoint end,Point3d endPoint, Vector3d dir,Vector3d offset, boolean hasOffsets,int iter, boolean reversed, ArrayList<ExpandIterInfo> toRemove) throws TransactionException {
\r
858 private static void processPathLeg(UpdateStruct2 u) {
\r
859 if (DEBUG) System.out.println("PipingRules.processPathLeg " + u.start.getResource() + " " + u.end.getResource());
\r
860 processPathLeg(u, true, true);
\r
864 private static void processPathLeg(UpdateStruct2 u, boolean updateEnds, boolean updateInline) {
\r
865 if (DEBUG) System.out.println("PipingRules.processPathLeg " + u.start.getResource() + " " + u.end.getResource());
\r
866 if (u.toRemove.size() > 0) {
\r
867 for (ExpandIterInfo info : u.toRemove) {
\r
868 if (info.getStart() != null) {
\r
869 ControlPointTools.removeControlPoint(info.getStart());
\r
871 if (info.getEnd() != null) {
\r
872 ControlPointTools.removeControlPoint(info.getEnd());
\r
875 // ControlPointTools.removeControlPoint may remove mo0re than one CP;
\r
876 // we must populate inline CP list again.
\r
878 ControlPointTools.findNextEnd(u.start, u.list);
\r
880 // FIXME : inline CPs are update twice because their positions must be updated before and after ends.
\r
881 updateInlineControlPoints(u,false);
\r
883 if (u.start.isInstanceOf(ProcessResource.plant3Dresource.TurnControlPoint)) {
\r
884 updateTurnControlPointTurn(u.start, u.start.getPrevious(), u.start.getNext());
\r
885 updatePathLegPrev(u.start, u.start, PathLegUpdateType.NONE);
\r
886 } else if (u.start.isInstanceOf(ProcessResource.plant3Dresource.EndComponentControlPoint)) {
\r
887 updateEndComponentControlPoint(u.start, u.startPoint, u.endPoint);
\r
889 if (u.end.isInstanceOf(ProcessResource.plant3Dresource.TurnControlPoint)) {
\r
890 updateTurnControlPointTurn( u.end, u.end.getPrevious(), u.end.getNext());
\r
891 updatePathLegNext(u.end, u.end, PathLegUpdateType.NONE);
\r
892 } else if (u.end.isInstanceOf(ProcessResource.plant3Dresource.EndComponentControlPoint)) {
\r
893 updateEndComponentControlPoint(u.end, u.startPoint, u.endPoint);
\r
897 if (u.start.isInstanceOf(ProcessResource.plant3Dresource.EndComponentControlPoint)) {
\r
898 updateEndComponentControlPoint(u.start, u.startPoint, u.endPoint);
\r
900 if (u.end.isInstanceOf(ProcessResource.plant3Dresource.EndComponentControlPoint)) {
\r
901 updateEndComponentControlPoint( u.end, u.startPoint, u.endPoint);
\r
905 updateInlineControlPoints(u,true);
\r
910 * Processes pipe run and recalculates offset
\r
912 //private static void processPathLeg(PipeControlPoint start, Point3d startPoint,ArrayList<InlineControlPoint> list, PipeControlPoint end,Point3d endPoint, Vector3d dir, boolean hasOffsets,int iter, boolean reversed, ArrayList<ExpandIterInfo> toRemove) throws TransactionException {
\r
913 private static void processPathLegNoOffset(UpdateStruct2 u) {
\r
914 if (DEBUG) System.out.println("PipingRules.processPathLeg " + u.start.getResource() + " " + u.end.getResource());
\r
915 Vector3d offset = new Vector3d();
\r
916 if (u.hasOffsets) {
\r
918 for (PipeControlPoint icp : u.list) {
\r
919 if (icp.isInstanceOf(ProcessResource.plant3Dresource.OffsetComponent)) {
\r
920 offset.add(ControlPointTools.getSizeChangeOffsetVector(icp,u.dir));
\r
921 } else if (icp.isInstanceOf(ProcessResource.plant3Dresource.DualSubControlPoint)) {
\r
922 ErrorLogger.defaultLogError("Updating pipe run, found offset controlpoint " + icp.getResource(), new Exception("ASSERT!"));
\r
929 private static void updateOffsetPoint(PipeControlPoint sccp, Vector3d offset) {
\r
930 Point3d world = G3DTools.getPoint(sccp.getWorldPosition());
\r
932 PipeControlPoint ocp = sccp.getSubPoint().iterator().next();
\r
933 ControlPointTools.setWorldPosition(ocp, world);
\r
936 private static void updatePathLegPrev(PipeControlPoint start, PipeControlPoint updated, PathLegUpdateType lengthChange) {
\r
937 ArrayList<PipeControlPoint> list = new ArrayList<PipeControlPoint>();
\r
938 PipeControlPoint end = ControlPointTools.findPreviousEnd(start,list);
\r
939 updatePathLegPrev(start, list, end,updated,lengthChange);
\r
942 private static void updatePathLegPrev(PipeControlPoint start, ArrayList<PipeControlPoint> list, PipeControlPoint end, PipeControlPoint updated, PathLegUpdateType lengthChange) {
\r
943 // reverses the list
\r
944 ArrayList<PipeControlPoint> nextList = new ArrayList<PipeControlPoint>();
\r
945 for (PipeControlPoint icp : list) {
\r
946 if (icp.isInstanceOf(ProcessResource.plant3Dresource.DualSubControlPoint)) {
\r
947 nextList.add(0, icp.getSubPointOf());
\r
949 nextList.add(0,icp);
\r
953 updatePathLeg(end, nextList, start, true,0,new ArrayList<ExpandIterInfo>(),updated,lengthChange);
\r
959 * Updates InlineControlPoints position when straight pipe's end(s) have
\r
967 private static void updateInlineControlPoint( PipeControlPoint icp, Point3d nextPoint, Point3d prevPoint, Vector3d dir) {
\r
968 if (DEBUG) System.out.println("PipingRules.updateInlineControlPoint() " + icp.getResource());
\r
970 Point3d inlinePoint = G3DTools.getPoint(icp.getLocalPosition());
\r
971 if (DEBUG) System.out.print("InlineControlPoint update "+icp.getResource() + " " + inlinePoint + " " + prevPoint + " " + nextPoint);
\r
972 Vector3d newInlinePoint = null;
\r
973 boolean branchUpdate = false;
\r
974 PipeControlPoint becp = null;
\r
975 for (PipeControlPoint pcp : icp.getSubPoint())
\r
976 if (pcp.isInstanceOf(ProcessResource.plant3Dresource.UndirectedControlPoint)) {
\r
977 branchUpdate = true;
\r
982 if (DUMMY || !branchUpdate) {
\r
983 newInlinePoint = MathTools.closestPointOnEdge(new Vector3d(inlinePoint), new Vector3d(nextPoint), new Vector3d(prevPoint));
\r
986 // FIXME : can only handle one branch
\r
987 PipeControlPoint p = null;
\r
988 if (becp.getNext() != null) {
\r
989 p = ControlPointTools.findNextEnd(becp);
\r
990 } else if (becp.getPrevious() != null) {
\r
991 p = ControlPointTools.findPreviousEnd(becp);
\r
994 newInlinePoint = MathTools.closestPointOnEdge(new Vector3d(inlinePoint), new Vector3d(nextPoint), new Vector3d(prevPoint));
\r
996 Point3d branchLegEnd = G3DTools.getPoint(p.getLocalPosition());
\r
997 Vector3d dir2 = new Vector3d(inlinePoint);
\r
998 dir2.sub(branchLegEnd);
\r
999 Vector3d dir1 = new Vector3d(nextPoint);
\r
1000 dir1.sub(prevPoint);
\r
1001 newInlinePoint = new Vector3d();
\r
1002 double mu[] = new double[2];
\r
1003 MathTools.intersectStraightStraight(new Vector3d(prevPoint), dir1, new Vector3d(branchLegEnd), dir2, newInlinePoint, new Vector3d(),mu);
\r
1004 if (DEBUG) System.out.println(mu[0]);
\r
1005 // FIXME : reserve space
\r
1006 if (mu[0] < 0.0) {
\r
1007 newInlinePoint = new Vector3d(prevPoint);
\r
1008 } else if (mu[0] > 1.0) {
\r
1009 newInlinePoint = new Vector3d(nextPoint);
\r
1013 if (DEBUG) System.out.println(" " + newInlinePoint);
\r
1015 ControlPointTools.setWorldPosition(icp, newInlinePoint);
\r
1016 updateControlPointOrientation(icp);
\r
1020 * Updates InlineControlPoints position when straight pipe's end(s) have
\r
1025 * @param nextPoint
\r
1026 * @param prevPoint
\r
1028 private static void updateEndComponentControlPoint( PipeControlPoint ecp, Point3d start, Point3d end) {
\r
1029 if (DEBUG) System.out.println("PipingRules.updateEndComponentControlPoint() " + ecp.getResource());
\r
1030 // PipeControlPoint next = ecp.getNext();
\r
1031 // PipeControlPoint prev = ecp.getPrevious();
\r
1032 // if (next != null) {
\r
1033 // end = G3DTools.getPoint(next.getLocalPosition());
\r
1034 // start = G3DTools.getPoint(ecp.getLocalPosition());
\r
1035 // } else if (prev != null) {
\r
1036 // end = G3DTools.getPoint(ecp.getLocalPosition());
\r
1037 // start = G3DTools.getPoint(prev.getLocalPosition());
\r
1039 // // TODO : warning?
\r
1042 //Vector3d dir = new Vector3d (end);
\r
1044 //dir.normalize();
\r
1045 //G3DTools.setTuple(ecp.getDirection(), dir);
\r
1047 updateControlPointOrientation(ecp);
\r
1049 for (PipeControlPoint pcp : ecp.getSubPoint()) {
\r
1050 // TODO update position
\r
1051 updatePathLegEndControlPoint(pcp);
\r
1055 private static void updateControlPointOrientation(PipeControlPoint pcp) {
\r
1056 // FIXME : hack to bypass variable length components orientation
\r
1057 if (pcp.getAtMostOneRelatedObject(ProcessResource.g3dResource.HasWorldOrientation) == null)
\r
1059 Double angleO = pcp.getAtMostOneRelatedScalarDouble(ProcessResource.plant3Dresource.HasRotationAngle);
\r
1060 double angle = 0.0;
\r
1061 if (angleO != null)
\r
1064 AxisAngle4d aa = ControlPointTools.getControlPointWorldRotation(pcp, angle);
\r
1065 ControlPointTools.setWorldOrientation(pcp,aa);
\r
1070 * Updates all branches when branch's position has been changed
\r
1073 private static void updateBranchControlPointBranches(PipeControlPoint bcp) {
\r
1074 if (DEBUG) System.out.println("PipingRules.updateBranchControlPointBranches() " + bcp.getResource());
\r
1075 Collection<PipeControlPoint> branches = bcp.getSubPoint();
\r
1076 if (branches.size() == 0) {
\r
1077 if (DEBUG) System.out.println("No Branches found");
\r
1080 for (PipeControlPoint pcp : branches) {
\r
1081 updatePathLegEndControlPoint(pcp);
\r
1086 * Recalculates turn control point's internal data (turn angle and offset)
\r
1091 private static double updateTurnControlPointTurn( PipeControlPoint tcp, PipeControlPoint prev, PipeControlPoint next) {
\r
1092 if (DEBUG) System.out.println("PipingTools.updateTurnControlPointTurn()" + tcp.getResource());
\r
1093 if (next == null || prev == null)
\r
1094 return Math.PI; // FIXME : argh
\r
1095 Point3d middlePoint = G3DTools.getPoint(tcp.getWorldPosition());
\r
1096 Point3d nextPoint = G3DTools.getPoint(next.getWorldPosition());
\r
1097 Point3d prevPoint = G3DTools.getPoint(prev.getWorldPosition());
\r
1098 return updateTurnControlPointTurn(tcp, middlePoint, prevPoint, nextPoint);
\r
1102 * Recalculates turn control point's internal data (turn angle and offset)
\r
1104 * @param middlePoint
\r
1105 * @param nextPoint
\r
1106 * @param prevPoint
\r
1108 private static double updateTurnControlPointTurn( PipeControlPoint tcp, Point3d middlePoint, Point3d prevPoint, Point3d nextPoint) {
\r
1110 Vector3d dir1 = new Vector3d(middlePoint);
\r
1111 dir1.sub(prevPoint);
\r
1112 Vector3d dir2 = new Vector3d(nextPoint);
\r
1113 dir2.sub(middlePoint);
\r
1114 if (DEBUG) System.out.println("PipingTools.updateTurnControlPointTurn " + tcp.getResource() + " " + prevPoint + " " + middlePoint + " " + nextPoint);
\r
1115 return updateTurnControlPointTurn(tcp, dir1, dir2);
\r
1118 private static double updateTurnControlPointTurn(PipeControlPoint tcp, Vector3d dir1, Vector3d dir2) {
\r
1119 double turnAngle = dir1.angle(dir2);
\r
1120 double angle = Math.PI - turnAngle;
\r
1122 double elbowRadius = tcp.getSingleRelatedScalarDouble(ProcessResource.plant3Dresource.HasTurnRadius);
\r
1123 double R = elbowRadius / Math.tan(angle * 0.5);
\r
1124 Vector3d turnAxis = new Vector3d();
\r
1125 turnAxis.cross(dir1, dir2);
\r
1126 turnAxis.normalize();
\r
1127 tcp.setRelatedScalarDouble(ProcessResource.plant3Dresource.HasTurnAngle,turnAngle);
\r
1128 tcp.setRelatedScalarDouble(ProcessResource.plant3Dresource.HasLength, R);//setComponentOffsetValue(R);
\r
1129 G3DTools.setTuple3(tcp.getSingleRelatedObject(ProcessResource.plant3Dresource.HasTurnAxis), turnAxis);
\r
1130 if (DEBUG) System.out.println("PipingTools.updateTurnControlPointTurn " + dir1 + " " + dir2 + " " + turnAngle + " " + turnAxis);
\r