organized imports
[sw/motorsim] / src / QuadTest.java
1 import java.awt.BasicStroke;\r
2 import java.awt.Color;\r
3 import java.awt.Graphics;\r
4 import java.awt.Graphics2D;\r
5 import java.awt.Shape;\r
6 import java.awt.geom.AffineTransform;\r
7 import java.awt.geom.Area;\r
8 import java.awt.geom.FlatteningPathIterator;\r
9 import java.awt.geom.GeneralPath;\r
10 import java.awt.geom.PathIterator;\r
11 \r
12 import javax.swing.JFrame;\r
13 import javax.swing.JPanel;\r
14 \r
15 \r
16 public class QuadTest extends JPanel {\r
17 \r
18 \r
19         public void paint(Graphics g){\r
20                 super.paint(g);\r
21                 Graphics2D g2d = (Graphics2D)g;\r
22 \r
23                 g2d.scale(30, 30);\r
24 \r
25                 Area a;\r
26                 GeneralPath p;\r
27 \r
28                 g2d.setStroke(new BasicStroke(.02f));\r
29                 \r
30                 \r
31                 /*\r
32                  a = new Area(new Rectangle2D.Double(0,0,1,1));\r
33                 //a.transform(AffineTransform.getRotateInstance(Math.PI/4.0));\r
34                 g2d.setColor(Color.black);\r
35                 g2d.draw(a);\r
36                 g2d.setColor(Color.red);\r
37                 \r
38                 g2d.draw(square( a ));\r
39                 System.out.println(\r
40                                 yRotatedVolume(a) + ", " +\r
41                                 yRotatedSurfaceArea(a) + "\n"\r
42                                 );\r
43 \r
44                 \r
45                 a = new Area( new Ellipse2D.Double(2, 5, 4, 4));\r
46                 g2d.setColor(Color.black);\r
47                 g2d.draw(a);\r
48                 g2d.setColor(Color.red);\r
49                 \r
50                 g2d.draw(square( a ));\r
51                 System.out.println(\r
52                                 yRotatedVolume(a) + ", " +\r
53                                 yRotatedSurfaceArea(a) + "\n"\r
54                                 );\r
55                 \r
56         \r
57                 */\r
58                 p = new GeneralPath();\r
59                 p.moveTo(0,0);\r
60                 p.lineTo(1, 1);\r
61                 p.lineTo(0,1);\r
62                 p.closePath();\r
63                 a = new Area(p);\r
64                 g2d.translate(0, 8);\r
65                 g2d.setColor(Color.black);\r
66                 g2d.draw(a);\r
67                 g2d.setColor(Color.red);\r
68                 \r
69                 g2d.draw(square( a ));\r
70                 System.out.println(\r
71                                 yRotatedVolume(a) + ", " +\r
72                                 yRotatedSurfaceArea(a) + "\n"\r
73                                 );\r
74                 \r
75                 p = new GeneralPath();\r
76                 p.moveTo(0,0);\r
77                 p.lineTo(2, 2);\r
78                 p.lineTo(0,2);\r
79                 p.closePath();\r
80                 a = new Area(p);\r
81                 g2d.translate(0, 2);\r
82                 g2d.setColor(Color.black);\r
83                 g2d.draw(a);\r
84                 g2d.setColor(Color.red);\r
85                 \r
86                 g2d.draw(square( a ));\r
87                 System.out.println(\r
88                                 yRotatedVolume(a) + ", " +\r
89                                 yRotatedSurfaceArea(a) + "\n"\r
90                                 );\r
91 \r
92                 p = new GeneralPath();\r
93                 p.moveTo(0,1);\r
94                 p.lineTo(1,1);\r
95                 p.lineTo(2, 2);\r
96                 p.lineTo(0,2);\r
97                 p.closePath();\r
98                 a = new Area(p);\r
99                 g2d.translate(0, 2);\r
100                 g2d.setColor(Color.black);\r
101                 g2d.draw(a);\r
102                 g2d.setColor(Color.red);\r
103                 \r
104                 g2d.draw(square( a ));\r
105                 System.out.println(\r
106                                 yRotatedVolume(a) + ", " +\r
107                                 yRotatedSurfaceArea(a) + "\n"\r
108                                 );\r
109                  \r
110 \r
111         }\r
112         \r
113         \r
114         private double yRotatedVolume(Area a){\r
115                 return Math.PI * area(new Area(square(a)));\r
116         }\r
117         \r
118         private Shape square(java.awt.geom.Area a) {\r
119                 PathIterator i = a.getPathIterator(new AffineTransform(), 0.0001);\r
120                 GeneralPath cur = new GeneralPath();\r
121 \r
122                 double last[] = {0,0};\r
123                 while (!i.isDone()) {\r
124                         double coords[] = new double[6];\r
125                         int type = i.currentSegment(coords);\r
126                         switch (type) {\r
127                         case PathIterator.SEG_CLOSE:\r
128                                 cur.closePath();\r
129                                 break;\r
130                         case PathIterator.SEG_MOVETO:\r
131                                 cur.moveTo(Math.pow(coords[0],2), coords[1]);\r
132                                 last[0] = coords[0];\r
133                                 last[1] = coords[1];\r
134                                 break;\r
135                         case PathIterator.SEG_CUBICTO:\r
136                                 throw new Error("Non-flattened geometry!");\r
137                         case PathIterator.SEG_LINETO:\r
138                                 double x = last[0];\r
139                                 double y = last[1];\r
140                                 double len = Math.sqrt(Math.pow(last[0]-coords[0], 2) + Math.pow(last[1]-coords[1], 2));\r
141                                 int steps = (int)(len / .01) + 5;\r
142                                 for (int s = 0; s < steps; s++) {\r
143                                         x += (coords[0] - last[0]) / steps;\r
144                                         y += (coords[1] - last[1]) / steps;\r
145                                         cur.lineTo(Math.pow(x, 2), y);\r
146                                 }\r
147                                 last[0] = coords[0];\r
148                                 last[1] = coords[1];\r
149                                 break;\r
150                         case PathIterator.SEG_QUADTO:\r
151                                 throw new Error("Non-flattened geometry!");\r
152 \r
153                         }\r
154                         i.next();\r
155                 }\r
156                 return cur;\r
157         }\r
158         \r
159         private double yRotatedSurfaceArea(java.awt.geom.Area a) {\r
160                 //TODO: I think I need to handle seg_close!!\r
161                 PathIterator i = a.getPathIterator(new AffineTransform(), .001);\r
162                 double x = 0, y = 0;\r
163                 double mx = 0, my = 0;\r
164                 double len = 0;\r
165                 while (!i.isDone()) {\r
166                         double coords[] = new double[6];\r
167                         int type = i.currentSegment(coords);\r
168                         if (type == PathIterator.SEG_LINETO || type == PathIterator.SEG_CLOSE) {\r
169 \r
170 \r
171                                 double nx = coords[0];\r
172                                 double ny = coords[1];\r
173                                 \r
174                                 if ( type == PathIterator.SEG_CLOSE ){\r
175                                         nx = mx;\r
176                                         ny = my;\r
177                                 }\r
178                                 \r
179                                 double dy = Math.abs(y-ny);\r
180                                 double dx = Math.abs(x-nx);\r
181                                 double xl = x>nx?x:nx;\r
182                                 double xs = x<nx?x:nx;  \r
183                                 \r
184                                 double add = 0;\r
185                                 if ( dx == 0 ){\r
186                                         add = 2 * Math.PI * xl * dy;\r
187                                 } else if ( dy == 0 ){\r
188                                          add = Math.PI * xl * xl - Math.PI * xs * xs;\r
189                                 }else{\r
190                                         double h = xl/dx * dy;\r
191                                         double s1 = Math.sqrt(xl*xl + h*h);\r
192                                         double s2 = Math.sqrt(xs*xs + (h-dy)*(h-dy));\r
193                                         add = Math.PI * (xl*s1 - xs*s2);\r
194                                 }\r
195                                 \r
196                                 len += add;\r
197 \r
198                                 x = nx;\r
199                                 y = ny;\r
200                         } else if (type == PathIterator.SEG_MOVETO) {\r
201                                 mx = x = coords[0];\r
202                                 my = y = coords[1];\r
203                         } else {\r
204                                 throw new Error("Non-flattened geometry!");\r
205                         }\r
206                         i.next();\r
207                 }\r
208                 return len;\r
209         }\r
210         \r
211 \r
212         \r
213         private double area(java.awt.geom.Area a) {\r
214                 if ( !a.isSingular() )\r
215                         throw new IllegalArgumentException("Can not calculate area of non-singular shape!");\r
216                 PathIterator i = a.getPathIterator(new AffineTransform(), .001);\r
217                 \r
218                 \r
219                 double x = 0, y = 0, sx = 0, sy = 0;\r
220                 double nx, ny;\r
221                 double area = 0;\r
222                 while (!i.isDone()) {\r
223                         double coords[] = new double[6];\r
224                         int type = i.currentSegment(coords);\r
225                         switch( type ){\r
226                         case PathIterator.SEG_CLOSE:\r
227                                 //Go back to the start\r
228                                 nx = sx;\r
229                                 ny = sy;\r
230                                 area += x * ny;\r
231                                 area -= y * nx;\r
232                                 break;\r
233                         case PathIterator.SEG_LINETO:\r
234                                 nx = coords[0];\r
235                                 ny = coords[1];\r
236                                 area += x * ny;\r
237                                 area -= y * nx;\r
238 \r
239                                 //Remember the last points\r
240                                 x = nx;\r
241                                 y = ny;\r
242                                 \r
243                                 break;\r
244                         case PathIterator.SEG_MOVETO:\r
245                                 //Remember the starting point\r
246                                 x = sx = coords[0];\r
247                                 y = sy = coords[1];\r
248                                 break;\r
249                         default:\r
250                                 throw new Error("Bad segment type from Flattening Path Iterator");\r
251                         }\r
252                         i.next();\r
253                 }\r
254                 \r
255                 area = area / 2.0; // Result so far is double the signed area\r
256                 \r
257                 if ( area < 0 ) //Depending on winding it could be negative\r
258                         area = area * -1.0;\r
259                 \r
260                 \r
261                 return area;\r
262         }\r
263 \r
264         \r
265         public class FancyPathIterator extends FlatteningPathIterator{\r
266 \r
267                 public FancyPathIterator(PathIterator path, double error) {\r
268                         super(path, error);\r
269                 }\r
270                 \r
271                 \r
272                 \r
273         }\r
274         \r
275         public static void main(String args[]){\r
276                 JFrame f = new JFrame();\r
277                 f.setContentPane(new QuadTest());\r
278                 f.setDefaultCloseOperation(f.DISPOSE_ON_CLOSE);\r
279                 f.setSize(1500,800);\r
280                 f.setLocation(1600, 100);\r
281                 f.show();\r
282         }\r
283 }\r