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.Ellipse2D;
\r
6 import java.awt.geom.Rectangle2D;
\r
7 import java.beans.PropertyVetoException;
\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 sun.reflect.ReflectionFactory.GetReflectionFactoryAction;
\r
18 import com.billkuker.rocketry.motorsim.Grain;
\r
19 import com.billkuker.rocketry.motorsim.MotorPart;
\r
20 import com.billkuker.rocketry.motorsim.grain.ExtrudedGrain;
\r
21 import com.billkuker.rocketry.motorsim.visual.Editor;
\r
22 import com.billkuker.rocketry.motorsim.visual.GrainPanel;
\r
24 public abstract class ExtrudedShapeGrain extends ExtrudedGrain {
\r
26 public static ExtrudedShapeGrain DEFAULT_GRAIN = new ExtrudedShapeGrain(){
\r
29 Shape outside = new Ellipse2D.Double(0, 0, 30, 30);
\r
30 xsection.add(outside);
\r
31 xsection.inhibit(outside);
\r
32 xsection.subtract(new Ellipse2D.Double(10,10, 10, 10));
\r
33 setLength(Amount.valueOf(70, SI.MILLIMETER));
\r
34 setForeEndInhibited(false);
\r
35 setAftEndInhibited(false);
\r
36 } catch ( Exception e ){
\r
42 protected BurningShape xsection = new BurningShape();
\r
44 protected Amount<Length> webThickness;
\r
46 public Amount<Area> surfaceArea(Amount<Length> regression) {
\r
47 Amount<Area> zero = Amount.valueOf(0, Area.UNIT);
\r
49 if (regression.isGreaterThan(webThickness()))
\r
52 Amount<Length> rLen = regressedLength(regression);
\r
54 if (rLen.isLessThan(Amount.valueOf(0, SI.MILLIMETER)))
\r
57 java.awt.geom.Area burn = getCrossSection(regression);
\r
62 burn.subtract(getCrossSection(regression.plus(Amount.valueOf(.001,
\r
65 Amount<Area> xSection = ShapeUtil.area(xsection.getShape(regression));
\r
67 Amount<Area> sides = ShapeUtil.perimeter(burn).divide(2).times(rLen).to(Area.UNIT);
\r
68 Amount<Area> ends = xSection.times(numberOfBurningEnds(regression));
\r
70 return sides.plus(ends);
\r
74 public Amount<Volume> volume(Amount<Length> regression) {
\r
75 Amount<Volume> zero = Amount.valueOf(0, Volume.UNIT);
\r
77 Amount<Length> rLen = regressedLength(regression);
\r
79 if (rLen.isLessThan(Amount.valueOf(0, SI.MILLIMETER)))
\r
82 Amount<Area> xSection = ShapeUtil.area(xsection.getShape(regression));
\r
84 return xSection.times(rLen).to(Volume.UNIT);
\r
89 public Amount<Length> webThickness() {
\r
90 if ( webThickness != null )
\r
91 return webThickness;
\r
92 java.awt.geom.Area a = getCrossSection(Amount.valueOf(0, SI.MILLIMETER));
\r
93 Rectangle r = a.getBounds();
\r
94 double max = r.getWidth() < r.getHeight() ? r.getHeight() : r
\r
95 .getWidth(); // The max size
\r
99 guess = min + (max - min) / 2; // Guess halfway through
\r
100 System.out.println("Min: " + min + " Guess: " + guess + " Max: "
\r
102 a = getCrossSection(Amount.valueOf(guess, SI.MILLIMETER));
\r
104 // guess is too big
\r
110 if ((max - min) < .01)
\r
113 webThickness = Amount.valueOf(guess, SI.MILLIMETER);
\r
115 //TODO Need to check # of burning ends!
\r
116 if (webThickness.isGreaterThan(getLength().divide(2)))
\r
117 webThickness = getLength().divide(2);
\r
119 return webThickness;
\r
122 public java.awt.geom.Area getCrossSection(Amount<Length> regression) {
\r
123 return xsection.getShape(regression);
\r
126 public java.awt.geom.Area getSideView(Amount<Length> regression) {
\r
127 java.awt.geom.Area res = new java.awt.geom.Area();
\r
129 Amount<Length> rLen = regressedLength(regression);
\r
131 double rLenmm = rLen.doubleValue(SI.MILLIMETER);
\r
133 //TODO Shift up or down based on burning ends
\r
134 for( java.awt.geom.Area a : ShapeUtil.separate(getCrossSection(regression))){
\r
135 Rectangle2D bounds = a.getBounds2D();
\r
136 Rectangle2D side = new Rectangle2D.Double(bounds.getMinX(), -rLenmm/2.0, bounds.getWidth(), rLenmm);
\r
137 res.add(new java.awt.geom.Area(side));
\r
142 public static void main(String args[]) throws Exception {
\r
143 ExtrudedShapeGrain e = DEFAULT_GRAIN;
\r
144 new Editor(e).showAsWindow();
\r
145 new GrainPanel(e).showAsWindow();
\r