]> gerrit.simantics Code Review - simantics/3d.git/blobdiff - org.simantics.plant3d/src/org/simantics/plant3d/scenegraph/PipelineComponent.java
New interfaces for volume and centroid calculation.
[simantics/3d.git] / org.simantics.plant3d / src / org / simantics / plant3d / scenegraph / PipelineComponent.java
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");
+               }
+       }
 }