]> gerrit.simantics Code Review - simantics/3d.git/commitdiff
New interfaces for volume and centroid calculation. 31/3331/1
authorReino Ruusu <reino.ruusu@semantum.fi>
Tue, 15 Oct 2019 10:15:38 +0000 (13:15 +0300)
committerReino Ruusu <reino.ruusu@semantum.fi>
Tue, 15 Oct 2019 10:15:38 +0000 (13:15 +0300)
gitlab #31

Also proper handling of unsymmetric reducers.

Change-Id: I370ba363d69ac6311d2afdfdf423e04871515113

org.simantics.plant3d/scl/Plant3d/Scenegraph/PipelineComponent.scl
org.simantics.plant3d/src/org/simantics/plant3d/scenegraph/PipelineComponent.java
org.simantics.plant3d/src/org/simantics/plant3d/scenegraph/controlpoint/PipeControlPoint.java

index 1883620a4cce92be04477c75b15e38bcb76f9a54..820e787aeebc8674a241b48f09ee564c9cac5886 100644 (file)
@@ -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 -> <Proc> String
   
-  //getControlPoint :: PipelineComponent -> <Proc> PipeControlPoint
+  @JavaName getControlPoint 
+  getControlPoint' :: PipelineComponent -> <Proc> PipeControlPoint
   
   @JavaName remove
   remove' :: PipelineComponent -> <Proc> ()
@@ -51,7 +53,15 @@ importJava "org.simantics.plant3d.scenegraph.PipelineComponent" where
   @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
@@ -88,13 +98,37 @@ class PipelineComponentClass a where
   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
index 6ddd7a09fc9ba3d68c83fd8bb6c6534d84485619..d66869ea2069219be8c6dae03e2ec378d235f40d 100644 (file)
@@ -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");
+               }
+       }
 }
index cb4b57eb898eefcb69d2797ccb3a182570d6c2a9..6e6a595bc3cefddd0fdab8864efec31666ea3618 100644 (file)
@@ -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());