View Javadoc

1   // Copyright 2001 FreeHEP.
2   package org.freehep.graphicsio;
3   
4   import java.awt.geom.Point2D;
5   import java.io.IOException;
6   import java.util.Stack;
7   
8   /**
9    * Implements cubics by approximating them using a polyline. Useful class for
10   * output formats that do NOT implement bezier curves at all, or if you need
11   * only straight lines.
12   * 
13   * @author Mark Donszelmann
14   * @version $Id: CubicToLinePathConstructor.java 8584 2006-08-10 23:06:37Z duns $
15   */
16  public abstract class CubicToLinePathConstructor extends
17          QuadToCubicPathConstructor {
18  
19      private double resolution;
20  
21      protected CubicToLinePathConstructor() {
22          this(0.025);
23      }
24  
25      protected CubicToLinePathConstructor(double resolution) {
26          this.resolution = Math.abs(resolution);
27      }
28  
29      public void cubic(double x1, double y1, double x2, double y2, double x3,
30                        double y3) throws IOException {
31  
32          // ControlSets are written at the end
33          Stack/*<ControlSet>*/ controls = new Stack/*<ControlSet>*/();
34  
35          // System.out.println("Cubic "+x1+" "+y1+" "+x2+" "+y2+" "+x3+" "+y3);
36          Point2D p0 = new Point2D.Double(currentX, currentY);
37          Point2D p1 = new Point2D.Double(x1, y1);
38          Point2D p2 = new Point2D.Double(x2, y2);
39          Point2D p3 = new Point2D.Double(x3, y3);
40  
41          // ControlSets to create the controls
42          Stack/*<ControlSet>*/ temps = new Stack/*<ControlSet>*/();
43          temps.push(new ControlSet(p0, p1, p2, p3));
44  
45          while (!temps.empty()) {
46              ControlSet control = (ControlSet) temps.pop();
47              if (control.breadth() > resolution) {
48                  temps.push(control);
49                  temps.push(control.bisect());
50              } else {
51                  controls.push(control);
52              }
53          }
54  
55          /*tempSet[l++] = new ControlSet(p0, p1, p2, p3);
56          while (l > 0) {
57              ControlSet control1 = tempSet[--l];
58              double b = control1.breadth();
59              if (b > resolution) {
60                  ControlSet control3 = control1.bisect();
61                  tempSet[l++] = control1;
62                  tempSet[l++] = control3;
63              } else {
64                  controls.push(control1);
65              }
66          }*/
67  
68          // write out control sets
69          // System.out.println(k);
70          while (!controls.empty()) {
71              Point2D p = ((ControlSet)controls.pop()).getPoint();
72              line(p.getX(), p.getY());
73              // System.out.println(control2.getPoint());
74          }
75  
76          // store currentX and currentY
77          super.cubic(x1, y1, x2, y2, x3, y3);
78      }
79  
80      class ControlSet {
81          private Point2D point0;
82  
83          private Point2D point1;
84  
85          private Point2D point2;
86  
87          private Point2D point3;
88  
89          public ControlSet(Point2D p0, Point2D p1, Point2D p2, Point2D p3) {
90              point0 = p0;
91              point1 = p1;
92              point2 = p2;
93              point3 = p3;
94          }
95  
96          public double breadth() {
97              double f0 = point0.getX();
98              double f4 = point0.getY();
99              double f1 = point1.getX();
100             double f5 = point1.getY();
101             double f2 = point2.getX();
102             double f6 = point2.getY();
103             double f3 = point3.getX();
104             double f7 = point3.getY();
105             if ((Math.abs(f0 - f3) < resolution)
106                     && (Math.abs(f4 - f7) < resolution)) {
107 
108                 double f8 = Math.abs(f1 - f0) + Math.abs(f5 - f4);
109                 double f10 = Math.abs(f2 - f0) + Math.abs(f6 - f4);
110                 return Math.max(f10, f8);
111 
112             } else {
113 
114                 double d0 = f4 - f7;
115                 double d1 = f3 - f0;
116                 double f12 = Math.sqrt(d0 * d0 + d1 * d1);
117                 double d2 = f3 * f4 - f0 * f7;
118                 double f9 = Math.abs((d0 * f2 + d1 * f6) - d2) / f12;
119                 double f11 = Math.abs((d0 * f1 + d1 * f5) - d2) / f12;
120                 return Math.max(f9, f11);
121             }
122         }
123 
124         public ControlSet bisect() {
125             Point2D p0 = average(point0, point1);
126             Point2D p1 = average(point1, point2);
127             Point2D p2 = average(point2, point3);
128             Point2D p3 = average(p0, p1);
129             Point2D p4 = average(p1, p2);
130             Point2D p5 = average(p3, p4);
131             ControlSet controlset = new ControlSet(p5, p4, p2, point3);
132             point1 = p0;
133             point2 = p3;
134             point3 = p5;
135             return controlset;
136         }
137 
138         public Point2D average(Point2D p1, Point2D p2) {
139             return new Point2D.Double((p1.getX() + p2.getX()) / 2.0,
140                     (p1.getY() + p2.getY()) / 2.0);
141         }
142 
143         public Point2D getPoint() {
144             return point3;
145         }
146     }
147 
148 }