svn-gvsig-desktop / trunk / org.gvsig.desktop / org.gvsig.desktop.compat.cdc / org.gvsig.fmap.geometry / org.gvsig.fmap.geometry.impl / src / main / java / org / gvsig / fmap / geom / primitive / impl / Spline2D.java @ 40559
History | View | Annotate | Download (8.1 KB)
1 | 40559 | jjdelcerro | /**
|
---|---|---|---|
2 | * gvSIG. Desktop Geographic Information System.
|
||
3 | 40435 | jjdelcerro | *
|
4 | 40559 | jjdelcerro | * Copyright (C) 2007-2013 gvSIG Association.
|
5 | 40435 | jjdelcerro | *
|
6 | * This program is free software; you can redistribute it and/or
|
||
7 | * modify it under the terms of the GNU General Public License
|
||
8 | 40559 | jjdelcerro | * as published by the Free Software Foundation; either version 3
|
9 | 40435 | jjdelcerro | * of the License, or (at your option) any later version.
|
10 | *
|
||
11 | * This program is distributed in the hope that it will be useful,
|
||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
14 | * GNU General Public License for more details.
|
||
15 | *
|
||
16 | * You should have received a copy of the GNU General Public License
|
||
17 | * along with this program; if not, write to the Free Software
|
||
18 | 40559 | jjdelcerro | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
19 | * MA 02110-1301, USA.
|
||
20 | 40435 | jjdelcerro | *
|
21 | 40559 | jjdelcerro | * For any additional information, do not hesitate to contact us
|
22 | * at info AT gvsig.com, or visit our website www.gvsig.com.
|
||
23 | 40435 | jjdelcerro | */
|
24 | package org.gvsig.fmap.geom.primitive.impl; |
||
25 | |||
26 | import java.awt.geom.AffineTransform; |
||
27 | import java.awt.geom.Point2D; |
||
28 | import java.util.ArrayList; |
||
29 | |||
30 | import org.cresques.cts.IProjection; |
||
31 | import org.gvsig.fmap.geom.handler.AbstractHandler; |
||
32 | import org.gvsig.fmap.geom.handler.FinalHandler; |
||
33 | import org.gvsig.fmap.geom.handler.Handler; |
||
34 | import org.gvsig.fmap.geom.primitive.FShape; |
||
35 | import org.gvsig.fmap.geom.primitive.GeneralPathX; |
||
36 | import org.gvsig.fmap.geom.primitive.Point; |
||
37 | import org.gvsig.fmap.geom.primitive.Spline; |
||
38 | import org.gvsig.fmap.geom.type.GeometryType; |
||
39 | |||
40 | |||
41 | /**
|
||
42 | * Spline2D.
|
||
43 | *
|
||
44 | * @author Vicente Caballero Navarro
|
||
45 | */
|
||
46 | public class Spline2D extends Curve2D implements Spline { |
||
47 | private static final long serialVersionUID = -8109393343595560984L; |
||
48 | private ArrayList points2d; |
||
49 | |||
50 | /**
|
||
51 | * The constructor with the GeometryType like and argument
|
||
52 | * is used by the {@link GeometryType}{@link #create()}
|
||
53 | * to create the geometry
|
||
54 | * @param type
|
||
55 | * The geometry type
|
||
56 | */
|
||
57 | public Spline2D(GeometryType geometryType) {
|
||
58 | super(geometryType);
|
||
59 | points2d = new ArrayList(); |
||
60 | gp = new GeneralPathX();
|
||
61 | } |
||
62 | |||
63 | Spline2D(GeometryType geometryType, String id, IProjection projection, Point2D[] ps) { |
||
64 | super(geometryType, id, projection, getGeneralPathX(ps));
|
||
65 | for (int i=0 ; i<ps.length ; i++){ |
||
66 | points2d.add(ps[i]); |
||
67 | } |
||
68 | } |
||
69 | |||
70 | private static GeneralPathX getGeneralPathX(Point2D[] ps) { |
||
71 | GeneralPathX gpx=new GeneralPathX();
|
||
72 | int num=ps.length;
|
||
73 | double[] px=new double[num]; |
||
74 | double[] py=new double[num]; |
||
75 | for (int i=0;i<num;i++) { |
||
76 | Point2D p=ps[i];
|
||
77 | px[i]=p.getX(); |
||
78 | py[i]=p.getY(); |
||
79 | |||
80 | } |
||
81 | Spline splineX = new Spline(px);
|
||
82 | Spline splineY = new Spline(py);
|
||
83 | gpx.moveTo(px[0],py[0]); |
||
84 | for (int i = 0; i < px.length - 1; i++) { |
||
85 | for (int t = 1; t < 31; t++) { |
||
86 | double x1 = splineX.fn(i, ((double) t) / 30.0); |
||
87 | double y1 = splineY.fn(i, ((double) t) / 30.0); |
||
88 | gpx.lineTo(x1,y1); |
||
89 | } |
||
90 | } |
||
91 | if (ps[0].getX()==ps[ps.length-1].getX() && ps[0].getY()==ps[ps.length-1].getY()) |
||
92 | gpx.closePath(); |
||
93 | return gpx;
|
||
94 | } |
||
95 | |||
96 | private static GeneralPathX getGeneralPathX(ArrayList ps) { |
||
97 | Point2D[] _ps = new Point2D[ps.size()]; |
||
98 | for (int i=0 ; i<ps.size() ; i++){ |
||
99 | _ps[i] = (Point2D)ps.get(i);
|
||
100 | } |
||
101 | return getGeneralPathX(_ps);
|
||
102 | } |
||
103 | |||
104 | /*
|
||
105 | * (non-Javadoc)
|
||
106 | * @see org.gvsig.fmap.geom.primitive.impl.Curve2D#getShapeType()
|
||
107 | */
|
||
108 | public int getShapeType() { |
||
109 | return TYPES.CURVE;
|
||
110 | } |
||
111 | |||
112 | /* (non-Javadoc)
|
||
113 | * @see com.iver.cit.gvsig.fmap.core.FShape#cloneFShape()
|
||
114 | */
|
||
115 | public FShape cloneFShape() {
|
||
116 | Spline2D curve = new Spline2D(getGeometryType());
|
||
117 | for (int i=0;i<points2d.size();i++){ |
||
118 | curve.addVertex(new org.gvsig.fmap.geom.primitive.impl.Point2D((Point2D)points2d.get(i))); |
||
119 | } |
||
120 | return (FShape)curve;
|
||
121 | } |
||
122 | |||
123 | /* (non-Javadoc)
|
||
124 | * @see com.iver.cit.gvsig.fmap.core.FShape#getStretchingHandlers()
|
||
125 | */
|
||
126 | public Handler[] getStretchingHandlers() { |
||
127 | ArrayList handlers = new ArrayList(); |
||
128 | for (int i=0;i<points2d.size();i++) { |
||
129 | handlers.add(new PointHandler(i,
|
||
130 | ((Point2D)points2d.get(i)).getX(),
|
||
131 | ((Point2D)points2d.get(i)).getY()));
|
||
132 | } |
||
133 | return (Handler[]) handlers.toArray(new Handler[0]); |
||
134 | } |
||
135 | |||
136 | /* (non-Javadoc)
|
||
137 | * @see com.iver.cit.gvsig.fmap.core.FShape#getSelectHandlers()
|
||
138 | */
|
||
139 | public Handler[] getSelectHandlers() { |
||
140 | ArrayList handlers = new ArrayList(); |
||
141 | for (int i=0;i<points2d.size();i++) { |
||
142 | Point2D p=((Point2D)points2d.get(i)); |
||
143 | handlers.add(new PointSelHandler(i, p.getX(), p.getY()));
|
||
144 | } |
||
145 | return (Handler[]) handlers.toArray(new Handler[0]); |
||
146 | } |
||
147 | |||
148 | /**
|
||
149 | * DOCUMENT ME!
|
||
150 | *
|
||
151 | * @author Vicente Caballero Navarro
|
||
152 | */
|
||
153 | class PointHandler extends AbstractHandler implements FinalHandler{ |
||
154 | /**
|
||
155 | * Crea un nuevo PointHandler.
|
||
156 | *
|
||
157 | * @param x DOCUMENT ME!
|
||
158 | * @param y DOCUMENT ME!
|
||
159 | */
|
||
160 | public PointHandler(int i,double x, double y) { |
||
161 | point = new Point2D.Double(x,y); |
||
162 | index=i; |
||
163 | } |
||
164 | |||
165 | /**
|
||
166 | * DOCUMENT ME!
|
||
167 | *
|
||
168 | * @param x DOCUMENT ME!
|
||
169 | * @param y DOCUMENT ME!
|
||
170 | *
|
||
171 | * @return DOCUMENT ME!
|
||
172 | */
|
||
173 | public void move(double x, double y) { |
||
174 | point.setLocation(point.getX()+x,point.getY()+y); |
||
175 | //TODO falta actualizar el GeneralPathX
|
||
176 | } |
||
177 | |||
178 | /**
|
||
179 | * @see org.gvsig.fmap.geom.handler.Handler#set(double, double)
|
||
180 | */
|
||
181 | public void set(double x, double y) { |
||
182 | point.setLocation(x,y); |
||
183 | //TODO falta actualizar el GeneralPathX
|
||
184 | } |
||
185 | } |
||
186 | /**
|
||
187 | * DOCUMENT ME!
|
||
188 | *
|
||
189 | * @author Vicente Caballero Navarro
|
||
190 | */
|
||
191 | class PointSelHandler extends AbstractHandler implements FinalHandler{ |
||
192 | /**
|
||
193 | * Crea un nuevo PointHandler.
|
||
194 | *
|
||
195 | * @param x DOCUMENT ME!
|
||
196 | * @param y DOCUMENT ME!
|
||
197 | */
|
||
198 | public PointSelHandler(int i,double x, double y) { |
||
199 | point = new Point2D.Double(x,y); |
||
200 | index=i; |
||
201 | } |
||
202 | |||
203 | /**
|
||
204 | * DOCUMENT ME!
|
||
205 | *
|
||
206 | * @param x DOCUMENT ME!
|
||
207 | * @param y DOCUMENT ME!
|
||
208 | *
|
||
209 | * @return DOCUMENT ME!
|
||
210 | */
|
||
211 | public void move(double x, double y) { |
||
212 | point.setLocation(point.getX()+x,point.getY()+y); |
||
213 | Point2D setp = (Point2D) points2d.get(index); |
||
214 | setp.setLocation(point.getX(), point.getY()); |
||
215 | gp = getGeneralPathX(points2d); |
||
216 | } |
||
217 | |||
218 | /**
|
||
219 | * @see org.gvsig.fmap.geom.handler.Handler#set(double, double)
|
||
220 | */
|
||
221 | public void set(double x, double y) { |
||
222 | point.setLocation(x,y); |
||
223 | |||
224 | Point2D setp = (Point2D) points2d.get(index); |
||
225 | setp.setLocation(point.getX(), point.getY()); |
||
226 | gp=getGeneralPathX(points2d); |
||
227 | } |
||
228 | } |
||
229 | static class Spline { |
||
230 | private double y[]; |
||
231 | private double y2[]; |
||
232 | |||
233 | /**
|
||
234 | * The constructor calculates the second derivatives of the interpolating function
|
||
235 | * at the tabulated points xi, with xi = (i, y[i]).
|
||
236 | * Based on numerical recipes in C, http://www.library.cornell.edu/nr/bookcpdf/c3-3.pdf .
|
||
237 | * @param y Array of y coordinates for cubic-spline interpolation.
|
||
238 | */
|
||
239 | public Spline(double y[]) { |
||
240 | this.y = y;
|
||
241 | int n = y.length;
|
||
242 | y2 = new double[n]; |
||
243 | double u[] = new double[n]; |
||
244 | for (int i = 1; i < n - 1; i++) { |
||
245 | y2[i] = -1.0 / (4.0 + y2[i - 1]); |
||
246 | u[i] = (6.0 * (y[i + 1] - 2.0 * y[i] + y[i - 1]) - u[i - 1]) / (4.0 + y2[i - 1]); |
||
247 | } |
||
248 | for (int i = n - 2; i >= 0; i--) { |
||
249 | y2[i] = y2[i] * y2[i + 1] + u[i];
|
||
250 | } |
||
251 | } |
||
252 | |||
253 | /**
|
||
254 | * Returns a cubic-spline interpolated value y for the point between
|
||
255 | * point (n, y[n]) and (n+1, y[n+1), with t ranging from 0 for (n, y[n])
|
||
256 | * to 1 for (n+1, y[n+1]).
|
||
257 | * @param n The start point.
|
||
258 | * @param t The distance to the next point (0..1).
|
||
259 | * @return A cubic-spline interpolated value.
|
||
260 | */
|
||
261 | public double fn(int n, double t) { |
||
262 | return t * y[n + 1] - ((t - 1.0) * t * ((t - 2.0) * y2[n] - (t + 1.0) * y2[n + 1])) / 6.0 + y[n] - t * y[n]; |
||
263 | } |
||
264 | |||
265 | } |
||
266 | |||
267 | /*
|
||
268 | * (non-Javadoc)
|
||
269 | * @see org.gvsig.fmap.geom.primitive.impl.OrientablePrimitive2D#transform(java.awt.geom.AffineTransform)
|
||
270 | */
|
||
271 | public void transform(AffineTransform at) { |
||
272 | |||
273 | if (at == null) { |
||
274 | return;
|
||
275 | } |
||
276 | |||
277 | for (int i=0;i<points2d.size();i++) { |
||
278 | Point2D p= (Point2D)points2d.get(i); |
||
279 | at.transform(p, p); |
||
280 | } |
||
281 | gp.transform(at); |
||
282 | } |
||
283 | |||
284 | /* (non-Javadoc)
|
||
285 | * @see org.gvsig.fmap.geom.primitive.Curve2D#addPoint(org.gvsig.fmap.geom.primitive.Point)
|
||
286 | */
|
||
287 | public void addVertex(Point point) { |
||
288 | points2d.add(new java.awt.geom.Point2D.Double(point.getX(), point.getY()));
|
||
289 | gp = getGeneralPathX(points2d); |
||
290 | } |
||
291 | |||
292 | |||
293 | } |