Statistics
| Revision:

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

History | View | Annotate | Download (11.8 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.aggregate.MultiCurve;
40
import org.gvsig.fmap.geom.aggregate.MultiSurface;
41
import org.gvsig.fmap.geom.primitive.Curve;
42
import org.gvsig.fmap.geom.primitive.Envelope;
43
import org.gvsig.fmap.geom.primitive.Surface;
44
import org.gvsig.fmap.mapcontrol.PrimitivesDrawer;
45
import org.gvsig.fmap.mapcontrol.tools.snapping.snappers.ISnapperGeometriesVectorial;
46
import org.gvsig.fmap.mapcontrol.tools.snapping.snappers.impl.AbstractSnapper;
47
import org.gvsig.i18n.Messages;
48

    
49

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

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

    
153

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

    
186

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

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

    
196
        primitivesDrawer.drawLine(x1, y1, x2, y2);
197
        primitivesDrawer.drawLine(x1, y2, x2, y1);
198
    }
199

    
200
    public String getToolTipText() {
201
        return Messages.getText("Intersection_point");
202
    }
203

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

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

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

    
340
}