package org.simantics.plant3d.geometry;
+import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
+import java.util.List;
import java.util.Map;
+import javax.vecmath.Point3d;
+import javax.vecmath.Tuple3d;
+import javax.vecmath.Vector3d;
+
import org.jcae.opencascade.jni.TopoDS_Shape;
import org.simantics.db.Resource;
import org.simantics.g3d.math.MathTools;
+import org.simantics.g3d.shape.Mesh;
+import org.simantics.g3d.shape.Tube;
import org.simantics.opencascade.OccTriangulator;
-public class ReducerGeometryProvider extends BuiltinGeometryProvider {
+//public class ReducerGeometryProvider extends BuiltinGeometryProvider {
+public class ReducerGeometryProvider extends BuiltinMeshProvider {
public ReducerGeometryProvider(Resource resource) {
super(resource);
private double radius = 0.01;
private double radius2 = 0.02;
+ private double offset = 0.0;
- @Override
+// @Override
public Collection<TopoDS_Shape> getModel() throws Exception {
// GP_Circ circ = new GP_Circ(new double[]{-length*0.5, 0.0, 0.0,1.0,0.0,0.0}, radius);
// GP_Circ circ2 = new GP_Circ(new double[]{length*0.5, 0.0, 0.0,1.0,0.0,0.0}, radius2);
return Collections.singletonList(shape);
}
+ @Override
+ public Mesh getMesh() {
+ double length = Math.max(0.1, Math.abs(radius-radius2)*4.0);
+ if (length < .0001)
+ return null;
+ Tube tube = new Tube();
+ tube.setResolution(16);
+ List<Tuple3d> vertices = new ArrayList<Tuple3d>();
+ List<Double> radius = new ArrayList<Double>();
+ List<Vector3d> tangents = new ArrayList<Vector3d>();
+ vertices.add(new Point3d(-length*0.5, 0.0, 0.0));
+ vertices.add(new Point3d( length*0.5, offset, 0.0));
+ radius.add(this.radius);
+ radius.add(this.radius2);
+ tangents.add(new Vector3d(1.0,0.0,0.0));
+ tangents.add(new Vector3d(1.0,0.0,0.0));
+ tube.setVertices(vertices);
+ tube.setRadiis(radius);
+ tube.setTangents(tangents);
+ tube.setCap(false);
+ return tube.create();
+ }
+
@Override
public void setProperties(Map<String, Object> props) {
radius2 = (Double)props.get("radius2");
}
+ if (props.containsKey("offset")) {
+ offset = (Double)props.get("offset");
+ }
+
}
component.setNext(next != null ? next.component : null);
else
component.setBranch0(next != null ? next.component : null);
+ updateSubPoint();
}
+
}
public void setPrevious(PipeControlPoint previous) {
// if (previous != null && getPipeRun() == null)
// throw new RuntimeException("Cannot connect control point befor piperun has been set");
this.previous = previous;
- if (component != null)
+ if (component != null) {
if (parent == null || sub)
component.setPrevious(previous != null ? previous.component : null);
else
component.setBranch0(previous != null ? previous.component : null);
+ updateSubPoint();
+ }
+
}
public PipeControlPoint parent;
if (rotationAngle == null)
rotationAngle = 0.0;
Quat4d q = getControlPointOrientationQuat(dir, rotationAngle);
- Vector3d v = new Vector3d(0.0,0.0,offset);
+ Vector3d v = new Vector3d(0.0,offset,0.0);
+ Vector3d offset = new Vector3d();
+ MathTools.rotate(q, v, offset);
+ return offset;
+ }
+
+ public Vector3d getSizeChangeOffsetVector() {
+ if (rotationAngle == null)
+ rotationAngle = 0.0;
+ Quat4d q = getControlPointOrientationQuat(rotationAngle);
+ Vector3d v = new Vector3d(0.0,offset,0.0);
Vector3d offset = new Vector3d();
MathTools.rotate(q, v, offset);
return offset;
} else {
if (isInline()) {
+ PipeControlPoint pcp = this;
+ if (pcp.isDualSub()) {
+ pcp = pcp.getParentPoint();
+ }
Vector3d v = new Vector3d();
- v.sub(getWorldPosition(),previous.getWorldPosition());
+ v.sub(pcp.getWorldPosition(),previous.getWorldPosition());
return v;
} else if (isDirected()) {
return getDirectedControlPointDirection();
return v;
} else {
if (isInline()) {
+ PipeControlPoint pcp = this;
+ if (pcp.isDualInline()) {
+ pcp = pcp.getSubPoint().get(0);
+ }
Vector3d v = new Vector3d();
- v.sub(getWorldPosition(),next.getWorldPosition());
+ v.sub(pcp.getWorldPosition(),next.getWorldPosition());
return v;
} else if (isDirected()) {
Vector3d v = getDirectedControlPointDirection();
super.setOrientation(orientation);
if (getParentPoint() == null && component != null)
component._setWorldOrientation(getWorldOrientation());
- for (PipeControlPoint sub : getSubPoint()) {
- sub.setWorldPosition(getWorldPosition());
- sub.setWorldOrientation(getWorldOrientation());
- }
+ updateSubPoint();
}
@Override
super.setPosition(position);
if (getParentPoint() == null && component != null)
component._setWorldPosition(getWorldPosition());
- for (PipeControlPoint sub : getSubPoint()) {
- sub.setWorldPosition(getWorldPosition());
- sub.setWorldOrientation(getWorldOrientation());
+ if (isDualSub())
+ System.out.println();
+ updateSubPoint();
+ }
+
+ private void updateSubPoint() {
+ if (isOffset()) {
+ if (next == null && previous == null) {
+ for (PipeControlPoint sub : getSubPoint()) {
+ sub.setWorldPosition(getWorldPosition());
+ sub.setWorldOrientation(getWorldOrientation());
+ }
+ return;
+ }
+ for (PipeControlPoint sub : getSubPoint()) {
+ Vector3d wp = getWorldPosition();
+ wp.add(getSizeChangeOffsetVector());
+ sub.setWorldPosition(wp);
+ sub.setWorldOrientation(getWorldOrientation());
+ }
+ } else {
+ for (PipeControlPoint sub : getSubPoint()) {
+ sub.setWorldPosition(getWorldPosition());
+ sub.setWorldOrientation(getWorldOrientation());
+ }
}
}
public void _setWorldPosition(Vector3d position) {
Vector3d localPos = getLocalPosition(position);
super.setPosition(localPos);
- for (PipeControlPoint sub : getSubPoint()) {
- sub.setWorldPosition(getWorldPosition());
- sub.setWorldOrientation(getWorldOrientation());
- }
+ updateSubPoint();
}
public void _setWorldOrientation(Quat4d orientation) {
Quat4d localOr = getLocalOrientation(orientation);
super.setOrientation(localOr);
- for (PipeControlPoint sub : getSubPoint()) {
- sub.setWorldPosition(getWorldPosition());
- sub.setWorldOrientation(getWorldOrientation());
- }
+ updateSubPoint();
}
@Override
private static boolean calculateOffset(Vector3d startPoint, Vector3d endPoint, ArrayList<PipeControlPoint> list, Vector3d dir, Vector3d offset) {
boolean hasOffsets = false;
- dir.set(startPoint);
- dir.sub(endPoint);
- if (dir.lengthSquared() > MathTools.NEAR_ZERO)
- dir.normalize();
- offset.set(0.0, 0.0, 0.0);
+ List<PipeControlPoint> offsets = new ArrayList<PipeControlPoint>(list.size());
for (PipeControlPoint icp : list) {
if (icp.isOffset()) {
- hasOffsets = true;
- offset.add(icp.getSizeChangeOffsetVector(dir));
+ offsets.add(icp);
} else if (icp.isDualSub())
ErrorLogger.defaultLogError("Updating pipe run, found offset controlpoint " + icp, new Exception("ASSERT!"));
}
+ if (offsets.size() == 0) {
+ dir.set(startPoint);
+ dir.sub(endPoint);
+ double l = dir.lengthSquared();
+ if (l > MathTools.NEAR_ZERO)
+ dir.scale(1.0/Math.sqrt(l));
+ offset.set(0.0, 0.0, 0.0);
+ return false;
+ } else {
+ Vector3d sp = new Vector3d(startPoint);
+ Point3d ep = new Point3d(endPoint);
+ dir.set(sp);
+ dir.sub(ep);
+ double l = dir.lengthSquared();
+ if (l > MathTools.NEAR_ZERO)
+ dir.scale(1.0/Math.sqrt(l));
+ int iter = 100;
+ while (iter >= 0) {
+ iter--;
+ offset.set(0.0, 0.0, 0.0);
+
+ for (PipeControlPoint icp : offsets) {
+ Vector3d v = icp.getSizeChangeOffsetVector(dir);
+ offset.add(v);
+ }
+ Point3d nep = new Point3d(endPoint);
+ nep.sub(offset);
+ if (nep.distance(ep) < 0.0000000001) {
+ break;
+ }
+ ep = nep;
+ dir.set(sp);
+ dir.sub(ep);
+ l = dir.lengthSquared();
+ if (l > MathTools.NEAR_ZERO)
+ dir.scale(1.0/Math.sqrt(l));
+ }
+ hasOffsets = true;
+ }
+
+// for (PipeControlPoint icp : list) {
+// if (icp.isOffset()) {
+// icp.setOffset(((InlineComponent)icp.getPipelineComponent()).getOffset());
+// hasOffsets = true;
+// Vector3d v = icp.getSizeChangeOffsetVector(dir);
+// offset.add(v);
+// } else if (icp.isDualSub())
+// ErrorLogger.defaultLogError("Updating pipe run, found offset controlpoint " + icp, new Exception("ASSERT!"));
+// }
+ if (DEBUG && hasOffsets)
+ System.out.println("calcOffset s:"+ startPoint + " e:" + endPoint + " d:" + dir + " o:"+offset) ;
return hasOffsets;
}
MathTools.mad(end, u.dir, -0.1);
for (PipeControlPoint icp : u.list) {
updateInlineControlPoint(icp, start, end, u.dir);
+
+ if (icp.isOffset()) {
+ // TODO : offset vector is already calculated and should be
+ // cached
+ Vector3d off = icp.getSizeChangeOffsetVector(u.dir);
+ updateOffsetPoint(icp, off);
+ }
}
return;
}
for (int i = 1; i < pathLegPoints.size(); i++) {
PipeControlPoint icp = pathLegPoints.get(i);
- PipeControlPoint prev;
- Vector3d prevPos;
- prev = pathLegPoints.get(i - 1);
- prevPos = prev.getWorldPosition();
- Vector3d currentPos = icp.getWorldPosition();
+ PipeControlPoint prev = pathLegPoints.get(i - 1);
+
if (icp.isVariableLength()) {
if (i != pathLegPoints.size() - 1) {
- PipeControlPoint next;
- Vector3d nextPos;
- next = pathLegPoints.get(i + 1);
- nextPos = next.getWorldPosition();
- Vector3d dir = new Vector3d(nextPos);
- dir.sub(prevPos);
- double l = dir.lengthSquared(); // distance between
- // control points
- // (square)
- double l2prev = prev.getInlineLength(); // distance
- // taken
- // by
- // components
- double l2next = next.getInlineLength();
- double l2 = l2prev + l2next;
- double l2s = MathTools.square(l2);
- if (l2s < l) { // check if there is enough space for
- // variable length component.
- // components fit
- dir.normalize();
- double length = Math.sqrt(l) - l2; // true length of
- // the variable
- // length
- // component
- dir.scale(length * 0.5 + l2prev); // calculate
- // center
- // position of
- // the component
- dir.add(prevPos);
- icp.setWorldPosition(dir);
- icp.setLength(length);
- } else {
- // components leave no space to the component and it
- // must be removed
- if (icp.isDeletable())
- icp._remove();
- }
+ PipeControlPoint next = pathLegPoints.get(i + 1);
+ updateVariableLength(icp, prev, next);
} else {
// this is variable length component at the end of the
// the problem is that we want to keep unconnected end
// of the component in the same
// place, but center of the component must be moved.
- double currentLength = icp.getLength();
-
- Vector3d dir = new Vector3d();
- dir.sub(currentPos, prevPos);
-
- if (currentLength < MathTools.NEAR_ZERO) {
- currentLength = (dir.length() - prev.getInlineLength()) * 2.0;
- }
-
- if (dir.lengthSquared() > MathTools.NEAR_ZERO)
- dir.normalize();
- Point3d endPos = new Point3d(dir);
- endPos.scale(currentLength * 0.5);
- endPos.add(currentPos); // this is the free end of the
- // component
-
- double offset = prev.getInlineLength();
- Point3d beginPos = new Point3d(dir);
- beginPos.scale(offset);
- beginPos.add(prevPos); // this is the connected end of
- // the component
-
- double l = beginPos.distance(endPos);
-
- if (Double.isNaN(l))
- System.out.println();
-
- dir.scale(l * 0.5);
- beginPos.add(dir); // center position
-
- if (DEBUG)
- System.out.println("PipingRules.updateInlineControlPoints() setting variable length to " + l);
- icp.setLength(l);
-
- icp.setWorldPosition(new Vector3d(beginPos));
+ updateVariableLengthEnd(icp, prev);
}
// space between them.
// I there is, we'll have to create new variable length
// component between them.
+ Vector3d currentPos = icp.getWorldPosition();
+ Vector3d prevPos = prev.getWorldPosition();
Vector3d dir = new Vector3d(currentPos);
dir.sub(prevPos);
double l = dir.lengthSquared();
}
}
} else {
- u.endPoint.sub(u.offset);
- // FIXME : straights
+ Vector3d sp = new Vector3d(u.startPoint);
+ Vector3d ep = new Vector3d(u.endPoint);
+ ep.sub(u.offset);
+
+ ArrayList<PipeControlPoint> pathLegPoints = new ArrayList<PipeControlPoint>();
+ pathLegPoints.add(u.start);
+
for (PipeControlPoint icp : u.list) {
- updateInlineControlPoint(icp, u.startPoint, u.endPoint, u.dir);
+ updateInlineControlPoint(icp, sp, ep, u.dir);
updateBranchControlPointBranches(icp);
-
+ pathLegPoints.add(icp);
if (icp.isOffset()) {
// TODO : offset vector is already calculated and should be
// cached
- u.offset = icp.getSizeChangeOffsetVector(u.dir);
- updateOffsetPoint(icp, u.offset);
- u.startPoint.add(u.offset);
- u.endPoint.add(u.offset);
+ Vector3d offset = icp.getSizeChangeOffsetVector(u.dir);
+ updateOffsetPoint(icp, offset);
+ sp.add(offset);
+ ep.add(offset);
+ }
+ }
+ pathLegPoints.add(u.end);
+
+ sp = new Vector3d(u.startPoint);
+ ep = new Vector3d(u.endPoint);
+ ep.sub(u.offset);
+
+ for (int i = 1; i < pathLegPoints.size(); i++) {
+ PipeControlPoint icp = pathLegPoints.get(i);
+
+ PipeControlPoint prev = pathLegPoints.get(i - 1);
+ if (prev.isDualInline())
+ prev = prev.getSubPoint().get(0);
+
+
+ if (icp.isVariableLength()) {
+ if (i != pathLegPoints.size() - 1) {
+ PipeControlPoint next;
+ next = pathLegPoints.get(i + 1);
+ updateVariableLength(icp, prev, next);
+
+ } else {
+ // this is variable length component at the end of the
+ // piperun.
+ // the problem is that we want to keep unconnected end
+ // of the component in the same
+ // place, but center of the component must be moved.
+ updateVariableLengthEnd(icp, prev);
+ }
+ } else if (icp.isOffset()) {
+ // TODO : offset vector is already calculated and should be
+ // cached
+ Vector3d offset = icp.getSizeChangeOffsetVector(u.dir);
+ sp.add(offset);
+ ep.add(offset);
}
}
}
}
+
+ private static void updateVariableLength(PipeControlPoint icp, PipeControlPoint prev, PipeControlPoint next) {
+ Vector3d prevPos = prev.getWorldPosition();
+ Vector3d nextPos = next.getWorldPosition();
+
+ Vector3d dir = new Vector3d(nextPos);
+ dir.sub(prevPos);
+ double l = dir.lengthSquared(); // distance between
+ // control points
+ // (square)
+ double l2prev = prev.getInlineLength(); // distance
+ // taken
+ // by
+ // components
+ double l2next = next.getInlineLength();
+ double l2 = l2prev + l2next;
+ double l2s = MathTools.square(l2);
+ if (l2s < l) { // check if there is enough space for
+ // variable length component.
+ // components fit
+ dir.normalize();
+ double length = Math.sqrt(l) - l2; // true length of
+ // the variable
+ // length
+ // component
+ dir.scale(length * 0.5 + l2prev); // calculate
+ // center
+ // position of
+ // the component
+ dir.add(prevPos);
+ icp.setWorldPosition(dir);
+ icp.setLength(length);
+ } else {
+ // components leave no space to the component and it
+ // must be removed
+ if (icp.isDeletable())
+ icp._remove();
+ }
+ }
+
+ private static void updateVariableLengthEnd(PipeControlPoint icp, PipeControlPoint prev) {
+ double currentLength = icp.getLength();
+ Vector3d currentPos = icp.getWorldPosition();
+ Vector3d prevPos = prev.getWorldPosition();
+
+ Vector3d dir = new Vector3d();
+ dir.sub(currentPos, prevPos);
+
+ if (currentLength < MathTools.NEAR_ZERO) {
+ currentLength = (dir.length() - prev.getInlineLength()) * 2.0;
+ }
+
+ if (dir.lengthSquared() > MathTools.NEAR_ZERO)
+ dir.normalize();
+ Point3d endPos = new Point3d(dir);
+ endPos.scale(currentLength * 0.5);
+ endPos.add(currentPos); // this is the free end of the
+ // component
+
+ double offset = prev.getInlineLength();
+ Point3d beginPos = new Point3d(dir);
+ beginPos.scale(offset);
+ beginPos.add(prevPos); // this is the connected end of
+ // the component
+
+ double l = beginPos.distance(endPos);
+
+ if (Double.isNaN(l))
+ System.out.println();
+
+ dir.scale(l * 0.5);
+ beginPos.add(dir); // center position
+
+ if (DEBUG)
+ System.out.println("PipingRules.updateInlineControlPoints() setting variable length to " + l);
+ icp.setLength(l);
+
+ icp.setWorldPosition(new Vector3d(beginPos));
+ }
private static void ppNoOffset(UpdateStruct2 u) throws Exception {
if (DEBUG)
private static void processPathLeg(UpdateStruct2 u, boolean updateEnds, boolean updateInline) throws Exception {
if (DEBUG)
- System.out.println("PipingRules.processPathLeg " + u.start + " " + u.end);
+ System.out.println("PipingRules.processPathLeg " + (updateEnds ? "ends " : "") + (updateInline ? "inline " : "") + u.start + " " + u.end);
if (u.toRemove.size() > 0) {
for (ExpandIterInfo info : u.toRemove) {