--- /dev/null
+import java.awt.BasicStroke;\r
+import java.awt.Color;\r
+import java.awt.Graphics;\r
+import java.awt.Graphics2D;\r
+import java.awt.Shape;\r
+import java.awt.geom.AffineTransform;\r
+import java.awt.geom.Area;\r
+import java.awt.geom.FlatteningPathIterator;\r
+import java.awt.geom.GeneralPath;\r
+import java.awt.geom.PathIterator;\r
+\r
+import javax.swing.JFrame;\r
+import javax.swing.JPanel;\r
+\r
+\r
+public class QuadTest extends JPanel {\r
+\r
+\r
+ public void paint(Graphics g){\r
+ super.paint(g);\r
+ Graphics2D g2d = (Graphics2D)g;\r
+\r
+ g2d.scale(30, 30);\r
+\r
+ Area a;\r
+ GeneralPath p;\r
+\r
+ g2d.setStroke(new BasicStroke(.02f));\r
+ \r
+ \r
+ /*\r
+ a = new Area(new Rectangle2D.Double(0,0,1,1));\r
+ //a.transform(AffineTransform.getRotateInstance(Math.PI/4.0));\r
+ g2d.setColor(Color.black);\r
+ g2d.draw(a);\r
+ g2d.setColor(Color.red);\r
+ \r
+ g2d.draw(square( a ));\r
+ System.out.println(\r
+ yRotatedVolume(a) + ", " +\r
+ yRotatedSurfaceArea(a) + "\n"\r
+ );\r
+\r
+ \r
+ a = new Area( new Ellipse2D.Double(2, 5, 4, 4));\r
+ g2d.setColor(Color.black);\r
+ g2d.draw(a);\r
+ g2d.setColor(Color.red);\r
+ \r
+ g2d.draw(square( a ));\r
+ System.out.println(\r
+ yRotatedVolume(a) + ", " +\r
+ yRotatedSurfaceArea(a) + "\n"\r
+ );\r
+ \r
+ \r
+ */\r
+ p = new GeneralPath();\r
+ p.moveTo(0,0);\r
+ p.lineTo(1, 1);\r
+ p.lineTo(0,1);\r
+ p.closePath();\r
+ a = new Area(p);\r
+ g2d.translate(0, 8);\r
+ g2d.setColor(Color.black);\r
+ g2d.draw(a);\r
+ g2d.setColor(Color.red);\r
+ \r
+ g2d.draw(square( a ));\r
+ System.out.println(\r
+ yRotatedVolume(a) + ", " +\r
+ yRotatedSurfaceArea(a) + "\n"\r
+ );\r
+ \r
+ p = new GeneralPath();\r
+ p.moveTo(0,0);\r
+ p.lineTo(2, 2);\r
+ p.lineTo(0,2);\r
+ p.closePath();\r
+ a = new Area(p);\r
+ g2d.translate(0, 2);\r
+ g2d.setColor(Color.black);\r
+ g2d.draw(a);\r
+ g2d.setColor(Color.red);\r
+ \r
+ g2d.draw(square( a ));\r
+ System.out.println(\r
+ yRotatedVolume(a) + ", " +\r
+ yRotatedSurfaceArea(a) + "\n"\r
+ );\r
+\r
+ p = new GeneralPath();\r
+ p.moveTo(0,1);\r
+ p.lineTo(1,1);\r
+ p.lineTo(2, 2);\r
+ p.lineTo(0,2);\r
+ p.closePath();\r
+ a = new Area(p);\r
+ g2d.translate(0, 2);\r
+ g2d.setColor(Color.black);\r
+ g2d.draw(a);\r
+ g2d.setColor(Color.red);\r
+ \r
+ g2d.draw(square( a ));\r
+ System.out.println(\r
+ yRotatedVolume(a) + ", " +\r
+ yRotatedSurfaceArea(a) + "\n"\r
+ );\r
+ \r
+\r
+ }\r
+ \r
+ \r
+ private double yRotatedVolume(Area a){\r
+ return Math.PI * area(new Area(square(a)));\r
+ }\r
+ \r
+ private Shape square(java.awt.geom.Area a) {\r
+ PathIterator i = a.getPathIterator(new AffineTransform(), 0.0001);\r
+ GeneralPath cur = new GeneralPath();\r
+\r
+ double last[] = {0,0};\r
+ while (!i.isDone()) {\r
+ double coords[] = new double[6];\r
+ int type = i.currentSegment(coords);\r
+ switch (type) {\r
+ case PathIterator.SEG_CLOSE:\r
+ cur.closePath();\r
+ break;\r
+ case PathIterator.SEG_MOVETO:\r
+ cur.moveTo(Math.pow(coords[0],2), coords[1]);\r
+ last[0] = coords[0];\r
+ last[1] = coords[1];\r
+ break;\r
+ case PathIterator.SEG_CUBICTO:\r
+ throw new Error("Non-flattened geometry!");\r
+ case PathIterator.SEG_LINETO:\r
+ double x = last[0];\r
+ double y = last[1];\r
+ double len = Math.sqrt(Math.pow(last[0]-coords[0], 2) + Math.pow(last[1]-coords[1], 2));\r
+ int steps = (int)(len / .01) + 5;\r
+ for (int s = 0; s < steps; s++) {\r
+ x += (coords[0] - last[0]) / steps;\r
+ y += (coords[1] - last[1]) / steps;\r
+ cur.lineTo(Math.pow(x, 2), y);\r
+ }\r
+ last[0] = coords[0];\r
+ last[1] = coords[1];\r
+ break;\r
+ case PathIterator.SEG_QUADTO:\r
+ throw new Error("Non-flattened geometry!");\r
+\r
+ }\r
+ i.next();\r
+ }\r
+ return cur;\r
+ }\r
+ \r
+ private double yRotatedSurfaceArea(java.awt.geom.Area a) {\r
+ //TODO: I think I need to handle seg_close!!\r
+ PathIterator i = a.getPathIterator(new AffineTransform(), .001);\r
+ double x = 0, y = 0;\r
+ double mx = 0, my = 0;\r
+ double len = 0;\r
+ while (!i.isDone()) {\r
+ double coords[] = new double[6];\r
+ int type = i.currentSegment(coords);\r
+ if (type == PathIterator.SEG_LINETO || type == PathIterator.SEG_CLOSE) {\r
+\r
+\r
+ double nx = coords[0];\r
+ double ny = coords[1];\r
+ \r
+ if ( type == PathIterator.SEG_CLOSE ){\r
+ nx = mx;\r
+ ny = my;\r
+ }\r
+ \r
+ double dy = Math.abs(y-ny);\r
+ double dx = Math.abs(x-nx);\r
+ double xl = x>nx?x:nx;\r
+ double xs = x<nx?x:nx; \r
+ \r
+ double add = 0;\r
+ if ( dx == 0 ){\r
+ add = 2 * Math.PI * xl * dy;\r
+ } else if ( dy == 0 ){\r
+ add = Math.PI * xl * xl - Math.PI * xs * xs;\r
+ }else{\r
+ double h = xl/dx * dy;\r
+ double s1 = Math.sqrt(xl*xl + h*h);\r
+ double s2 = Math.sqrt(xs*xs + (h-dy)*(h-dy));\r
+ add = Math.PI * (xl*s1 - xs*s2);\r
+ }\r
+ \r
+ len += add;\r
+\r
+ x = nx;\r
+ y = ny;\r
+ } else if (type == PathIterator.SEG_MOVETO) {\r
+ mx = x = coords[0];\r
+ my = y = coords[1];\r
+ } else {\r
+ throw new Error("Non-flattened geometry!");\r
+ }\r
+ i.next();\r
+ }\r
+ return len;\r
+ }\r
+ \r
+\r
+ \r
+ private double area(java.awt.geom.Area a) {\r
+ if ( !a.isSingular() )\r
+ throw new IllegalArgumentException("Can not calculate area of non-singular shape!");\r
+ PathIterator i = a.getPathIterator(new AffineTransform(), .001);\r
+ \r
+ \r
+ double x = 0, y = 0, sx = 0, sy = 0;\r
+ double nx, ny;\r
+ double area = 0;\r
+ while (!i.isDone()) {\r
+ double coords[] = new double[6];\r
+ int type = i.currentSegment(coords);\r
+ switch( type ){\r
+ case PathIterator.SEG_CLOSE:\r
+ //Go back to the start\r
+ nx = sx;\r
+ ny = sy;\r
+ area += x * ny;\r
+ area -= y * nx;\r
+ break;\r
+ case PathIterator.SEG_LINETO:\r
+ nx = coords[0];\r
+ ny = coords[1];\r
+ area += x * ny;\r
+ area -= y * nx;\r
+\r
+ //Remember the last points\r
+ x = nx;\r
+ y = ny;\r
+ \r
+ break;\r
+ case PathIterator.SEG_MOVETO:\r
+ //Remember the starting point\r
+ x = sx = coords[0];\r
+ y = sy = coords[1];\r
+ break;\r
+ default:\r
+ throw new Error("Bad segment type from Flattening Path Iterator");\r
+ }\r
+ i.next();\r
+ }\r
+ \r
+ area = area / 2.0; // Result so far is double the signed area\r
+ \r
+ if ( area < 0 ) //Depending on winding it could be negative\r
+ area = area * -1.0;\r
+ \r
+ \r
+ return area;\r
+ }\r
+\r
+ \r
+ public class FancyPathIterator extends FlatteningPathIterator{\r
+\r
+ public FancyPathIterator(PathIterator path, double error) {\r
+ super(path, error);\r
+ }\r
+ \r
+ \r
+ \r
+ }\r
+ \r
+ public static void main(String args[]){\r
+ JFrame f = new JFrame();\r
+ f.setContentPane(new QuadTest());\r
+ f.setDefaultCloseOperation(f.DISPOSE_ON_CLOSE);\r
+ f.setSize(1500,800);\r
+ f.setLocation(1600, 100);\r
+ f.show();\r
+ }\r
+}\r
import org.jscience.physics.amount.Amount;\r
import org.jscience.physics.amount.Constants;\r
\r
-import com.billkuker.rocketry.motorsim.fuel.KNSB;\r
-import com.billkuker.rocketry.motorsim.fuel.KNSU;\r
-import com.billkuker.rocketry.motorsim.grain.CompoundGrain;\r
-import com.billkuker.rocketry.motorsim.grain.CoredCylindricalGrain;\r
-import com.billkuker.rocketry.motorsim.grain.MultiGrain;\r
-import com.billkuker.rocketry.motorsim.visual.BurnPanel;\r
-\r
public class Burn {\r
\r
private static Logger log = Logger.getLogger(Burn.class);\r
//This unit conversion helps JScience to convert nozzle flow rate to\r
//kg/s a little later on I verified the conversion by hand and\r
//JScience checks it too.\r
- specificGasConstant = specificGasConstant.to(\r
- SI.METER.pow(2).divide(SI.SECOND.pow(2).times(SI.KELVIN)));\r
+ specificGasConstant = convertSpecificGasConstantUnits(specificGasConstant);\r
\r
log.debug("Specific Gas Constant: (good)" + specificGasConstant);\r
\r
\r
}\r
\r
+ @SuppressWarnings("unchecked")\r
+ /*\r
+ * This converts the units of this constant to something JScience is able\r
+ * to work from. This conversion is unchecked at compile time, but\r
+ * JScience keeps me honest at runtime.\r
+ */\r
+ private Amount convertSpecificGasConstantUnits(Amount a){\r
+ return a.to(\r
+ SI.METER.pow(2).divide(SI.SECOND.pow(2).times(SI.KELVIN)));\r
+ }\r
+ \r
public Amount<Pressure> pressure(Amount<Duration> time){\r
return data.get(time).chamberPressure;\r
}\r
return motor.getGrain().surfaceArea(regression).divide(motor.getNozzle().throatArea()).to(Dimensionless.UNIT);\r
}\r
\r
- public static void main( String args[]) throws Exception{\r
- Motor m = new Motor();\r
- m.setFuel(new KNSB());\r
- \r
- CylindricalChamber c = new CylindricalChamber();\r
- c.setLength(Amount.valueOf(300, SI.MILLIMETER));\r
- c.setID(Amount.valueOf(30, SI.MILLIMETER));\r
- m.setChamber(c);\r
- \r
- CoredCylindricalGrain g = new CoredCylindricalGrain();\r
- g.setLength(Amount.valueOf(35, SI.MILLIMETER));\r
- g.setOD(Amount.valueOf(30, SI.MILLIMETER));\r
- g.setID(Amount.valueOf(10, SI.MILLIMETER));\r
- m.setGrain(g);\r
- \r
- CoredCylindricalGrain g1 = new CoredCylindricalGrain();\r
- g1.setLength(Amount.valueOf(70, SI.MILLIMETER));\r
- g1.setOD(Amount.valueOf(30, SI.MILLIMETER));\r
- g1.setID(Amount.valueOf(18, SI.MILLIMETER));\r
- g1.inhibit(false, true, true);\r
- \r
- CoredCylindricalGrain g2 = new CoredCylindricalGrain();\r
- g2.setLength(Amount.valueOf(70, SI.MILLIMETER));\r
- g2.setOD(Amount.valueOf(12, SI.MILLIMETER));\r
- g2.setID(Amount.valueOf(0, SI.MILLIMETER));\r
- g2.inhibit(true, false, true);\r
- \r
- CompoundGrain cg = new CompoundGrain();\r
- cg.add(g1);\r
- cg.add(g2);\r
- \r
- //m.setGrain( new MultiGrain(cg, 2) );\r
- \r
- //g.setAftEndInhibited(true);\r
- //g.setForeEndInhibited(true);\r
- m.setGrain(new MultiGrain(g,3));\r
- \r
- //m.setGrain(new ExtrudedGrain());\r
- \r
- ConvergentDivergentNozzle n = new ConvergentDivergentNozzle();\r
- n.setThroatDiameter(Amount.valueOf(5.500, SI.MILLIMETER));\r
- n.setExitDiameter(Amount.valueOf(20.87, SI.MILLIMETER));\r
- n.setEfficiency(.87);\r
- m.setNozzle(n);\r
- \r
- Burn b = new Burn(m);\r
- \r
- b.burn();\r
- \r
- new BurnPanel(b).show();\r
- /*\r
- Chart<Duration, Pressure> r = new Chart<Duration, Pressure>(\r
- SI.SECOND,\r
- SI.MEGA(SI.PASCAL),\r
- b,\r
- "pressure");\r
- r.setDomain(b.data.keySet());\r
- r.show();\r
- \r
- Chart<Duration, Force> t = new Chart<Duration, Force>(\r
- SI.SECOND,\r
- SI.NEWTON,\r
- b,\r
- "thrust");\r
- t.setDomain(b.data.keySet());\r
- t.show();\r
- \r
- new GrainPanel( m.getGrain() ).show();*/\r
- \r
- }\r
}\r