import "G3D/Math/Tuple3d"
import "G3D/Math/Quat4d"
import "G3D/Math/Vector3d"
+import "G3D/Math/Point3d"
include "G3D/Scenegraph/Node"
include "G3D/Scenegraph/G3DNode"
@JavaName getType
getType' :: PipelineComponent -> <Proc> String
- //getControlPoint :: PipelineComponent -> <Proc> PipeControlPoint
+ @JavaName getControlPoint
+ getControlPoint' :: PipelineComponent -> <Proc> PipeControlPoint
@JavaName remove
remove' :: PipelineComponent -> <Proc> ()
@JavaName getFlowLength
getFlowLength' :: PipelineComponent -> <Proc> Maybe Double
@JavaName getEnds
- getEnds' :: PipelineComponent -> Tuple3d -> Tuple3d -> <Proc> ()
+ getEnds' :: PipelineComponent -> MTuple3d -> MTuple3d -> <Proc> ()
+ @JavaName getEndDirections
+ getEndDirections' :: PipelineComponent -> MTuple3d -> MTuple3d -> <Proc> ()
+
+ @JavaName getVolume
+ getVolume' :: PipelineComponent -> <Proc> Double
+
+ @JavaName getCentroid
+ getCentroid' :: PipelineComponent -> MTuple3d -> <Proc> ()
class PipelineComponentClass a where
asPipelineComponent :: a -> PipelineComponent
getType :: a -> <Proc> String
getType c = getType' (asPipelineComponent c)
+ getControlPoint :: a -> <Proc> PipeControlPoint
+ getControlPoint c = getControlPoint (asPipelineComponent c)
+
remove :: a -> <Proc> ()
remove c = remove' (asPipelineComponent c)
- getFlowLength :: a -> <Proc>Maybe Double
+ getFlowLength :: a -> <Proc> Maybe Double
getFlowLength c = getFlowLength' (asPipelineComponent c)
- getEnds :: a -> Tuple3d -> Tuple3d -> <Proc> ()
- getEnds c = getEnds' (asPipelineComponent c)
+
+ getEnds :: a -> <Proc> (Vector3d, Vector3d)
+ getEnds c = runProc let
+ p1 = defaultMVector3d
+ p2 = defaultMVector3d
+ getEnds' (asPipelineComponent c) (asMTuple p1) (asMTuple p2)
+ in (freeze p1, freeze p2)
+
+ getEndDirections :: a -> <Proc> (Vector3d, Vector3d)
+ getEndDirections c = runProc let
+ p1 = defaultMVector3d
+ p2 = defaultMVector3d
+ getEndDirections' (asPipelineComponent c) (asMTuple p1) (asMTuple p2)
+ in (freeze p1, freeze p2)
+
+ getVolume :: a -> <Proc> Double
+ getVolume c = getVolume' (asPipelineComponent c)
+
+ getCentroid :: a -> <Proc> Vector3d
+ getCentroid c = runProc let
+ p = defaultMVector3d
+ getCentroid' (asPipelineComponent c) (asMTuple p)
+ in freeze p
instance NodeClass PipelineComponent
instance G3DNodeClass PipelineComponent
import org.simantics.objmap.graph.annotations.RelatedSetObj;
import org.simantics.plant3d.ontology.Plant3D;
import org.simantics.plant3d.scenegraph.controlpoint.PipeControlPoint;
+import org.simantics.plant3d.scenegraph.controlpoint.PipeControlPoint.Direction;
import org.simantics.plant3d.scenegraph.controlpoint.PipeControlPoint.PointType;
+import org.simantics.plant3d.scenegraph.controlpoint.PipeControlPoint.PositionType;
import org.simantics.plant3d.scenegraph.controlpoint.PipingRules;
/**
getControlPoint().getControlPointEnds(p1, p2);
}
+ public void getEndDirections(Tuple3d v1, Tuple3d v2) {
+ getControlPoint().getEndDirections(v1, v2);
+ }
+
+ public void getCentroid(Tuple3d p) {
+ PipeControlPoint pcp = getControlPoint();
+ if (pcp == null)
+ throw new IllegalStateException("No centroid defined");
+
+ switch (pcp.getType()) {
+ case INLINE:
+ case END:
+ // Just return the world location
+ if (!pcp.isSizeChange()) {
+ p.set(pcp.getWorldPosition());
+ return;
+ }
+
+ // Calculate center of mass for the frustum
+ double r1 = getPipeRun().getPipeDiameter();
+ double r2 = getAlternativePipeRun().getPipeDiameter();
+
+ Vector3d p1 = new Vector3d(), p2 = new Vector3d();
+ pcp.getInlineControlPointEnds(p1, p2);
+
+ // Squared sum of radii
+ double r12 = r1 + r2;
+ r12 *= r12;
+
+ // The larger of the radii form the base of a frustum
+ double rmax = Math.max(r1, r2);
+
+ // Relative distance from the base of the frustum
+ double h = (r12 + 2*rmax*rmax) / (4 * (r12 - r1*r2));
+
+ // Relative distance from p1 to p2
+ if (r1 < r2)
+ h = 1 - h;
+
+ p2.sub(p1);
+ p1.scaleAdd(h, p2);
+
+ p.set(p1);
+ return;
+ case TURN: {
+ Vector3d loc = pcp.getRealPosition(PositionType.PREVIOUS);
+
+ double r = getPipeRun().getTurnRadius();
+ double a = pcp.getTurnAngle();
+ double pipeRadius = pcp.getPipeRun().getPipeDiameter() / 2;
+
+ // Unit vector in inlet flow direction
+ Vector3d inletDir = pcp.getPathLegDirection(Direction.PREVIOUS);
+ inletDir.scale(-1.0);
+ inletDir.normalize();
+
+ // Normal to both inletDir and turn axis in world coordinates
+ Vector3d outletDir = pcp.getPathLegDirection(Direction.NEXT);
+ Vector3d normal = new Vector3d(inletDir);
+ normal.scaleAdd(-inletDir.dot(outletDir), outletDir);
+ normal.normalize();
+
+ // Location of turn axis
+ Vector3d center = new Vector3d(normal);
+ center.scaleAdd(r, loc);
+
+ // Add vector components from axis to centroid
+ double c = r + pipeRadius * pipeRadius / (4 * r);
+ double c1 = c * Math.sin(a) / a;
+ double c2 = c * (1 - Math.cos(a)) / a;
+ normal.scale(-c1);
+ inletDir.scale(c2);
+ center.add(normal);
+ center.add(inletDir);
+
+ // Return value
+ p.set(center);
+ return;
+ }
+ default:
+ throw new IllegalStateException("No centroid defined");
+ }
+ }
+
+ public double getVolume() {
+ PipeControlPoint pcp = getControlPoint();
+ if (pcp == null)
+ throw new IllegalStateException("No centroid defined");
+
+ double pipeRadius = getPipeRun().getPipeDiameter() / 2;
+
+ switch (pcp.getType()) {
+ case INLINE:
+ case END:
+ if (!pcp.isSizeChange()) {
+ // Just return the cylinder volume
+ return pcp.getLength() * Math.PI * pipeRadius * pipeRadius;
+ }
+
+ // Calculate center of mass for the frustum
+ double r1 = pipeRadius;
+ double r2 = getAlternativePipeRun().getPipeDiameter() / 2;
+ return pcp.getLength() * Math.PI * (r1*r1 + r1*r2 + r2*r2) / 4;
+ case TURN: {
+ double r = getPipeRun().getTurnRadius();
+ double a = pcp.getTurnAngle();
+ return r * a * Math.PI * pipeRadius * pipeRadius;
+ }
+ default:
+ throw new IllegalStateException("No centroid defined");
+ }
+ }
}
return children.size() == 1 && children.get(0).isDualSub();
}
+ public boolean isAxial() {
+ return isInline() && !isDualInline();
+ }
+
public boolean isSizeChange() {
return isSizeChange;
// if (children.size() == 0)
public void getInlineControlPointEnds(Tuple3d p1, Tuple3d p2) {
assert (isInline());
- Vector3d pos = getWorldPosition();
- Vector3d dir = getPathLegDirection(Direction.NEXT);
+ PipeControlPoint sub = isAxial() ? this : getSubPoint().get(0);
+ Vector3d pos = getWorldPosition(), pos2 = sub == this ? pos : sub.getWorldPosition();
+ Vector3d dir = sub.getPathLegDirection(Direction.NEXT);
+
dir.normalize();
dir.scale(length * 0.5);
p1.set(pos);
- p2.set(pos);
+ p2.set(pos2);
p1.sub(dir);
p2.add(dir);
}
public void getControlPointEnds(Tuple3d p1, Tuple3d p2) {
- Vector3d pos = getWorldPosition();
+ PipeControlPoint sub = isAxial() ? this : getSubPoint().get(0);
+ Vector3d pos = getWorldPosition(), pos2 = sub == this ? pos : sub.getWorldPosition();
+
Vector3d dir1 = getPathLegDirection(Direction.PREVIOUS);
dir1.normalize();
- Vector3d dir2 = getPathLegDirection(Direction.NEXT);
+ Vector3d dir2 = sub.getPathLegDirection(Direction.NEXT);
dir2.normalize();
if (isInline()) {
dir1.scale(length * 0.5);
dir2.scale(length);
}
p1.set(pos);
- p2.set(pos);
+ p2.set(pos2);
p1.add(dir1);
p2.add(dir2);
}
+ public void getEndDirections(Tuple3d v1, Tuple3d v2) {
+ PipeControlPoint sub = isAxial() ? this : getSubPoint().get(0);
+
+ Vector3d dir1 = getPathLegDirection(Direction.PREVIOUS);
+ dir1.normalize();
+ Vector3d dir2 = sub.getPathLegDirection(Direction.NEXT);
+ dir2.normalize();
+ v1.set(dir1);
+ v2.set(dir2);
+ }
+
public void getInlineControlPointEnds(Tuple3d p1, Tuple3d p2, Vector3d dir) {
assert (isInline());