Revision 1520

View differences:

branches/pilotoDWG/libraries/libFMap/src/com/iver/cit/gvsig/fmap/core/FEllipse2D.java
1
/*
2
 * Created on 08-feb-2005
3
 *
4
 * gvSIG. Sistema de Informaci?n Geogr?fica de la Generalitat Valenciana
5
 *
6
 * Copyright (C) 2004 IVER T.I. and Generalitat Valenciana.
7
 *
8
 * This program is free software; you can redistribute it and/or
9
 * modify it under the terms of the GNU General Public License
10
 * as published by the Free Software Foundation; either version 2
11
 * of the License, or (at your option) any later version.
12
 *
13
 * This program is distributed in the hope that it will be useful,
14
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
 * GNU General Public License for more details.
17
 *
18
 * You should have received a copy of the GNU General Public License
19
 * along with this program; if not, write to the Free Software
20
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,
21
   USA.
22
 *
23
 * For more information, contact:
24
 *
25
 *  Generalitat Valenciana
26
 *   Conselleria d'Infraestructures i Transport
27
 *   Av. Blasco Ib??ez, 50
28
 *   46010 VALENCIA
29
 *   SPAIN
30
 *
31
 *      +34 963862235
32
 *   gvsig@gva.es
33
 *      www.gvsig.gva.es
34
 *
35
 *    or
36
 *
37
 *   IVER T.I. S.A
38
 *   Salamanca 50
39
 *   46005 Valencia
40
 *   Spain
41
 *
42
 *   +34 963163400
43
 *   dac@iver.es
44
 */
45
package com.iver.cit.gvsig.fmap.core;
46

  
47
import com.iver.cit.gvsig.fmap.ViewPort;
48
import com.iver.cit.gvsig.fmap.core.v02.FLabel;
49
import com.iver.cit.gvsig.fmap.core.v02.FSymbol;
50
import com.iver.cit.gvsig.fmap.rendering.styling.FStyle2D;
51

  
52
import com.vividsolutions.jts.geom.Geometry;
53

  
54
import org.cresques.cts.ICoordTrans;
55

  
56
import java.awt.Graphics2D;
57
import java.awt.geom.AffineTransform;
58
import java.awt.geom.Ellipse2D;
59
import java.awt.geom.Point2D;
60
import java.awt.geom.Rectangle2D;
61

  
62

  
63
/**
64
 * DOCUMENT ME!
65
 *
66
 * @author Vicente Caballero Navarro
67
 */
68
public class FEllipse2D implements IGeometry {
69
	private Ellipse2D elipse;
70

  
71
	/**
72
	 * Crea un nuevo FEllipse2D.
73
	 */
74
	private FEllipse2D() {
75
	}
76

  
77
	/**
78
	 * Crea un nuevo FEllipse2D.
79
	 *
80
	 * @param center DOCUMENT ME!
81
	 * @param r1 DOCUMENT ME!
82
	 * @param r2 DOCUMENT ME!
83
	 */
84
	public FEllipse2D(Point2D center, double r1, double r2) {
85
		elipse = new Ellipse2D.Double(center.getX() - r1, center.getY() - r2,
86
				2 * r1, 2 * r2);
87
	}
88

  
89
	/**
90
	 * @see com.iver.cit.gvsig.fmap.core.IGeometry#draw(java.awt.Graphics2D,
91
	 * 		com.iver.cit.gvsig.fmap.ViewPort,
92
	 * 		com.iver.cit.gvsig.fmap.rendering.styling.FStyle2D)
93
	 */
94
	public void draw(Graphics2D g, ViewPort vp, FStyle2D symbol) {
95
	}
96

  
97
	/**
98
	 * @see com.iver.cit.gvsig.fmap.core.IGeometry#draw(java.awt.Graphics2D,
99
	 * 		com.iver.cit.gvsig.fmap.ViewPort,
100
	 * 		com.iver.cit.gvsig.fmap.core.v02.FSymbol)
101
	 */
102
	public void draw(Graphics2D g, ViewPort vp, FSymbol symbol) {
103
		Rectangle2D r = elipse.getBounds2D();
104
		g.setColor(symbol.getColor());
105

  
106
		GeneralPathX gp = new GeneralPathX(r);
107
		gp.transform(vp.getAffineTransform());
108
		r = gp.getBounds2D();
109

  
110
		g.draw(new Ellipse2D.Double(r.getX(), r.getY(), r.getWidth(),
111
				r.getHeight()));
112
	}
113

  
114
	/**
115
	 * @see com.iver.cit.gvsig.fmap.core.IGeometry#toJTSGeometry()
116
	 */
117
	public Geometry toJTSGeometry() {
118
		return null;
119
	}
120

  
121
	/**
122
	 * @see com.iver.cit.gvsig.fmap.core.IGeometry#createLabels(int, boolean)
123
	 */
124
	public FLabel[] createLabels(int position, boolean duplicates) {
125
		return null;
126
	}
127

  
128
	/**
129
	 * @see com.iver.cit.gvsig.fmap.core.IGeometry#getGeometryType()
130
	 */
131
	public int getGeometryType() {
132
		return 0;
133
	}
134

  
135
	/**
136
	 * @see com.iver.cit.gvsig.fmap.core.IGeometry#cloneGeometry()
137
	 */
138
	public IGeometry cloneGeometry() {
139
		FEllipse2D ret = new FEllipse2D();
140
		ret.elipse = (Ellipse2D) elipse.clone();
141

  
142
		return ret;
143
	}
144

  
145
	/**
146
	 * @see com.iver.cit.gvsig.fmap.core.IGeometry#intersects(java.awt.geom.Rectangle2D)
147
	 */
148
	public boolean intersects(Rectangle2D r) {
149
		return false;
150
	}
151

  
152
	/**
153
	 * @see com.iver.cit.gvsig.fmap.core.IGeometry#fastIntersects(double,
154
	 * 		double, double, double)
155
	 */
156
	public boolean fastIntersects(double x, double y, double w, double h) {
157
		return false;
158
	}
159

  
160
	/**
161
	 * @see com.iver.cit.gvsig.fmap.core.IGeometry#getBounds2D()
162
	 */
163
	public Rectangle2D getBounds2D() {
164
		return elipse.getBounds2D();
165
	}
166

  
167
	/**
168
	 * @see com.iver.cit.gvsig.fmap.core.IGeometry#reProject(org.cresques.cts.ICoordTrans)
169
	 */
170
	public void reProject(ICoordTrans ct) {
171
	}
172

  
173
	/**
174
	 * @see com.iver.cit.gvsig.fmap.core.IGeometry#getGeneralPathXIterator()
175
	 */
176
	public GeneralPathXIterator getGeneralPathXIterator() {
177
		return null;
178
	}
179

  
180
	/**
181
	 * @see com.iver.cit.gvsig.fmap.core.IGeometry#move(double, double)
182
	 */
183
	public void move(double x, double y) {
184
		Point2D first=new Point2D.Double();
185
		Point2D last=new Point2D.Double();
186
		first.setLocation(elipse.getMinX(),elipse.getMinY());
187
		last.setLocation(elipse.getMaxX(),elipse.getMaxY());
188
		AffineTransform at =new AffineTransform();
189
		at.translate(x,y);
190
		at.transform(first,first);
191
		at.transform(last,last);
192
		elipse=new Ellipse2D.Double(first.getX(), first.getY(),
193
				last.getX()-first.getX(),last.getY()-first.getY());
194
	}
195

  
196
	/**
197
	 * @see com.iver.cit.gvsig.fmap.core.IGeometry#rotate(double, double,
198
	 * 		double)
199
	 */
200
	public void rotate(double r, double x, double y) {
201
		AffineTransform at =new AffineTransform();
202
		at.rotate(r,x,y);
203
		//Shape shape=(Shape)at.createTransformedShape(elipse);
204
		//elipse=(Ellipse2D)shape;
205
		///girando los ejes.
206
	}
207

  
208
	/**
209
	 * @see com.iver.cit.gvsig.fmap.core.IGeometry#getHandlers()
210
	 */
211
	public Handler[] getHandlers() {
212
		Handler[] handlers = {
213
				new CenterHandler(0, elipse.getCenterX(), elipse.getCenterY()),
214
				new RightHandler(1,
215
					(elipse.getWidth() / 2) + elipse.getCenterX(),
216
					elipse.getCenterY()),
217
				new LeftHandler(2,
218
					elipse.getCenterX()-(elipse.getWidth() / 2) ,
219
					elipse.getCenterY()),
220
				new DownHandler(3,
221
					elipse.getCenterX(),
222
					elipse.getCenterY()-(elipse.getHeight()/2)),
223
				new UpHandler(4,
224
					elipse.getCenterX(),
225
					elipse.getCenterY()+(elipse.getHeight()/2))
226
			};
227

  
228
		return handlers;
229
	}
230

  
231
	/**
232
	 * DOCUMENT ME!
233
	 *
234
	 * @author Vicente Caballero Navarro
235
	 */
236
	class CenterHandler extends AbstractHandler {
237
		
238
		/**
239
		 * Crea un nuevo PointHandler.
240
		 *
241
		 * @param i DOCUMENT ME!
242
		 * @param x DOCUMENT ME!
243
		 * @param y DOCUMENT ME!
244
		 */
245
		public CenterHandler(int i, double x, double y) {
246
			point = new Point2D.Double(x, y);
247
			index = i;
248
		}
249

  
250
		/**
251
		 * DOCUMENT ME!
252
		 *
253
		 * @param x DOCUMENT ME!
254
		 * @param y DOCUMENT ME!
255
		 *
256
		 * @return DOCUMENT ME!
257
		 */
258
		public void move(double x, double y) {
259
		}
260
	}
261
	/**
262
	 * DOCUMENT ME!
263
	 *
264
	 * @author Vicente Caballero Navarro
265
	 */
266
	class RightHandler extends AbstractHandler {
267
		/**
268
		 * Crea un nuevo PointHandler.
269
		 *
270
		 * @param i DOCUMENT ME!
271
		 * @param x DOCUMENT ME!
272
		 * @param y DOCUMENT ME!
273
		 */
274
		public RightHandler(int i, double x, double y) {
275
			point = new Point2D.Double(x, y);
276
			index = i;
277
		}
278

  
279
		/**
280
		 * DOCUMENT ME!
281
		 *
282
		 * @param x DOCUMENT ME!
283
		 * @param y DOCUMENT ME!
284
		 *
285
		 * @return DOCUMENT ME!
286
		 */
287
		public void move(double x, double y) {
288
		}
289
	}
290
	/**
291
	 * DOCUMENT ME!
292
	 *
293
	 * @author Vicente Caballero Navarro
294
	 */
295
	class LeftHandler extends AbstractHandler {
296
		/**
297
		 * Crea un nuevo PointHandler.
298
		 *
299
		 * @param i DOCUMENT ME!
300
		 * @param x DOCUMENT ME!
301
		 * @param y DOCUMENT ME!
302
		 */
303
		public LeftHandler(int i, double x, double y) {
304
			point = new Point2D.Double(x, y);
305
			index = i;
306
		}
307

  
308
		/**
309
		 * DOCUMENT ME!
310
		 *
311
		 * @param x DOCUMENT ME!
312
		 * @param y DOCUMENT ME!
313
		 *
314
		 * @return DOCUMENT ME!
315
		 */
316
		public void move(double x, double y) {
317
		}
318
	}
319
	/**
320
	 * DOCUMENT ME!
321
	 *
322
	 * @author Vicente Caballero Navarro
323
	 */
324
	class DownHandler extends AbstractHandler {
325
		/**
326
		 * Crea un nuevo PointHandler.
327
		 *
328
		 * @param i DOCUMENT ME!
329
		 * @param x DOCUMENT ME!
330
		 * @param y DOCUMENT ME!
331
		 */
332
		public DownHandler(int i, double x, double y) {
333
			point = new Point2D.Double(x, y);
334
			index = i;
335
		}
336

  
337
		/**
338
		 * DOCUMENT ME!
339
		 *
340
		 * @param x DOCUMENT ME!
341
		 * @param y DOCUMENT ME!
342
		 *
343
		 * @return DOCUMENT ME!
344
		 */
345
		public void move(double x, double y) {
346
		}
347
	}
348
	/**
349
	 * DOCUMENT ME!
350
	 *
351
	 * @author Vicente Caballero Navarro
352
	 */
353
	class UpHandler extends AbstractHandler {
354
		/**
355
		 * Crea un nuevo PointHandler.
356
		 *
357
		 * @param i DOCUMENT ME!
358
		 * @param x DOCUMENT ME!
359
		 * @param y DOCUMENT ME!
360
		 */
361
		public UpHandler(int i, double x, double y) {
362
			point = new Point2D.Double(x, y);
363
			index = i;
364
		}
365

  
366
		/**
367
		 * DOCUMENT ME!
368
		 *
369
		 * @param x DOCUMENT ME!
370
		 * @param y DOCUMENT ME!
371
		 *
372
		 * @return DOCUMENT ME!
373
		 */
374
		public void move(double x, double y) {
375
		}
376
	}
377
	/**
378
	 * @see com.iver.cit.gvsig.fmap.core.IGeometry#scale(java.awt.geom.Point2D, double, double)
379
	 */
380
	public void scale(Point2D point, double x, double y) {
381
	}
382
}
branches/pilotoDWG/libraries/libFMap/src/com/iver/cit/gvsig/fmap/core/GeneralPathX.java
46 46
 */
47 47
package com.iver.cit.gvsig.fmap.core;
48 48

  
49
import org.cresques.cts.ICoordTrans;
50

  
51
import sun.awt.geom.Crossings;
52
import sun.awt.geom.Curve;
53

  
49 54
/**
50
 * @author FJP
51
 *
52 55
 */
56

  
53 57
/*
54
 * @(#)GeneralPathX.java	1.58 03/01/23
58
 * @(#)GeneralPathX.java        1.58 03/01/23
55 59
 *
56 60
 * Copyright 2003 Sun Microsystems, Inc. All rights reserved.
57 61
 * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
58 62
 */
59

  
60 63
import java.awt.Shape;
61 64
import java.awt.geom.AffineTransform;
65
import java.awt.geom.CubicCurve2D;
62 66
import java.awt.geom.FlatteningPathIterator;
63 67
import java.awt.geom.IllegalPathStateException;
68
import java.awt.geom.Line2D;
64 69
import java.awt.geom.PathIterator;
65 70
import java.awt.geom.Point2D;
71
import java.awt.geom.QuadCurve2D;
66 72
import java.awt.geom.Rectangle2D;
67 73

  
68
import org.cresques.cts.ICoordTrans;
69 74

  
70
import sun.awt.geom.Crossings;
71
import sun.awt.geom.Curve;
72

  
73 75
/**
74
 * The <code>GeneralPathX</code> class represents a geometric path 
75
 * constructed from straight lines, and quadratic and cubic
76
 * (B&eacute;zier) curves.  It can contain multiple subpaths.
76
 * The <code>GeneralPathX</code> class represents a geometric path  constructed
77
 * from straight lines, and quadratic and cubic (B&eacute;zier) curves.  It
78
 * can contain multiple subpaths.
79
 * 
77 80
 * <p>
78
 * The winding rule specifies how the interior of a path is
79
 * determined.  There are two types of winding rules:  
80
 * EVEN_ODD and NON_ZERO.
81
 * The winding rule specifies how the interior of a path is determined.  There
82
 * are two types of winding rules:   EVEN_ODD and NON_ZERO.
83
 * </p>
84
 * 
81 85
 * <p>
82
 * An EVEN_ODD winding rule means that enclosed regions
83
 * of the path alternate between interior and exterior areas as
84
 * traversed from the outside of the path towards a point inside
85
 * the region.  
86
 * An EVEN_ODD winding rule means that enclosed regions of the path alternate
87
 * between interior and exterior areas as traversed from the outside of the
88
 * path towards a point inside the region.
89
 * </p>
90
 * 
86 91
 * <p>
87
 * A NON_ZERO winding rule means that if a ray is 
88
 * drawn in any direction from a given point to infinity
89
 * and the places where the path intersects
90
 * the ray are examined, the point is inside of the path if and only if
91
 * the number of times that the path crosses the ray from
92
 * left to right does not equal the  number of times that the path crosses
93
 * the ray from right to left.  
92
 * A NON_ZERO winding rule means that if a ray is  drawn in any direction from
93
 * a given point to infinity and the places where the path intersects the ray
94
 * are examined, the point is inside of the path if and only if the number of
95
 * times that the path crosses the ray from left to right does not equal the
96
 * number of times that the path crosses the ray from right to left.
97
 * </p>
98
 *
99
 * @author Jim Graham
94 100
 * @version 1.58, 01/23/03
95
 * @author Jim Graham
96 101
 */
97 102
public class GeneralPathX implements Shape, Cloneable {
98
    /**
99
     * An even-odd winding rule for determining the interior of
100
     * a path.  
101
     */
102
    public static final int WIND_EVEN_ODD = PathIterator.WIND_EVEN_ODD;
103
	/** An even-odd winding rule for determining the interior of a path. */
104
	public static final int WIND_EVEN_ODD = PathIterator.WIND_EVEN_ODD;
103 105

  
104
    /**
105
     * A non-zero winding rule for determining the interior of a
106
     * path.  
107
     */
108
    public static final int WIND_NON_ZERO = PathIterator.WIND_NON_ZERO;
109
    
110
    // For code simplicity, copy these constants to our namespace
111
    // and cast them to byte constants for easy storage.
112
    private static final byte SEG_MOVETO  = (byte) PathIterator.SEG_MOVETO;
113
    private static final byte SEG_LINETO  = (byte) PathIterator.SEG_LINETO;
114
    private static final byte SEG_QUADTO  = (byte) PathIterator.SEG_QUADTO;
115
    private static final byte SEG_CUBICTO = (byte) PathIterator.SEG_CUBICTO;
116
    private static final byte SEG_CLOSE   = (byte) PathIterator.SEG_CLOSE;
106
	/** A non-zero winding rule for determining the interior of a path. */
107
	public static final int WIND_NON_ZERO = PathIterator.WIND_NON_ZERO;
117 108

  
118
    byte[] pointTypes;
119
    double[] pointCoords;
120
    int numTypes;
121
    int numCoords;
122
    int windingRule;
109
	// For code simplicity, copy these constants to our namespace
110
	// and cast them to byte constants for easy storage.
111
	private static final byte SEG_MOVETO = (byte) PathIterator.SEG_MOVETO;
112
	private static final byte SEG_LINETO = (byte) PathIterator.SEG_LINETO;
113
	private static final byte SEG_QUADTO = (byte) PathIterator.SEG_QUADTO;
114
	private static final byte SEG_CUBICTO = (byte) PathIterator.SEG_CUBICTO;
115
	private static final byte SEG_CLOSE = (byte) PathIterator.SEG_CLOSE;
116
	static final int INIT_SIZE = 20;
117
	static final int EXPAND_MAX = 500;
118
	byte[] pointTypes;
119
	double[] pointCoords;
120
	int numTypes;
121
	int numCoords;
122
	int windingRule;
123 123

  
124
    static final int INIT_SIZE = 20;
125
    static final int EXPAND_MAX = 500;
124
	/**
125
	 * Constructs a new <code>GeneralPathX</code> object. If an operation
126
	 * performed on this path requires the interior of the path to be defined
127
	 * then the default NON_ZERO winding rule is used.
128
	 *
129
	 * @see #WIND_NON_ZERO
130
	 */
131
	public GeneralPathX() {
132
		this(WIND_NON_ZERO, INIT_SIZE, INIT_SIZE);
133
	}
126 134

  
127
    /**
128
     * Constructs a new <code>GeneralPathX</code> object.
129
     * If an operation performed on this path requires the
130
     * interior of the path to be defined then the default NON_ZERO
131
     * winding rule is used.
132
     * @see #WIND_NON_ZERO
133
     */
134
    public GeneralPathX() {
135
	this(WIND_NON_ZERO, INIT_SIZE, INIT_SIZE);
136
    }
135
	/**
136
	 * Constructs a new <code>GeneralPathX</code> object with the specified
137
	 * winding rule to control operations that require the interior of the
138
	 * path to be defined.
139
	 *
140
	 * @param rule the winding rule
141
	 *
142
	 * @see #WIND_EVEN_ODD
143
	 * @see #WIND_NON_ZERO
144
	 */
145
	public GeneralPathX(int rule) {
146
		this(rule, INIT_SIZE, INIT_SIZE);
147
	}
137 148

  
138
    /**
139
     * Constructs a new <code>GeneralPathX</code> object with the specified 
140
     * winding rule to control operations that require the interior of the
141
     * path to be defined.
142
     * @param rule the winding rule
143
     * @see #WIND_EVEN_ODD
144
     * @see #WIND_NON_ZERO
145
     */
146
    public GeneralPathX(int rule) {
147
	this(rule, INIT_SIZE, INIT_SIZE);
148
    }
149
	/**
150
	 * Constructs a new <code>GeneralPathX</code> object with the specified
151
	 * winding rule and the specified initial capacity to store path
152
	 * coordinates. This number is an initial guess as to how many path
153
	 * segments are in the path, but the storage is expanded  as needed to
154
	 * store whatever path segments are added to this path.
155
	 *
156
	 * @param rule the winding rule
157
	 * @param initialCapacity the estimate for the number of path segments in
158
	 * 		  the path
159
	 *
160
	 * @see #WIND_EVEN_ODD
161
	 * @see #WIND_NON_ZERO
162
	 */
163
	public GeneralPathX(int rule, int initialCapacity) {
164
		this(rule, initialCapacity, initialCapacity);
165
	}
149 166

  
150
    /**
151
     * Constructs a new <code>GeneralPathX</code> object with the specified 
152
     * winding rule and the specified initial capacity to store path 
153
     * coordinates. This number is an initial guess as to how many path 
154
     * segments are in the path, but the storage is expanded 
155
     * as needed to store whatever path segments are added to this path.
156
     * @param rule the winding rule
157
     * @param initialCapacity the estimate for the number of path segments
158
     * in the path
159
     * @see #WIND_EVEN_ODD
160
     * @see #WIND_NON_ZERO
161
     */
162
    public GeneralPathX(int rule, int initialCapacity) {
163
	this(rule, initialCapacity, initialCapacity);
164
    }
167
	/**
168
	 * Constructs a new <code>GeneralPathX</code> object with the specified
169
	 * winding rule and the specified initial capacities to store point types
170
	 * and coordinates. These numbers are an initial guess as to how many path
171
	 * segments and how many points are to be in the path, but the storage is
172
	 * expanded as needed to store whatever path segments are added to this
173
	 * path.
174
	 *
175
	 * @param rule the winding rule
176
	 * @param initialTypes the estimate for the number of path segments in the
177
	 * 		  path
178
	 * @param initialCoords the estimate for the number of points
179
	 *
180
	 * @see #WIND_EVEN_ODD
181
	 * @see #WIND_NON_ZERO
182
	 */
183
	GeneralPathX(int rule, int initialTypes, int initialCoords) {
184
		setWindingRule(rule);
185
		pointTypes = new byte[initialTypes];
186
		pointCoords = new double[initialCoords * 2];
187
	}
165 188

  
166
    /**
167
     * Constructs a new <code>GeneralPathX</code> object with the specified 
168
     * winding rule and the specified initial capacities to store point types
169
     * and coordinates.
170
     * These numbers are an initial guess as to how many path segments
171
     * and how many points are to be in the path, but the
172
     * storage is expanded as needed to store whatever path segments are
173
     * added to this path.
174
     * @param rule the winding rule
175
     * @param initialTypes the estimate for the number of path segments
176
     * in the path
177
     * @param initialCapacity the estimate for the number of points
178
     * @see #WIND_EVEN_ODD
179
     * @see #WIND_NON_ZERO
180
     */
181
    GeneralPathX(int rule, int initialTypes, int initialCoords) {
182
	setWindingRule(rule);
183
	pointTypes = new byte[initialTypes];
184
	pointCoords = new double[initialCoords * 2];
185
    }
189
	/**
190
	 * Constructs a new <code>GeneralPathX</code> object from an arbitrary
191
	 * {@link Shape} object. All of the initial geometry and the winding rule
192
	 * for this path are taken from the specified <code>Shape</code> object.
193
	 *
194
	 * @param s the specified <code>Shape</code> object
195
	 */
196
	public GeneralPathX(Shape s) {
197
		this(WIND_NON_ZERO, INIT_SIZE, INIT_SIZE);
186 198

  
187
    /**
188
     * Constructs a new <code>GeneralPathX</code> object from an arbitrary 
189
     * {@link Shape} object.
190
     * All of the initial geometry and the winding rule for this path are
191
     * taken from the specified <code>Shape</code> object.
192
     * @param s the specified <code>Shape</code> object
193
     */
194
    public GeneralPathX(Shape s) {
195
	this(WIND_NON_ZERO, INIT_SIZE, INIT_SIZE);
196
	PathIterator pi = s.getPathIterator(null);
197
	setWindingRule(pi.getWindingRule());
198
	append(pi, false);
199
    }
200
 
201
    private void needRoom(int newTypes, int newCoords, boolean needMove) {
202
	if (needMove && numTypes == 0) {
203
	    throw new IllegalPathStateException("missing initial moveto "+
204
						"in path definition");
199
		PathIterator pi = s.getPathIterator(null);
200
		setWindingRule(pi.getWindingRule());
201
		append(pi, false);
205 202
	}
206
	int size = pointCoords.length;
207
	if (numCoords + newCoords > size) {
208
	    int grow = size;
209
	    if (grow > EXPAND_MAX * 2) {
210
		grow = EXPAND_MAX * 2;
211
	    }
212
	    if (grow < newCoords) {
213
		grow = newCoords;
214
	    }
215
	    double[] arr = new double[size + grow];
216
	    System.arraycopy(pointCoords, 0, arr, 0, numCoords);
217
	    pointCoords = arr;
203

  
204
	/**
205
	 * Crea un nuevo GeneralPathX.
206
	 *
207
	 * @param windingRule DOCUMENT ME!
208
	 * @param pointTypes DOCUMENT ME!
209
	 * @param numTypes DOCUMENT ME!
210
	 * @param pointCoords DOCUMENT ME!
211
	 * @param numCoords DOCUMENT ME!
212
	 */
213
	GeneralPathX(int windingRule, byte[] pointTypes, int numTypes,
214
		double[] pointCoords, int numCoords) {
215
		// used to construct from native
216
		this.windingRule = windingRule;
217
		this.pointTypes = pointTypes;
218
		this.numTypes = numTypes;
219
		this.pointCoords = pointCoords;
220
		this.numCoords = numCoords;
218 221
	}
219
	size = pointTypes.length;
220
	if (numTypes + newTypes > size) {
221
	    int grow = size;
222
	    if (grow > EXPAND_MAX) {
223
		grow = EXPAND_MAX;
224
	    }
225
	    if (grow < newTypes) {
226
		grow = newTypes;
227
	    }
228
	    byte[] arr = new byte[size + grow];
229
	    System.arraycopy(pointTypes, 0, arr, 0, numTypes);
230
	    pointTypes = arr;
222

  
223
	/**
224
	 * DOCUMENT ME!
225
	 *
226
	 * @param newTypes DOCUMENT ME!
227
	 * @param newCoords DOCUMENT ME!
228
	 * @param needMove DOCUMENT ME!
229
	 */
230
	private void needRoom(int newTypes, int newCoords, boolean needMove) {
231
		if (needMove && (numTypes == 0)) {
232
			throw new IllegalPathStateException("missing initial moveto " +
233
				"in path definition");
234
		}
235

  
236
		int size = pointCoords.length;
237

  
238
		if ((numCoords + newCoords) > size) {
239
			int grow = size;
240

  
241
			if (grow > (EXPAND_MAX * 2)) {
242
				grow = EXPAND_MAX * 2;
243
			}
244

  
245
			if (grow < newCoords) {
246
				grow = newCoords;
247
			}
248

  
249
			double[] arr = new double[size + grow];
250
			System.arraycopy(pointCoords, 0, arr, 0, numCoords);
251
			pointCoords = arr;
252
		}
253

  
254
		size = pointTypes.length;
255

  
256
		if ((numTypes + newTypes) > size) {
257
			int grow = size;
258

  
259
			if (grow > EXPAND_MAX) {
260
				grow = EXPAND_MAX;
261
			}
262

  
263
			if (grow < newTypes) {
264
				grow = newTypes;
265
			}
266

  
267
			byte[] arr = new byte[size + grow];
268
			System.arraycopy(pointTypes, 0, arr, 0, numTypes);
269
			pointTypes = arr;
270
		}
231 271
	}
232
    }
233 272

  
234
    /**
235
     * Adds a point to the path by moving to the specified
236
     * coordinates.
237
     * @param x,&nbsp;y the specified coordinates
238
     */
239
    public synchronized void moveTo(double x, double y) {
240
	if (numTypes > 0 && pointTypes[numTypes - 1] == SEG_MOVETO) {
241
	    pointCoords[numCoords - 2] = x;
242
	    pointCoords[numCoords - 1] = y;
243
	} else {
244
	    needRoom(1, 2, false);
245
	    pointTypes[numTypes++] = SEG_MOVETO;
246
	    pointCoords[numCoords++] = x;
247
	    pointCoords[numCoords++] = y;
273
	/**
274
	 * Adds a point to the path by moving to the specified coordinates.
275
	 *
276
	 * @param x the specified coordinates
277
	 * @param y DOCUMENT ME!
278
	 */
279
	public synchronized void moveTo(double x, double y) {
280
		if ((numTypes > 0) && (pointTypes[numTypes - 1] == SEG_MOVETO)) {
281
			pointCoords[numCoords - 2] = x;
282
			pointCoords[numCoords - 1] = y;
283
		} else {
284
			needRoom(1, 2, false);
285
			pointTypes[numTypes++] = SEG_MOVETO;
286
			pointCoords[numCoords++] = x;
287
			pointCoords[numCoords++] = y;
288
		}
248 289
	}
249
    }
250 290

  
251
    /**
252
     * Adds a point to the path by drawing a straight line from the
253
     * current coordinates to the new specified coordinates.
254
     * @param x,&nbsp;y the specified coordinates
255
     */
256
    public synchronized void lineTo(double x, double y) {
257
	needRoom(1, 2, true);
258
	pointTypes[numTypes++] = SEG_LINETO;
259
	pointCoords[numCoords++] = x;
260
	pointCoords[numCoords++] = y;
261
    }
291
	/**
292
	 * Adds a point to the path by drawing a straight line from the current
293
	 * coordinates to the new specified coordinates.
294
	 *
295
	 * @param x the specified coordinates
296
	 * @param y DOCUMENT ME!
297
	 */
298
	public synchronized void lineTo(double x, double y) {
299
		needRoom(1, 2, true);
300
		pointTypes[numTypes++] = SEG_LINETO;
301
		pointCoords[numCoords++] = x;
302
		pointCoords[numCoords++] = y;
303
	}
262 304

  
263
    /**
264
     * Adds a curved segment, defined by two new points, to the path by
265
     * drawing a Quadratic curve that intersects both the current
266
     * coordinates and the coordinates (x2,&nbsp;y2), using the 
267
     * specified point (x1,&nbsp;y1) as a quadratic parametric control
268
     * point.
269
     * @param x1,&nbsp;y1 the coordinates of the first quadratic control
270
     *		point
271
     * @param x2,&nbsp;y2 the coordinates of the final endpoint
272
     */
273
    public synchronized void quadTo(double x1, double y1, double x2, double y2) {
274
	needRoom(1, 4, true);
275
	pointTypes[numTypes++] = SEG_QUADTO;
276
	pointCoords[numCoords++] = x1;
277
	pointCoords[numCoords++] = y1;
278
	pointCoords[numCoords++] = x2;
279
	pointCoords[numCoords++] = y2;
280
    }
305
	/**
306
	 * Adds a curved segment, defined by two new points, to the path by drawing
307
	 * a Quadratic curve that intersects both the current coordinates and the
308
	 * coordinates (x2,&nbsp;y2), using the  specified point (x1,&nbsp;y1) as
309
	 * a quadratic parametric control point.
310
	 *
311
	 * @param x1 the coordinates of the first quadratic control point
312
	 * @param y1 the coordinates of the final endpoint
313
	 * @param x2 DOCUMENT ME!
314
	 * @param y2 DOCUMENT ME!
315
	 */
316
	public synchronized void quadTo(double x1, double y1, double x2, double y2) {
317
		needRoom(1, 4, true);
318
		pointTypes[numTypes++] = SEG_QUADTO;
319
		pointCoords[numCoords++] = x1;
320
		pointCoords[numCoords++] = y1;
321
		pointCoords[numCoords++] = x2;
322
		pointCoords[numCoords++] = y2;
323
	}
281 324

  
282
    /**
283
     * Adds a curved segment, defined by three new points, to the path by
284
     * drawing a B&eacute;zier curve that intersects both the current
285
     * coordinates and the coordinates (x3,&nbsp;y3), using the    
286
     * specified points (x1,&nbsp;y1) and (x2,&nbsp;y2) as
287
     * B&eacute;zier control points.
288
     * @param x1,&nbsp;y1 the coordinates of the first B&eacute;ezier
289
     *		control point
290
     * @param x2,&nbsp;y2 the coordinates of the second B&eacute;zier
291
     *		control point
292
     * @param x3,&nbsp;y3 the coordinates of the final endpoint
293
     */
294
    public synchronized void curveTo(double x1, double y1,
295
    		double x2, double y2,
296
    		double x3, double y3) {
297
	needRoom(1, 6, true);
298
	pointTypes[numTypes++] = SEG_CUBICTO;
299
	pointCoords[numCoords++] = x1;
300
	pointCoords[numCoords++] = y1;
301
	pointCoords[numCoords++] = x2;
302
	pointCoords[numCoords++] = y2;
303
	pointCoords[numCoords++] = x3;
304
	pointCoords[numCoords++] = y3;
305
    }
325
	/**
326
	 * Adds a curved segment, defined by three new points, to the path by
327
	 * drawing a B&eacute;zier curve that intersects both the current
328
	 * coordinates and the coordinates (x3,&nbsp;y3), using the     specified
329
	 * points (x1,&nbsp;y1) and (x2,&nbsp;y2) as B&eacute;zier control points.
330
	 *
331
	 * @param x1 the coordinates of the first B&eacute;ezier control point
332
	 * @param y1 the coordinates of the second B&eacute;zier control point
333
	 * @param x2 the coordinates of the final endpoint
334
	 * @param y2 DOCUMENT ME!
335
	 * @param x3 DOCUMENT ME!
336
	 * @param y3 DOCUMENT ME!
337
	 */
338
	public synchronized void curveTo(double x1, double y1, double x2,
339
		double y2, double x3, double y3) {
340
		needRoom(1, 6, true);
341
		pointTypes[numTypes++] = SEG_CUBICTO;
342
		pointCoords[numCoords++] = x1;
343
		pointCoords[numCoords++] = y1;
344
		pointCoords[numCoords++] = x2;
345
		pointCoords[numCoords++] = y2;
346
		pointCoords[numCoords++] = x3;
347
		pointCoords[numCoords++] = y3;
348
	}
306 349

  
307
    /**
308
     * Closes the current subpath by drawing a straight line back to
309
     * the coordinates of the last <code>moveTo</code>.  If the path is already
310
     * closed then this method has no effect.
311
     */
312
    public synchronized void closePath() {
313
	if (numTypes == 0 || pointTypes[numTypes - 1] != SEG_CLOSE) {
314
	    needRoom(1, 0, true);
315
	    pointTypes[numTypes++] = SEG_CLOSE;
350
	/**
351
	 * Closes the current subpath by drawing a straight line back to the
352
	 * coordinates of the last <code>moveTo</code>.  If the path is already
353
	 * closed then this method has no effect.
354
	 */
355
	public synchronized void closePath() {
356
		if ((numTypes == 0) || (pointTypes[numTypes - 1] != SEG_CLOSE)) {
357
			needRoom(1, 0, true);
358
			pointTypes[numTypes++] = SEG_CLOSE;
359
		}
316 360
	}
317
    }
318 361

  
319
    /**
320
     * Appends the geometry of the specified <code>Shape</code> object to the
321
     * path, possibly connecting the new geometry to the existing path
322
     * segments with a line segment.
323
     * If the <code>connect</code> parameter is <code>true</code> and the 
324
     * path is not empty then any initial <code>moveTo</code> in the
325
     * geometry of the appended <code>Shape</code>
326
     * is turned into a <code>lineTo</code> segment.
327
     * If the destination coordinates of such a connecting <code>lineTo</code>
328
     * segment match the ending coordinates of a currently open
329
     * subpath then the segment is omitted as superfluous.
330
     * The winding rule of the specified <code>Shape</code> is ignored
331
     * and the appended geometry is governed by the winding
332
     * rule specified for this path.
333
     * @param s the <code>Shape</code> whose geometry is appended 
334
     * to this path
335
     * @param connect a boolean to control whether or not to turn an
336
     * initial <code>moveTo</code> segment into a <code>lineTo</code>
337
     * segment to connect the new geometry to the existing path
338
     */
339
    public void append(Shape s, boolean connect) {
340
	PathIterator pi = s.getPathIterator(null);
341
        append(pi,connect);
342
    }
362
	/**
363
	 * Appends the geometry of the specified <code>Shape</code> object to the
364
	 * path, possibly connecting the new geometry to the existing path
365
	 * segments with a line segment. If the <code>connect</code> parameter is
366
	 * <code>true</code> and the  path is not empty then any initial
367
	 * <code>moveTo</code> in the geometry of the appended <code>Shape</code>
368
	 * is turned into a <code>lineTo</code> segment. If the destination
369
	 * coordinates of such a connecting <code>lineTo</code> segment match the
370
	 * ending coordinates of a currently open subpath then the segment is
371
	 * omitted as superfluous. The winding rule of the specified
372
	 * <code>Shape</code> is ignored and the appended geometry is governed by
373
	 * the winding rule specified for this path.
374
	 *
375
	 * @param s the <code>Shape</code> whose geometry is appended  to this path
376
	 * @param connect a boolean to control whether or not to turn an initial
377
	 * 		  <code>moveTo</code> segment into a <code>lineTo</code> segment
378
	 * 		  to connect the new geometry to the existing path
379
	 */
380
	public void append(Shape s, boolean connect) {
381
		PathIterator pi = s.getPathIterator(null);
382
		append(pi, connect);
383
	}
343 384

  
344
    /**
345
     * Appends the geometry of the specified
346
     * {@link PathIterator} object 
347
     * to the path, possibly connecting the new geometry to the existing
348
     * path segments with a line segment.
349
     * If the <code>connect</code> parameter is <code>true</code> and the 
350
     * path is not empty then any initial <code>moveTo</code> in the
351
     * geometry of the appended <code>Shape</code> is turned into a
352
     * <code>lineTo</code> segment.
353
     * If the destination coordinates of such a connecting <code>lineTo</code>
354
     * segment match the ending coordinates of a currently open
355
     * subpath then the segment is omitted as superfluous.
356
     * The winding rule of the specified <code>Shape</code> is ignored
357
     * and the appended geometry is governed by the winding
358
     * rule specified for this path.
359
     * @param pi the <code>PathIterator</code> whose geometry is appended to 
360
     * this path
361
     * @param connect a boolean to control whether or not to turn an
362
     * initial <code>moveTo</code> segment into a <code>lineTo</code> segment
363
     * to connect the new geometry to the existing path
364
     */
365
    public void append(PathIterator pi, boolean connect) {
366
	double coords[] = new double[6];
367
	while (!pi.isDone()) {
368
	    switch (pi.currentSegment(coords)) {
369
	    case SEG_MOVETO:
370
		if (!connect || numTypes < 1 || numCoords < 2) {
371
		    moveTo(coords[0], coords[1]);
372
		    break;
385
	/**
386
	 * Appends the geometry of the specified {@link PathIterator} object  to
387
	 * the path, possibly connecting the new geometry to the existing path
388
	 * segments with a line segment. If the <code>connect</code> parameter is
389
	 * <code>true</code> and the  path is not empty then any initial
390
	 * <code>moveTo</code> in the geometry of the appended <code>Shape</code>
391
	 * is turned into a <code>lineTo</code> segment. If the destination
392
	 * coordinates of such a connecting <code>lineTo</code> segment match the
393
	 * ending coordinates of a currently open subpath then the segment is
394
	 * omitted as superfluous. The winding rule of the specified
395
	 * <code>Shape</code> is ignored and the appended geometry is governed by
396
	 * the winding rule specified for this path.
397
	 *
398
	 * @param pi the <code>PathIterator</code> whose geometry is appended to
399
	 * 		  this path
400
	 * @param connect a boolean to control whether or not to turn an initial
401
	 * 		  <code>moveTo</code> segment into a <code>lineTo</code> segment
402
	 * 		  to connect the new geometry to the existing path
403
	 */
404
	public void append(PathIterator pi, boolean connect) {
405
		double[] coords = new double[6];
406

  
407
		while (!pi.isDone()) {
408
			switch (pi.currentSegment(coords)) {
409
				case SEG_MOVETO:
410

  
411
					if (!connect || (numTypes < 1) || (numCoords < 2)) {
412
						moveTo(coords[0], coords[1]);
413

  
414
						break;
415
					}
416

  
417
					if ((pointTypes[numTypes - 1] != SEG_CLOSE) &&
418
							(pointCoords[numCoords - 2] == coords[0]) &&
419
							(pointCoords[numCoords - 1] == coords[1])) {
420
						// Collapse out initial moveto/lineto
421
						break;
422
					}
423

  
424
				// NO BREAK;
425
				case SEG_LINETO:
426
					lineTo(coords[0], coords[1]);
427

  
428
					break;
429

  
430
				case SEG_QUADTO:
431
					quadTo(coords[0], coords[1], coords[2], coords[3]);
432

  
433
					break;
434

  
435
				case SEG_CUBICTO:
436
					curveTo(coords[0], coords[1], coords[2], coords[3],
437
						coords[4], coords[5]);
438

  
439
					break;
440

  
441
				case SEG_CLOSE:
442
					closePath();
443

  
444
					break;
445
			}
446

  
447
			pi.next();
448
			connect = false;
373 449
		}
374
		if (pointTypes[numTypes - 1] != SEG_CLOSE &&
375
		    pointCoords[numCoords - 2] == coords[0] &&
376
		    pointCoords[numCoords - 1] == coords[1])
377
		{
378
		    // Collapse out initial moveto/lineto
379
		    break;
450
	}
451

  
452
	/**
453
	 * Returns the fill style winding rule.
454
	 *
455
	 * @return an integer representing the current winding rule.
456
	 *
457
	 * @see #WIND_EVEN_ODD
458
	 * @see #WIND_NON_ZERO
459
	 * @see #setWindingRule
460
	 */
461
	public synchronized int getWindingRule() {
462
		return windingRule;
463
	}
464

  
465
	/**
466
	 * Sets the winding rule for this path to the specified value.
467
	 *
468
	 * @param rule an integer representing the specified  winding rule
469
	 *
470
	 * @exception IllegalArgumentExceptionIllegalArgumentException </code> if
471
	 * 			  <code>rule</code> is not either  <code>WIND_EVEN_ODD</code>
472
	 * 			  or <code>WIND_NON_ZERO</code>
473
	 *
474
	 * @see #WIND_EVEN_ODD
475
	 * @see #WIND_NON_ZERO
476
	 * @see #getWindingRule
477
	 */
478
	public void setWindingRule(int rule) {
479
		if ((rule != WIND_EVEN_ODD) && (rule != WIND_NON_ZERO)) {
480
			throw new IllegalArgumentException("winding rule must be " +
481
				"WIND_EVEN_ODD or " + "WIND_NON_ZERO");
380 482
		}
381
		// NO BREAK;
382
	    case SEG_LINETO:
383
		lineTo(coords[0], coords[1]);
384
		break;
385
	    case SEG_QUADTO:
386
		quadTo(coords[0], coords[1],
387
		       coords[2], coords[3]);
388
		break;
389
	    case SEG_CUBICTO:
390
		curveTo(coords[0], coords[1],
391
			coords[2], coords[3],
392
			coords[4], coords[5]);
393
		break;
394
	    case SEG_CLOSE:
395
		closePath();
396
		break;
397
	    }
398
	    pi.next();
399
	    connect = false;
483

  
484
		windingRule = rule;
400 485
	}
401
    }
402 486

  
403
    /**
404
     * Returns the fill style winding rule.
405
     * @return an integer representing the current winding rule.
406
     * @see #WIND_EVEN_ODD  
407
     * @see #WIND_NON_ZERO
408
     * @see #setWindingRule
409
     */
410
    public synchronized int getWindingRule() {
411
        return windingRule;
412
    }
487
	/**
488
	 * Returns the coordinates most recently added to the end of the path as a
489
	 * {@link Point2D} object.
490
	 *
491
	 * @return a <code>Point2D</code> object containing the ending  coordinates
492
	 * 		   of the path or <code>null</code> if there are no points in the
493
	 * 		   path.
494
	 */
495
	public synchronized Point2D getCurrentPoint() {
496
		if ((numTypes < 1) || (numCoords < 2)) {
497
			return null;
498
		}
413 499

  
414
    /**
415
     * Sets the winding rule for this path to the specified value.
416
     * @param rule an integer representing the specified 
417
     * winding rule
418
     * @exception <code>IllegalArgumentException</code> if 
419
     *		<code>rule</code> is not either 
420
     *		<code>WIND_EVEN_ODD</code> or
421
     *		<code>WIND_NON_ZERO</code>
422
     * @see #WIND_EVEN_ODD  
423
     * @see #WIND_NON_ZERO
424
     * @see #getWindingRule
425
     */
426
    public void setWindingRule(int rule) {
427
	if (rule != WIND_EVEN_ODD && rule != WIND_NON_ZERO) {
428
	    throw new IllegalArgumentException("winding rule must be "+
429
					       "WIND_EVEN_ODD or "+
430
					       "WIND_NON_ZERO");
500
		int index = numCoords;
501

  
502
		if (pointTypes[numTypes - 1] == SEG_CLOSE) {
503
loop: 
504
			for (int i = numTypes - 2; i > 0; i--) {
505
				switch (pointTypes[i]) {
506
					case SEG_MOVETO:
507
						break loop;
508

  
509
					case SEG_LINETO:
510
						index -= 2;
511

  
512
						break;
513

  
514
					case SEG_QUADTO:
515
						index -= 4;
516

  
517
						break;
518

  
519
					case SEG_CUBICTO:
520
						index -= 6;
521

  
522
						break;
523

  
524
					case SEG_CLOSE:
525
						break;
526
				}
527
			}
528
		}
529

  
530
		return new Point2D.Double(pointCoords[index - 2], pointCoords[index -
531
			1]);
431 532
	}
432
	windingRule = rule;
433
    }
434 533

  
435
    /**
436
     * Returns the coordinates most recently added to the end of the path
437
     * as a {@link Point2D} object.
438
     * @return a <code>Point2D</code> object containing the ending 
439
     * coordinates of the path or <code>null</code> if there are no points
440
     * in the path.
441
     */
442
    public synchronized Point2D getCurrentPoint() {
443
	if (numTypes < 1 || numCoords < 2) {
444
	    return null;
534
	/**
535
	 * Resets the path to empty.  The append position is set back to the
536
	 * beginning of the path and all coordinates and point types are
537
	 * forgotten.
538
	 */
539
	public synchronized void reset() {
540
		numTypes = numCoords = 0;
445 541
	}
446
	int index = numCoords;
447
	if (pointTypes[numTypes - 1] == SEG_CLOSE) {
448
	loop:
449
	    for (int i = numTypes - 2; i > 0; i--) {
450
		switch (pointTypes[i]) {
451
		case SEG_MOVETO:
452
		    break loop;
453
		case SEG_LINETO:
454
		    index -= 2;
455
		    break;
456
		case SEG_QUADTO:
457
		    index -= 4;
458
		    break;
459
		case SEG_CUBICTO:
460
		    index -= 6;
461
		    break;
462
		case SEG_CLOSE:
463
		    break;
542

  
543
	/**
544
	 * Transforms the geometry of this path using the specified  {@link
545
	 * AffineTransform}. The geometry is transformed in place, which
546
	 * permanently changes the boundary defined by this object.
547
	 *
548
	 * @param at the <code>AffineTransform</code> used to transform the area
549
	 */
550
	public void transform(AffineTransform at) {
551
		at.transform(pointCoords, 0, pointCoords, 0, numCoords / 2);
552
	}
553

  
554
	/**
555
	 * DOCUMENT ME!
556
	 *
557
	 * @param ct DOCUMENT ME!
558
	 */
559
	public void reProject(ICoordTrans ct) {
560
		Point2D pt = new Point2D.Double();
561

  
562
		for (int i = 0; i < numCoords; i += 2) {
563
			pt.setLocation(pointCoords[i], pointCoords[i + 1]);
564
			pt = ct.convert(pt, null);
565
			pointCoords[i] = pt.getX();
566
			pointCoords[i + 1] = pt.getY();
464 567
		}
465
	    }
466 568
	}
467
	return new Point2D.Double(pointCoords[index - 2],
468
				 pointCoords[index - 1]);
469
    }
470 569

  
471
    /**
472
     * Resets the path to empty.  The append position is set back to the
473
     * beginning of the path and all coordinates and point types are
474
     * forgotten.
475
     */
476
    public synchronized void reset() {
477
	numTypes = numCoords = 0;
478
    }
570
	/**
571
	 * Returns a new transformed <code>Shape</code>.
572
	 *
573
	 * @param at the <code>AffineTransform</code> used to transform a  new
574
	 * 		  <code>Shape</code>.
575
	 *
576
	 * @return a new <code>Shape</code>, transformed with the specified
577
	 * 		   <code>AffineTransform</code>.
578
	 */
579
	public synchronized Shape createTransformedShape(AffineTransform at) {
580
		GeneralPathX gp = (GeneralPathX) clone();
479 581

  
480
    /**
481
     * Transforms the geometry of this path using the specified 
482
     * {@link AffineTransform}.
483
     * The geometry is transformed in place, which permanently changes the
484
     * boundary defined by this object.
485
     * @param at the <code>AffineTransform</code> used to transform the area
486
     */
487
    public void transform(AffineTransform at) {
488
	at.transform(pointCoords, 0, pointCoords, 0, numCoords / 2);
489
    }
490
    
491
    public void reProject(ICoordTrans ct)
492
    {
493
    	Point2D pt = new Point2D.Double();
494
    	for (int i = 0; i < numCoords; i+=2)
495
    	{
496
    		pt.setLocation(pointCoords[i], pointCoords[i+1]);
497
    		pt = ct.convert(pt,null);
498
    		pointCoords[i] = pt.getX();
499
    		pointCoords[i+1] = pt.getY();
500
    	}
501
    	
502
    }
582
		if (at != null) {
583
			gp.transform(at);
584
		}
503 585

  
504
    /**
505
     * Returns a new transformed <code>Shape</code>.
506
     * @param at the <code>AffineTransform</code> used to transform a 
507
     * new <code>Shape</code>.
508
     * @return a new <code>Shape</code>, transformed with the specified 
509
     * <code>AffineTransform</code>.
510
     */
511
    public synchronized Shape createTransformedShape(AffineTransform at) {
512
	GeneralPathX gp = (GeneralPathX) clone();
513
	if (at != null) {
514
	    gp.transform(at);
586
		return gp;
515 587
	}
516
	return gp;
517
    }
518 588

  
519
    /**
520
     * Return the bounding box of the path.
521
     * @return a {@link java.awt.Rectangle} object that
522
     * bounds the current path.
523
     */
524
    public java.awt.Rectangle getBounds() {
525
	return getBounds2D().getBounds();
526
    }
589
	/**
590
	 * Return the bounding box of the path.
591
	 *
592
	 * @return a {@link java.awt.Rectangle} object that bounds the current
593
	 * 		   path.
594
	 */
595
	public java.awt.Rectangle getBounds() {
596
		return getBounds2D().getBounds();
597
	}
527 598

  
528
    /**
529
     * Returns the bounding box of the path.
530
     * @return a {@link Rectangle2D} object that
531
     *          bounds the current path.
532
     */
533
    public synchronized Rectangle2D getBounds2D() {
534
	double x1, y1, x2, y2;
535
	int i = numCoords;
536
	if (i > 0) {
537
	    y1 = y2 = pointCoords[--i];
538
	    x1 = x2 = pointCoords[--i];
539
	    while (i > 0) {
540
		double y = pointCoords[--i];
541
		double x = pointCoords[--i];
542
		if (x < x1) x1 = x;
543
		if (y < y1) y1 = y;
544
		if (x > x2) x2 = x;
545
		if (y > y2) y2 = y;
546
	    }
547
	} else {
548
	    x1 = y1 = x2 = y2 = 0.0f;
599
	/**
600
	 * Returns the bounding box of the path.
601
	 *
602
	 * @return a {@link Rectangle2D} object that bounds the current path.
603
	 */
604
	public synchronized Rectangle2D getBounds2D() {
605
		double x1;
606
		double y1;
607
		double x2;
608
		double y2;
609
		int i = numCoords;
610

  
611
		if (i > 0) {
612
			y1 = y2 = pointCoords[--i];
613
			x1 = x2 = pointCoords[--i];
614

  
615
			while (i > 0) {
616
				double y = pointCoords[--i];
617
				double x = pointCoords[--i];
618

  
619
				if (x < x1) {
620
					x1 = x;
621
				}
622

  
623
				if (y < y1) {
624
					y1 = y;
625
				}
626

  
627
				if (x > x2) {
628
					x2 = x;
629
				}
630

  
631
				if (y > y2) {
632
					y2 = y;
633
				}
634
			}
635
		} else {
636
			x1 = y1 = x2 = y2 = 0.0f;
637
		}
638

  
639
		return new Rectangle2D.Double(x1, y1, x2 - x1, y2 - y1);
549 640
	}
550
	return new Rectangle2D.Double(x1, y1, x2 - x1, y2 - y1);
551
    }
552 641

  
553
    /**
554
     * Tests if the specified coordinates are inside the boundary of 
555
     * this <code>Shape</code>.
556
     * @param x,&nbsp;y the specified coordinates
557
     * @return <code>true</code> if the specified coordinates are inside this 
558
     * <code>Shape</code>; <code>false</code> otherwise
559
     */
560
    public boolean contains(double x, double y) {
561
	if (numTypes < 2) {
562
	    return false;
642
	/**
643
	 * Tests if the specified coordinates are inside the boundary of  this
644
	 * <code>Shape</code>.
645
	 *
646
	 * @param x the specified coordinates
647
	 * @param y DOCUMENT ME!
648
	 *
649
	 * @return <code>true</code> if the specified coordinates are inside this
650
	 * 		   <code>Shape</code>; <code>false</code> otherwise
651
	 */
652
	public boolean contains(double x, double y) {
653
		if (numTypes < 2) {
654
			return false;
655
		}
656

  
657
		int cross = Curve.crossingsForPath(getPathIterator(null), x, y);
658

  
659
		if (windingRule == WIND_NON_ZERO) {
660
			return (cross != 0);
661
		} else {
662
			return ((cross & 1) != 0);
663
		}
563 664
	}
564
	int cross = Curve.crossingsForPath(getPathIterator(null), x, y);
565
	if (windingRule == WIND_NON_ZERO) {
566
	    return (cross != 0);
567
	} else {
568
	    return ((cross & 1) != 0);
665

  
666
	/**
667
	 * Tests if the specified <code>Point2D</code> is inside the boundary of
668
	 * this <code>Shape</code>.
669
	 *
670
	 * @param p the specified <code>Point2D</code>
671
	 *
672
	 * @return <code>true</code> if this <code>Shape</code> contains the
673
	 * 		   specified <code>Point2D</code>, <code>false</code> otherwise.
674
	 */
675
	public boolean contains(Point2D p) {
676
		return contains(p.getX(), p.getY());
569 677
	}
570
    }
571 678

  
572
    /**
573
     * Tests if the specified <code>Point2D</code> is inside the boundary
574
     * of this <code>Shape</code>.
575
     * @param p the specified <code>Point2D</code>
576
     * @return <code>true</code> if this <code>Shape</code> contains the 
577
     * specified <code>Point2D</code>, <code>false</code> otherwise.
578
     */
579
    public boolean contains(Point2D p) {
580
	return contains(p.getX(), p.getY());
581
    }
679
	/**
680
	 * Tests if the specified rectangular area is inside the boundary of this
681
	 * <code>Shape</code>.
682
	 *
683
	 * @param x the specified coordinates
684
	 * @param y DOCUMENT ME!
685
	 * @param w the width of the specified rectangular area
... This diff was truncated because it exceeds the maximum size that can be displayed.

Also available in: Unified diff