+ 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 = ((TurnComponent)this).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 = ((TurnComponent)this).getTurnRadius();
+ double a = pcp.getTurnAngle();
+ return r * a * Math.PI * pipeRadius * pipeRadius;
+ }
+ default:
+ throw new IllegalStateException("No centroid defined");
+ }
+ }