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