1 : /******************************************************************************
2 : * $Id: ogrpoint.cpp 16853 2009-04-26 12:22:10Z rouault $
3 : *
4 : * Project: OpenGIS Simple Features Reference Implementation
5 : * Purpose: The Point geometry class.
6 : * Author: Frank Warmerdam, warmerdam@pobox.com
7 : *
8 : ******************************************************************************
9 : * Copyright (c) 1999, Frank Warmerdam
10 : *
11 : * Permission is hereby granted, free of charge, to any person obtaining a
12 : * copy of this software and associated documentation files (the "Software"),
13 : * to deal in the Software without restriction, including without limitation
14 : * the rights to use, copy, modify, merge, publish, distribute, sublicense,
15 : * and/or sell copies of the Software, and to permit persons to whom the
16 : * Software is furnished to do so, subject to the following conditions:
17 : *
18 : * The above copyright notice and this permission notice shall be included
19 : * in all copies or substantial portions of the Software.
20 : *
21 : * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
22 : * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23 : * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
24 : * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25 : * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
26 : * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
27 : * DEALINGS IN THE SOFTWARE.
28 : ****************************************************************************/
29 :
30 : #include "ogr_geometry.h"
31 : #include "ogr_p.h"
32 :
33 : CPL_CVSID("$Id: ogrpoint.cpp 16853 2009-04-26 12:22:10Z rouault $");
34 :
35 : /************************************************************************/
36 : /* OGRPoint() */
37 : /************************************************************************/
38 :
39 : /**
40 : * \brief Create a (0,0) point.
41 : */
42 :
43 15596 : OGRPoint::OGRPoint()
44 :
45 : {
46 15596 : empty();
47 15596 : }
48 :
49 : /************************************************************************/
50 : /* OGRPoint() */
51 : /* */
52 : /* Initialize point to value. */
53 : /************************************************************************/
54 :
55 29864 : OGRPoint::OGRPoint( double xIn, double yIn, double zIn )
56 :
57 : {
58 29864 : x = xIn;
59 29864 : y = yIn;
60 29864 : z = zIn;
61 29864 : nCoordDimension = 3;
62 29864 : }
63 :
64 : /************************************************************************/
65 : /* OGRPoint() */
66 : /* */
67 : /* Initialize point to value. */
68 : /************************************************************************/
69 :
70 11464 : OGRPoint::OGRPoint( double xIn, double yIn )
71 :
72 : {
73 11464 : x = xIn;
74 11464 : y = yIn;
75 11464 : z = 0.0;
76 11464 : nCoordDimension = 2;
77 11464 : }
78 :
79 : /************************************************************************/
80 : /* ~OGRPoint() */
81 : /************************************************************************/
82 :
83 113486 : OGRPoint::~OGRPoint()
84 :
85 : {
86 113486 : }
87 :
88 : /************************************************************************/
89 : /* clone() */
90 : /* */
91 : /* Make a new object that is a copy of this object. */
92 : /************************************************************************/
93 :
94 15002 : OGRGeometry *OGRPoint::clone() const
95 :
96 : {
97 15002 : OGRPoint *poNewPoint = new OGRPoint( x, y, z );
98 :
99 15002 : poNewPoint->assignSpatialReference( getSpatialReference() );
100 15002 : poNewPoint->setCoordinateDimension( nCoordDimension );
101 :
102 15002 : return poNewPoint;
103 : }
104 :
105 : /************************************************************************/
106 : /* empty() */
107 : /************************************************************************/
108 15600 : void OGRPoint::empty()
109 :
110 : {
111 15600 : x = y = z = 0.0;
112 15600 : nCoordDimension = 0;
113 15600 : }
114 :
115 : /************************************************************************/
116 : /* getDimension() */
117 : /************************************************************************/
118 :
119 1 : int OGRPoint::getDimension() const
120 :
121 : {
122 1 : return 0;
123 : }
124 :
125 : /************************************************************************/
126 : /* getGeometryType() */
127 : /************************************************************************/
128 :
129 46323 : OGRwkbGeometryType OGRPoint::getGeometryType() const
130 :
131 : {
132 46323 : if( nCoordDimension < 3 )
133 1794 : return wkbPoint;
134 : else
135 44529 : return wkbPoint25D;
136 : }
137 :
138 : /************************************************************************/
139 : /* getGeometryName() */
140 : /************************************************************************/
141 :
142 278 : const char * OGRPoint::getGeometryName() const
143 :
144 : {
145 278 : return "POINT";
146 : }
147 :
148 : /************************************************************************/
149 : /* flattenTo2D() */
150 : /************************************************************************/
151 :
152 72 : void OGRPoint::flattenTo2D()
153 :
154 : {
155 72 : z = 0;
156 72 : if (nCoordDimension > 2)
157 2 : nCoordDimension = 2;
158 72 : }
159 :
160 : /************************************************************************/
161 : /* setCoordinateDimension() */
162 : /************************************************************************/
163 :
164 15066 : void OGRPoint::setCoordinateDimension( int nNewDimension )
165 :
166 : {
167 15066 : nCoordDimension = nNewDimension;
168 :
169 15066 : if( nCoordDimension == 2 )
170 351 : z = 0;
171 15066 : }
172 :
173 : /************************************************************************/
174 : /* WkbSize() */
175 : /* */
176 : /* Return the size of this object in well known binary */
177 : /* representation including the byte order, and type information. */
178 : /************************************************************************/
179 :
180 251 : int OGRPoint::WkbSize() const
181 :
182 : {
183 251 : if( nCoordDimension != 3 )
184 192 : return 21;
185 : else
186 59 : return 29;
187 : }
188 :
189 : /************************************************************************/
190 : /* importFromWkb() */
191 : /* */
192 : /* Initialize from serialized stream in well known binary */
193 : /* format. */
194 : /************************************************************************/
195 :
196 122 : OGRErr OGRPoint::importFromWkb( unsigned char * pabyData,
197 : int nSize )
198 :
199 : {
200 : OGRwkbByteOrder eByteOrder;
201 :
202 122 : if( nSize < 21 && nSize != -1 )
203 0 : return OGRERR_NOT_ENOUGH_DATA;
204 :
205 : /* -------------------------------------------------------------------- */
206 : /* Get the byte order byte. */
207 : /* -------------------------------------------------------------------- */
208 122 : eByteOrder = DB2_V72_FIX_BYTE_ORDER((OGRwkbByteOrder) *pabyData);
209 122 : if (!( eByteOrder == wkbXDR || eByteOrder == wkbNDR ))
210 0 : return OGRERR_CORRUPT_DATA;
211 :
212 : /* -------------------------------------------------------------------- */
213 : /* Get the geometry feature type. For now we assume that */
214 : /* geometry type is between 0 and 255 so we only have to fetch */
215 : /* one byte. */
216 : /* -------------------------------------------------------------------- */
217 : OGRwkbGeometryType eGeometryType;
218 : int bIs3D;
219 :
220 122 : if( eByteOrder == wkbNDR )
221 : {
222 105 : eGeometryType = (OGRwkbGeometryType) pabyData[1];
223 105 : bIs3D = pabyData[4] & 0x80 || pabyData[2] & 0x80;
224 : }
225 : else
226 : {
227 17 : eGeometryType = (OGRwkbGeometryType) pabyData[4];
228 17 : bIs3D = pabyData[1] & 0x80 || pabyData[3] & 0x80;
229 : }
230 :
231 122 : if( eGeometryType != wkbPoint )
232 0 : return OGRERR_CORRUPT_DATA;
233 :
234 : /* -------------------------------------------------------------------- */
235 : /* Get the vertex. */
236 : /* -------------------------------------------------------------------- */
237 122 : memcpy( &x, pabyData + 5, 16 );
238 :
239 122 : if( OGR_SWAP( eByteOrder ) )
240 : {
241 17 : CPL_SWAPDOUBLE( &x );
242 17 : CPL_SWAPDOUBLE( &y );
243 : }
244 :
245 122 : if( bIs3D )
246 : {
247 24 : memcpy( &z, pabyData + 5 + 16, 8 );
248 24 : if( OGR_SWAP( eByteOrder ) )
249 : {
250 3 : CPL_SWAPDOUBLE( &z );
251 : }
252 24 : nCoordDimension = 3;
253 : }
254 : else
255 : {
256 98 : z = 0;
257 98 : nCoordDimension = 2;
258 : }
259 :
260 122 : return OGRERR_NONE;
261 : }
262 :
263 : /************************************************************************/
264 : /* exportToWkb() */
265 : /* */
266 : /* Build a well known binary representation of this object. */
267 : /************************************************************************/
268 :
269 71 : OGRErr OGRPoint::exportToWkb( OGRwkbByteOrder eByteOrder,
270 : unsigned char * pabyData ) const
271 :
272 : {
273 : /* -------------------------------------------------------------------- */
274 : /* Set the byte order. */
275 : /* -------------------------------------------------------------------- */
276 71 : pabyData[0] = DB2_V72_UNFIX_BYTE_ORDER((unsigned char) eByteOrder);
277 :
278 : /* -------------------------------------------------------------------- */
279 : /* Set the geometry feature type. */
280 : /* -------------------------------------------------------------------- */
281 71 : GUInt32 nGType = getGeometryType();
282 :
283 71 : if( eByteOrder == wkbNDR )
284 55 : nGType = CPL_LSBWORD32( nGType );
285 : else
286 16 : nGType = CPL_MSBWORD32( nGType );
287 :
288 71 : memcpy( pabyData + 1, &nGType, 4 );
289 :
290 : /* -------------------------------------------------------------------- */
291 : /* Copy in the raw data. */
292 : /* -------------------------------------------------------------------- */
293 71 : memcpy( pabyData+5, &x, 16 );
294 :
295 71 : if( nCoordDimension == 3 )
296 : {
297 11 : memcpy( pabyData + 5 + 16, &z, 8 );
298 : }
299 :
300 : /* -------------------------------------------------------------------- */
301 : /* Swap if needed. */
302 : /* -------------------------------------------------------------------- */
303 71 : if( OGR_SWAP( eByteOrder ) )
304 : {
305 16 : CPL_SWAPDOUBLE( pabyData + 5 );
306 16 : CPL_SWAPDOUBLE( pabyData + 5 + 8 );
307 :
308 16 : if( nCoordDimension == 3 )
309 3 : CPL_SWAPDOUBLE( pabyData + 5 + 16 );
310 : }
311 :
312 71 : return OGRERR_NONE;
313 : }
314 :
315 : /************************************************************************/
316 : /* importFromWkt() */
317 : /* */
318 : /* Instantiate point from well known text format ``POINT */
319 : /* (x,y)''. */
320 : /************************************************************************/
321 :
322 14881 : OGRErr OGRPoint::importFromWkt( char ** ppszInput )
323 :
324 : {
325 : char szToken[OGR_WKT_TOKEN_MAX];
326 14881 : const char *pszInput = *ppszInput;
327 :
328 : /* -------------------------------------------------------------------- */
329 : /* Read and verify the ``POINT'' keyword token. */
330 : /* -------------------------------------------------------------------- */
331 14881 : pszInput = OGRWktReadToken( pszInput, szToken );
332 :
333 14881 : if( !EQUAL(szToken,"POINT") )
334 0 : return OGRERR_CORRUPT_DATA;
335 :
336 : /* -------------------------------------------------------------------- */
337 : /* Check for EMPTY ... but treat like a point at 0,0. */
338 : /* -------------------------------------------------------------------- */
339 : const char *pszPreScan;
340 :
341 14881 : pszPreScan = OGRWktReadToken( pszInput, szToken );
342 14881 : if( EQUAL(szToken,"EMPTY") )
343 : {
344 3 : *ppszInput = (char *) pszInput;
345 3 : empty();
346 3 : return OGRERR_NONE;
347 : }
348 :
349 14878 : if( !EQUAL(szToken,"(") )
350 0 : return OGRERR_CORRUPT_DATA;
351 :
352 14878 : pszPreScan = OGRWktReadToken( pszPreScan, szToken );
353 14878 : if( EQUAL(szToken,"EMPTY") )
354 : {
355 1 : pszInput = OGRWktReadToken( pszPreScan, szToken );
356 :
357 1 : if( !EQUAL(szToken,")") )
358 0 : return OGRERR_CORRUPT_DATA;
359 : else
360 : {
361 1 : *ppszInput = (char *) pszInput;
362 1 : empty();
363 1 : return OGRERR_NONE;
364 : }
365 : }
366 :
367 : /* -------------------------------------------------------------------- */
368 : /* Read the point list which should consist of exactly one point. */
369 : /* -------------------------------------------------------------------- */
370 14877 : OGRRawPoint *poPoints = NULL;
371 14877 : double *padfZ = NULL;
372 14877 : int nMaxPoint = 0, nPoints = 0;
373 :
374 : pszInput = OGRWktReadPoints( pszInput, &poPoints, &padfZ,
375 14877 : &nMaxPoint, &nPoints );
376 14877 : if( pszInput == NULL || nPoints != 1 )
377 0 : return OGRERR_CORRUPT_DATA;
378 :
379 14877 : x = poPoints[0].x;
380 14877 : y = poPoints[0].y;
381 :
382 14877 : CPLFree( poPoints );
383 :
384 14877 : if( padfZ != NULL )
385 : {
386 14703 : z = padfZ[0];
387 14703 : nCoordDimension = 3;
388 14703 : CPLFree( padfZ );
389 : }
390 : else
391 174 : nCoordDimension = 2;
392 :
393 14877 : *ppszInput = (char *) pszInput;
394 :
395 14877 : return OGRERR_NONE;
396 : }
397 :
398 : /************************************************************************/
399 : /* exportToWkt() */
400 : /* */
401 : /* Translate this structure into it's well known text format */
402 : /* equivelent. */
403 : /************************************************************************/
404 :
405 112 : OGRErr OGRPoint::exportToWkt( char ** ppszDstText ) const
406 :
407 : {
408 : char szTextEquiv[140];
409 : char szCoordinate[80];
410 :
411 112 : if (nCoordDimension == 0)
412 2 : *ppszDstText = CPLStrdup( "POINT EMPTY" );
413 : else
414 : {
415 110 : OGRMakeWktCoordinate(szCoordinate, x, y, z, nCoordDimension );
416 110 : sprintf( szTextEquiv, "POINT (%s)", szCoordinate );
417 110 : *ppszDstText = CPLStrdup( szTextEquiv );
418 : }
419 :
420 112 : return OGRERR_NONE;
421 : }
422 :
423 : /************************************************************************/
424 : /* getEnvelope() */
425 : /************************************************************************/
426 :
427 118 : void OGRPoint::getEnvelope( OGREnvelope * psEnvelope ) const
428 :
429 : {
430 118 : psEnvelope->MinX = psEnvelope->MaxX = getX();
431 118 : psEnvelope->MinY = psEnvelope->MaxY = getY();
432 118 : }
433 :
434 :
435 :
436 : /**
437 : * \fn double OGRPoint::getX() const;
438 : *
439 : * \brief Fetch X coordinate.
440 : *
441 : * Relates to the SFCOM IPoint::get_X() method.
442 : *
443 : * @return the X coordinate of this point.
444 : */
445 :
446 : /**
447 : * \fn double OGRPoint::getY() const;
448 : *
449 : * \brief Fetch Y coordinate.
450 : *
451 : * Relates to the SFCOM IPoint::get_Y() method.
452 : *
453 : * @return the Y coordinate of this point.
454 : */
455 :
456 : /**
457 : * \fn double OGRPoint::getZ() const;
458 : *
459 : * \brief Fetch Z coordinate.
460 : *
461 : * Relates to the SFCOM IPoint::get_Z() method.
462 : *
463 : * @return the Z coordinate of this point, or zero if it is a 2D point.
464 : */
465 :
466 : /**
467 : * \fn void OGRPoint::setX( double xIn );
468 : *
469 : * \brief Assign point X coordinate.
470 : *
471 : * There is no corresponding SFCOM method.
472 : */
473 :
474 : /**
475 : * \fn void OGRPoint::setY( double yIn );
476 : *
477 : * \brief Assign point Y coordinate.
478 : *
479 : * There is no corresponding SFCOM method.
480 : */
481 :
482 : /**
483 : * \fn void OGRPoint::setZ( double zIn );
484 : *
485 : * \brief Assign point Z coordinate.
486 : * Calling this method will force the geometry
487 : * coordinate dimension to 3D (wkbPoint|wkbZ).
488 : *
489 : * There is no corresponding SFCOM method.
490 : */
491 :
492 : /************************************************************************/
493 : /* Equal() */
494 : /************************************************************************/
495 :
496 155 : OGRBoolean OGRPoint::Equals( OGRGeometry * poOther ) const
497 :
498 : {
499 155 : OGRPoint *poOPoint = (OGRPoint *) poOther;
500 :
501 155 : if( poOPoint== this )
502 0 : return TRUE;
503 :
504 155 : if( poOther->getGeometryType() != getGeometryType() )
505 0 : return FALSE;
506 :
507 : // we should eventually test the SRS.
508 :
509 155 : if( poOPoint->getX() != getX()
510 : || poOPoint->getY() != getY()
511 : || poOPoint->getZ() != getZ() )
512 142 : return FALSE;
513 : else
514 13 : return TRUE;
515 : }
516 :
517 : /************************************************************************/
518 : /* transform() */
519 : /************************************************************************/
520 :
521 4 : OGRErr OGRPoint::transform( OGRCoordinateTransformation *poCT )
522 :
523 : {
524 : #ifdef DISABLE_OGRGEOM_TRANSFORM
525 : return OGRERR_FAILURE;
526 : #else
527 4 : if( poCT->Transform( 1, &x, &y, &z ) )
528 : {
529 4 : assignSpatialReference( poCT->GetTargetCS() );
530 4 : return OGRERR_NONE;
531 : }
532 : else
533 0 : return OGRERR_FAILURE;
534 : #endif
535 : }
536 :
537 : /************************************************************************/
538 : /* IsEmpty() */
539 : /************************************************************************/
540 :
541 14806 : OGRBoolean OGRPoint::IsEmpty( ) const
542 : {
543 14806 : return nCoordDimension == 0;
544 : }
|