source: osm/applications/editors/josm/plugins/opendata/includes/org/geotools/resources/geometry/ShapeUtilities.java@ 28000

Last change on this file since 28000 was 28000, checked in by donvip, 12 years ago

Import new "opendata" JOSM plugin

File size: 8.5 KB
Line 
1/*
2 * GeoTools - The Open Source Java GIS Toolkit
3 * http://geotools.org
4 *
5 * (C) 2001-2008, Open Source Geospatial Foundation (OSGeo)
6 *
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation;
10 * version 2.1 of the License.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 */
17package org.geotools.resources.geometry;
18
19import static java.lang.Math.abs;
20import static java.lang.Math.hypot;
21
22import java.awt.Shape;
23import java.awt.geom.CubicCurve2D;
24import java.awt.geom.GeneralPath;
25import java.awt.geom.Line2D;
26import java.awt.geom.PathIterator;
27import java.awt.geom.Point2D;
28import java.awt.geom.QuadCurve2D;
29
30
31/**
32 * Static utilities methods. Those methods operate on geometric
33 * shapes from the {@code java.awt.geom} package.
34 *
35 * @since 2.0
36 *
37 * @source $URL: http://svn.osgeo.org/geotools/branches/2.7.x/modules/library/referencing/src/main/java/org/geotools/resources/geometry/ShapeUtilities.java $
38 * @version $Id: ShapeUtilities.java 37299 2011-05-25 05:21:24Z mbedward $
39 * @author Martin Desruisseaux (IRD)
40 */
41public final class ShapeUtilities {
42 /**
43 * Valeur limite pour détecter si des points sont
44 * colinéaires ou si des coordonnées sont identiques.
45 */
46 private static final double EPS = 1E-6;
47
48 /**
49 * Constante pour les calculs de paraboles. Cette constante indique que l'axe des
50 * <var>x</var> de la parabole doit être parallèle à la droite joignant les points
51 * P0 et P2.
52 */
53 public static final int PARALLEL = 0;
54
55 /**
56 * Constante pour les calculs de paraboles. Cette constante indique que l'axe des
57 * <var>x</var> de la parabole doit être horizontale, quelle que soit la pente de
58 * la droite joignant les points P0 et P2.
59 */
60 public static final int HORIZONTAL = 1;
61
62 /**
63 * Interdit la création d'objets de cette classe.
64 */
65 private ShapeUtilities() {
66 }
67
68 /**
69 * Retourne le point de contrôle d'une courbe quadratique passant par les trois points spécifiés.
70 * Il peut exister une infinité de courbes quadratiques passant par trois points. On peut voir
71 * les choses en disant qu'une courbe quadratique correspond à une parabole produite par une
72 * équation de la forme <code>y=ax²+bx+c</code>, mais que l'axe des <var>x</var> de cette
73 * équation n'est pas nécessairement horizontal. La direction de cet axe des <var>x</var> dépend
74 * du paramètre {@code orientation} spécifié à cette méthode. La valeur {@link #HORIZONTAL}
75 * signifie que l'axe des <var>x</var> de la parabole sera toujours horizontal. La courbe
76 * quadratique produite ressemblera alors à une parabole classique telle qu'on en voit dans les
77 * ouvrages de mathématiques élémentaires. La valeur {@link #PARALLEL} indique plutôt que l'axe
78 * des <var>x</var> de la parabole doit être parallèle à la droite joignant les points
79 * {@code (x0,y0)} et {@code (x2,y2)}. Ce dernier type produira le même résultat que
80 * {@link #HORIZONTAL} si {@code y0==y2}.
81 *
82 * @param x0 <var>x</var> value of the first point.
83 * @param y0 <var>y</var> value of the first point.
84 * @param x1 <var>x</var> value of the second point.
85 * @param y1 <var>y</var> value of the second point.
86 * @param x2 <var>x</var> value of the third point.
87 * @param y2 <var>y</var> value of the third point.
88 * @param orientation Orientation de l'axe des <var>x</var> de la parabole: {@link #PARALLEL}
89 * ou {@link #HORIZONTAL}.
90 * @param dest Where to store the control point.
91 * @return Le point de contrôle d'une courbe quadratique passant par les trois points spécifiés.
92 * La courbe commencera au point {@code (x0,y0)} et se terminera au point {@code (x2,y2)}.
93 * Si deux points ont des coordonnées presque identiques, ou si les trois points sont
94 * colinéaires, alors cette méthode retourne {@code null}.
95 * @throws IllegalArgumentException si l'argument {@code orientation} n'est pas une des
96 * constantes valides.
97 */
98 public static Point2D parabolicControlPoint(final double x0, final double y0,
99 double x1, double y1,
100 double x2, double y2,
101 final int orientation, final Point2D dest)
102 throws IllegalArgumentException
103 {
104 /*
105 * Applique une translation de façon à ce que (x0,y0)
106 * devienne l'origine du système d'axes. Il ne faudra
107 * plus utiliser (x0,y0) avant la fin de ce code.
108 */
109 x1 -= x0;
110 y1 -= y0;
111 x2 -= x0;
112 y2 -= y0;
113 switch (orientation) {
114 case PARALLEL: {
115 /*
116 * Applique une rotation de façon à ce que (x2,y2)
117 * tombe sur l'axe des x, c'est-à-dire que y2=0.
118 */
119 final double rx2 = x2;
120 final double ry2 = y2;
121 x2 = hypot(x2,y2);
122 y2 = (x1*rx2 + y1*ry2) / x2; // use 'y2' as a temporary variable for 'x1'
123 y1 = (y1*rx2 - x1*ry2) / x2;
124 x1 = y2;
125 y2 = 0;
126 /*
127 * Calcule maintenant les coordonnées du point
128 * de contrôle selon le nouveau système d'axes.
129 */
130 final double x = 0.5; // Really "x/x2"
131 final double y = (y1*x*x2) / (x1*(x2-x1)); // Really "y/y2"
132 final double check = abs(y);
133 if (!(check <= 1/EPS)) return null; // Deux points ont les mêmes coordonnées.
134 if (!(check >= EPS)) return null; // Les trois points sont colinéaires.
135 /*
136 * Applique une rotation inverse puis une translation pour
137 * ramener le système d'axe dans sa position d'origine.
138 */
139 x1 = (x*rx2 - y*ry2) + x0;
140 y1 = (y*rx2 + x*ry2) + y0;
141 break;
142 }
143 case HORIZONTAL: {
144 final double a = (y2 - y1*x2/x1) / (x2-x1); // Really "a*x2"
145 final double check = abs(a);
146 if (!(check <= 1/EPS)) return null; // Deux points ont les mêmes coordonnées.
147 if (!(check >= EPS)) return null; // Les trois points sont colinéaires.
148 final double b = y2/x2 - a;
149 x1 = (1 + b/(2*a))*x2 - y2/(2*a);
150 y1 = y0 + b*x1;
151 x1 += x0;
152 break;
153 }
154 default: throw new IllegalArgumentException();
155 }
156 if (dest != null) {
157 dest.setLocation(x1,y1);
158 return dest;
159 } else {
160 return new Point2D.Double(x1,y1);
161 }
162 }
163
164 /**
165 * Tente de remplacer la forme géométrique {@code path} par une des formes standards
166 * de Java2D. Par exemple, si {@code path} ne contient qu'un simple segment de droite
167 * ou une courbe quadratique, alors cette méthode retournera un objet {@link Line2D} ou
168 * {@link QuadCurve2D} respectivement.
169 *
170 * @param path Forme géométrique à simplifier (généralement un objet {@link GeneralPath}).
171 * @return Forme géométrique standard, ou {@code path} si aucun remplacement n'est proposé.
172 */
173 public static Shape toPrimitive(final Shape path) {
174 final float[] buffer = new float[6];
175 final PathIterator it = path.getPathIterator(null);
176 if (!it.isDone() && it.currentSegment(buffer) == PathIterator.SEG_MOVETO && !it.isDone()) {
177 final float x1 = buffer[0];
178 final float y1 = buffer[1];
179 final int code = it.currentSegment(buffer);
180 if (it.isDone()) {
181 switch (code) {
182 case PathIterator.SEG_LINETO: return new Line2D.Float(x1,y1, buffer[0],buffer[1]);
183 case PathIterator.SEG_QUADTO: return new QuadCurve2D.Float(x1,y1, buffer[0],buffer[1], buffer[2],buffer[3]);
184 case PathIterator.SEG_CUBICTO: return new CubicCurve2D.Float(x1,y1, buffer[0],buffer[1], buffer[2],buffer[3], buffer[4],buffer[5]);
185 }
186 }
187 }
188 return path;
189 }
190}
Note: See TracBrowser for help on using the repository browser.