1 package com.billkuker.rocketry.motorsim.grain.util;
\r
3 import java.awt.Rectangle;
\r
4 import java.awt.Shape;
\r
5 import java.awt.geom.AffineTransform;
\r
6 import java.awt.geom.Ellipse2D;
\r
7 import java.awt.geom.Rectangle2D;
\r
9 import javax.measure.quantity.Area;
\r
10 import javax.measure.quantity.Length;
\r
11 import javax.measure.quantity.Volume;
\r
12 import javax.measure.unit.SI;
\r
14 import org.jscience.physics.amount.Amount;
\r
16 import com.billkuker.rocketry.motorsim.grain.ExtrudedGrain;
\r
17 import com.billkuker.rocketry.motorsim.visual.Editor;
\r
18 import com.billkuker.rocketry.motorsim.visual.GrainPanel;
\r
20 public abstract class ExtrudedShapeGrain extends ExtrudedGrain {
\r
22 public static ExtrudedShapeGrain DEFAULT_GRAIN = new ExtrudedShapeGrain(){
\r
25 Shape outside = new Ellipse2D.Double(0, 0, 30, 30);
\r
26 xsection.add(outside);
\r
27 xsection.inhibit(outside);
\r
28 xsection.subtract(new Ellipse2D.Double(10,10, 10, 10));
\r
29 setLength(Amount.valueOf(70, SI.MILLIMETER));
\r
30 setForeEndInhibited(false);
\r
31 setAftEndInhibited(false);
\r
32 } catch ( Exception e ){
\r
38 protected BurningShape xsection = new BurningShape();
\r
40 protected Amount<Length> webThickness;
\r
42 public Amount<Area> surfaceArea(Amount<Length> regression) {
\r
43 Amount<Area> zero = Amount.valueOf(0, Area.UNIT);
\r
45 if (regression.isGreaterThan(webThickness()))
\r
48 Amount<Length> rLen = regressedLength(regression);
\r
50 if (rLen.isLessThan(Amount.valueOf(0, SI.MILLIMETER)))
\r
53 java.awt.geom.Area burn = getCrossSection(regression);
\r
58 burn.subtract(getCrossSection(regression.plus(Amount.valueOf(.001,
\r
61 Amount<Area> xSection = ShapeUtil.area(xsection.getShape(regression));
\r
63 Amount<Area> sides = ShapeUtil.perimeter(burn).divide(2).times(rLen).to(Area.UNIT);
\r
64 Amount<Area> ends = xSection.times(numberOfBurningEnds(regression));
\r
66 return sides.plus(ends);
\r
70 public Amount<Volume> volume(Amount<Length> regression) {
\r
71 Amount<Volume> zero = Amount.valueOf(0, Volume.UNIT);
\r
73 Amount<Length> rLen = regressedLength(regression);
\r
75 if (rLen.isLessThan(Amount.valueOf(0, SI.MILLIMETER)))
\r
78 Amount<Area> xSection = ShapeUtil.area(xsection.getShape(regression));
\r
80 return xSection.times(rLen).to(Volume.UNIT);
\r
85 public Amount<Length> webThickness() {
\r
86 if ( webThickness != null )
\r
87 return webThickness;
\r
88 java.awt.geom.Area a = getCrossSection(Amount.valueOf(0, SI.MILLIMETER));
\r
89 Rectangle r = a.getBounds();
\r
90 double max = r.getWidth() < r.getHeight() ? r.getHeight() : r
\r
91 .getWidth(); // The max size
\r
95 guess = min + (max - min) / 2; // Guess halfway through
\r
97 a = getCrossSection(Amount.valueOf(guess, SI.MILLIMETER));
\r
105 if ((max - min) < .01)
\r
108 webThickness = Amount.valueOf(guess, SI.MILLIMETER);
\r
110 //TODO Need to check # of burning ends!
\r
111 if (webThickness.isGreaterThan(getLength().divide(2)))
\r
112 webThickness = getLength().divide(2);
\r
114 return webThickness;
\r
117 public java.awt.geom.Area getCrossSection(Amount<Length> regression) {
\r
118 return xsection.getShape(regression);
\r
121 public java.awt.geom.Area getSideView(Amount<Length> regression) {
\r
122 java.awt.geom.Area res = new java.awt.geom.Area();
\r
124 Amount<Length> rLen = regressedLength(regression);
\r
126 double rLenmm = rLen.doubleValue(SI.MILLIMETER);
\r
128 for( java.awt.geom.Area a : ShapeUtil.separate(getCrossSection(regression))){
\r
129 Rectangle2D bounds = a.getBounds2D();
\r
130 Rectangle2D side = new Rectangle2D.Double(bounds.getMinX(), -rLenmm/2.0, bounds.getWidth(), rLenmm);
\r
131 res.add(new java.awt.geom.Area(side));
\r
134 //Shift up or down based on burning ends
\r
135 if ( isForeEndInhibited() ){
\r
136 res.transform(AffineTransform.getTranslateInstance(0, +rLenmm/2.0));
\r
138 if ( isAftEndInhibited() ){
\r
139 res.transform(AffineTransform.getTranslateInstance(0, -rLenmm/2.0));
\r
144 public static void main(String args[]) throws Exception {
\r
145 ExtrudedShapeGrain e = DEFAULT_GRAIN;
\r
146 new Editor(e).showAsWindow();
\r
147 new GrainPanel(e).showAsWindow();
\r