1 /******************************************************************************
2 * $Id: ogrpoint.cpp 13909 2008-03-01 19:00:03Z 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 #include <assert.h>
33
34 CPL_CVSID("$Id: ogrpoint.cpp 13909 2008-03-01 19:00:03Z rouault $");
35
36 /************************************************************************/
37 /* OGRPoint() */
38 /************************************************************************/
39
40 /**
41 * Create a (0,0) point.
42 */
43
OGRPoint()44 OGRPoint::OGRPoint()
45
46 {
47 empty();
48 }
49
50 /************************************************************************/
51 /* OGRPoint() */
52 /* */
53 /* Initialize point to value. */
54 /************************************************************************/
55
OGRPoint(double xIn,double yIn,double zIn)56 OGRPoint::OGRPoint( double xIn, double yIn, double zIn )
57
58 {
59 x = xIn;
60 y = yIn;
61 z = zIn;
62 nCoordDimension = 3;
63 }
64
65 /************************************************************************/
66 /* OGRPoint() */
67 /* */
68 /* Initialize point to value. */
69 /************************************************************************/
70
OGRPoint(double xIn,double yIn)71 OGRPoint::OGRPoint( double xIn, double yIn )
72
73 {
74 x = xIn;
75 y = yIn;
76 z = 0.0;
77 nCoordDimension = 2;
78 }
79
80 /************************************************************************/
81 /* ~OGRPoint() */
82 /************************************************************************/
83
~OGRPoint()84 OGRPoint::~OGRPoint()
85
86 {
87 }
88
89 /************************************************************************/
90 /* clone() */
91 /* */
92 /* Make a new object that is a copy of this object. */
93 /************************************************************************/
94
clone() const95 OGRGeometry *OGRPoint::clone() const
96
97 {
98 OGRPoint *poNewPoint = new OGRPoint( x, y, z );
99
100 poNewPoint->assignSpatialReference( getSpatialReference() );
101 poNewPoint->setCoordinateDimension( nCoordDimension );
102
103 return poNewPoint;
104 }
105
106 /************************************************************************/
107 /* empty() */
108 /************************************************************************/
empty()109 void OGRPoint::empty()
110
111 {
112 x = y = z = 0.0;
113 nCoordDimension = 0;
114 }
115
116 /************************************************************************/
117 /* getDimension() */
118 /************************************************************************/
119
getDimension() const120 int OGRPoint::getDimension() const
121
122 {
123 return 0;
124 }
125
126 /************************************************************************/
127 /* getGeometryType() */
128 /************************************************************************/
129
getGeometryType() const130 OGRwkbGeometryType OGRPoint::getGeometryType() const
131
132 {
133 if( nCoordDimension < 3 )
134 return wkbPoint;
135 else
136 return wkbPoint25D;
137 }
138
139 /************************************************************************/
140 /* getGeometryName() */
141 /************************************************************************/
142
getGeometryName() const143 const char * OGRPoint::getGeometryName() const
144
145 {
146 return "POINT";
147 }
148
149 /************************************************************************/
150 /* flattenTo2D() */
151 /************************************************************************/
152
flattenTo2D()153 void OGRPoint::flattenTo2D()
154
155 {
156 z = 0;
157 if (nCoordDimension > 2)
158 nCoordDimension = 2;
159 }
160
161 /************************************************************************/
162 /* setCoordinateDimension() */
163 /************************************************************************/
164
setCoordinateDimension(int nNewDimension)165 void OGRPoint::setCoordinateDimension( int nNewDimension )
166
167 {
168 nCoordDimension = nNewDimension;
169
170 if( nCoordDimension == 2 )
171 z = 0;
172 }
173
174 /************************************************************************/
175 /* WkbSize() */
176 /* */
177 /* Return the size of this object in well known binary */
178 /* representation including the byte order, and type information. */
179 /************************************************************************/
180
WkbSize() const181 int OGRPoint::WkbSize() const
182
183 {
184 if( nCoordDimension != 3 )
185 return 21;
186 else
187 return 29;
188 }
189
190 /************************************************************************/
191 /* importFromWkb() */
192 /* */
193 /* Initialize from serialized stream in well known binary */
194 /* format. */
195 /************************************************************************/
196
importFromWkb(unsigned char * pabyData,int nSize)197 OGRErr OGRPoint::importFromWkb( unsigned char * pabyData,
198 int nSize )
199
200 {
201 OGRwkbByteOrder eByteOrder;
202
203 if( nSize < 21 && nSize != -1 )
204 return OGRERR_NOT_ENOUGH_DATA;
205
206 /* -------------------------------------------------------------------- */
207 /* Get the byte order byte. */
208 /* -------------------------------------------------------------------- */
209 eByteOrder = DB2_V72_FIX_BYTE_ORDER((OGRwkbByteOrder) *pabyData);
210 assert( eByteOrder == wkbXDR || eByteOrder == wkbNDR );
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 if( eByteOrder == wkbNDR )
221 {
222 eGeometryType = (OGRwkbGeometryType) pabyData[1];
223 bIs3D = pabyData[4] & 0x80 || pabyData[2] & 0x80;
224 }
225 else
226 {
227 eGeometryType = (OGRwkbGeometryType) pabyData[4];
228 bIs3D = pabyData[1] & 0x80 || pabyData[3] & 0x80;
229 }
230
231 assert( eGeometryType == wkbPoint );
232
233 /* -------------------------------------------------------------------- */
234 /* Get the vertex. */
235 /* -------------------------------------------------------------------- */
236 memcpy( &x, pabyData + 5, 16 );
237
238 if( OGR_SWAP( eByteOrder ) )
239 {
240 CPL_SWAPDOUBLE( &x );
241 CPL_SWAPDOUBLE( &y );
242 }
243
244 if( bIs3D )
245 {
246 memcpy( &z, pabyData + 5 + 16, 8 );
247 if( OGR_SWAP( eByteOrder ) )
248 {
249 CPL_SWAPDOUBLE( &z );
250 }
251 nCoordDimension = 3;
252 }
253 else
254 {
255 z = 0;
256 nCoordDimension = 2;
257 }
258
259 return OGRERR_NONE;
260 }
261
262 /************************************************************************/
263 /* exportToWkb() */
264 /* */
265 /* Build a well known binary representation of this object. */
266 /************************************************************************/
267
exportToWkb(OGRwkbByteOrder eByteOrder,unsigned char * pabyData) const268 OGRErr OGRPoint::exportToWkb( OGRwkbByteOrder eByteOrder,
269 unsigned char * pabyData ) const
270
271 {
272 /* -------------------------------------------------------------------- */
273 /* Set the byte order. */
274 /* -------------------------------------------------------------------- */
275 pabyData[0] = DB2_V72_UNFIX_BYTE_ORDER((unsigned char) eByteOrder);
276
277 /* -------------------------------------------------------------------- */
278 /* Set the geometry feature type. */
279 /* -------------------------------------------------------------------- */
280 GUInt32 nGType = getGeometryType();
281
282 if( eByteOrder == wkbNDR )
283 nGType = CPL_LSBWORD32( nGType );
284 else
285 nGType = CPL_MSBWORD32( nGType );
286
287 memcpy( pabyData + 1, &nGType, 4 );
288
289 /* -------------------------------------------------------------------- */
290 /* Copy in the raw data. */
291 /* -------------------------------------------------------------------- */
292 memcpy( pabyData+5, &x, 16 );
293
294 if( nCoordDimension == 3 )
295 {
296 memcpy( pabyData + 5 + 16, &z, 8 );
297 }
298
299 /* -------------------------------------------------------------------- */
300 /* Swap if needed. */
301 /* -------------------------------------------------------------------- */
302 if( OGR_SWAP( eByteOrder ) )
303 {
304 CPL_SWAPDOUBLE( pabyData + 5 );
305 CPL_SWAPDOUBLE( pabyData + 5 + 8 );
306
307 if( nCoordDimension == 3 )
308 CPL_SWAPDOUBLE( pabyData + 5 + 16 );
309 }
310
311 return OGRERR_NONE;
312 }
313
314 /************************************************************************/
315 /* importFromWkt() */
316 /* */
317 /* Instantiate point from well known text format ``POINT */
318 /* (x,y)''. */
319 /************************************************************************/
320
importFromWkt(char ** ppszInput)321 OGRErr OGRPoint::importFromWkt( char ** ppszInput )
322
323 {
324 char szToken[OGR_WKT_TOKEN_MAX];
325 const char *pszInput = *ppszInput;
326
327 /* -------------------------------------------------------------------- */
328 /* Read and verify the ``POINT'' keyword token. */
329 /* -------------------------------------------------------------------- */
330 pszInput = OGRWktReadToken( pszInput, szToken );
331
332 if( !EQUAL(szToken,"POINT") )
333 return OGRERR_CORRUPT_DATA;
334
335 /* -------------------------------------------------------------------- */
336 /* Check for EMPTY ... but treat like a point at 0,0. */
337 /* -------------------------------------------------------------------- */
338 const char *pszPreScan;
339
340 pszPreScan = OGRWktReadToken( pszInput, szToken );
341 if( EQUAL(szToken,"EMPTY") )
342 {
343 *ppszInput = (char *) pszInput;
344 empty();
345 return OGRERR_NONE;
346 }
347
348 if( !EQUAL(szToken,"(") )
349 return OGRERR_CORRUPT_DATA;
350
351 pszPreScan = OGRWktReadToken( pszPreScan, szToken );
352 if( EQUAL(szToken,"EMPTY") )
353 {
354 pszInput = OGRWktReadToken( pszPreScan, szToken );
355
356 if( !EQUAL(szToken,")") )
357 return OGRERR_CORRUPT_DATA;
358 else
359 {
360 *ppszInput = (char *) pszInput;
361 empty();
362 return OGRERR_NONE;
363 }
364 }
365
366 /* -------------------------------------------------------------------- */
367 /* Read the point list which should consist of exactly one point. */
368 /* -------------------------------------------------------------------- */
369 OGRRawPoint *poPoints = NULL;
370 double *padfZ = NULL;
371 int nMaxPoint = 0, nPoints = 0;
372
373 pszInput = OGRWktReadPoints( pszInput, &poPoints, &padfZ,
374 &nMaxPoint, &nPoints );
375 if( pszInput == NULL || nPoints != 1 )
376 return OGRERR_CORRUPT_DATA;
377
378 x = poPoints[0].x;
379 y = poPoints[0].y;
380
381 CPLFree( poPoints );
382
383 if( padfZ != NULL )
384 {
385 z = padfZ[0];
386 nCoordDimension = 3;
387 CPLFree( padfZ );
388 }
389 else
390 nCoordDimension = 2;
391
392 *ppszInput = (char *) pszInput;
393
394 return OGRERR_NONE;
395 }
396
397 /************************************************************************/
398 /* exportToWkt() */
399 /* */
400 /* Translate this structure into it's well known text format */
401 /* equivelent. */
402 /************************************************************************/
403
exportToWkt(char ** ppszDstText) const404 OGRErr OGRPoint::exportToWkt( char ** ppszDstText ) const
405
406 {
407 char szTextEquiv[140];
408 char szCoordinate[80];
409
410 if (nCoordDimension == 0)
411 *ppszDstText = CPLStrdup( "POINT EMPTY" );
412 else
413 {
414 OGRMakeWktCoordinate(szCoordinate, x, y, z, nCoordDimension );
415 sprintf( szTextEquiv, "POINT (%s)", szCoordinate );
416 *ppszDstText = CPLStrdup( szTextEquiv );
417 }
418
419 return OGRERR_NONE;
420 }
421
422 /************************************************************************/
423 /* getEnvelope() */
424 /************************************************************************/
425
getEnvelope(OGREnvelope * psEnvelope) const426 void OGRPoint::getEnvelope( OGREnvelope * psEnvelope ) const
427
428 {
429 psEnvelope->MinX = psEnvelope->MaxX = getX();
430 psEnvelope->MinY = psEnvelope->MaxY = getY();
431 }
432
433
434
435 /**
436 * \fn double OGRPoint::getX() const;
437 *
438 * Fetch X coordinate.
439 *
440 * Relates to the SFCOM IPoint::get_X() method.
441 *
442 * @return the X coordinate of this point.
443 */
444
445 /**
446 * \fn double OGRPoint::getY() const;
447 *
448 * Fetch Y coordinate.
449 *
450 * Relates to the SFCOM IPoint::get_Y() method.
451 *
452 * @return the Y coordinate of this point.
453 */
454
455 /**
456 * \fn double OGRPoint::getZ() const;
457 *
458 * Fetch Z coordinate.
459 *
460 * Relates to the SFCOM IPoint::get_Z() method.
461 *
462 * @return the Z coordinate of this point, or zero if it is a 2D point.
463 */
464
465 /**
466 * \fn void OGRPoint::setX( double xIn );
467 *
468 * Assign point X coordinate.
469 *
470 * There is no corresponding SFCOM method.
471 */
472
473 /**
474 * \fn void OGRPoint::setY( double yIn );
475 *
476 * Assign point Y coordinate.
477 *
478 * There is no corresponding SFCOM method.
479 */
480
481 /**
482 * \fn void OGRPoint::setZ( double zIn );
483 *
484 * Assign point Z coordinate. Calling this method will force the geometry
485 * coordinate dimension to 3D (wkbPoint|wkbZ).
486 *
487 * There is no corresponding SFCOM method.
488 */
489
490 /************************************************************************/
491 /* Equal() */
492 /************************************************************************/
493
Equals(OGRGeometry * poOther) const494 OGRBoolean OGRPoint::Equals( OGRGeometry * poOther ) const
495
496 {
497 OGRPoint *poOPoint = (OGRPoint *) poOther;
498
499 if( poOPoint== this )
500 return TRUE;
501
502 if( poOther->getGeometryType() != getGeometryType() )
503 return FALSE;
504
505 // we should eventually test the SRS.
506
507 if( poOPoint->getX() != getX()
508 || poOPoint->getY() != getY()
509 || poOPoint->getZ() != getZ() )
510 return FALSE;
511 else
512 return TRUE;
513 }
514
515 /************************************************************************/
516 /* transform() */
517 /************************************************************************/
518
transform(OGRCoordinateTransformation * poCT)519 OGRErr OGRPoint::transform( OGRCoordinateTransformation *poCT )
520
521 {
522 #ifdef DISABLE_OGRGEOM_TRANSFORM
523 return OGRERR_FAILURE;
524 #else
525 if( poCT->Transform( 1, &x, &y, &z ) )
526 {
527 assignSpatialReference( poCT->GetTargetCS() );
528 return OGRERR_NONE;
529 }
530 else
531 return OGRERR_FAILURE;
532 #endif
533 }
534
535 /************************************************************************/
536 /* IsEmpty() */
537 /************************************************************************/
538
IsEmpty() const539 OGRBoolean OGRPoint::IsEmpty( ) const
540 {
541 return nCoordDimension == 0;
542 }
543