Statistics
| Revision:

svn-gvsig-desktop / trunk / libraries / libFMap / src / com / vividsolutions / jts / algorithms / SnapPointLocator.java @ 9178

History | View | Annotate | Download (6.92 KB)

1
/*
2
 * Created on 06-oct-2006
3
 *
4
 * gvSIG. Sistema de Informaci?n Geogr?fica de la Generalitat Valenciana
5
 *
6
 * Copyright (C) 2004 IVER T.I. and Generalitat Valenciana.
7
 *
8
 * This program is free software; you can redistribute it and/or
9
 * modify it under the terms of the GNU General Public License
10
 * as published by the Free Software Foundation; either version 2
11
 * of the License, or (at your option) any later version.
12
 *
13
 * This program is distributed in the hope that it will be useful,
14
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
 * GNU General Public License for more details.
17
 *
18
 * You should have received a copy of the GNU General Public License
19
 * along with this program; if not, write to the Free Software
20
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,USA.
21
 *
22
 * For more information, contact:
23
 *
24
 *  Generalitat Valenciana
25
 *   Conselleria d'Infraestructures i Transport
26
 *   Av. Blasco Ib??ez, 50
27
 *   46010 VALENCIA
28
 *   SPAIN
29
 *
30
 *      +34 963862235
31
 *   gvsig@gva.es
32
 *      www.gvsig.gva.es
33
 *
34
 *    or
35
 *
36
 *   IVER T.I. S.A
37
 *   Salamanca 50
38
 *   46005 Valencia
39
 *   Spain
40
 *
41
 *   +34 963163400
42
 *   dac@iver.es
43
 */
44
/* CVS MESSAGES:
45
*
46
* $Id: SnapPointLocator.java 9178 2006-12-04 19:30:23Z azabala $
47
* $Log$
48
* Revision 1.1  2006-12-04 19:29:31  azabala
49
* *** empty log message ***
50
*
51
* Revision 1.1  2006/10/17 18:25:53  azabala
52
* *** empty log message ***
53
*
54
* Revision 1.1  2006/10/09 19:10:56  azabala
55
* First version in CVS
56
*
57
*
58
*/
59
package com.vividsolutions.jts.algorithms;
60

    
61
import java.util.Iterator;
62

    
63

    
64
import com.vividsolutions.jts.geom.Coordinate;
65
import com.vividsolutions.jts.geom.Geometry;
66
import com.vividsolutions.jts.geom.GeometryCollection;
67
import com.vividsolutions.jts.geom.GeometryCollectionIterator;
68
import com.vividsolutions.jts.geom.LineString;
69
import com.vividsolutions.jts.geom.LinearRing;
70
import com.vividsolutions.jts.geom.Location;
71
import com.vividsolutions.jts.geom.MultiLineString;
72
import com.vividsolutions.jts.geom.MultiPolygon;
73
import com.vividsolutions.jts.geom.Polygon;
74
import com.vividsolutions.jts.geomgraph.SnappingGeometryGraph;
75

    
76
public class SnapPointLocator extends com.vividsolutions.jts.algorithm.PointLocator {
77
         private boolean isIn;         // true if the point lies in or on any Geometry element
78
          private int numBoundaries;    // the number of sub-elements whose boundaries the point lies in
79

    
80
          public SnapPointLocator() {
81
          }
82

    
83
          /**
84
           * Convenience method to test a point for intersection with
85
           * a Geometry
86
           * @param p the coordinate to test
87
           * @param geom the Geometry to test
88
           * @return <code>true</code> if the point is in the interior or boundary of the Geometry
89
           */
90
          public boolean intersects(Coordinate p, Geometry geom, double snapTolerance)
91
          {
92
            return locate(p, geom, snapTolerance) != Location.EXTERIOR;
93
          }
94

    
95
          /**
96
           * Computes the topological relationship ({@link Location}) of a single point
97
           * to a Geometry.
98
           * It handles both single-element
99
           * and multi-element Geometries.
100
           * The algorithm for multi-part Geometries
101
           * takes into account the SFS Boundary Determination Rule.
102
           *
103
           * @return the {@link Location} of the point relative to the input Geometry
104
           */
105
          public int locate(Coordinate p, Geometry geom, double snapTolerance)
106
          {
107
            if (geom.isEmpty()) return Location.EXTERIOR;
108

    
109
            if (geom instanceof LinearRing) {
110
              return locate(p, (LinearRing) geom, snapTolerance);
111
            }
112
            if (geom instanceof LineString) {
113
              return locate(p, (LineString) geom, snapTolerance);
114
            }
115
            else if (geom instanceof Polygon) {
116
              return locate(p, (Polygon) geom, snapTolerance);
117
            }
118

    
119
            isIn = false;
120
            numBoundaries = 0;
121
            computeLocation(p, geom, snapTolerance);
122
            if (SnappingGeometryGraph.isInBoundary(numBoundaries)) 
123
                    return Location.BOUNDARY;
124
            if (numBoundaries > 0 || isIn) 
125
                    return Location.INTERIOR;
126
            return Location.EXTERIOR;
127
          }
128

    
129
          private void computeLocation(Coordinate p, Geometry geom, double snapTolerance)
130
          {
131
            if (geom instanceof LinearRing) {
132
              updateLocationInfo(locate(p, (LinearRing) geom, snapTolerance));
133
            }
134
            if (geom instanceof LineString) {
135
              updateLocationInfo(locate(p, (LineString) geom, snapTolerance));
136
            }
137
            else if (geom instanceof Polygon) {
138
              updateLocationInfo(locate(p, (Polygon) geom, snapTolerance));
139
            }
140
            else if (geom instanceof MultiLineString) {
141
              MultiLineString ml = (MultiLineString) geom;
142
              for (int i = 0; i < ml.getNumGeometries(); i++) {
143
                LineString l = (LineString) ml.getGeometryN(i);
144
                updateLocationInfo(locate(p, l, snapTolerance));
145
              }
146
            }
147
            else if (geom instanceof MultiPolygon) {
148
              MultiPolygon mpoly = (MultiPolygon) geom;
149
              for (int i = 0; i < mpoly.getNumGeometries(); i++) {
150
                Polygon poly = (Polygon) mpoly.getGeometryN(i);
151
                updateLocationInfo(locate(p, poly, snapTolerance));
152
              }
153
            }
154
            else if (geom instanceof GeometryCollection) {
155
              Iterator geomi = new GeometryCollectionIterator((GeometryCollection) geom);
156
              while (geomi.hasNext()) {
157
                Geometry g2 = (Geometry) geomi.next();
158
                if (g2 != geom)
159
                  computeLocation(p, g2, snapTolerance);
160
              }
161
            }
162
          }
163

    
164
          private void updateLocationInfo(int loc)
165
          {
166
            if (loc == Location.INTERIOR) isIn = true;
167
            if (loc == Location.BOUNDARY) numBoundaries++;
168
          }
169

    
170
          private int locate(Coordinate p, LineString l, double snapTolerance)
171
          {
172
            Coordinate[] pt = l.getCoordinates();
173
            if (! l.isClosed()) {
174
              if (p.distance(pt[0]) <= snapTolerance
175
                  || p.distance(pt[pt.length - 1]) <= snapTolerance ) {
176
                return Location.BOUNDARY;
177
              }
178
            }
179
            if (SnapCGAlgorithms.isOnLine(p, pt, snapTolerance))
180
              return Location.INTERIOR;
181
            return Location.EXTERIOR;
182
          }
183

    
184
          private int locate(Coordinate p, LinearRing ring, double snapTolerance)
185
          {
186
            // can this test be folded into isPointInRing ?
187
            if (SnapCGAlgorithms.isOnLine(p, ring.getCoordinates())) {
188
              return Location.BOUNDARY;
189
            }
190
            if (SnapCGAlgorithms.isPointInRing(p, ring.getCoordinates(), snapTolerance))
191
              return Location.INTERIOR;
192
            return Location.EXTERIOR;
193
          }
194

    
195
          private int locate(Coordinate p, Polygon poly, double snapTolerance)
196
          {
197
            if (poly.isEmpty()) return Location.EXTERIOR;
198
            LinearRing shell = (LinearRing) poly.getExteriorRing();
199

    
200
            int shellLoc = locate(p, shell, snapTolerance);
201
            if (shellLoc == Location.EXTERIOR) return Location.EXTERIOR;
202
            if (shellLoc == Location.BOUNDARY) return Location.BOUNDARY;
203
            // now test if the point lies in or on the holes
204
            for (int i = 0; i < poly.getNumInteriorRing(); i++) {
205
              LinearRing hole = (LinearRing) poly.getInteriorRingN(i);
206
              int holeLoc = locate(p, hole, snapTolerance);
207
              if (holeLoc == Location.INTERIOR) return Location.EXTERIOR;
208
              if (holeLoc == Location.BOUNDARY) return Location.BOUNDARY;
209
            }
210
            return Location.INTERIOR;
211
          }
212
}
213