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