Statistics
| Revision:

svn-gvsig-desktop / branches / v2_0_0_prep / libraries / libGeocoding / src / org / gvsig / geocoding / geommatches / MatcherUtils.java @ 28375

History | View | Annotate | Download (14.5 KB)

1
/* gvSIG. Geographic Information System of the Valencian Government
2
 *
3
 * Copyright (C) 2007-2008 Infrastructures and Transports Department
4
 * of the Valencian Government (CIT)
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 2
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
 */
22

    
23
/*
24
 * AUTHORS (In addition to CIT):
25
 * 2008 Prodevelop S.L. main development
26
 */
27

    
28
package org.gvsig.geocoding.geommatches;
29

    
30
import java.awt.geom.PathIterator;
31
import java.util.ArrayList;
32
import java.util.HashMap;
33
import java.util.Iterator;
34
import java.util.LinkedList;
35
import java.util.List;
36

    
37
import org.gvsig.fmap.dal.exception.DataException;
38
import org.gvsig.fmap.dal.feature.Feature;
39
import org.gvsig.fmap.geom.Geometry;
40
import org.gvsig.fmap.geom.GeometryLocator;
41
import org.gvsig.fmap.geom.exception.CreateGeometryException;
42
import org.gvsig.fmap.geom.primitive.Point;
43
import org.gvsig.fmap.geom.util.Converter;
44
import org.gvsig.fmap.geom.util.UtilFunctions;
45
import org.gvsig.geocoding.result.DissolveResult;
46
import org.gvsig.geocoding.result.ScoredFeature;
47
import org.gvsig.geocoding.result.impl.DefaultDissolveResult;
48
import org.gvsig.tools.locator.LocatorException;
49
import org.slf4j.Logger;
50
import org.slf4j.LoggerFactory;
51

    
52
import com.vividsolutions.jts.geom.Coordinate;
53
import com.vividsolutions.jts.linearref.LengthIndexedLine;
54
import com.vividsolutions.jts.operation.overlay.OverlayOp;
55

    
56
/**
57
 * This class has the utilities to work with geometries and search the geocoding
58
 * point
59
 * 
60
 * @author <a href="mailto:jsanz@prodevelop.es"> Jorge Gaspar Sanz Salinas</a>
61
 * @author <a href="mailto:vsanjaime@prodevelop.es"> Vicente Sanjaime Calvet</a>
62
 */
63

    
64
public class MatcherUtils {
65

    
66
        private static final Logger log = LoggerFactory
67
                        .getLogger(MatcherUtils.class);
68

    
69
        public static final String LINES = "LINES";
70
        public static final String POLYS = "POLYS";
71

    
72
        /**
73
         * Get internal point from one polygon geometry
74
         * 
75
         * @param geomGV
76
         * @return
77
         */
78
        public static Point internalPointGeometry(Geometry geomGV) {
79

    
80
                if (geomGV != null) {
81
                        com.vividsolutions.jts.geom.Geometry geomJTS = Converter
82
                                        .geometryToJts(geomGV);
83
                        if (geomJTS != null) {
84
                                com.vividsolutions.jts.geom.Point pto = geomJTS
85
                                                .getInteriorPoint();
86
                                if (pto != null) {
87
                                        return getPoint(pto.getX(), pto.getY());
88
                                }
89
                        }
90
                }
91
                return null;
92
        }
93

    
94
        /**
95
         * parse geometries of gvSIG model to JTS model
96
         * 
97
         * @param geoms
98
         *            list of gvSIG geometries
99
         * @return list of JTS geometries
100
         */
101
        public static List<com.vividsolutions.jts.geom.Geometry> parseGeomsGVToJTS(
102
                        List<Geometry> geoms) {
103

    
104
                List<com.vividsolutions.jts.geom.Geometry> list = new ArrayList<com.vividsolutions.jts.geom.Geometry>();
105

    
106
                if (geoms != null && geoms.size() > 0) {
107
                        com.vividsolutions.jts.geom.Geometry ge = null;
108
                        for (Geometry geometry : geoms) {
109
                                ge = Converter.geometryToJts(geometry);
110
                                list.add(ge);
111
                        }
112
                }
113
                return list;
114
        }
115

    
116
        /**
117
         * parse a list of gvSIG geometries to JTS geometries
118
         * 
119
         * @param geoms
120
         *            list gvSIG geometries to JTS geometries
121
         * @return
122
         */
123
        public static List<Geometry> parseGeomsJTSToGV(
124
                        List<com.vividsolutions.jts.geom.Geometry> geoms) {
125

    
126
                List<Geometry> list = new ArrayList<Geometry>();
127

    
128
                if (geoms != null && geoms.size() > 0) {
129
                        for (com.vividsolutions.jts.geom.Geometry geometry : geoms) {
130
                                list.add(Converter.jtsToGeometry(geometry));
131
                        }
132
                }
133
                return list;
134
        }
135

    
136
        /**
137
         * This method intersect two lines and return the intersection point. If
138
         * result is null, two lines doesn't intersect
139
         * 
140
         * @param geom1Jts
141
         * @param geom2Jts
142
         * @return
143
         */
144
        public static Point intersectTwoLinesJTS(
145
                        com.vividsolutions.jts.geom.Geometry geom1Jts,
146
                        com.vividsolutions.jts.geom.Geometry geom2Jts) {
147

    
148
                com.vividsolutions.jts.geom.Geometry interBBoxJTS = null;
149
                com.vividsolutions.jts.geom.Geometry geomPointJTS = null;
150

    
151
                if (geom1Jts != null && geom2Jts != null) {
152

    
153
                        interBBoxJTS = OverlayOp.overlayOp(geom1Jts.getEnvelope(), geom2Jts
154
                                        .getEnvelope(), OverlayOp.INTERSECTION);
155
                        if (interBBoxJTS.getGeometryType().compareTo("LineString") == 0
156
                                        || interBBoxJTS.getGeometryType().compareTo("Polygon") == 0) {
157
                                log.debug("Intersect: Intersect two BBOX");
158
                                geomPointJTS = OverlayOp.overlayOp(geom1Jts, geom2Jts,
159
                                                OverlayOp.INTERSECTION);
160

    
161
                                if (geomPointJTS.getGeometryType().compareTo("Point") == 0) {
162
                                        log.debug("Intersect: Intersect in the point X= "
163
                                                        + geomPointJTS.getCoordinate().x + " Y= "
164
                                                        + geomPointJTS.getCoordinate().y);
165
                                        Point pto = getPoint(geomPointJTS.getCoordinate().x,
166
                                                        geomPointJTS.getCoordinate().y);
167

    
168
                                        return pto;
169
                                } else {
170
                                        log.debug("Intersect: Two lines don't intersect");
171
                                        return null;
172
                                }
173
                        } else {
174
                                log.debug("Intersect: Two BBOX don't intersect");
175
                                return null;
176
                        }
177
                }
178
                log.debug("Some Geometries are NULL  ......");
179
                return null;
180
        }
181

    
182
        /**
183
         * This method does the union the geometries (Features) with a attribute
184
         * common
185
         * 
186
         * @param sFeats
187
         * @param geomType
188
         *            LINES, POLYS
189
         * @return
190
         * @throws DataException
191
         */
192
        public static List<DissolveResult> dissolveGeomsJTS(
193
                        List<ScoredFeature> sFeats, String geomType) throws DataException {
194

    
195
                List<DissolveResult> results = new ArrayList<DissolveResult>();
196

    
197
                // None elements
198
                if (sFeats.size() == 0) {
199
                        return results;
200
                }
201

    
202
                // Only one element
203
                else if (sFeats.size() == 1) {
204
                        DissolveResult result = new DefaultDissolveResult();
205
                        Feature feat = null;
206
                        try {
207
                                feat = sFeats.get(0).getFeature();
208
                                result.setGeom(feat.getDefaultGeometry());
209
                                List<ScoredFeature> list = new ArrayList<ScoredFeature>();
210
                                list.add(sFeats.get(0));
211
                                result.setScoredFeatures(list);
212
                                results.add(result);
213
                        } catch (DataException e) {
214
                                log.debug("Error getting the feature", e);
215
                        }
216
                        return results;
217
                }
218

    
219
                // more elements
220
                else {
221

    
222
                        LinkedList<ScoredFeature> list = new LinkedList<ScoredFeature>();
223
                        com.vividsolutions.jts.geom.Geometry geo1, geo2;
224

    
225
                        for (ScoredFeature scoredFeature : sFeats) {
226
                                list.add(scoredFeature);
227
                        }
228

    
229
                        // Iterate over the linked list
230
                        while (list.size() > 0) {
231
                                // Remove the first element of the list
232
                                ScoredFeature sFeat = list.poll();
233

    
234
                                // create first dissolve result and add it to the list
235
                                DissolveResult result = new DefaultDissolveResult();
236
                                ArrayList<ScoredFeature> dissolveList = new ArrayList<ScoredFeature>();
237
                                dissolveList.add(sFeat);
238

    
239
                                geo1 = Converter.geometryToJts(sFeat.getFeature()
240
                                                .getDefaultGeometry());
241

    
242
                                ScoredFeature touchingSFeat = null;
243
                                // LINES
244

    
245
                                if (geomType.compareTo(LINES) == 0) {
246
                                        touchingSFeat = getFirstLineTouchingSF(geo1, list);
247
                                }
248
                                // POLYS
249
                                if (geomType.compareTo(POLYS) == 0) {
250
                                        touchingSFeat = getFirstPolyTouchingSF(geo1, list);
251
                                }
252

    
253
                                while (touchingSFeat != null) {
254
                                        list.remove(touchingSFeat);
255
                                        geo2 = Converter.geometryToJts(touchingSFeat.getFeature()
256
                                                        .getDefaultGeometry());
257

    
258
                                        geo1 = OverlayOp.overlayOp(geo1, geo2, OverlayOp.UNION);
259

    
260
                                        dissolveList.add(touchingSFeat);
261

    
262
                                        touchingSFeat = getFirstLineTouchingSF(geo1, list);
263
                                }
264
                                result.setJTSGeom(geo1);
265
                                result.setScoredFeatures(dissolveList);
266
                                results.add(result);
267
                        }
268
                }
269
                return results;
270
        }
271

    
272
        /**
273
         * Get first line of the list that it is touching the in geometry
274
         * 
275
         * @param geometry
276
         * @param list
277
         * @return
278
         * @throws DataException
279
         */
280
        private static ScoredFeature getFirstLineTouchingSF(
281
                        com.vividsolutions.jts.geom.Geometry geometry,
282
                        LinkedList<ScoredFeature> list) throws DataException {
283

    
284
                com.vividsolutions.jts.geom.Geometry geo2;
285
                for (ScoredFeature listedSF : list) {
286
                        geo2 = Converter.geometryToJts(listedSF.getFeature()
287
                                        .getDefaultGeometry());
288
                        if (geometry.touches(geo2))
289
                                return listedSF;
290
                }
291
                return null;
292
        }
293

    
294
        /**
295
         * Get first poly of the list that it is touching the in geometry
296
         * 
297
         * @param geometry
298
         * @param list
299
         * @return
300
         * @throws DataException
301
         */
302
        private static ScoredFeature getFirstPolyTouchingSF(
303
                        com.vividsolutions.jts.geom.Geometry geometry,
304
                        LinkedList<ScoredFeature> list) throws DataException {
305

    
306
                com.vividsolutions.jts.geom.Geometry geo2;
307
                com.vividsolutions.jts.geom.Geometry geo3;
308
                for (ScoredFeature listedSF : list) {
309
                        geo2 = Converter.geometryToJts(listedSF.getFeature()
310
                                        .getDefaultGeometry());
311
                        geo3 = geometry.intersection(geo2);
312
                        for (int i = 0; i < geo3.getNumGeometries(); i++) {
313
                                int dim = geo3.getGeometryN(i).getDimension();
314
                                if (dim == 1) {
315
                                        return listedSF;
316
                                }
317
                        }
318
                }
319
                return null;
320
        }
321

    
322
        /**
323
         * This method group geometries to one attribute
324
         * 
325
         * @param desc
326
         * @param features
327
         * @return
328
         */
329
        public static HashMap<String, List<ScoredFeature>> groupScoredFeaturesByAttribute(
330
                        String desc, List<ScoredFeature> features) {
331

    
332
                HashMap<String, List<ScoredFeature>> groups = new HashMap<String, List<ScoredFeature>>();
333
                Iterator<ScoredFeature> it = features.iterator();
334
                // Go for all geometries of the collection
335
                while (it.hasNext()) {
336
                        // Get feature
337
                        ScoredFeature sFeat = (ScoredFeature) it.next();
338
                        Feature feat = null;
339
                        try {
340
                                feat = sFeat.getFeature();
341
                                String key = feat.get(desc).toString();
342
                                // Store the geometries for attribute in the List
343
                                boolean contiene = groups.containsKey(key);
344
                                if (!contiene) {
345
                                        List<ScoredFeature> featss = new ArrayList<ScoredFeature>();
346
                                        featss.add(sFeat);
347
                                        groups.put(key, featss);
348
                                } else {
349
                                        ((List<ScoredFeature>) groups.get(key)).add(sFeat);
350
                                }
351
                        } catch (DataException e) {
352
                                log.debug("Error clustering element", e);
353
                                continue;
354
                        }
355
                }
356
                return groups;
357
        }
358

    
359
        /**
360
         * Calculate the position inside single line from distance
361
         * 
362
         * @param geomJTS
363
         * @param distance
364
         * @return
365
         */
366
        public static Point getLinePositionFromDistance(
367
                        com.vividsolutions.jts.geom.Geometry geomJTS, double distance) {
368

    
369
                if (geomJTS != null) {
370
                        LengthIndexedLine lenline = new LengthIndexedLine(geomJTS);
371
                        if (distance < 0) {
372
                                distance = 0.0;
373
                        }
374
                        if (distance > geomJTS.getLength()) {
375
                                distance = geomJTS.getLength();
376
                        }
377
                        if (lenline.isValidIndex(distance)) {
378
                                Coordinate coors = lenline.extractPoint(distance);
379

    
380
                                return getPoint(coors.x, coors.y);
381

    
382
                        }
383
                }
384
                return null;
385
        }
386

    
387
        /**
388
         * Calculate the position inside single line from relative distance
389
         * 
390
         * @param geomJTS
391
         * @param distance
392
         * @return
393
         */
394
        public static Point getLinePositionFromRelativeDistance(
395
                        com.vividsolutions.jts.geom.Geometry geomJTS, int relative) {
396
                if (geomJTS != null) {
397
                        double totaldistance = geomJTS.getLength();
398
                        LengthIndexedLine lenline = new LengthIndexedLine(geomJTS);
399

    
400
                        Coordinate coors = null;
401

    
402
                        if (relative < 0) {
403
                                coors = lenline.extractPoint(0);
404
                                return getPoint(coors.x, coors.y);
405
                        } else if (relative <= 100 && relative >= 0) {
406
                                double dist = (relative * totaldistance) / 100.0;
407
                                coors = lenline.extractPoint(dist);
408
                                return getPoint(coors.x, coors.y);
409
                        } else {
410
                                coors = lenline.extractPoint(totaldistance);
411
                                return getPoint(coors.x, coors.y);
412
                        }
413
                }
414
                return null;
415
        }
416

    
417
        /**
418
         * This method calculates a point perpendicular to the line at a distance
419
         * 
420
         * @param inicio
421
         * @param fin
422
         * @param linePoint
423
         * @param dist
424
         * @return
425
         */
426
        public static Point getPerpendicularPointFromLine(Point inicio, Point fin,
427
                        Point linePoint, double dist) {
428

    
429
                java.awt.geom.Point2D pto1 = new java.awt.geom.Point2D.Double(inicio
430
                                .getX(), inicio.getY());
431
                java.awt.geom.Point2D pto2 = new java.awt.geom.Point2D.Double(fin
432
                                .getX(), fin.getY());
433

    
434
                java.awt.geom.Point2D perpPoint = new java.awt.geom.Point2D.Double(
435
                                linePoint.getX(), linePoint.getY());
436

    
437
                java.awt.geom.Point2D[] p = UtilFunctions.getPerpendicular(pto1, pto2,
438
                                perpPoint);
439
                java.awt.geom.Point2D unit = UtilFunctions.getUnitVector(p[0], p[1]);
440

    
441
                java.awt.geom.Point2D res = new java.awt.geom.Point2D.Double(perpPoint
442
                                .getX()
443
                                + (unit.getX() * dist), perpPoint.getY() + (unit.getY() * dist));
444

    
445
                return getPoint(res.getX(), res.getY());
446
        }
447

    
448
        /**
449
         * Calculate the position in the line with offset
450
         * 
451
         * @param geoms
452
         * @param linePoint
453
         * @param dist
454
         * @return
455
         */
456
        public static Point getOffsetPosition(Geometry[] geoms, Point linePoint,
457
                        double dist) {
458

    
459
                for (int j = 0; j < geoms.length; j++) {
460
                        double[] coords = new double[6];
461
                        Point inicio = null;
462
                        Point fin = null;
463

    
464
                        boolean inter = geoms[j].intersects(linePoint.getBounds2D());
465
                        if (inter) {
466
                                PathIterator iter = geoms[j].getGeneralPath().getPathIterator(
467
                                                null);
468
                                iter.currentSegment(coords);
469
                                inicio = getPoint(coords[0], coords[1]);
470

    
471
                                iter.next();
472
                                iter.currentSegment(coords);
473
                                fin = getPoint(coords[0], coords[1]);
474

    
475
                                log.debug("Return point with offset");
476
                                return MatcherUtils.getPerpendicularPointFromLine(inicio, fin,
477
                                                linePoint, dist);
478
                        }
479
                }
480
                log.debug("Return original point without offset");
481
                return linePoint;
482
        }
483

    
484
        /**
485
         * get geometry dimension
486
         * 
487
         * @param geom
488
         * @return
489
         */
490
        public static int getGeometryDimension(Geometry geom) {
491
                com.vividsolutions.jts.geom.Geometry geomJTS = Converter
492
                                .geometryToJts(geom);
493
                return geomJTS.getDimension();
494
        }
495

    
496
        /**
497
         * Get point 2D from x and y coordinates
498
         * 
499
         * @param x
500
         * @param y
501
         * @return
502
         */
503
        public static Point getPoint(double x, double y) {
504
                Point pto = null;
505
                try {
506
                        pto = GeometryLocator.getGeometryManager().createPoint(x, y,
507
                                        Geometry.SUBTYPES.GEOM2D);
508
                } catch (LocatorException e) {
509
                        log.error("Error getting the geometry locator", e);
510
                        return null;
511
                } catch (CreateGeometryException e) {
512
                        log.error("Error creating geometry", e);
513
                        return null;
514
                }
515
                return pto;
516
        }
517

    
518
}