KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > batik > ext > awt > geom > Quadradic


1 /*
2
3    Copyright 2003 The Apache Software Foundation
4
5    Licensed under the Apache License, Version 2.0 (the "License");
6    you may not use this file except in compliance with the License.
7    You may obtain a copy of the License at
8
9        http://www.apache.org/licenses/LICENSE-2.0
10
11    Unless required by applicable law or agreed to in writing, software
12    distributed under the License is distributed on an "AS IS" BASIS,
13    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14    See the License for the specific language governing permissions and
15    limitations under the License.
16
17  */

18 package org.apache.batik.ext.awt.geom;
19
20 import java.awt.geom.CubicCurve2D JavaDoc;
21 import java.awt.geom.Point2D JavaDoc;
22 import java.awt.geom.QuadCurve2D JavaDoc;
23 import java.awt.geom.Rectangle2D JavaDoc;
24
25 /**
26  * A class representing a quadratic path segment.
27  *
28  * @version $Id: Quadradic.java,v 1.3 2005/03/27 08:58:32 cam Exp $
29  */

30 public class Quadradic extends AbstractSegment {
31     public Point2D.Double JavaDoc p1, p2, p3;
32
33     public Quadradic() {
34         p1 = new Point2D.Double JavaDoc();
35         p2 = new Point2D.Double JavaDoc();
36         p3 = new Point2D.Double JavaDoc();
37     }
38
39     public Quadradic(double x1, double y1,
40                      double x2, double y2,
41                      double x3, double y3) {
42         p1 = new Point2D.Double JavaDoc(x1, y1);
43         p2 = new Point2D.Double JavaDoc(x2, y2);
44         p3 = new Point2D.Double JavaDoc(x3, y3);
45     }
46
47     public Quadradic(Point2D.Double JavaDoc p1,
48                      Point2D.Double JavaDoc p2,
49                      Point2D.Double JavaDoc p3) {
50         this.p1 = p1;
51         this.p2 = p2;
52         this.p3 = p3;
53     }
54
55     public Object JavaDoc clone() {
56         return new Quadradic(new Point2D.Double JavaDoc(p1.x, p1.y),
57                              new Point2D.Double JavaDoc(p2.x, p2.y),
58                              new Point2D.Double JavaDoc(p3.x, p3.y));
59     }
60
61     public Segment reverse() {
62         return new Quadradic(new Point2D.Double JavaDoc(p3.x, p3.y),
63                              new Point2D.Double JavaDoc(p2.x, p2.y),
64                              new Point2D.Double JavaDoc(p1.x, p1.y));
65     }
66
67     private void getMinMax(double p1, double p2,
68                            double p3, double [] minMax) {
69         if (p3 > p1){
70             minMax[0] = p1; minMax[1] = p3;
71         } else {
72             minMax[0] = p3; minMax[1] = p1;
73         }
74
75         double a = (p1-2*p2+p3);
76         double b = (p2-p1);
77
78         if (a == 0) return;
79
80         double tv = b/a;
81         if ((tv <= 0) || (tv >= 1)) return;
82
83         tv = ((p1-2*p2+p3)*tv+2*(p2-p1))*tv + p1;
84         if (tv < minMax[0]) minMax[0] = tv;
85         else if (tv > minMax[1]) minMax[1] = tv;
86     }
87
88     public double minX() {
89         double [] minMax = {0, 0};
90         getMinMax(p1.x, p2.x, p3.x, minMax);
91         return minMax[0];
92     }
93     public double maxX() {
94         double [] minMax = {0, 0};
95         getMinMax(p1.x, p2.x, p3.x, minMax);
96         return minMax[1];
97     }
98     public double minY() {
99         double [] minMax = {0, 0};
100         getMinMax(p1.y, p2.y, p3.y, minMax);
101         return minMax[0];
102     }
103     public double maxY() {
104         double [] minMax = {0, 0};
105         getMinMax(p1.y, p2.y, p3.y, minMax);
106         return minMax[1];
107     }
108     public Rectangle2D JavaDoc getBounds2D() {
109         double [] minMaxX = {0, 0};
110         getMinMax(p1.x, p2.x, p3.x, minMaxX);
111         double [] minMaxY = {0, 0};
112         getMinMax(p1.y, p2.y, p3.y, minMaxY);
113
114         return new Rectangle2D.Double JavaDoc
115             (minMaxX[0], minMaxY[0],
116              minMaxX[1]-minMaxX[0], minMaxY[1]-minMaxY[0]);
117     }
118
119     protected int findRoots(double y, double [] roots) {
120         double [] eqn = { p1.y-y, 2*(p2.y-p1.y), p1.y-2*p2.y+p3.y };
121         return QuadCurve2D.solveQuadratic(eqn, roots);
122         // return solveQuad(eqn[2], eqn[1], eqn[0], roots);
123
}
124
125     public Point2D.Double JavaDoc evalDt(double t) {
126         double x = 2*(p1.x-2*p2.x+p3.x)*t + 2*(p2.x-p1.x);
127         double y = 2*(p1.y-2*p2.y+p3.y)*t + 2*(p2.y-p1.y);
128         return new Point2D.Double JavaDoc(x, y);
129     }
130     public Point2D.Double JavaDoc eval(double t) {
131         double x = ((p1.x-2*p2.x+p3.x)*t+2*(p2.x-p1.x))*t + p1.x;
132         double y = ((p1.y-2*p2.y+p3.y)*t+2*(p2.y-p1.y))*t + p1.y;
133         return new Point2D.Double JavaDoc(x, y);
134     }
135
136     public Segment getSegment(double t0, double t1) {
137         double dt = t1-t0;
138         Point2D.Double JavaDoc np1 = eval(t0);
139         Point2D.Double JavaDoc dp1 = evalDt(t0);
140
141         Point2D.Double JavaDoc np2 = new Point2D.Double JavaDoc
142             (np1.x+.5*dt*dp1.x, np1.y+.5*dt*dp1.y);
143         
144         Point2D.Double JavaDoc np3 = eval(t1);
145         return new Quadradic(np1, np2, np3);
146     }
147
148     /**
149      * Subdivides this Quadradic curve into two curves at t = 0.5.
150      * can be done with getSegment but this is more efficent.
151      * @param q0 if non-null contains portion of curve from 0->.5
152      * @param q1 if non-null contains portion of curve from .5->1
153      */

154     public void subdivide(Quadradic q0, Quadradic q1) {
155         if ((q0 == null) && (q1 == null)) return;
156
157         double x = (p1.x-2*p2.x+p3.x)*.25+(p2.x-p1.x) + p1.x;
158         double y = (p1.y-2*p2.y+p3.y)*.25+(p2.y-p1.y) + p1.y;
159
160         double dx = (p1.x-2*p2.x+p3.x)*.25 + (p2.x-p1.x)*.5;
161         double dy = (p1.y-2*p2.y+p3.y)*.25 + (p2.y-p1.y)*.5;
162
163         if (q0 != null) {
164             q0.p1.x = p1.x;
165             q0.p1.y = p1.y;
166             q0.p2.x = x-dx;
167             q0.p2.y = y-dy;
168             q0.p3.x = x;
169             q0.p3.y = y;
170         }
171
172         if (q1 != null) {
173             q1.p1.x = x;
174             q1.p1.y = y;
175             q1.p2.x = x+dx;
176             q1.p2.y = y+dy;
177             q1.p3.x = p3.x;
178             q1.p3.y = p3.y;
179         }
180     }
181
182     /**
183      * Subdivides this Quadradic curve into two curves at given t.
184      * @param q0 if non-null contains portion of curve from 0->t.
185      * @param q1 if non-null contains portion of curve from t->1.
186      */

187     public void subdivide(double t, Quadradic q0, Quadradic q1) {
188         Point2D.Double JavaDoc np = eval(t);
189         Point2D.Double JavaDoc npd = evalDt(t);
190
191         if (q0 != null) {
192             q0.p1.x = p1.x;
193             q0.p1.y = p1.y;
194             q0.p2.x = np.x-(npd.x*t*.5);
195             q0.p2.y = np.y-(npd.y*t*.5);
196             q0.p3.x = np.x;
197             q0.p3.y = np.y;
198         }
199
200         if (q1 != null) {
201             q1.p1.x = np.x;
202             q1.p1.y = np.y;
203             q1.p2.x = np.x+(npd.x*(1-t)*.5);
204             q1.p2.y = np.y+(npd.y*(1-t)*.5);
205             q1.p3.x = p3.x;
206             q1.p3.y = p3.y;
207         }
208     }
209
210     /**
211      * Subdivides this Quadradic curve into two curves at t = 0.5.
212      * can be done with getSegment but this is more efficent.
213      * @param s0 if non-null contains portion of curve from 0->.5
214      * @param s1 if non-null contains portion of curve from .5->1
215      */

216     public void subdivide(Segment s0, Segment s1) {
217         Quadradic q0=null, q1=null;
218         if (s0 instanceof Quadradic) q0 = (Quadradic)s0;
219         if (s1 instanceof Quadradic) q1 = (Quadradic)s1;
220         subdivide(q0, q1);
221     }
222
223     /**
224      * Subdivides this Quadradic curve into two curves at t.
225      * can be done with getSegment but this is more efficent.
226      * @param s0 if non-null contains portion of curve from 0->.5
227      * @param s1 if non-null contains portion of curve from .5->1
228      */

229     public void subdivide(double t, Segment s0, Segment s1) {
230         Quadradic q0=null, q1=null;
231         if (s0 instanceof Quadradic) q0 = (Quadradic)s0;
232         if (s1 instanceof Quadradic) q1 = (Quadradic)s1;
233         subdivide(t, q0, q1);
234     }
235
236     static int count = 0;
237     protected double subLength(double leftLegLen, double rightLegLen,
238                                double maxErr) {
239         count++;
240         double dx, dy;
241         dx = p3.x-p1.x;
242         dy = p3.y-p1.y;
243         double cordLen = Math.sqrt(dx*dx+dy*dy);
244
245         double hullLen = leftLegLen+rightLegLen;
246         if (hullLen < maxErr) return (hullLen+cordLen)*.5;
247
248         double err = (hullLen-cordLen);
249         if (err < maxErr)
250             return (hullLen+cordLen)*.5;
251
252         Quadradic q = new Quadradic();
253         double x = (p1.x+2*p2.x+p3.x)*.25;
254         double y = (p1.y+2*p2.y+p3.y)*.25;
255
256         dx = .25*dx;
257         dy = .25*dy;
258         
259         q.p1.x = p1.x;
260         q.p1.y = p1.y;
261         q.p2.x = x-dx;
262         q.p2.y = y-dy;
263         q.p3.x = x;
264         q.p3.y = y;
265         
266         double midLen = .25*cordLen;
267         double len = q.subLength(leftLegLen*.5, midLen, maxErr*.5);
268
269         q.p1.x = x;
270         q.p1.y = y;
271         q.p2.x = x+dx;
272         q.p2.y = y+dy;
273         q.p3.x = p3.x;
274         q.p3.y = p3.y;
275
276         len += q.subLength(midLen, rightLegLen*.5, maxErr*.5);
277         return len;
278     }
279
280     public double getLength() {
281         return getLength(0.000001);
282     }
283
284     public double getLength(double maxErr) {
285         double dx, dy;
286         dx = p2.x-p1.x;
287         dy = p2.y-p1.y;
288         double leftLegLen = Math.sqrt(dx*dx+dy*dy);
289         dx = p3.x-p2.x;
290         dy = p3.y-p2.y;
291         double rightLegLen = Math.sqrt(dx*dx+dy*dy);
292         
293         double eps = maxErr*(leftLegLen+rightLegLen);
294
295         return subLength(leftLegLen, rightLegLen, eps);
296     }
297
298     public String JavaDoc toString() {
299         return ("M" + p1.x + "," + p1.y +
300                 "Q" + p2.x + "," + p2.y + " " +
301                 p3.x + "," + p3.y );
302     }
303
304     /*
305     public static boolean epsEq(double a, double b) {
306         final double eps = 0.00001;
307         return (((a + eps) > b) && ((a-eps) < b));
308     }
309
310     public static void sub(Quadradic orig, Quadradic curr,
311                            double t, double inc, int lev) {
312         Quadradic left=new Quadradic();
313         Quadradic right=new Quadradic();
314         curr.subdivide(left, right);
315         Point2D.Double ptl = left.eval(.5);
316         Point2D.Double ptr = right.eval(.5);
317         Point2D.Double pt1 = orig.eval(t-inc);
318         Point2D.Double pt2 = orig.eval(t+inc);
319         int steps = 100;
320         Point2D.Double l, r, o;
321         for (int i=0; i<=steps; i++) {
322             l = left.eval(i/(double)steps);
323             o = orig.eval(t-(2*inc)*(1-i/(double)steps));
324             if (!epsEq(l.x, o.x) || !epsEq(l.y, o.y))
325                 System.err.println("Lf Pt: [" + l.x + "," + l.y +
326                                    "] Orig: [" + o.x + "," + o.y +"]");
327             r = right.eval(i/(double)steps);
328             o = orig.eval(t+(2*inc*i/(double)steps));
329             if (!epsEq(r.x, o.x) || !epsEq(r.y, o.y))
330                 System.err.println("Rt Pt: [" + r.x + "," + r.y +
331                                    "] Orig: [" + o.x + "," + o.y +"]");
332         }
333         if (lev != 0) {
334             sub(orig, left, t-inc, inc/2, lev-1);
335             sub(orig, right, t+inc, inc/2, lev-1);
336         }
337     }
338
339     public static void evalQuad(Quadradic q) {
340
341         int steps = 1000000;
342         Point2D.Double oldP = q.eval(0);
343         Point2D.Double newP;
344         double len = 0;
345         for (int i=1; i<=steps; i++) {
346             newP = q.eval(i/(double)steps);
347             double dx = newP.x-oldP.x;
348             double dy = newP.y-oldP.y;
349             len += Math.sqrt(dx*dx + dy*dy);
350             oldP = newP;
351         }
352         System.err.println("Length(.1): " + q.getLength(.001) +
353                            " x " + count); count = 0;
354         System.err.println("Length : " + q.getLength() +
355                            " x " + count); count = 0;
356         System.err.println("D Len : " + len);
357     }
358
359     public static void main(String args[]) {
360         Quadradic q;
361
362         q = new Quadradic(0,0, 10,10, 30,0);
363         sub(q, q, .5, .25, 3);
364         evalQuad(q);
365
366         q = new Quadradic(0,0, 1,2, 3,0);
367         sub(q, q, .5, .25, 3);
368         evalQuad(q);
369
370         
371     }
372 */

373 }
374
Popular Tags