Statistics
| Revision:

svn-gvsig-desktop / trunk / org.gvsig.desktop / org.gvsig.desktop.plugin / org.gvsig.snapping.app / org.gvsig.snapping.app.mainplugin / src / main / java / org / gvsig / app / project / documents / view / toolListeners / snapping / snappers / IntersectionPointSnapper.java @ 44135

History | View | Annotate | Download (11.9 KB)

1
/**
2
 * gvSIG. Desktop Geographic Information System.
3
 *
4
 * Copyright (C) 2007-2013 gvSIG Association.
5
 *
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
 * as published by the Free Software Foundation; either version 3
9
 * 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
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
19
 * MA  02110-1301, USA.
20
 *
21
 * For any additional information, do not hesitate to contact us
22
 * at info AT gvsig.com, or visit our website www.gvsig.com.
23
 */
24
package org.gvsig.app.project.documents.view.toolListeners.snapping.snappers;
25

    
26
import java.awt.geom.Point2D;
27
import java.util.ArrayList;
28
import java.util.Iterator;
29
import java.util.List;
30

    
31
import com.vividsolutions.jts.geom.GeometryFactory;
32
import com.vividsolutions.jts.geom.MultiPoint;
33
import com.vividsolutions.jts.geom.Point;
34

    
35
import org.slf4j.Logger;
36
import org.slf4j.LoggerFactory;
37

    
38
import org.gvsig.fmap.geom.Geometry;
39
import org.gvsig.fmap.geom.GeometryLocator;
40
import org.gvsig.fmap.geom.aggregate.MultiCurve;
41
import org.gvsig.fmap.geom.aggregate.MultiSurface;
42
import org.gvsig.fmap.geom.primitive.Curve;
43
import org.gvsig.fmap.geom.primitive.Envelope;
44
import org.gvsig.fmap.geom.primitive.Surface;
45
import org.gvsig.fmap.mapcontrol.PrimitivesDrawer;
46
import org.gvsig.fmap.mapcontrol.tools.snapping.snappers.ISnapperGeometriesVectorial;
47
import org.gvsig.fmap.mapcontrol.tools.snapping.snappers.impl.AbstractSnapper;
48
import org.gvsig.i18n.Messages;
49

    
50

    
51
/**
52
 * Intersection point snapper.
53
 *
54
 * @author Vicente Caballero Navarro
55
 */
56
public class IntersectionPointSnapper extends AbstractSnapper
57
    implements ISnapperGeometriesVectorial {
58
    private static final Logger LOG = LoggerFactory.getLogger(IntersectionPointSnapper.class);
59
    
60
    public static final int MAX_GEOMETRIES_IN_RELAXED_LIST = 30;
61
    public static final int MAX_GEOMETRIES_WITHIN_TOLERANCE = 5;
62
    
63
        private List relaxedList = null;
64
        private GeometryFactory jtsGeoFact = null;
65
        private long errorMsgCount = 0;
66

    
67
    public Point2D getSnapPoint(
68
        Point2D point,
69
        Geometry geom,
70
        double tolerance,
71
        Point2D lastPointEntered) {
72
        
73
        if (geom == null) {
74
            return null;
75
        }
76
        
77
        if (relaxedList == null
78
            || relaxedList.size() < 2 /* We need 2 to intersect */
79
            || relaxedList.size() > MAX_GEOMETRIES_IN_RELAXED_LIST) {
80
            /*
81
             * If there are a lot of geometries, we assume the user
82
             * is not interested in snapping now. The relaxed list
83
             * might be long because the spatial index used perhaps
84
             * is "lazy" so the value of MAX_GEOMETRIES_IN_RELAXED_LIST
85
             * has to be not very small
86
             */
87
            return null;
88
        }
89
        
90
        List<Geometry> refinedList = null;
91
        try {
92
            refinedList = refineList(relaxedList, point, tolerance);
93
        } catch (Exception e1) {
94
            errorMsgCount++;
95
            if (errorMsgCount % 100 == 0) {
96
                /*
97
                 * Prevents too many lines in logger. If this happens,
98
                 * it will happen many times, so we'll see it in the log file.
99
                 */
100
                LOG.info("Error while refining list: " + e1.getMessage());
101
                errorMsgCount = 0;
102
            }
103
            return null;
104
        }
105
        
106
        if (refinedList.size() > MAX_GEOMETRIES_WITHIN_TOLERANCE) {
107
            /*
108
             * This refined list contains the geometries that are
109
             * close to the current mouse. Again we use an upper limit
110
             * to prevent the case where the user is in a zoom where
111
             * he is not interested in snapping.
112
             */
113
            return null;
114
        }
115
        
116
        List<Point> interPoints = getInterPoints(refinedList);
117
        
118
        if (interPoints.size() == 0) {
119
            return null;
120
        }
121
        
122
        com.vividsolutions.jts.geom.Geometry jtsg = null;
123
        try {
124
            jtsg = (com.vividsolutions.jts.geom.Geometry) geom.invokeOperation("toJTS", null);
125
        } catch (Exception e) {
126
            errorMsgCount++;
127
            if (errorMsgCount % 100 == 0) {
128
                /*
129
                 * Prevents too many lines in logger. If this happens,
130
                 * it will happen many times, so we'll see it in the log file.
131
                 */
132
                LOG.info("Error while refining list: " + e.getMessage());
133
                errorMsgCount = 0;
134
            }
135
            return null;
136
        }
137
        
138
        double zerodist = 0.001 * tolerance;
139
        int n = interPoints.size();
140
        Point po = null;
141
        for (int i=0; i<n; i++) {
142
            po = interPoints.get(i);
143
            if (point.distance(po.getX(), po.getY()) < tolerance) {
144
                // This is a candidate, now we check that it belongs to the
145
                // current geometry
146
                if (jtsg.distance(po) < zerodist) {
147
                    return new Point2D.Double(po.getX(), po.getY());
148
                }
149
            }
150
        }
151
        return null;
152
    }
153

    
154

    
155
    private List<Geometry> refineList(
156
        List geomlist,
157
        Point2D point,
158
        double tolerance) throws Exception {
159
        
160
        List<Geometry> resp = new ArrayList<Geometry>();
161
        if (geomlist == null || geomlist.size() == 0) {
162
            return resp;
163
        }
164
        
165
        double point_tol_north = point.getY() + tolerance; 
166
        double point_tol_south = point.getY() - tolerance;
167
        double point_tol_east = point.getX() + tolerance;
168
        double point_tol_west = point.getX() - tolerance;
169
        
170
        Geometry item;
171
        Iterator iter = geomlist.iterator();
172
        while (iter.hasNext()) {
173
            item = (Geometry) iter.next();
174
            Envelope interGeom = GeometryLocator.getGeometryManager().createEnvelope(
175
                    point_tol_west,
176
                    point_tol_south,
177
                    point_tol_east,
178
                    point_tol_north,
179
                    Geometry.SUBTYPES.GEOM2D);
180
            
181
            if (item.intersects(interGeom.getGeometry())) {
182
                resp.add(item);
183
            }
184
        }
185
        return resp;
186
    }
187

    
188

    
189
    public void draw(PrimitivesDrawer primitivesDrawer, Point2D pPixels) {
190
            primitivesDrawer.setColor(getColor());
191

    
192
        int half = getSizePixels() / 2;
193
        int x1 = (int) (pPixels.getX() - half);
194
        int x2 = (int) (pPixels.getX() + half);
195
        int y1 = (int) (pPixels.getY() - half);
196
        int y2 = (int) (pPixels.getY() + half);
197

    
198
        primitivesDrawer.drawLine(x1, y1, x2, y2);
199
        primitivesDrawer.drawLine(x1, y2, x2, y1);
200
    }
201

    
202
    public String getToolTipText() {
203
        return Messages.getText("Intersection_point_snapper");
204
    }
205

    
206
        public void setGeometries(List geoms) {
207
            relaxedList = leaveUsefulGeometries(geoms);
208
        }
209
        
210
        private List<Point> getInterPoints(List geomes) {
211
            
212
            List<Point> resp = new ArrayList<Point>();
213
            List borders = getJTSBorders(geomes);
214
            com.vividsolutions.jts.geom.Geometry jtsg1 = null;
215
            com.vividsolutions.jts.geom.Geometry jtsg2 = null;
216
            com.vividsolutions.jts.geom.Geometry jtsinter = null;
217
            int n = borders.size();
218
            Point jtsp = null;
219
            MultiPoint jtsmp = null;
220
            
221
            for (int i=0; i<n; i++) {
222
                for (int j=0; j<i; j++) {
223
                    if (i != j) {
224
                        jtsg1 = (com.vividsolutions.jts.geom.Geometry) borders.get(i);
225
                        jtsg2 = (com.vividsolutions.jts.geom.Geometry) borders.get(j);
226
                        jtsinter = jtsg1.intersection(jtsg2);
227
                        if (jtsinter instanceof Point) {
228
                            jtsp = (Point) jtsinter;
229
                            resp.add(jtsp);
230
                        } else {
231
                            if (jtsinter instanceof MultiPoint) {
232
                                
233
                                jtsmp = (MultiPoint) jtsinter;
234
                                int m = jtsmp.getNumGeometries();
235
                                for (int k=0; k<m; k++) {
236
                                    jtsp = (Point) jtsmp.getGeometryN(k);
237
                                    resp.add(jtsp);
238
                                }
239
                            }
240
                        }
241
                    }
242
                }
243
            }
244
            return resp;
245
        }
246
        
247

    
248
    private List getJTSBorders(List gvsigGeoms) {
249
        
250
        List resp = new ArrayList();
251
        com.vividsolutions.jts.geom.Geometry jtsborder = null;
252
        
253
        if (gvsigGeoms != null && gvsigGeoms.size() > 0) {
254
            
255
            Iterator iter = gvsigGeoms.iterator();
256
            Object itemobj = null;
257
            
258
            while (iter.hasNext()) {
259
                itemobj = iter.next();
260
                if (itemobj instanceof Geometry) {
261
                    jtsborder = getJTSBorder((Geometry) itemobj);
262
                    if (jtsborder != null) {
263
                        resp.add(jtsborder);
264
                    }
265
                }
266
            }
267
        }
268
        return resp;
269
    }
270

    
271
    private com.vividsolutions.jts.geom.Geometry getJTSBorder(Geometry geom) {
272
        
273
        com.vividsolutions.jts.geom.Geometry resp = null;
274
        
275
        if (geom instanceof Curve || geom instanceof MultiCurve) {
276
            
277
            try {
278
                resp = (com.vividsolutions.jts.geom.Geometry)
279
                    geom.invokeOperation("toJTS", null);
280
            } catch (Exception e) {
281
                errorMsgCount++;
282
                if (errorMsgCount % 100 == 0) {
283
                    /*
284
                     * Prevents too many lines in logger. If this happens,
285
                     * it will happen many times, so we'll see it in the log file.
286
                     */
287
                    LOG.info("Error while refining list: " + e.getMessage());
288
                    errorMsgCount = 0;
289
                }
290
                return null;
291
            }
292
            return resp;
293
            
294
        } else {
295
            if (geom instanceof Surface || geom instanceof MultiSurface) {
296
                
297
                try {
298
                    resp = (com.vividsolutions.jts.geom.Geometry)
299
                        geom.invokeOperation("toJTS", null);
300
                    return resp.getBoundary();
301
                } catch (Exception e) {
302
                    
303
                    errorMsgCount++;
304
                    if (errorMsgCount % 100 == 0) {
305
                        /*
306
                         * Prevents too many lines in logger. If this happens,
307
                         * it will happen many times, so we'll see it in the log file.
308
                         */
309
                        LOG.info("Error while refining list: " + e.getMessage());
310
                        errorMsgCount = 0;
311
                    }
312
                    return null;
313
                }
314
                
315
            } else {
316
                return null;
317
            }
318
        }
319
        
320
    }
321
  
322
    
323
    private List<Geometry> leaveUsefulGeometries(List geoms) {
324
        
325
        List resp = new ArrayList();
326
        if (geoms == null || geoms.size() == 0) {
327
            return resp;
328
        }
329
        
330
        Object item = null;
331
        Iterator iter = geoms.iterator();
332
        while (iter.hasNext()) {
333
            item = iter.next();
334
            if (item instanceof Curve || item instanceof Surface
335
                || item instanceof MultiCurve || item instanceof MultiSurface) {
336
                resp.add(item);
337
            }
338
        }
339
        return resp;
340
    }        
341

    
342
}