From c07ac416dfbe99201084e71c53dc95c9c41d906c Mon Sep 17 00:00:00 2001 From: Reino Ruusu Date: Tue, 15 Oct 2019 13:15:38 +0300 Subject: [PATCH] New interfaces for volume and centroid calculation. gitlab #31 Also proper handling of unsymmetric reducers. Change-Id: I370ba363d69ac6311d2afdfdf423e04871515113 --- .../Plant3d/Scenegraph/PipelineComponent.scl | 44 ++++++- .../plant3d/scenegraph/PipelineComponent.java | 114 ++++++++++++++++++ .../controlpoint/PipeControlPoint.java | 31 ++++- 3 files changed, 178 insertions(+), 11 deletions(-) diff --git a/org.simantics.plant3d/scl/Plant3d/Scenegraph/PipelineComponent.scl b/org.simantics.plant3d/scl/Plant3d/Scenegraph/PipelineComponent.scl index 1883620a..820e787a 100644 --- a/org.simantics.plant3d/scl/Plant3d/Scenegraph/PipelineComponent.scl +++ b/org.simantics.plant3d/scl/Plant3d/Scenegraph/PipelineComponent.scl @@ -1,6 +1,7 @@ import "G3D/Math/Tuple3d" import "G3D/Math/Quat4d" import "G3D/Math/Vector3d" +import "G3D/Math/Point3d" include "G3D/Scenegraph/Node" include "G3D/Scenegraph/G3DNode" @@ -43,7 +44,8 @@ importJava "org.simantics.plant3d.scenegraph.PipelineComponent" where @JavaName getType getType' :: PipelineComponent -> String - //getControlPoint :: PipelineComponent -> PipeControlPoint + @JavaName getControlPoint + getControlPoint' :: PipelineComponent -> PipeControlPoint @JavaName remove remove' :: PipelineComponent -> () @@ -51,7 +53,15 @@ importJava "org.simantics.plant3d.scenegraph.PipelineComponent" where @JavaName getFlowLength getFlowLength' :: PipelineComponent -> Maybe Double @JavaName getEnds - getEnds' :: PipelineComponent -> Tuple3d -> Tuple3d -> () + getEnds' :: PipelineComponent -> MTuple3d -> MTuple3d -> () + @JavaName getEndDirections + getEndDirections' :: PipelineComponent -> MTuple3d -> MTuple3d -> () + + @JavaName getVolume + getVolume' :: PipelineComponent -> Double + + @JavaName getCentroid + getCentroid' :: PipelineComponent -> MTuple3d -> () class PipelineComponentClass a where asPipelineComponent :: a -> PipelineComponent @@ -88,13 +98,37 @@ class PipelineComponentClass a where getType :: a -> String getType c = getType' (asPipelineComponent c) + getControlPoint :: a -> PipeControlPoint + getControlPoint c = getControlPoint (asPipelineComponent c) + remove :: a -> () remove c = remove' (asPipelineComponent c) - getFlowLength :: a -> Maybe Double + getFlowLength :: a -> Maybe Double getFlowLength c = getFlowLength' (asPipelineComponent c) - getEnds :: a -> Tuple3d -> Tuple3d -> () - getEnds c = getEnds' (asPipelineComponent c) + + getEnds :: a -> (Vector3d, Vector3d) + getEnds c = runProc let + p1 = defaultMVector3d + p2 = defaultMVector3d + getEnds' (asPipelineComponent c) (asMTuple p1) (asMTuple p2) + in (freeze p1, freeze p2) + + getEndDirections :: a -> (Vector3d, Vector3d) + getEndDirections c = runProc let + p1 = defaultMVector3d + p2 = defaultMVector3d + getEndDirections' (asPipelineComponent c) (asMTuple p1) (asMTuple p2) + in (freeze p1, freeze p2) + + getVolume :: a -> Double + getVolume c = getVolume' (asPipelineComponent c) + + getCentroid :: a -> Vector3d + getCentroid c = runProc let + p = defaultMVector3d + getCentroid' (asPipelineComponent c) (asMTuple p) + in freeze p instance NodeClass PipelineComponent instance G3DNodeClass PipelineComponent diff --git a/org.simantics.plant3d/src/org/simantics/plant3d/scenegraph/PipelineComponent.java b/org.simantics.plant3d/src/org/simantics/plant3d/scenegraph/PipelineComponent.java index 6ddd7a09..d66869ea 100644 --- a/org.simantics.plant3d/src/org/simantics/plant3d/scenegraph/PipelineComponent.java +++ b/org.simantics.plant3d/src/org/simantics/plant3d/scenegraph/PipelineComponent.java @@ -14,7 +14,9 @@ import org.simantics.objmap.graph.annotations.RelatedGetObj; 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; /** @@ -467,4 +469,116 @@ public abstract class PipelineComponent extends GeometryNode { 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"); + } + } } diff --git a/org.simantics.plant3d/src/org/simantics/plant3d/scenegraph/controlpoint/PipeControlPoint.java b/org.simantics.plant3d/src/org/simantics/plant3d/scenegraph/controlpoint/PipeControlPoint.java index cb4b57eb..6e6a595b 100644 --- a/org.simantics.plant3d/src/org/simantics/plant3d/scenegraph/controlpoint/PipeControlPoint.java +++ b/org.simantics.plant3d/src/org/simantics/plant3d/scenegraph/controlpoint/PipeControlPoint.java @@ -167,6 +167,10 @@ public class PipeControlPoint extends G3DNode implements IP3DNode { return children.size() == 1 && children.get(0).isDualSub(); } + public boolean isAxial() { + return isInline() && !isDualInline(); + } + public boolean isSizeChange() { return isSizeChange; // if (children.size() == 0) @@ -749,21 +753,25 @@ public class PipeControlPoint extends G3DNode implements IP3DNode { 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); @@ -773,11 +781,22 @@ public class PipeControlPoint extends G3DNode implements IP3DNode { 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()); -- 2.45.2