1 package com.billkuker.rocketry.motorsim.grain;
\r
3 import java.awt.BasicStroke;
\r
4 import java.awt.Color;
\r
5 import java.awt.Graphics2D;
\r
6 import java.awt.Rectangle;
\r
7 import java.awt.Shape;
\r
8 import java.awt.geom.Ellipse2D;
\r
9 import java.awt.geom.Rectangle2D;
\r
11 import javax.measure.quantity.Area;
\r
12 import javax.measure.quantity.Length;
\r
13 import javax.measure.quantity.Volume;
\r
14 import javax.measure.unit.SI;
\r
16 import org.jscience.physics.amount.Amount;
\r
18 import com.billkuker.rocketry.motorsim.Grain;
\r
19 import com.billkuker.rocketry.motorsim.validation.Validating;
\r
20 import com.billkuker.rocketry.motorsim.validation.ValidationException;
\r
22 public class CoredCylindricalGrain implements Grain, Validating, Grain.Graphical {
\r
24 private Amount<Length> length, oD, iD;
\r
25 private boolean oInh = true, iInh = false, eInh = false;
\r
27 public CoredCylindricalGrain() {
\r
32 public Amount<Area> surfaceArea(Amount<Length> regression) {
\r
33 Amount<Length> zero = Amount.valueOf(0, SI.MILLIMETER);
\r
35 //Calculated regressed length
\r
36 Amount<Length> cLength = length;
\r
38 cLength = cLength.minus(regression.times(2));
\r
41 //Calculate regressed iD
\r
42 Amount<Length> cID = iD;
\r
44 cID = iD.plus(regression.times(2));
\r
47 //Calculate regressed oD
\r
48 Amount<Length> cOD = oD;
\r
50 cOD = oD.minus(regression.times(2));
\r
53 if ( cID.isGreaterThan(cOD) )
\r
54 return Amount.valueOf(0, SI.SQUARE_METRE);
\r
55 if ( cOD.isLessThan(cID) )
\r
56 return Amount.valueOf(0, SI.SQUARE_METRE);
\r
57 if ( cLength.isLessThan(zero) )
\r
58 return Amount.valueOf(0, SI.SQUARE_METRE);
\r
60 Amount<Area> inner = cID.times(Math.PI).times(cLength).to(SI.SQUARE_METRE);
\r
62 Amount<Area> outer = cOD.times(Math.PI).times(cLength).to(SI.SQUARE_METRE);
\r
64 Amount<Area> ends = (cOD.divide(2).pow(2).times(Math.PI)).minus(cID.divide(2).pow(2).times(Math.PI)).times(2).to(SI.SQUARE_METRE);
\r
66 Amount<Area> total = inner.times(iInh?0:1).plus(outer.times(oInh?0:1)).plus(ends.times(eInh?0:1));
\r
72 public Amount<Volume> volume(Amount<Length> regression) {
\r
73 Amount<Length> zero = Amount.valueOf(0, SI.MILLIMETER);
\r
75 //Calculated regressed length
\r
76 Amount<Length> cLength = length;
\r
78 cLength = cLength.minus(regression.times(2));
\r
81 //Calculate regressed iD
\r
82 Amount<Length> cID = iD;
\r
84 cID = iD.plus(regression.times(2));
\r
87 //Calculate regressed oD
\r
88 Amount<Length> cOD = oD;
\r
90 cOD = oD.minus(regression.times(2));
\r
93 if ( cID.isGreaterThan(cOD) )
\r
94 return Amount.valueOf(0, SI.CUBIC_METRE);
\r
95 if ( cOD.isLessThan(cID) )
\r
96 return Amount.valueOf(0, SI.CUBIC_METRE);
\r
97 if ( cLength.isLessThan(zero) )
\r
98 return Amount.valueOf(0, SI.CUBIC_METRE);
\r
101 Amount<Area> end = (cOD.divide(2).pow(2).times(Math.PI)).minus(cID.divide(2).pow(2).times(Math.PI)).to(SI.SQUARE_METRE);
\r
103 return end.times(cLength).to(SI.CUBIC_METRE);
\r
106 public void setLength(Amount<Length> length) {
\r
107 this.length = length;
\r
110 public void setOD(Amount<Length> od) {
\r
114 public void setID(Amount<Length> id) {
\r
118 public void checkValidity() throws ValidationException{
\r
119 if ( iD.equals(Amount.ZERO) )
\r
120 throw new ValidationException(this, "Invalid iD");
\r
121 if ( oD.equals(Amount.ZERO) )
\r
122 throw new ValidationException(this, "Invalid oD");
\r
123 if ( length.equals(Amount.ZERO) )
\r
124 throw new ValidationException(this, "Invalid Length");
\r
125 if ( iD.isGreaterThan(oD) )
\r
126 throw new ValidationException(this, "iD > oD");
\r
128 if ( iInh && oInh && eInh )
\r
129 throw new ValidationException(this, "No exposed grain surface");
\r
134 public Amount<Length> webThickness() {
\r
135 Amount<Length> radial = null;
\r
136 if ( !iInh && !oInh )
\r
137 radial = oD.minus(iD).divide(4); //Outer and inner exposed
\r
138 else if ( !iInh || !oInh )
\r
139 radial = oD.minus(iD).divide(2); //Outer or inner exposed
\r
141 Amount<Length> axial = null;
\r
144 axial = length.divide(2);
\r
146 if ( axial == null )
\r
148 if ( radial == null )
\r
150 if ( radial.isLessThan(axial) )
\r
155 public Amount<Length> getLength() {
\r
159 public Amount<Length> getOD() {
\r
163 public Amount<Length> getID() {
\r
168 public java.awt.geom.Area getCrossSection(Amount<Length> regression){
\r
169 double rmm = regression.doubleValue(SI.MILLIMETER);
\r
170 double oDmm = oD.doubleValue(SI.MILLIMETER);
\r
171 double iDmm = iD.doubleValue(SI.MILLIMETER);
\r
178 Shape oDs = new Ellipse2D.Double(-oDmm/2.0, -oDmm/2.0, oDmm, oDmm);
\r
179 Shape iDs = new Ellipse2D.Double(-iDmm/2.0, -iDmm/2.0, iDmm, iDmm);
\r
181 java.awt.geom.Area a = new java.awt.geom.Area(oDs);
\r
182 a.subtract(new java.awt.geom.Area(iDs));
\r
186 public java.awt.geom.Area getSideView(Amount<Length> regression){
\r
187 double rmm = regression.doubleValue(SI.MILLIMETER);
\r
188 double oDmm = oD.doubleValue(SI.MILLIMETER);
\r
189 double iDmm = iD.doubleValue(SI.MILLIMETER);
\r
190 double lmm = length.doubleValue(SI.MILLIMETER);
\r
199 java.awt.geom.Area a = new java.awt.geom.Area();
\r
200 a.add( new java.awt.geom.Area(new Rectangle2D.Double(-oDmm/2,-lmm/2,oDmm, lmm)));
\r
201 a.subtract( new java.awt.geom.Area(new Rectangle2D.Double(-iDmm/2,-lmm/2,iDmm, lmm)));
\r