001 //$HeadURL: https://svn.wald.intevation.org/svn/deegree/base/branches/2.3_testing/src/org/deegree/model/spatialschema/LinearContains.java $
002 /*----------------------------------------------------------------------------
003 This file is part of deegree, http://deegree.org/
004 Copyright (C) 2001-2009 by:
005 Department of Geography, University of Bonn
006 and
007 lat/lon GmbH
008
009 This library is free software; you can redistribute it and/or modify it under
010 the terms of the GNU Lesser General Public License as published by the Free
011 Software Foundation; either version 2.1 of the License, or (at your option)
012 any later version.
013 This library is distributed in the hope that it will be useful, but WITHOUT
014 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
015 FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
016 details.
017 You should have received a copy of the GNU Lesser General Public License
018 along with this library; if not, write to the Free Software Foundation, Inc.,
019 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
020
021 Contact information:
022
023 lat/lon GmbH
024 Aennchenstr. 19, 53177 Bonn
025 Germany
026 http://lat-lon.de/
027
028 Department of Geography, University of Bonn
029 Prof. Dr. Klaus Greve
030 Postfach 1147, 53001 Bonn
031 Germany
032 http://www.geographie.uni-bonn.de/deegree/
033
034 e-mail: info@deegree.org
035 ----------------------------------------------------------------------------*/
036 package org.deegree.model.spatialschema;
037
038 import java.util.ArrayList;
039
040 /**
041 *
042 *
043 *
044 * @version $Revision: 18195 $
045 * @author <a href="mailto:poth@lat-lon.de">Andreas Poth</a>
046 * @author last edited by: $Author: mschneider $
047 *
048 * @version 1.0. $Revision: 18195 $, $Date: 2009-06-18 17:55:39 +0200 (Do, 18. Jun 2009) $
049 *
050 * @since 2.0
051 */
052 public class LinearContains {
053
054 /**
055 *
056 * @param geom1
057 * @param geom2
058 * @return maximum tolerance of geom1 and geom2
059 */
060 public static double getTolerance( Geometry geom1, Geometry geom2 ) {
061 double d = geom1.getTolerance();
062 if ( geom2.getTolerance() > d ) {
063 d = geom2.getTolerance();
064 }
065 return d;
066 }
067
068 /**
069 * Currently not supported
070 *
071 * @param point1
072 * @param point2
073 * @return true if the the two submitted points are the same......maybe.
074 */
075 public static boolean contains( Position point1, Position point2 ) {
076 throw new UnsupportedOperationException( "contains(Position, Position)" + " not supported at the moment." );
077 }
078
079 /**
080 * Currently not supported
081 *
082 * @param curve
083 * @param point
084 * @return true if the submitted point contains the submitted curve segment
085 */
086 public static boolean contains( CurveSegment curve, Position point ) {
087 throw new UnsupportedOperationException( "contains(CurveSegment, Position)" + " not supported at the moment." );
088 }
089
090 /**
091 * the operation returns true if the submitted point contains the submitted surface patch
092 *
093 * @param surface
094 * @param point
095 * @param tolerance
096 * @return true if the passed point contains the submitted surface patch
097 */
098 public static boolean contains( SurfacePatch surface, Position point, double tolerance ) {
099 boolean con = false;
100 Position[] ex = surface.getExteriorRing();
101 con = contains( ex, point, tolerance );
102
103 if ( con ) {
104 Position[][] inner = surface.getInteriorRings();
105
106 if ( inner != null ) {
107 for ( int i = 0; i < inner.length; i++ ) {
108 if ( contains( inner[i], point, tolerance ) ) {
109 con = false;
110 break;
111 }
112 }
113 }
114 }
115
116 return con;
117 }
118
119 /**
120 * the operation is currently not supported
121 *
122 * @param curve1
123 * @param curve2
124 * @return true if the two submitted curves segments contain each other.
125 */
126 public static boolean contains( CurveSegment curve1, CurveSegment curve2 ) {
127 throw new UnsupportedOperationException( "contains(CurveSegment, CurveSegment)"
128 + " not supported at the moment." );
129 }
130
131 /**
132 * the operation returns true if the submitted curve segment contains the submitted surface patch
133 *
134 * @param surface
135 * @param curve
136 * @param tolerance
137 * @return true if the submitted curve segment contains the submitted surface patch
138 */
139 public static boolean contains( SurfacePatch surface, CurveSegment curve, double tolerance ) {
140 boolean con = true;
141 Position[] ex = surface.getExteriorRing();
142 Position[] cu = curve.getPositions();
143
144 for ( int i = 0; i < cu.length; i++ ) {
145 if ( !contains( ex, cu[i], tolerance ) ) {
146 con = false;
147 break;
148 }
149 }
150
151 if ( con ) {
152 Position[][] inner = surface.getInteriorRings();
153
154 if ( inner != null ) {
155 for ( int i = 0; i < inner.length; i++ ) {
156 for ( int j = 0; j < cu.length; j++ ) {
157 if ( contains( inner[i], cu[j], tolerance ) ) {
158 con = false;
159 break;
160 }
161 }
162
163 if ( !con ) {
164 break;
165 }
166 }
167 }
168 }
169
170 return con;
171 }
172
173 /**
174 * the operation returns true if the first surface patches contains the second one
175 *
176 * @param surface1
177 * @param surface2
178 * @param tolerance
179 * @return true if the first surface patches contains
180 */
181 public static boolean contains( SurfacePatch surface1, SurfacePatch surface2, double tolerance ) {
182 boolean con = true;
183 Position[] ex = surface1.getExteriorRing();
184 Position[] ex_ = surface2.getExteriorRing();
185
186 for ( int i = 0; i < ex_.length; i++ ) {
187 if ( !contains( ex, ex_[i], tolerance ) ) {
188 con = false;
189 break;
190 }
191 }
192
193 if ( con ) {
194 Position[][] inner = surface1.getInteriorRings();
195 Position[][] inner_ = surface2.getInteriorRings();
196
197 if ( inner != null ) {
198 for ( int i = 0; i < inner.length; i++ ) {
199 // a point of the second exterior is not allowed to be
200 // within a inner ring of the first
201 for ( int j = 0; j < ex_.length; j++ ) {
202 if ( contains( inner[i], ex_[j], tolerance ) ) {
203 con = false;
204 break;
205 }
206 }
207
208 if ( !con ) {
209 break;
210 }
211
212 // a point of the inner rings of the second is not allowed
213 // to be within a inner ring of the first
214 if ( inner_ != null ) {
215 for ( int k = 0; k < inner_.length; k++ ) {
216 for ( int j = 0; j < inner_[k].length; j++ ) {
217 if ( contains( inner[i], inner_[k][j], tolerance ) ) {
218 con = false;
219 break;
220 }
221 }
222
223 if ( !con ) {
224 break;
225 }
226 }
227 }
228
229 // a point of the inner rings of the first is not allowed
230 // to be within the second surface
231 for ( int j = 0; j < inner[i].length; j++ ) {
232 if ( contains( surface2, inner[i][j], tolerance ) ) {
233 con = false;
234 break;
235 }
236 }
237
238 if ( !con ) {
239 break;
240 }
241 }
242 }
243 }
244
245 // surface2 is not allowed to contain one point of surface1
246 if ( con ) {
247 for ( int i = 0; i < ex.length; i++ ) {
248 if ( contains( surface2, ex[i], tolerance ) ) {
249 con = false;
250 break;
251 }
252 }
253 }
254
255 return con;
256 }
257
258 /**
259 * the operations returns true if two the passed points contains
260 *
261 * @param point1
262 * @param point2
263 * @return true if two the passed points contains
264 */
265 public static boolean contains( Point point1, Point point2 ) {
266 return point1.equals( point2 );
267 }
268
269 /**
270 * the operation is currently not supported.
271 *
272 * @param curve
273 * @param point
274 * @return true if the submitted point contains the submitted curve
275 */
276 public static boolean contains( Curve curve, Point point ) {
277 throw new UnsupportedOperationException( "contains(Curve, Point)" + " not supported at the moment." );
278 }
279
280 /**
281 * the operation returns true if the submitted point contains the submitted surface
282 *
283 * @param surface
284 * @param point
285 * @return true if the submitted point contains the submitted surface
286 * @throws Exception
287 */
288 public static boolean contains( Surface surface, Point point )
289 throws Exception {
290 boolean contain = false;
291 int cnt = surface.getNumberOfSurfacePatches();
292
293 double tolerance = getTolerance( surface, point );
294 for ( int i = 0; i < cnt; i++ ) {
295 if ( contains( surface.getSurfacePatchAt( i ), point.getPosition(), tolerance ) ) {
296 contain = true;
297 break;
298 }
299 }
300
301 return contain;
302 }
303
304 /**
305 * the operation is currently not supported.
306 *
307 * @param curve1
308 * @param curve2
309 * @return true if the two submitted curves contains
310 */
311 public static boolean contains( Curve curve1, Curve curve2 ) {
312 throw new UnsupportedOperationException( "contains(Curve, Curve)" + " not supported at the moment." );
313 }
314
315 /**
316 * Convenience method to extract all <tt>Position</tt>s from a <tt>Curve</tt>.
317 */
318 private static Position[] getPositions( Curve curve )
319 throws GeometryException {
320 ArrayList<Position> positions = new ArrayList<Position>( 1000 );
321
322 for ( int i = 0; i < curve.getNumberOfCurveSegments(); i++ ) {
323 CurveSegment segment = curve.getCurveSegmentAt( i );
324 Position[] segmentPos = segment.getPositions();
325
326 for ( int j = 0; j < segmentPos.length; j++ )
327 positions.add( segmentPos[j] );
328 }
329
330 return positions.toArray( new Position[positions.size()] );
331 }
332
333 /**
334 * the operation returns true if the submitted curve contains the submitted surface
335 *
336 * @param surface
337 * @param curve
338 * @return true if the submitted curve contains the submitted surface
339 * @throws GeometryException
340 */
341 public static boolean contains( Surface surface, Curve curve )
342 throws GeometryException {
343 // gather the positions of the crings (exterior and interior) and
344 // the curve as arrays of Positions
345 SurfaceBoundary boundary = (SurfaceBoundary) surface.getBoundary();
346 Ring extRing = boundary.getExteriorRing();
347 Ring[] intRings = boundary.getInteriorRings();
348
349 Position[] curvePos = getPositions( curve );
350 Position[] extRingPos = extRing.getPositions();
351 Position[][] intRingsPos = new Position[intRings.length][];
352
353 for ( int i = 0; i < intRings.length; i++ )
354 intRingsPos[i] = intRings[i].getPositions();
355
356 // necessary condition: all points of the curve have to be inside
357 // of the surface's exterior ring and none must be inside of one
358 // of the interior rings
359 for ( int i = 0; i < curvePos.length; i++ ) {
360 if ( !contains( extRingPos, curvePos[i], getTolerance( surface, curve ) ) ) {
361 return false;
362 }
363
364 for ( int j = 0; j < intRings.length; j++ ) {
365 if ( contains( intRingsPos[j], curvePos[i], getTolerance( surface, curve ) ) ) {
366 return false;
367 }
368 }
369 }
370
371 return true;
372 }
373
374 /**
375 * the operation returns true if the two submitted surfaces contains
376 *
377 * @param surface2
378 * @param surface1
379 * @return true if the two submitted surfaces contains
380 * @throws Exception
381 */
382 public static boolean contains( Surface surface2, Surface surface1 )
383 throws Exception {
384 double tolerance = getTolerance( surface1, surface2 );
385 return contains( surface2.getSurfacePatchAt( 0 ), surface1.getSurfacePatchAt( 0 ), tolerance );
386 }
387
388 /**
389 * the operation returns true if polygon defined by an array of Position contains the submitted point.
390 *
391 * @param positions
392 * @param point
393 * @param tolerance
394 * @return true if polygon defined by an array of Position contains the submitted point.
395 */
396 protected static boolean contains( Position[] positions, Position point, double tolerance ) {
397
398 // TODO
399 // consider tolerance value
400
401 if ( positions.length <= 2 ) {
402 return false;
403 }
404
405 int hits = 0;
406
407 double lastx = positions[positions.length - 1].getX();
408 double lasty = positions[positions.length - 1].getY();
409 double curx;
410 double cury;
411
412 // Walk the edges of the polygon
413 for ( int i = 0; i < positions.length; lastx = curx, lasty = cury, i++ ) {
414 curx = positions[i].getX();
415 cury = positions[i].getY();
416
417 if ( cury == lasty ) {
418 continue;
419 }
420
421 double leftx;
422
423 if ( curx < lastx ) {
424 if ( point.getX() >= lastx ) {
425 continue;
426 }
427
428 leftx = curx;
429 } else {
430 if ( point.getX() >= curx ) {
431 continue;
432 }
433
434 leftx = lastx;
435 }
436
437 double test1;
438 double test2;
439
440 if ( cury < lasty ) {
441 if ( ( point.getY() < cury ) || ( point.getY() >= lasty ) ) {
442 continue;
443 }
444
445 if ( point.getX() < leftx ) {
446 hits++;
447 continue;
448 }
449
450 test1 = point.getX() - curx;
451 test2 = point.getY() - cury;
452 } else {
453 if ( ( point.getY() < lasty ) || ( point.getY() >= cury ) ) {
454 continue;
455 }
456
457 if ( point.getX() < leftx ) {
458 hits++;
459 continue;
460 }
461
462 test1 = point.getX() - lastx;
463 test2 = point.getY() - lasty;
464 }
465
466 if ( test1 < ( test2 / ( lasty - cury ) * ( lastx - curx ) ) ) {
467 hits++;
468 }
469 }
470
471 return ( ( hits & 1 ) != 0 );
472 }
473 }