]> git.gag.com Git - sw/motorsim/commitdiff
Changed to using better math to get rid of little imperfections in the results.
authorBill Kuker <bkuker@billkuker.com>
Wed, 15 Apr 2009 18:44:32 +0000 (18:44 +0000)
committerBill Kuker <bkuker@billkuker.com>
Wed, 15 Apr 2009 18:44:32 +0000 (18:44 +0000)
Rather than create a rect and rotate it, create the rect in place using the exact values of the coincident points.

Add / subtract the circles seperatly because adding them to the rects leads to imprecise (because of floating point) intersections, leading to non-coincident edges again.

src/TriTest.java

index 59957c1c0f098102d60155ee267ad3d7b163f707..be0e4229953f968e3d03a7553516ac6323dccd2d 100644 (file)
@@ -8,6 +8,7 @@ import java.awt.geom.Area;
 import java.awt.geom.Ellipse2D;\r
 import java.awt.geom.GeneralPath;\r
 import java.awt.geom.PathIterator;\r
+import java.awt.geom.Point2D;\r
 import java.awt.geom.Rectangle2D;\r
 \r
 import javax.swing.JFrame;\r
@@ -28,11 +29,20 @@ public class TriTest extends JPanel {
                }\r
                \r
                public Area getRegressedShape(double regression){\r
-                       Area ret = new Area();  \r
+                       if ( regression == 0 )\r
+                               return a;\r
+                       \r
+                       //Build these separatly because intersecting the line\r
+                       //with the circle creates a small amount of error which\r
+                       //shows up when the resulting edge is no longer exactly\r
+                       //colinear with the original edge.\r
+                       Area rRect = new Area();        \r
+                       Area rCirc = new Area();\r
                        \r
                        PathIterator i = a.getPathIterator(new AffineTransform(), .001);\r
                        double last[] = {0,0};\r
                        double first[] = {0,0};\r
+\r
                        while (!i.isDone()) {\r
                                double coords[] = new double[6];\r
                                int type = i.currentSegment(coords);\r
@@ -45,31 +55,27 @@ public class TriTest extends JPanel {
                                                coords[0] = first[0];\r
                                                coords[1] = first[1];\r
                                        case PathIterator.SEG_LINETO:\r
-                                               //Do it;\r
-                                               \r
-                                               //TODO XXX\r
-                                               //Usint arctan is imprecise, the base of the rectangle does not perfectly coincide with the\r
-                                               //edge of the poly. Instead I should find the normal vector and build the rect myself prerotated.\r
-                                               double len = Math.sqrt(Math.pow(last[0] - coords[0], 2) + Math.pow(last[1] - coords[1], 2));\r
+                                               //Calculate the normal to this edge\r
                                                double dx = coords[0]-last[0];\r
                                                double dy = coords[1]-last[1];\r
-                                               double angle = Math.atan2(dy, dx);\r
-                                                               \r
-                                               Area rect;\r
-                                               if ( regression > 0 )\r
-                                                       rect = new Area(new Rectangle2D.Double(0,0,len,regression));\r
-                                               else\r
-                                                       rect = new Area(new Rectangle2D.Double(0,regression,len,-regression));\r
-                                               rect.transform(AffineTransform.getRotateInstance(angle));\r
-                                               rect.transform(AffineTransform.getTranslateInstance(last[0], last[1]));\r
-                                               ret.add(rect);\r
-                                               \r
-                                               if ( regression > 0 ){\r
-                                                       ret.add(new Area(new Ellipse2D.Double(coords[0]-regression, coords[1]-regression, regression*2, regression*2)));\r
-                                               } else {\r
-                                                       ret.add(new Area(new Ellipse2D.Double(coords[0]+regression, coords[1]+regression, -regression*2, -regression*2)));\r
-                                               }\r
+                                               double len = Math.sqrt(dx*dx + dy*dy);                                          \r
+                                               double normal[] = {-dy/len,dx/len};\r
                                                \r
+                                               //Calculate the displacement of the endpoints\r
+                                               //to create a rect\r
+                                               double displacement[] = {regression*normal[0], regression*normal[1]};\r
+\r
+                                               //Create that rect. Winding does not seem to matter...\r
+                                               GeneralPath p = new GeneralPath();\r
+                                               p.moveTo(last[0], last[1]);\r
+                                               p.lineTo(last[0]+displacement[0], last[1]+displacement[1]);\r
+                                               p.lineTo(coords[0]+displacement[0], coords[1]+displacement[1]);\r
+                                               p.lineTo(coords[0], coords[1]);\r
+                                               p.closePath();\r
+                                               rRect.add( new Area(p));\r
+\r
+                                               double er = Math.abs(regression);\r
+                                               rCirc.add(new Area(new Ellipse2D.Double(coords[0]-er, coords[1]-er, 2*er, 2*er)));\r
                                                \r
                                                last[0] = coords[0];\r
                                                last[1] = coords[1];\r
@@ -81,14 +87,18 @@ public class TriTest extends JPanel {
                                i.next();\r
                        }\r
                        \r
+\r
                        if ( regression > 0 ){\r
-                               ret.add(a);\r
+                               //Combine all together\r
+                               rRect.add(a);\r
+                               rRect.add(rCirc);\r
                        }else{\r
                                Area acp = (Area)a.clone();\r
-                               acp.subtract(ret);\r
-                               ret = acp;\r
+                               acp.subtract(rRect);\r
+                               acp.subtract(rCirc);\r
+                               rRect = acp;\r
                        }\r
-                       return ret;\r
+                       return rRect;\r
                }\r
        }\r
        \r
@@ -110,10 +120,14 @@ public class TriTest extends JPanel {
                \r
                g.clearRect(0, 0, 600, 600);\r
 \r
+\r
+               g.setColor(Color.black);\r
+               g.fill(shape.getRegressedShape(r));\r
+               g.setColor(Color.yellow);               \r
+               g.draw(shape.getRegressedShape(0));\r
                g.setColor(Color.red);\r
                g.draw(shape.getRegressedShape(r));\r
-               //g.setColor(Color.black);              \r
-               //g.draw(shape.getRegressedShape(0));\r
+\r
                \r
        }\r
        \r