svn-gvsig-desktop / trunk / org.gvsig.desktop / org.gvsig.desktop.compat.cdc / org.gvsig.fmap.geometry / org.gvsig.fmap.geometry.jts / src / main / java / org / gvsig / fmap / geom / jts / primitive / curve / arc / AbstractArc.java @ 44617
History | View | Annotate | Download (13.5 KB)
1 | 42267 | fdiaz | /* gvSIG. Desktop Geographic Information System.
|
---|---|---|---|
2 | *
|
||
3 | * Copyright ? 2007-2015 gvSIG Association
|
||
4 | *
|
||
5 | * This program is free software; you can redistribute it and/or
|
||
6 | * modify it under the terms of the GNU General Public License
|
||
7 | * as published by the Free Software Foundation; either version 2
|
||
8 | * of the License, or (at your option) any later version.
|
||
9 | *
|
||
10 | * This program is distributed in the hope that it will be useful,
|
||
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
13 | * GNU General Public License for more details.
|
||
14 | *
|
||
15 | * You should have received a copy of the GNU General Public License
|
||
16 | * along with this program; if not, write to the Free Software
|
||
17 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||
18 | * MA 02110-1301, USA.
|
||
19 | *
|
||
20 | * For any additional information, do not hesitate to contact us
|
||
21 | * at info AT gvsig.com, or visit our website www.gvsig.com.
|
||
22 | */
|
||
23 | package org.gvsig.fmap.geom.jts.primitive.curve.arc; |
||
24 | |||
25 | import java.awt.Shape; |
||
26 | import java.awt.geom.AffineTransform; |
||
27 | import java.awt.geom.PathIterator; |
||
28 | |||
29 | 42464 | fdiaz | import org.cresques.cts.CoordTransRuntimeException; |
30 | 42267 | fdiaz | import org.cresques.cts.ICoordTrans; |
31 | |||
32 | import org.gvsig.fmap.geom.Geometry; |
||
33 | import org.gvsig.fmap.geom.jts.gputils.DefaultGeneralPathX; |
||
34 | import org.gvsig.fmap.geom.jts.primitive.curve.AbstractCurve; |
||
35 | import org.gvsig.fmap.geom.jts.primitive.point.PointJTS; |
||
36 | import org.gvsig.fmap.geom.jts.util.UtilFunctions; |
||
37 | 42281 | fdiaz | import org.gvsig.fmap.geom.operation.GeometryOperationException; |
38 | import org.gvsig.fmap.geom.operation.GeometryOperationNotSupportedException; |
||
39 | 42267 | fdiaz | import org.gvsig.fmap.geom.primitive.Arc; |
40 | import org.gvsig.fmap.geom.primitive.GeneralPathX; |
||
41 | 44617 | jjdelcerro | import org.gvsig.fmap.geom.primitive.OrientablePrimitive; |
42 | 42267 | fdiaz | import org.gvsig.fmap.geom.primitive.Point; |
43 | |||
44 | |||
45 | /**
|
||
46 | * @author fdiaz
|
||
47 | *
|
||
48 | */
|
||
49 | public abstract class AbstractArc extends AbstractCurve implements Arc { |
||
50 | |||
51 | /**
|
||
52 | *
|
||
53 | */
|
||
54 | private static final long serialVersionUID = 454301669807892457L; |
||
55 | |||
56 | /**
|
||
57 | * @param subtype
|
||
58 | */
|
||
59 | protected AbstractArc(int subtype) { |
||
60 | super(Geometry.TYPES.ARC, subtype);
|
||
61 | } |
||
62 | |||
63 | protected Point init; |
||
64 | |||
65 | /**
|
||
66 | * This is the middle point (belongs to the arc), not the center
|
||
67 | * of the circle/ellipse
|
||
68 | */
|
||
69 | protected Point middle; |
||
70 | protected Point end; |
||
71 | |||
72 | |||
73 | 44617 | jjdelcerro | @Override
|
74 | 42267 | fdiaz | public void setPoints(Point initialPoint, Point endPoint) { |
75 | 42271 | fdiaz | String message = "Calling deprecated method setPoints of a arc"; |
76 | notifyDeprecated(message); |
||
77 | throw new UnsupportedOperationException(message); |
||
78 | 42267 | fdiaz | } |
79 | |||
80 | 44617 | jjdelcerro | @Override
|
81 | 42267 | fdiaz | public double getCoordinateAt(int index, int dimension) { |
82 | 42271 | fdiaz | String message = "Calling deprecated method setPoints of a arc"; |
83 | notifyDeprecated(message); |
||
84 | throw new UnsupportedOperationException(message); |
||
85 | 42267 | fdiaz | } |
86 | |||
87 | 44617 | jjdelcerro | @Override
|
88 | public OrientablePrimitive setCoordinateAt(int index, int dimension, double value) { |
||
89 | 42271 | fdiaz | String message = "Calling deprecated method setPoints of a arc"; |
90 | notifyDeprecated(message); |
||
91 | throw new UnsupportedOperationException(message); |
||
92 | 42267 | fdiaz | } |
93 | |||
94 | 44617 | jjdelcerro | @Override
|
95 | public OrientablePrimitive addVertex(Point point) { |
||
96 | 42271 | fdiaz | String message = "Calling deprecated method setPoints of a arc"; |
97 | notifyDeprecated(message); |
||
98 | throw new UnsupportedOperationException(message); |
||
99 | 42267 | fdiaz | } |
100 | |||
101 | 44617 | jjdelcerro | @Override
|
102 | public OrientablePrimitive addVertex(double x, double y) { |
||
103 | 42271 | fdiaz | String message = "Calling deprecated method setPoints of a arc"; |
104 | notifyDeprecated(message); |
||
105 | throw new UnsupportedOperationException(message); |
||
106 | 42267 | fdiaz | } |
107 | |||
108 | 44617 | jjdelcerro | @Override
|
109 | public OrientablePrimitive addVertex(double x, double y, double z) { |
||
110 | 42271 | fdiaz | String message = "Calling deprecated method setPoints of a arc"; |
111 | notifyDeprecated(message); |
||
112 | throw new UnsupportedOperationException(message); |
||
113 | 42267 | fdiaz | } |
114 | |||
115 | 44617 | jjdelcerro | @Override
|
116 | 42267 | fdiaz | public void removeVertex(int index) { |
117 | 42271 | fdiaz | String message = "Calling deprecated method setPoints of a arc"; |
118 | notifyDeprecated(message); |
||
119 | throw new UnsupportedOperationException(message); |
||
120 | 42267 | fdiaz | } |
121 | |||
122 | 44617 | jjdelcerro | @Override
|
123 | 42267 | fdiaz | public Point getVertex(int index) { |
124 | 42271 | fdiaz | String message = "Calling deprecated method setPoints of a arc"; |
125 | notifyDeprecated(message); |
||
126 | throw new UnsupportedOperationException(message); |
||
127 | 42267 | fdiaz | } |
128 | |||
129 | 44617 | jjdelcerro | @Override
|
130 | 42267 | fdiaz | public int getNumVertices() { |
131 | 42271 | fdiaz | String message = "Calling deprecated method setPoints of a arc"; |
132 | notifyDeprecated(message); |
||
133 | throw new UnsupportedOperationException(message); |
||
134 | 42267 | fdiaz | } |
135 | |||
136 | 44617 | jjdelcerro | @Override
|
137 | public OrientablePrimitive insertVertex(int index, Point p) { |
||
138 | 42271 | fdiaz | String message = "Calling deprecated method setPoints of a arc"; |
139 | notifyDeprecated(message); |
||
140 | throw new UnsupportedOperationException(message); |
||
141 | 42267 | fdiaz | } |
142 | |||
143 | 44617 | jjdelcerro | @Override
|
144 | public OrientablePrimitive setVertex(int index, Point p) { |
||
145 | 42271 | fdiaz | String message = "Calling deprecated method setPoints of a arc"; |
146 | notifyDeprecated(message); |
||
147 | throw new UnsupportedOperationException(message); |
||
148 | 42267 | fdiaz | } |
149 | |||
150 | 44617 | jjdelcerro | @Override
|
151 | 42267 | fdiaz | public void setGeneralPath(GeneralPathX generalPathX) { |
152 | 42271 | fdiaz | String message = "Calling deprecated method setPoints of a arc"; |
153 | notifyDeprecated(message); |
||
154 | throw new UnsupportedOperationException(message); |
||
155 | 42267 | fdiaz | } |
156 | |||
157 | 44617 | jjdelcerro | @Override
|
158 | 42267 | fdiaz | public void addMoveToVertex(Point point) { |
159 | 42271 | fdiaz | String message = "Calling deprecated method setPoints of a arc"; |
160 | notifyDeprecated(message); |
||
161 | throw new UnsupportedOperationException(message); |
||
162 | 42267 | fdiaz | } |
163 | |||
164 | 44617 | jjdelcerro | @Override
|
165 | 42267 | fdiaz | public void closePrimitive() { |
166 | 42271 | fdiaz | String message = "Calling deprecated method setPoints of a arc"; |
167 | notifyDeprecated(message); |
||
168 | throw new UnsupportedOperationException(message); |
||
169 | 42267 | fdiaz | } |
170 | |||
171 | 44617 | jjdelcerro | @Override
|
172 | public OrientablePrimitive ensureCapacity(int capacity) { |
||
173 | 42267 | fdiaz | // TODO Auto-generated method stub
|
174 | 44617 | jjdelcerro | return this; |
175 | 42267 | fdiaz | } |
176 | |||
177 | 44617 | jjdelcerro | @Override
|
178 | 42267 | fdiaz | public void reProject(ICoordTrans ct) { |
179 | 42283 | fdiaz | //FIXME: Esto solo ser?a correcto para transformaciones de traslaci?n, rotaci?n y escala
|
180 | // Ser?a incorrecto para las de deformaci?n en cizallamiento
|
||
181 | 42267 | fdiaz | |
182 | 42464 | fdiaz | try {
|
183 | 42283 | fdiaz | init.reProject(ct); |
184 | middle.reProject(ct); |
||
185 | end.reProject(ct); |
||
186 | 43785 | jjdelcerro | this.setProjection(ct.getPDest());
|
187 | 42464 | fdiaz | } catch (CoordTransRuntimeException e){
|
188 | //Si ha fallado la reproyecci?n de alguno de los puntos, ponemos todas las coordenadas a 0
|
||
189 | init.setX(0);
|
||
190 | init.setY(0);
|
||
191 | middle.setX(0);
|
||
192 | middle.setY(0);
|
||
193 | end.setX(0);
|
||
194 | end.setY(0);
|
||
195 | } |
||
196 | 42267 | fdiaz | } |
197 | |||
198 | 44617 | jjdelcerro | @Override
|
199 | 42267 | fdiaz | public void transform(AffineTransform at) { |
200 | 42283 | fdiaz | //FIXME: Esto solo ser?a correcto para transformaciones de traslaci?n, rotaci?n y escala
|
201 | // Ser?a incorrecto para las de deformaci?n en cizallamiento
|
||
202 | 42267 | fdiaz | |
203 | 42268 | fdiaz | init.transform(at); |
204 | middle.transform(at); |
||
205 | end.transform(at); |
||
206 | 42267 | fdiaz | } |
207 | |||
208 | 44617 | jjdelcerro | @Override
|
209 | 42267 | fdiaz | public int getDimension() { |
210 | return init.getDimension();
|
||
211 | } |
||
212 | |||
213 | 44617 | jjdelcerro | @Override
|
214 | 42267 | fdiaz | public Shape getShape(AffineTransform affineTransform) { |
215 | 42268 | fdiaz | return new DefaultGeneralPathX(getPathIterator(affineTransform),false,0); |
216 | 42267 | fdiaz | } |
217 | |||
218 | 44617 | jjdelcerro | @Override
|
219 | 42267 | fdiaz | public Shape getShape() { |
220 | 42268 | fdiaz | return getShape(null); |
221 | 42267 | fdiaz | } |
222 | |||
223 | 44617 | jjdelcerro | @Override
|
224 | 42267 | fdiaz | public boolean is3D() { |
225 | return ((PointJTS)init).is3D();
|
||
226 | } |
||
227 | |||
228 | /**
|
||
229 | 44617 | jjdelcerro | * @param point
|
230 | 42267 | fdiaz | * @return
|
231 | */
|
||
232 | protected abstract Point fixPoint(Point point); |
||
233 | |||
234 | 44617 | jjdelcerro | @Override
|
235 | 42267 | fdiaz | public void setPoints(Point startPoint, Point midPoint, Point endPoint) { |
236 | init = fixPoint(startPoint); |
||
237 | middle = fixPoint(midPoint); |
||
238 | end = fixPoint(endPoint); |
||
239 | } |
||
240 | |||
241 | 44617 | jjdelcerro | @Override
|
242 | 42267 | fdiaz | public Point getInitPoint() { |
243 | return init;
|
||
244 | } |
||
245 | |||
246 | 44617 | jjdelcerro | @Override
|
247 | 42267 | fdiaz | public Point getEndPoint() { |
248 | return end;
|
||
249 | } |
||
250 | |||
251 | 44617 | jjdelcerro | @Override
|
252 | 42283 | fdiaz | public Point getMiddlePoint() { |
253 | return middle;
|
||
254 | } |
||
255 | |||
256 | 42267 | fdiaz | /**
|
257 | * Leaves the angle between PI and -PI
|
||
258 | * @param angle (radians)
|
||
259 | * @return
|
||
260 | */
|
||
261 | protected double normalizeAngle(double angle) { |
||
262 | if (angle > -Math.PI && angle <= Math.PI) { |
||
263 | return angle;
|
||
264 | } |
||
265 | |||
266 | if (angle == Double.NEGATIVE_INFINITY || angle == Double.POSITIVE_INFINITY) { |
||
267 | return 0; |
||
268 | } |
||
269 | |||
270 | double abs_ang = Math.abs(angle); |
||
271 | double remove = Math.floor(abs_ang / (2 * Math.PI)); |
||
272 | remove = remove * 2 * Math.PI; |
||
273 | double resp = 0; |
||
274 | |||
275 | if (angle > 0) { |
||
276 | resp = angle - remove; |
||
277 | if (resp > Math.PI) { |
||
278 | // final adjustment
|
||
279 | resp = resp - 2 * Math.PI; |
||
280 | } |
||
281 | } else {
|
||
282 | resp = angle + remove; |
||
283 | if (resp <= -Math.PI) { |
||
284 | // final adjustment
|
||
285 | resp = resp + 2 * Math.PI; |
||
286 | } |
||
287 | } |
||
288 | |||
289 | return resp;
|
||
290 | } |
||
291 | |||
292 | |||
293 | 44617 | jjdelcerro | @Override
|
294 | 42267 | fdiaz | public void setPointsStartExt(Point center, double radius, double startAngle, double angleExt) { |
295 | setPoints(center, radius, startAngle, angleExt); |
||
296 | } |
||
297 | |||
298 | 44617 | jjdelcerro | @Override
|
299 | 42267 | fdiaz | public void setPointsStartEnd(Point center, double radius, double startAngle, double endAngle) { |
300 | |||
301 | if (startAngle == endAngle) {
|
||
302 | setPointsStartExt(center, radius, startAngle, 0);
|
||
303 | } else {
|
||
304 | |||
305 | /*
|
||
306 | * Normalize then force clockwise:
|
||
307 | */
|
||
308 | double norm_start = normalizeAngle(startAngle);
|
||
309 | double norm_end = normalizeAngle(endAngle);
|
||
310 | double ang_ext = 0; |
||
311 | |||
312 | // clockwise
|
||
313 | // ang_ext must be positive
|
||
314 | if (norm_start >= norm_end) {
|
||
315 | ang_ext = norm_start - norm_end; |
||
316 | } else {
|
||
317 | ang_ext = 2 * Math.PI - (norm_end - norm_start); |
||
318 | } |
||
319 | 42283 | fdiaz | setPointsStartExt(center, radius, startAngle, ang_ext); |
320 | 42267 | fdiaz | |
321 | // finally call other method with ang_ext
|
||
322 | } |
||
323 | } |
||
324 | |||
325 | 44617 | jjdelcerro | @Override
|
326 | 42267 | fdiaz | public GeneralPathX getGeneralPath() {
|
327 | |||
328 | GeneralPathX gp = new DefaultGeneralPathX(getPathIterator(null, getManager().getFlatness()), is3D(), 0.0); |
||
329 | return gp;
|
||
330 | } |
||
331 | |||
332 | |||
333 | 44617 | jjdelcerro | @Override
|
334 | 42267 | fdiaz | public PathIterator getPathIterator(AffineTransform at) { |
335 | return getPathIterator(at, getManager().getFlatness());
|
||
336 | } |
||
337 | |||
338 | |||
339 | 44617 | jjdelcerro | @Override
|
340 | 42267 | fdiaz | public PathIterator getPathIterator(AffineTransform at, double flatness) { |
341 | |||
342 | java.awt.geom.Point2D.Double p1 = new java.awt.geom.Point2D.Double(init.getX(), init.getY());
|
||
343 | java.awt.geom.Point2D.Double p2 = new java.awt.geom.Point2D.Double(middle.getX(), middle.getY());
|
||
344 | java.awt.geom.Point2D.Double p3 = new java.awt.geom.Point2D.Double(end.getX(), end.getY());
|
||
345 | |||
346 | java.awt.geom.Arc2D arco = UtilFunctions.createArc(p1, p2, p3); |
||
347 | if (arco == null) { |
||
348 | logger.info("Did not set arc points (probably aligned points): " + p1.getX() + " " + p1.getY() + " :: " |
||
349 | + p2.getX() + " " + p2.getY() + " :: " + p3.getX() + " " + p3.getY()); |
||
350 | throw new IllegalArgumentException("Did not set arc points (probably aligned points)."); |
||
351 | } |
||
352 | |||
353 | return arco.getPathIterator(at, flatness);
|
||
354 | } |
||
355 | 42281 | fdiaz | |
356 | 44617 | jjdelcerro | @Override
|
357 | 42281 | fdiaz | public void flip() throws GeometryOperationNotSupportedException, GeometryOperationException { |
358 | Point aux = init;
|
||
359 | init = end; |
||
360 | end = aux; |
||
361 | } |
||
362 | 42356 | fdiaz | |
363 | |||
364 | 44617 | jjdelcerro | @Override
|
365 | 42356 | fdiaz | public double getStartAngle() throws GeometryOperationNotSupportedException, GeometryOperationException { |
366 | return getAngle(getCenterPoint(), getInitPoint());
|
||
367 | } |
||
368 | |||
369 | 44617 | jjdelcerro | @Override
|
370 | 42356 | fdiaz | public double getEndAngle() throws GeometryOperationNotSupportedException, GeometryOperationException { |
371 | return getAngle(getCenterPoint(), getEndPoint());
|
||
372 | } |
||
373 | |||
374 | private double getAngle(Point start, Point end) throws GeometryOperationNotSupportedException, GeometryOperationException { |
||
375 | double angle = Math.acos((end.getX() - start.getX()) / start.distance(end)); |
||
376 | |||
377 | if (start.getY() > end.getY()) {
|
||
378 | angle = -angle; |
||
379 | } |
||
380 | |||
381 | if (angle < 0) { |
||
382 | angle += (2 * Math.PI); |
||
383 | } |
||
384 | |||
385 | return angle;
|
||
386 | } |
||
387 | |||
388 | 42441 | fdiaz | |
389 | 44617 | jjdelcerro | @Override
|
390 | 42441 | fdiaz | public Geometry offset(double distance) throws GeometryOperationNotSupportedException, GeometryOperationException { |
391 | // TODO Auto-generated method stub
|
||
392 | Point center = getCenterPoint();
|
||
393 | double radius = center.distance(init);
|
||
394 | double scale = (radius+distance)/radius;
|
||
395 | AffineTransform at = getScaleAffineTransform(center, scale);
|
||
396 | Geometry cloned = this.cloneGeometry();
|
||
397 | cloned.transform(at); |
||
398 | return cloned;
|
||
399 | } |
||
400 | |||
401 | protected AffineTransform getScaleAffineTransform(Point center, Double scale) |
||
402 | throws GeometryOperationNotSupportedException,
|
||
403 | GeometryOperationException { |
||
404 | |||
405 | AffineTransform translate =
|
||
406 | AffineTransform
|
||
407 | .getTranslateInstance(-center.getX(), -center.getY()); |
||
408 | |||
409 | AffineTransform scaleTransform = AffineTransform.getScaleInstance(scale,scale); |
||
410 | |||
411 | AffineTransform inverseTranslate =
|
||
412 | AffineTransform.getTranslateInstance(center.getX(), center.getY());
|
||
413 | AffineTransform at = new AffineTransform(translate); |
||
414 | |||
415 | at.preConcatenate(scaleTransform); |
||
416 | at.preConcatenate(inverseTranslate); |
||
417 | return at;
|
||
418 | } |
||
419 | 43002 | fdiaz | |
420 | @Override
|
||
421 | public boolean canBeTransformed(AffineTransform at) { |
||
422 | return false; |
||
423 | } |
||
424 | |||
425 | @Override
|
||
426 | public boolean canBeReprojected(ICoordTrans ct) { |
||
427 | return false; |
||
428 | } |
||
429 | 44612 | jjdelcerro | |
430 | @Override
|
||
431 | public Geometry force2D() throws GeometryOperationNotSupportedException, GeometryOperationException { |
||
432 | Arc2D other = new Arc2D(); |
||
433 | other.setProjection(this.getProjection());
|
||
434 | Point clonedInit = (Point)init.force2D(); |
||
435 | Point clonedMiddle = (Point)middle.force2D(); |
||
436 | Point clonedEnd = (Point)end.force2D(); |
||
437 | other.setPoints(clonedInit, clonedMiddle, clonedEnd); |
||
438 | return other;
|
||
439 | } |
||
440 | |||
441 | 42267 | fdiaz | } |