Statistics
| Revision:

root / branches / v2_0_0_prep / libraries / org.gvsig.geocoding / src / org / gvsig / geocoding / geommatches / MatcherUtils.java @ 32474

History | View | Annotate | Download (15.9 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.awt.geom.Rectangle2D;
32
import java.util.ArrayList;
33
import java.util.HashMap;
34
import java.util.Iterator;
35
import java.util.LinkedList;
36
import java.util.List;
37

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

    
54
import com.vividsolutions.jts.geom.Coordinate;
55
import com.vividsolutions.jts.linearref.LengthIndexedLine;
56
import com.vividsolutions.jts.operation.overlay.OverlayOp;
57

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

    
66
public class MatcherUtils {
67

    
68
        private static final Logger log = LoggerFactory
69
                        .getLogger(MatcherUtils.class);
70

    
71
        public static final String LINES = "LINES";
72
        public static final String POLYS = "POLYS";
73

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

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

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

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

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

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

    
129
                List<Geometry> list = new ArrayList<Geometry>();
130

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

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

    
151
//                com.vividsolutions.jts.geom.Geometry interBBoxJTS = null;
152
//                com.vividsolutions.jts.geom.Geometry geomPointJTS = null;
153
                
154
                List<Point> points = new ArrayList<Point>();
155

    
156
                if (geom1Jts != null && geom2Jts != null) {
157

    
158
                        com.vividsolutions.jts.geom.Geometry ugeoms = geom1Jts.intersection(geom2Jts);
159
                        
160
                        if(ugeoms instanceof com.vividsolutions.jts.geom.Point){
161
                                com.vividsolutions.jts.geom.Point ptojts = (com.vividsolutions.jts.geom.Point)ugeoms;
162
                                Point pto = getPoint(ptojts.getCoordinate().x,
163
                                                ptojts.getCoordinate().y);
164
                                points.clear();
165
                                points.add(pto);
166
                                return points;
167
                        }else if(ugeoms instanceof com.vividsolutions.jts.geom.MultiPoint){
168
                                com.vividsolutions.jts.geom.MultiPoint ptosjts = (com.vividsolutions.jts.geom.MultiPoint)ugeoms;
169
                                Coordinate[] coords = ptosjts.getCoordinates();
170
                                points.clear();
171
                                for (int i = 0; i < coords.length; i++) {
172
                                        Coordinate coor = coords[i];
173
                                        Point pto = getPoint(coor.x,coor.y);
174
                                        points.add(pto);
175
                                }
176
                                
177
                                return points;
178
                        }
179
                        
180
//                        interBBoxJTS = OverlayOp.overlayOp(geom1Jts.getEnvelope(), geom2Jts
181
//                                        .getEnvelope(), OverlayOp.INTERSECTION);
182
//                        if (interBBoxJTS.getGeometryType().compareTo("LineString") == 0
183
//                                        || interBBoxJTS.getGeometryType().compareTo("Polygon") == 0) {
184
//                                log.debug("Intersect: Intersect two BBOX");
185
//                                geomPointJTS = OverlayOp.overlayOp(geom1Jts, geom2Jts,
186
//                                                OverlayOp.INTERSECTION);
187
//
188
//                                if (geomPointJTS.getGeometryType().compareTo("Point") == 0) {
189
//                                        
190
//                                        Point pto = getPoint(geomPointJTS.getCoordinate().x,
191
//                                                        geomPointJTS.getCoordinate().y);
192
//                                        points.add(pto);
193
//                                        return points;
194
//                                } else if (geomPointJTS.getGeometryType().compareTo("MultiPoint") == 0) {
195
//                                        log.debug("Intersect: Intersect );
196
//                                        Point pto = getPoint(geomPointJTS.getCoordinate().x,
197
//                                                        geomPointJTS.getCoordinate().y);
198
//                                        points.add(pto);
199
//                                        return points;
200
//                                }
201
//                        } else {
202
//                                log.debug("Intersect: Two BBOX don't intersect");
203
//                                return null;
204
//                        }
205
                }
206
                log.debug("Intersect: Two lines nor intersect or not touch");
207
                return points;
208
        }
209

    
210
        /**
211
         * This method does the union the geometries (Features) with a attribute
212
         * common
213
         * 
214
         * @param sFeats
215
         * @param geomType
216
         *            LINES, POLYS
217
         * @return
218
         * @throws DataException
219
         */
220
        public static List<DissolveResult> dissolveGeomsJTS(
221
                        List<ScoredFeature> sFeats, String geomType) throws DataException {
222

    
223
                List<DissolveResult> results = new ArrayList<DissolveResult>();
224

    
225
                // None elements
226
                if (sFeats.size() == 0) {
227
                        return results;
228
                }
229

    
230
                // Only one element
231
                else if (sFeats.size() == 1) {
232
                        DissolveResult result = new DefaultDissolveResult();
233
                        Feature feat = null;
234
                        try {
235
                                feat = sFeats.get(0).getFeature();
236
                                result.setGeom(feat.getDefaultGeometry());
237
                                List<ScoredFeature> list = new ArrayList<ScoredFeature>();
238
                                list.add(sFeats.get(0));
239
                                result.setScoredFeatures(list);
240
                                results.add(result);
241
                        } catch (DataException e) {
242
                                log.debug("Error getting the feature", e);
243
                        }
244
                        return results;
245
                }
246

    
247
                // more elements
248
                else {
249

    
250
                        LinkedList<ScoredFeature> list = new LinkedList<ScoredFeature>();
251
                        com.vividsolutions.jts.geom.Geometry geo1, geo2;
252

    
253
                        for (ScoredFeature scoredFeature : sFeats) {
254
                                list.add(scoredFeature);
255
                        }
256

    
257
                        // Iterate over the linked list
258
                        while (list.size() > 0) {
259
                                // Remove the first element of the list
260
                                ScoredFeature sFeat = list.poll();
261

    
262
                                // create first dissolve result and add it to the list
263
                                DissolveResult result = new DefaultDissolveResult();
264
                                ArrayList<ScoredFeature> dissolveList = new ArrayList<ScoredFeature>();
265
                                dissolveList.add(sFeat);
266

    
267
                                geo1 = Converter.geometryToJts(sFeat.getFeature()
268
                                                .getDefaultGeometry());
269

    
270
                                ScoredFeature touchingSFeat = null;
271
                                // LINES
272

    
273
                                if (geomType.compareTo(LINES) == 0) {
274
                                        touchingSFeat = getFirstLineTouchingSF(geo1, list);
275
                                }
276
                                // POLYS
277
                                if (geomType.compareTo(POLYS) == 0) {
278
                                        touchingSFeat = getFirstPolyTouchingSF(geo1, list);
279
                                }
280

    
281
                                while (touchingSFeat != null) {
282
                                        list.remove(touchingSFeat);
283
                                        geo2 = Converter.geometryToJts(touchingSFeat.getFeature()
284
                                                        .getDefaultGeometry());
285

    
286
                                        geo1 = OverlayOp.overlayOp(geo1, geo2, OverlayOp.UNION);
287

    
288
                                        dissolveList.add(touchingSFeat);
289

    
290
                                        touchingSFeat = getFirstLineTouchingSF(geo1, list);
291
                                }
292
                                result.setJTSGeom(geo1);
293
                                result.setScoredFeatures(dissolveList);
294
                                results.add(result);
295
                        }
296
                }
297
                return results;
298
        }
299

    
300
        /**
301
         * Get first line of the list that it is touching the in geometry
302
         * 
303
         * @param geometry
304
         * @param list
305
         * @return
306
         * @throws DataException
307
         */
308
        private static ScoredFeature getFirstLineTouchingSF(
309
                        com.vividsolutions.jts.geom.Geometry geometry,
310
                        LinkedList<ScoredFeature> list) throws DataException {
311

    
312
                com.vividsolutions.jts.geom.Geometry geo2;
313
                for (ScoredFeature listedSF : list) {
314
                        geo2 = Converter.geometryToJts(listedSF.getFeature()
315
                                        .getDefaultGeometry());
316
                        if (geometry.touches(geo2))
317
                                return listedSF;
318
                }
319
                return null;
320
        }
321

    
322
        /**
323
         * Get first poly of the list that it is touching the in geometry
324
         * 
325
         * @param geometry
326
         * @param list
327
         * @return
328
         * @throws DataException
329
         */
330
        private static ScoredFeature getFirstPolyTouchingSF(
331
                        com.vividsolutions.jts.geom.Geometry geometry,
332
                        LinkedList<ScoredFeature> list) throws DataException {
333

    
334
                com.vividsolutions.jts.geom.Geometry geo2;
335
                com.vividsolutions.jts.geom.Geometry geo3;
336
                for (ScoredFeature listedSF : list) {
337
                        geo2 = Converter.geometryToJts(listedSF.getFeature()
338
                                        .getDefaultGeometry());
339
                        geo3 = geometry.intersection(geo2);
340
                        for (int i = 0; i < geo3.getNumGeometries(); i++) {
341
                                int dim = geo3.getGeometryN(i).getDimension();
342
                                if (dim == 1) {
343
                                        return listedSF;
344
                                }
345
                        }
346
                }
347
                return null;
348
        }
349

    
350
        /**
351
         * This method group geometries to one attribute
352
         * 
353
         * @param desc
354
         * @param features
355
         * @return
356
         */
357
        public static HashMap<String, List<ScoredFeature>> groupScoredFeaturesByAttribute(
358
                        String desc, List<ScoredFeature> features) {
359

    
360
                HashMap<String, List<ScoredFeature>> groups = new HashMap<String, List<ScoredFeature>>();
361
                Iterator<ScoredFeature> it = features.iterator();
362
                // Go for all geometries of the collection
363
                while (it.hasNext()) {
364
                        // Get feature
365
                        ScoredFeature sFeat = (ScoredFeature) it.next();
366
                        Feature feat = null;
367
                        try {
368
                                feat = sFeat.getFeature();
369
                                String key = feat.get(desc).toString();
370
                                // Store the geometries for attribute in the List
371
                                boolean contiene = groups.containsKey(key);
372
                                if (!contiene) {
373
                                        List<ScoredFeature> featss = new ArrayList<ScoredFeature>();
374
                                        featss.add(sFeat);
375
                                        groups.put(key, featss);
376
                                } else {
377
                                        ((List<ScoredFeature>) groups.get(key)).add(sFeat);
378
                                }
379
                        } catch (DataException e) {
380
                                log.debug("Error clustering element", e);
381
                                continue;
382
                        }
383
                }
384
                return groups;
385
        }
386

    
387
        /**
388
         * Calculate the position inside single line from distance
389
         * 
390
         * @param geomJTS
391
         * @param distance
392
         * @return
393
         */
394
        public static Point getLinePositionFromDistance(
395
                        com.vividsolutions.jts.geom.Geometry geomJTS, double distance) {
396

    
397
                if (geomJTS != null) {
398
                        LengthIndexedLine lenline = new LengthIndexedLine(geomJTS);
399
                        if (distance < 0) {
400
                                distance = 0.0;
401
                        }
402
                        if (distance > geomJTS.getLength()) {
403
                                distance = geomJTS.getLength();
404
                        }
405
                        log.debug("distance:" +geomJTS.getLength());
406
                        if (lenline.isValidIndex(distance)) {
407
                                Coordinate coors = lenline.extractPoint(distance);
408

    
409
                                return getPoint(coors.x, coors.y);
410

    
411
                        }
412
                }
413
                return null;
414
        }
415

    
416
        /**
417
         * Calculate the position inside single line from relative distance
418
         * 
419
         * @param geomJTS
420
         * @param distance
421
         * @return
422
         */
423
        public static Point getLinePositionFromRelativeDistance(
424
                        com.vividsolutions.jts.geom.Geometry geomJTS, int relative) {
425
                if (geomJTS != null) {
426
                        double totaldistance = geomJTS.getLength();
427
                        LengthIndexedLine lenline = new LengthIndexedLine(geomJTS);
428

    
429
                        Coordinate coors = null;
430

    
431
                        if (relative < 0) {
432
                                coors = lenline.extractPoint(0);
433
                                return getPoint(coors.x, coors.y);
434
                        } else if (relative <= 100 && relative >= 0) {
435
                                double dist = (relative * totaldistance) / 100.0;
436
                                coors = lenline.extractPoint(dist);
437
                                return getPoint(coors.x, coors.y);
438
                        } else {
439
                                coors = lenline.extractPoint(totaldistance);
440
                                return getPoint(coors.x, coors.y);
441
                        }
442
                }
443
                return null;
444
        }
445

    
446
        /**
447
         * This method calculates a point perpendicular to the line at a distance
448
         * 
449
         * @param inicio
450
         * @param fin
451
         * @param linePoint
452
         * @param dist
453
         * @return
454
         */
455
        public static Point getPerpendicularPointFromLine(Point inicio, Point fin,
456
                        Point linePoint, double dist) {
457

    
458
                java.awt.geom.Point2D pto1 = new java.awt.geom.Point2D.Double(inicio
459
                                .getX(), inicio.getY());
460
                java.awt.geom.Point2D pto2 = new java.awt.geom.Point2D.Double(fin
461
                                .getX(), fin.getY());
462

    
463
                java.awt.geom.Point2D perpPoint = new java.awt.geom.Point2D.Double(
464
                                linePoint.getX(), linePoint.getY());
465

    
466
                java.awt.geom.Point2D[] p = UtilFunctions.getPerpendicular(pto1, pto2,
467
                                perpPoint);
468
                java.awt.geom.Point2D unit = UtilFunctions.getUnitVector(p[0], p[1]);
469

    
470
                java.awt.geom.Point2D res = new java.awt.geom.Point2D.Double(perpPoint
471
                                .getX()
472
                                + (unit.getX() * dist), perpPoint.getY() + (unit.getY() * dist));
473

    
474
                return getPoint(res.getX(), res.getY());
475
        }
476

    
477
        /**
478
         * Calculate the position in the line with offset
479
         * 
480
         * @param geoms
481
         * @param linePoint
482
         * @param dist
483
         * @return
484
         */
485
        public static Point getOffsetPosition(Geometry[] geoms, Point linePoint,
486
                        double dist) {
487

    
488
                for (int j = 0; j < geoms.length; j++) {
489
                        double[] coords = new double[6];
490
                        Point inicio = null;
491
                        Point fin = null;
492

    
493
                        Envelope enve = linePoint.getEnvelope();
494
                        Point minPto = enve.getLowerCorner();
495
                        Point maxPto = enve.getUpperCorner();
496
                        Rectangle2D rectan = new Rectangle2D.Double(minPto.getX(), minPto.getY(), maxPto.getX(), maxPto.getY()); 
497
                        boolean inter = geoms[j].intersects(rectan);
498
                        if (inter) {
499
                                PathIterator iter = geoms[j].getGeneralPath().getPathIterator(
500
                                                null);
501
                                iter.currentSegment(coords);
502
                                inicio = getPoint(coords[0], coords[1]);
503

    
504
                                iter.next();
505
                                iter.currentSegment(coords);
506
                                fin = getPoint(coords[0], coords[1]);
507

    
508
                                log.debug("Return point with offset");
509
                                return MatcherUtils.getPerpendicularPointFromLine(inicio, fin,
510
                                                linePoint, dist);
511
                        }
512
                }
513
                log.debug("Return original point without offset");
514
                return linePoint;
515
        }
516

    
517
        /**
518
         * get geometry dimension
519
         * 
520
         * @param geom
521
         * @return
522
         */
523
        public static int getGeometryDimension(Geometry geom) {
524
                com.vividsolutions.jts.geom.Geometry geomJTS = Converter
525
                                .geometryToJts(geom);
526
                return geomJTS.getDimension();
527
        }
528

    
529
        /**
530
         * Get point 2D from x and y coordinates
531
         * 
532
         * @param x
533
         * @param y
534
         * @return
535
         */
536
        public static Point getPoint(double x, double y) {
537
                Point pto = null;
538
                try {
539
                        pto = GeometryLocator.getGeometryManager().createPoint(x, y,
540
                                        Geometry.SUBTYPES.GEOM2D);
541
                } catch (LocatorException e) {
542
                        log.error("Error getting the geometry locator", e);
543
                        return null;
544
                } catch (CreateGeometryException e) {
545
                        log.error("Error creating geometry", e);
546
                        return null;
547
                }
548
                return pto;
549
        }
550

    
551
}