1 /******************************************************************************
2 *
3 * Project: OpenGIS Simple Features Reference Implementation
4 * Purpose: The OGRLinearRing geometry class.
5 * Author: Frank Warmerdam, warmerda@home.com
6 *
7 ******************************************************************************
8 * Copyright (c) 1999, Frank Warmerdam
9 *
10 * Permission is hereby granted, free of charge, to any person obtaining a
11 * copy of this software and associated documentation files (the "Software"),
12 * to deal in the Software without restriction, including without limitation
13 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
14 * and/or sell copies of the Software, and to permit persons to whom the
15 * Software is furnished to do so, subject to the following conditions:
16 *
17 * The above copyright notice and this permission notice shall be included
18 * in all copies or substantial portions of the Software.
19 *
20 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
21 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
23 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
25 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
26 * DEALINGS IN THE SOFTWARE.
27 ******************************************************************************
28 *
29 * $Log: ogrlinearring.cpp,v $
30 * Revision 1.1.1.1 2006/08/21 05:52:19 dsr
31 * Initial import as opencpn, GNU Automake compliant.
32 *
33 * Revision 1.1.1.1 2006/04/19 03:23:28 dsr
34 * Rename/Import to OpenCPN
35 *
36 * Revision 1.16 2004/02/21 15:36:14 warmerda
37 * const correctness updates for geometry: bug 289
38 *
39 * Revision 1.15 2003/09/11 22:47:54 aamici
40 * add class constructors and destructors where needed in order to
41 * let the mingw/cygwin binutils produce sensible partially linked objet files
42 * with 'ld -r'.
43 *
44 * Revision 1.14 2003/07/08 13:59:35 warmerda
45 * added poSrcRing check in copy constructor, bug 361
46 *
47 * Revision 1.13 2003/05/28 19:16:42 warmerda
48 * fixed up argument names and stuff for docs
49 *
50 * Revision 1.12 2003/01/14 22:13:35 warmerda
51 * added isClockwise() method on OGRLinearRing
52 *
53 * Revision 1.11 2002/10/24 20:38:45 warmerda
54 * fixed bug byte swapping point count in exporttowkb
55 *
56 * Revision 1.10 2002/05/02 19:44:53 warmerda
57 * fixed 3D binary support for polygon/linearring
58 *
59 * Revision 1.9 2002/04/17 21:46:22 warmerda
60 * Ensure padfZ copied in copy constructor.
61 *
62 * Revision 1.8 2002/02/22 22:24:31 warmerda
63 * fixed 3d support in clone
64 *
65 * Revision 1.7 2001/07/18 05:03:05 warmerda
66 *
67 * Revision 1.6 1999/11/18 19:02:19 warmerda
68 * expanded tabs
69 *
70 * Revision 1.5 1999/07/08 20:25:39 warmerda
71 * Remove getGeometryType() method ... now returns wkbLineString.
72 *
73 * Revision 1.4 1999/06/25 20:44:43 warmerda
74 * implemented assignSpatialReference, carry properly
75 *
76 * Revision 1.3 1999/05/23 05:34:40 warmerda
77 * added support for clone(), multipolygons and geometry collections
78 *
79 * Revision 1.2 1999/05/20 14:35:44 warmerda
80 * added support for well known text format
81 *
82 * Revision 1.1 1999/03/30 21:21:05 warmerda
83 * New
84 *
85 */
86
87 #include "ogr_geometry.h"
88 #include "ogr_p.h"
89
90 /************************************************************************/
91 /* OGRLinearRing() */
92 /************************************************************************/
93
OGRLinearRing()94 OGRLinearRing::OGRLinearRing()
95
96 {
97 }
98
99 /************************************************************************/
100 /* ~OGRLinearRing() */
101 /************************************************************************/
~OGRLinearRing()102 OGRLinearRing::~OGRLinearRing()
103
104 {
105 }
106
107 /************************************************************************/
108 /* OGRLinearRing() */
109 /************************************************************************/
110
OGRLinearRing(OGRLinearRing * poSrcRing)111 OGRLinearRing::OGRLinearRing( OGRLinearRing * poSrcRing )
112
113 {
114 if( poSrcRing == NULL )
115 {
116 CPLDebug( "OGR", "OGRLinearRing::OGRLinearRing(OGRLinearRing*poSrcRing) - passed in ring is NULL!" );
117 return;
118 }
119
120 setNumPoints( poSrcRing->getNumPoints() );
121
122 memcpy( paoPoints, poSrcRing->paoPoints,
123 sizeof(OGRRawPoint) * getNumPoints() );
124
125 if( poSrcRing->padfZ )
126 {
127 Make3D();
128 memcpy( padfZ, poSrcRing->padfZ, sizeof(double) * getNumPoints() );
129 }
130 }
131
132 /************************************************************************/
133 /* getGeometryName() */
134 /************************************************************************/
135
getGeometryName() const136 const char * OGRLinearRing::getGeometryName() const
137
138 {
139 return "LINEARRING";
140 }
141
142 /************************************************************************/
143 /* WkbSize() */
144 /* */
145 /* Disable this method. */
146 /************************************************************************/
147
WkbSize() const148 int OGRLinearRing::WkbSize() const
149
150 {
151 return 0;
152 }
153
154 /************************************************************************/
155 /* importFromWkb() */
156 /* */
157 /* Disable method for this class. */
158 /************************************************************************/
159
importFromWkb(unsigned char * pabyData,int nSize)160 OGRErr OGRLinearRing::importFromWkb( unsigned char *pabyData, int nSize )
161
162 {
163 (void) pabyData;
164 (void) nSize;
165
166 return OGRERR_UNSUPPORTED_OPERATION;
167 }
168
169 /************************************************************************/
170 /* exportToWkb() */
171 /* */
172 /* Disable method for this class. */
173 /************************************************************************/
174
exportToWkb(OGRwkbByteOrder eByteOrder,unsigned char * pabyData) const175 OGRErr OGRLinearRing::exportToWkb( OGRwkbByteOrder eByteOrder,
176 unsigned char * pabyData ) const
177
178 {
179 (void) eByteOrder;
180 (void) pabyData;
181
182 return OGRERR_UNSUPPORTED_OPERATION;
183 }
184
185 /************************************************************************/
186 /* _importFromWkb() */
187 /* */
188 /* Helper method for OGRPolygon. NOT A NORMAL importFromWkb() */
189 /* method! */
190 /************************************************************************/
191
_importFromWkb(OGRwkbByteOrder eByteOrder,int b3D,unsigned char * pabyData,int nBytesAvailable)192 OGRErr OGRLinearRing::_importFromWkb( OGRwkbByteOrder eByteOrder, int b3D,
193 unsigned char * pabyData,
194 int nBytesAvailable )
195
196 {
197 if( nBytesAvailable < 4 && nBytesAvailable != -1 )
198 return OGRERR_NOT_ENOUGH_DATA;
199
200 /* -------------------------------------------------------------------- */
201 /* Get the vertex count. */
202 /* -------------------------------------------------------------------- */
203 int nNewNumPoints;
204
205 memcpy( &nNewNumPoints, pabyData, 4 );
206
207 if( OGR_SWAP( eByteOrder ) )
208 nNewNumPoints = CPL_SWAP32(nNewNumPoints);
209
210 setNumPoints( nNewNumPoints );
211
212 if( b3D )
213 Make3D();
214 else
215 Make2D();
216
217 /* -------------------------------------------------------------------- */
218 /* Get the vertices */
219 /* -------------------------------------------------------------------- */
220 int i;
221
222 if( !b3D )
223 memcpy( paoPoints, pabyData + 4, 16 * nPointCount );
224 else
225 {
226 for( int i = 0; i < nPointCount; i++ )
227 {
228 memcpy( &(paoPoints[i].x), pabyData + 4 + 24 * i, 8 );
229 memcpy( &(paoPoints[i].y), pabyData + 4 + 24 * i + 8, 8 );
230 memcpy( padfZ + i, pabyData + 4 + 24 * i + 16, 8 );
231 }
232 }
233
234 /* -------------------------------------------------------------------- */
235 /* Byte swap if needed. */
236 /* -------------------------------------------------------------------- */
237 if( OGR_SWAP( eByteOrder ) )
238 {
239 for( i = 0; i < nPointCount; i++ )
240 {
241 CPL_SWAPDOUBLE( &(paoPoints[i].x) );
242 CPL_SWAPDOUBLE( &(paoPoints[i].y) );
243
244 if( b3D )
245 {
246 CPL_SWAPDOUBLE( padfZ + i );
247 }
248 }
249 }
250
251 return OGRERR_NONE;
252 }
253
254 /************************************************************************/
255 /* _exportToWkb() */
256 /* */
257 /* Helper method for OGRPolygon. THIS IS NOT THE NORMAL */
258 /* exportToWkb() METHOD! */
259 /************************************************************************/
260
_exportToWkb(OGRwkbByteOrder eByteOrder,int b3D,unsigned char * pabyData) const261 OGRErr OGRLinearRing::_exportToWkb( OGRwkbByteOrder eByteOrder, int b3D,
262 unsigned char * pabyData ) const
263
264 {
265 int i, nWords;
266
267 /* -------------------------------------------------------------------- */
268 /* Copy in the raw data. */
269 /* -------------------------------------------------------------------- */
270 memcpy( pabyData, &nPointCount, 4 );
271
272 /* -------------------------------------------------------------------- */
273 /* Copy in the raw data. */
274 /* -------------------------------------------------------------------- */
275 if( b3D )
276 {
277 nWords = 3 * nPointCount;
278 for( i = 0; i < nPointCount; i++ )
279 {
280 memcpy( pabyData+4+i*24, &(paoPoints[i].x), 8 );
281 memcpy( pabyData+4+i*24+8, &(paoPoints[i].y), 8 );
282 if( padfZ == NULL )
283 memset( pabyData+4+i*24+16, 0, 8 );
284 else
285 memcpy( pabyData+4+i*24+16, padfZ + i, 8 );
286 }
287 }
288 else
289 {
290 nWords = 2 * nPointCount;
291 memcpy( pabyData+4, paoPoints, 16 * nPointCount );
292 }
293
294 /* -------------------------------------------------------------------- */
295 /* Swap if needed. */
296 /* -------------------------------------------------------------------- */
297 if( OGR_SWAP( eByteOrder ) )
298 {
299 int nCount;
300
301 nCount = CPL_SWAP32( nPointCount );
302 memcpy( pabyData, &nCount, 4 );
303
304 for( i = 0; i < nWords; i++ )
305 {
306 CPL_SWAPDOUBLE( pabyData + 4 + 8 * i );
307 }
308 }
309
310 return OGRERR_NONE;
311 }
312
313 /************************************************************************/
314 /* _WkbSize() */
315 /* */
316 /* Helper method for OGRPolygon. NOT THE NORMAL WkbSize() METHOD! */
317 /************************************************************************/
318
_WkbSize(int b3D) const319 int OGRLinearRing::_WkbSize( int b3D ) const
320
321 {
322 if( b3D )
323 return 4 + 24 * nPointCount;
324 else
325 return 4 + 16 * nPointCount;
326 }
327
328 /************************************************************************/
329 /* clone() */
330 /* */
331 /* We override the OGRCurve clone() to ensure that we get the */
332 /* correct virtual table. */
333 /************************************************************************/
334
clone() const335 OGRGeometry *OGRLinearRing::clone() const
336
337 {
338 OGRLinearRing *poNewLinearRing;
339
340 poNewLinearRing = new OGRLinearRing();
341 poNewLinearRing->assignSpatialReference( getSpatialReference() );
342
343 poNewLinearRing->setPoints( nPointCount, paoPoints, padfZ );
344
345 return poNewLinearRing;
346 }
347
348 /************************************************************************/
349 /* isClockwise() */
350 /************************************************************************/
351
352 /**
353 * Returns TRUE if the ring has clockwise winding.
354 *
355 * @return TRUE if clockwise otherwise FALSE.
356 */
357
isClockwise() const358 int OGRLinearRing::isClockwise() const
359
360 {
361 double dfSum = 0.0;
362
363 for( int iVert = 0; iVert < nPointCount-1; iVert++ )
364 {
365 dfSum += paoPoints[iVert].x * paoPoints[iVert+1].y
366 - paoPoints[iVert].y * paoPoints[iVert+1].x;
367 }
368
369 dfSum += paoPoints[nPointCount-1].x * paoPoints[0].y
370 - paoPoints[nPointCount-1].y * paoPoints[0].x;
371
372 return dfSum < 0.0;
373 }
374
375