New panels.
[sw/motorsim] / src / com / billkuker / rocketry / motorsim / grain / CoredCylindricalGrain.java
1 package com.billkuker.rocketry.motorsim.grain;\r
2 \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
10 \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
15 \r
16 import org.jscience.physics.amount.Amount;\r
17 \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
21 \r
22 public class CoredCylindricalGrain implements Grain, Validating, Grain.Graphical {\r
23 \r
24         private Amount<Length> length, oD, iD;\r
25         private boolean oInh = true, iInh = false, eInh = false;\r
26 \r
27         public CoredCylindricalGrain() {\r
28 \r
29         }\r
30 \r
31         @Override\r
32         public Amount<Area> surfaceArea(Amount<Length> regression) {\r
33                 Amount<Length> zero = Amount.valueOf(0, SI.MILLIMETER);\r
34                 \r
35                 //Calculated regressed length\r
36                 Amount<Length> cLength = length;\r
37                 if ( !eInh ){\r
38                         cLength = cLength.minus(regression.times(2));\r
39                 }\r
40                 \r
41                 //Calculate regressed iD\r
42                 Amount<Length> cID = iD;\r
43                 if ( !iInh ){\r
44                         cID = iD.plus(regression.times(2));\r
45                 }\r
46                 \r
47                 //Calculate regressed oD\r
48                 Amount<Length> cOD = oD;\r
49                 if ( !oInh ){\r
50                         cOD = oD.minus(regression.times(2));\r
51                 }\r
52                 \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
59                 \r
60                 Amount<Area> inner = cID.times(Math.PI).times(cLength).to(SI.SQUARE_METRE);\r
61                 \r
62                 Amount<Area> outer = cOD.times(Math.PI).times(cLength).to(SI.SQUARE_METRE);\r
63                 \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
65                 \r
66                 Amount<Area> total = inner.times(iInh?0:1).plus(outer.times(oInh?0:1)).plus(ends.times(eInh?0:1));\r
67                 \r
68                 return total;\r
69         }\r
70 \r
71         @Override\r
72         public Amount<Volume> volume(Amount<Length> regression) {\r
73                 Amount<Length> zero = Amount.valueOf(0, SI.MILLIMETER);\r
74                 \r
75                 //Calculated regressed length\r
76                 Amount<Length> cLength = length;\r
77                 if ( !eInh ){\r
78                         cLength = cLength.minus(regression.times(2));\r
79                 }\r
80                 \r
81                 //Calculate regressed iD\r
82                 Amount<Length> cID = iD;\r
83                 if ( !iInh ){\r
84                         cID = iD.plus(regression.times(2));\r
85                 }\r
86                 \r
87                 //Calculate regressed oD\r
88                 Amount<Length> cOD = oD;\r
89                 if ( !oInh ){\r
90                         cOD = oD.minus(regression.times(2));\r
91                 }\r
92                 \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
99         \r
100                 \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
102 \r
103                 return end.times(cLength).to(SI.CUBIC_METRE);\r
104         }\r
105 \r
106         public void setLength(Amount<Length> length) {\r
107                 this.length = length;\r
108         }\r
109 \r
110         public void setOD(Amount<Length> od) {\r
111                 oD = od;\r
112         }\r
113 \r
114         public void setID(Amount<Length> id) {\r
115                 iD = id;\r
116         }\r
117         \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
127                 \r
128                 if ( iInh && oInh && eInh )\r
129                         throw new ValidationException(this, "No exposed grain surface");\r
130                 \r
131         }\r
132 \r
133         @Override\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
140                 \r
141                 Amount<Length> axial = null;\r
142                 \r
143                 if ( !eInh )\r
144                         axial = length.divide(2);\r
145                 \r
146                 if ( axial == null )\r
147                         return radial;\r
148                 if ( radial == null )\r
149                         return axial;\r
150                 if ( radial.isLessThan(axial) )\r
151                         return radial;\r
152                 return axial;\r
153         }\r
154 \r
155         public Amount<Length> getLength() {\r
156                 return length;\r
157         }\r
158 \r
159         public Amount<Length> getOD() {\r
160                 return oD;\r
161         }\r
162 \r
163         public Amount<Length> getID() {\r
164                 return iD;\r
165         }\r
166         \r
167         @Override\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
172 \r
173                 if ( !oInh )\r
174                         oDmm -= 2.0 * rmm;\r
175                 if ( !iInh )\r
176                         iDmm += 2.0 * rmm;\r
177                 \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
180                 \r
181                 java.awt.geom.Area a = new java.awt.geom.Area(oDs);\r
182                 a.subtract(new java.awt.geom.Area(iDs));\r
183                 return a;\r
184         }\r
185         \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
191 \r
192                 if ( !oInh )\r
193                         oDmm -= 2.0 * rmm;\r
194                 if ( !iInh )\r
195                         iDmm += 2.0 * rmm;\r
196                 if ( !eInh )\r
197                         lmm -= 2.0 * rmm;\r
198                 \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
202                 \r
203                 return a;\r
204         }\r
205         \r
206 \r
207 }\r