1
2 package org.freehep.graphicsio;
3
4 import java.awt.geom.Point2D;
5 import java.io.IOException;
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25 public abstract class CubicToQuadPathConstructor extends
26 AbstractPathConstructor {
27
28 private double resolutionSq;
29
30 protected CubicToQuadPathConstructor(double resolution) {
31 super();
32 resolutionSq = resolution * resolution;
33 }
34
35 public void move(double x, double y) throws IOException {
36 currentX = x;
37 currentY = y;
38 }
39
40 public void line(double x, double y) throws IOException {
41 currentX = x;
42 currentY = y;
43 }
44
45 public void cubic(double x1, double y1, double x2, double y2, double x3,
46 double y3) throws IOException {
47 quadratify(new Point2D.Double(currentX, currentY), new Point2D.Double(
48 x1, y1), new Point2D.Double(x2, y2), new Point2D.Double(x3, y3));
49
50 currentX = x3;
51 currentY = y3;
52 }
53
54 public void closePath(double x0, double y0) throws IOException {
55 currentX = 0;
56 currentY = 0;
57 }
58
59 public static Point2D intersect(Point2D p1, Point2D p2, Point2D p3,
60 Point2D p4) {
61
62 double dx1 = p2.getX() - p1.getX();
63 double dx2 = p3.getX() - p4.getX();
64
65
66 if ((dx1 == 0) && (dx2 == 0)) return null;
67
68 double dy1 = p2.getY() - p1.getY();
69 double dy2 = p3.getY() - p4.getY();
70
71
72 if ((dy1 == 0) && (dy2 == 0)) return null;
73
74 double m1 = (p2.getY() - p1.getY()) / dx1;
75 double m2 = (p3.getY() - p4.getY()) / dx2;
76
77 if (dx1 == 0) {
78
79 return new Point2D.Double(p1.getX(), m2 * (p1.getX() - p4.getX())
80 + p4.getY());
81 } else if (dx2 == 0) {
82
83 return new Point2D.Double(p4.getX(), m1 * (p4.getX() - p1.getX())
84 + p1.getY());
85 }
86
87
88 if (m1 == m2) return null;
89
90 double x = (-m2 * p4.getX() + p4.getY() + m1 * p1.getX() - p1.getY())
91 / (m1 - m2);
92 double y = m1 * (x - p1.getX()) + p1.getY();
93 return new Point2D.Double(x, y);
94 }
95
96 public static Point2D midPoint(Point2D a, Point2D b) {
97 return new Point2D.Double((a.getX() + b.getX()) / 2.0, (a.getY() + b
98 .getY()) / 2.0);
99 }
100
101 public void quadratify(Point2D a, Point2D b, Point2D c, Point2D d)
102 throws IOException {
103
104 Point2D s = intersect(a, b, c, d);
105 if (s == null) return;
106
107
108 double dx = (a.getX() + d.getX() + s.getX() * 4 - (b.getX() + c.getX()) * 3) * .125;
109 double dy = (a.getY() + d.getY() + s.getY() * 4 - (b.getY() + c.getY()) * 3) * .125;
110
111 if (dx * dx + dy * dy > resolutionSq) {
112 Point2D p01 = midPoint(a, b);
113 Point2D p12 = midPoint(b, c);
114 Point2D p23 = midPoint(c, d);
115 Point2D p02 = midPoint(p01, p12);
116 Point2D p13 = midPoint(p12, p23);
117 Point2D p03 = midPoint(p02, p13);
118
119 quadratify(a, p01, p02, p03);
120 quadratify(p03, p13, p23, d);
121 } else {
122
123 quad(s.getX(), s.getY(), d.getX(), d.getY());
124 }
125 }
126
127 static class Test extends CubicToQuadPathConstructor {
128 public Test(double resolution) {
129 super(resolution);
130 }
131
132 public void quad(double x1, double y1, double x2, double y2) {
133 System.out.println("Quad: (" + currentX + ", " + currentY + ") ("
134 + x1 + ", " + y1 + ") (" + x2 + ", " + y2 + ")");
135 currentX = x2;
136 currentY = y2;
137 }
138
139 }
140
141 public static void main(String[] args) throws Exception {
142 PathConstructor pc = new Test(0.5);
143
144 pc.move(20, 20);
145 pc.cubic(20, 40, 40, 60, 60, 60);
146
147
148 pc.move(20, 20);
149 pc.cubic(20, 40, 60, 60, 40, 60);
150
151
152 pc.move(183, 149);
153 pc.cubic(189, 291, 256, 347, 295, 244);
154 pc.cubic(334, 141, 286, 216, 214, 228);
155 pc.cubic(142, 240, 142, 256, 176, 284);
156 }
157 }