1 : /******************************************************************************
2 : * $Id: ogrlinestring.cpp 19999 2010-07-10 09:59:58Z rouault $
3 : *
4 : * Project: OpenGIS Simple Features Reference Implementation
5 : * Purpose: The OGRLineString 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: ogrlinestring.cpp 19999 2010-07-10 09:59:58Z rouault $");
35 :
36 : /************************************************************************/
37 : /* OGRLineString() */
38 : /************************************************************************/
39 :
40 : /**
41 : * \brief Create an empty line string.
42 : */
43 :
44 19462 : OGRLineString::OGRLineString()
45 :
46 : {
47 19462 : nPointCount = 0;
48 19462 : paoPoints = NULL;
49 19462 : padfZ = NULL;
50 19462 : }
51 :
52 : /************************************************************************/
53 : /* ~OGRLineString() */
54 : /************************************************************************/
55 :
56 19462 : OGRLineString::~OGRLineString()
57 :
58 : {
59 19462 : if( paoPoints != NULL )
60 19237 : OGRFree( paoPoints );
61 19462 : if( padfZ != NULL )
62 3880 : OGRFree( padfZ );
63 19462 : }
64 :
65 : /************************************************************************/
66 : /* getGeometryType() */
67 : /************************************************************************/
68 :
69 69950 : OGRwkbGeometryType OGRLineString::getGeometryType() const
70 :
71 : {
72 69950 : if( getCoordinateDimension() == 3 )
73 28916 : return wkbLineString25D;
74 : else
75 41034 : return wkbLineString;
76 : }
77 :
78 : /************************************************************************/
79 : /* flattenTo2D() */
80 : /************************************************************************/
81 :
82 22 : void OGRLineString::flattenTo2D()
83 :
84 : {
85 22 : Make2D();
86 22 : }
87 :
88 : /************************************************************************/
89 : /* getGeometryName() */
90 : /************************************************************************/
91 :
92 635 : const char * OGRLineString::getGeometryName() const
93 :
94 : {
95 635 : return "LINESTRING";
96 : }
97 :
98 : /************************************************************************/
99 : /* clone() */
100 : /************************************************************************/
101 :
102 1834 : OGRGeometry *OGRLineString::clone() const
103 :
104 : {
105 : OGRLineString *poNewLineString;
106 :
107 1834 : poNewLineString = new OGRLineString();
108 :
109 1834 : poNewLineString->assignSpatialReference( getSpatialReference() );
110 1834 : poNewLineString->setPoints( nPointCount, paoPoints, padfZ );
111 1834 : poNewLineString->setCoordinateDimension( getCoordinateDimension() );
112 :
113 1834 : return poNewLineString;
114 : }
115 :
116 : /************************************************************************/
117 : /* empty() */
118 : /************************************************************************/
119 :
120 80 : void OGRLineString::empty()
121 :
122 : {
123 80 : setNumPoints( 0 );
124 80 : }
125 :
126 : /************************************************************************/
127 : /* getDimension() */
128 : /************************************************************************/
129 :
130 0 : int OGRLineString::getDimension() const
131 :
132 : {
133 0 : return 1;
134 : }
135 :
136 : /************************************************************************/
137 : /* setCoordinateDimension() */
138 : /************************************************************************/
139 :
140 3968 : void OGRLineString::setCoordinateDimension( int nNewDimension )
141 :
142 : {
143 3968 : nCoordDimension = nNewDimension;
144 3968 : if( nNewDimension == 2 )
145 2582 : Make2D();
146 1386 : else if( nNewDimension == 3 )
147 1386 : Make3D();
148 3968 : }
149 :
150 : /************************************************************************/
151 : /* WkbSize() */
152 : /* */
153 : /* Return the size of this object in well known binary */
154 : /* representation including the byte order, and type information. */
155 : /************************************************************************/
156 :
157 345 : int OGRLineString::WkbSize() const
158 :
159 : {
160 345 : return 5 + 4 + 8 * nPointCount * getCoordinateDimension();
161 : }
162 :
163 : /************************************************************************/
164 : /* Make2D() */
165 : /************************************************************************/
166 :
167 3035 : void OGRLineString::Make2D()
168 :
169 : {
170 3035 : if( padfZ != NULL )
171 : {
172 1422 : OGRFree( padfZ );
173 1422 : padfZ = NULL;
174 : }
175 3035 : nCoordDimension = 2;
176 3035 : }
177 :
178 : /************************************************************************/
179 : /* Make3D() */
180 : /************************************************************************/
181 :
182 28608 : void OGRLineString::Make3D()
183 :
184 : {
185 28608 : if( padfZ == NULL )
186 : {
187 5267 : if( nPointCount == 0 )
188 3561 : padfZ = (double *) OGRCalloc(sizeof(double),1);
189 : else
190 1706 : padfZ = (double *) OGRCalloc(sizeof(double),nPointCount);
191 : }
192 28608 : nCoordDimension = 3;
193 28608 : }
194 :
195 : /************************************************************************/
196 : /* getPoint() */
197 : /************************************************************************/
198 :
199 : /**
200 : * \brief Fetch a point in line string.
201 : *
202 : * This method relates to the SFCOM ILineString::get_Point() method.
203 : *
204 : * @param i the vertex to fetch, from 0 to getNumPoints()-1.
205 : * @param poPoint a point to initialize with the fetched point.
206 : */
207 :
208 516 : void OGRLineString::getPoint( int i, OGRPoint * poPoint ) const
209 :
210 : {
211 516 : assert( i >= 0 );
212 516 : assert( i < nPointCount );
213 516 : assert( poPoint != NULL );
214 :
215 516 : poPoint->setX( paoPoints[i].x );
216 516 : poPoint->setY( paoPoints[i].y );
217 :
218 516 : if( getCoordinateDimension() == 3 && padfZ != NULL )
219 100 : poPoint->setZ( padfZ[i] );
220 516 : }
221 :
222 : /**
223 : * \fn int OGRLineString::getNumPoints() const;
224 : *
225 : * \brief Fetch vertex count.
226 : *
227 : * Returns the number of vertices in the line string.
228 : *
229 : * @return vertex count.
230 : */
231 :
232 : /**
233 : * \fn double OGRLineString::getX( int iVertex ) const;
234 : *
235 : * \brief Get X at vertex.
236 : *
237 : * Returns the X value at the indicated vertex. If iVertex is out of range a
238 : * crash may occur, no internal range checking is performed.
239 : *
240 : * @param iVertex the vertex to return, between 0 and getNumPoints()-1.
241 : *
242 : * @return X value.
243 : */
244 :
245 : /**
246 : * \fn double OGRLineString::getY( int iVertex ) const;
247 : *
248 : * \brief Get Y at vertex.
249 : *
250 : * Returns the Y value at the indicated vertex. If iVertex is out of range a
251 : * crash may occur, no internal range checking is performed.
252 : *
253 : * @param iVertex the vertex to return, between 0 and getNumPoints()-1.
254 : *
255 : * @return X value.
256 : */
257 :
258 : /************************************************************************/
259 : /* getZ() */
260 : /************************************************************************/
261 :
262 : /**
263 : * \brief Get Z at vertex.
264 : *
265 : * Returns the Z (elevation) value at the indicated vertex. If no Z
266 : * value is available, 0.0 is returned. If iVertex is out of range a
267 : * crash may occur, no internal range checking is performed.
268 : *
269 : * @param iVertex the vertex to return, between 0 and getNumPoints()-1.
270 : *
271 : * @return Z value.
272 : */
273 :
274 75551 : double OGRLineString::getZ( int iVertex ) const
275 :
276 : {
277 75551 : if( padfZ != NULL && iVertex >= 0 && iVertex < nPointCount
278 : && nCoordDimension >= 3 )
279 55422 : return( padfZ[iVertex] );
280 : else
281 20129 : return 0.0;
282 : }
283 :
284 : /************************************************************************/
285 : /* setNumPoints() */
286 : /************************************************************************/
287 :
288 : /**
289 : * \brief Set number of points in geometry.
290 : *
291 : * This method primary exists to preset the number of points in a linestring
292 : * geometry before setPoint() is used to assign them to avoid reallocating
293 : * the array larger with each call to addPoint().
294 : *
295 : * This method has no SFCOM analog.
296 : *
297 : * @param nNewPointCount the new number of points for geometry.
298 : */
299 :
300 43360 : void OGRLineString::setNumPoints( int nNewPointCount )
301 :
302 : {
303 43360 : if( nNewPointCount == 0 )
304 : {
305 154 : OGRFree( paoPoints );
306 154 : paoPoints = NULL;
307 :
308 154 : OGRFree( padfZ );
309 154 : padfZ = NULL;
310 :
311 154 : nPointCount = 0;
312 154 : return;
313 : }
314 :
315 43206 : if( nNewPointCount > nPointCount )
316 : {
317 : paoPoints = (OGRRawPoint *)
318 34298 : OGRRealloc(paoPoints, sizeof(OGRRawPoint) * nNewPointCount);
319 :
320 34298 : assert( paoPoints != NULL );
321 :
322 : memset( paoPoints + nPointCount,
323 34298 : 0, sizeof(OGRRawPoint) * (nNewPointCount - nPointCount) );
324 :
325 34298 : if( getCoordinateDimension() == 3 )
326 : {
327 : padfZ = (double *)
328 4780 : OGRRealloc( padfZ, sizeof(double)*nNewPointCount );
329 : memset( padfZ + nPointCount, 0,
330 4780 : sizeof(double) * (nNewPointCount - nPointCount) );
331 : }
332 : }
333 :
334 43206 : nPointCount = nNewPointCount;
335 : }
336 :
337 : /************************************************************************/
338 : /* setPoint() */
339 : /************************************************************************/
340 :
341 : /**
342 : * \brief Set the location of a vertex in line string.
343 : *
344 : * If iPoint is larger than the number of necessary the number of existing
345 : * points in the line string, the point count will be increased to
346 : * accomodate the request.
347 : *
348 : * There is no SFCOM analog to this method.
349 : *
350 : * @param iPoint the index of the vertex to assign (zero based).
351 : * @param poPoint the value to assign to the vertex.
352 : */
353 :
354 0 : void OGRLineString::setPoint( int iPoint, OGRPoint * poPoint )
355 :
356 : {
357 0 : setPoint( iPoint, poPoint->getX(), poPoint->getY(), poPoint->getZ() );
358 0 : }
359 :
360 : /************************************************************************/
361 : /* setPoint() */
362 : /************************************************************************/
363 :
364 : /**
365 : * \brief Set the location of a vertex in line string.
366 : *
367 : * If iPoint is larger than the number of necessary the number of existing
368 : * points in the line string, the point count will be increased to
369 : * accomodate the request.
370 : *
371 : * There is no SFCOM analog to this method.
372 : *
373 : * @param iPoint the index of the vertex to assign (zero based).
374 : * @param xIn input X coordinate to assign.
375 : * @param yIn input Y coordinate to assign.
376 : * @param zIn input Z coordinate to assign (defaults to zero).
377 : */
378 :
379 23297 : void OGRLineString::setPoint( int iPoint, double xIn, double yIn, double zIn )
380 :
381 : {
382 23297 : if( getCoordinateDimension() == 2 )
383 873 : Make3D();
384 :
385 23297 : if( iPoint >= nPointCount )
386 2064 : setNumPoints( iPoint+1 );
387 :
388 23297 : paoPoints[iPoint].x = xIn;
389 23297 : paoPoints[iPoint].y = yIn;
390 :
391 23297 : if( zIn != 0.0 )
392 : {
393 21987 : Make3D();
394 21987 : padfZ[iPoint] = zIn;
395 : }
396 1310 : else if( getCoordinateDimension() == 3 )
397 : {
398 1310 : padfZ[iPoint] = 0.0;
399 : }
400 23297 : }
401 :
402 121375 : void OGRLineString::setPoint( int iPoint, double xIn, double yIn )
403 :
404 : {
405 121375 : if( iPoint >= nPointCount )
406 14652 : setNumPoints( iPoint+1 );
407 :
408 121375 : paoPoints[iPoint].x = xIn;
409 121375 : paoPoints[iPoint].y = yIn;
410 121375 : }
411 :
412 : /************************************************************************/
413 : /* addPoint() */
414 : /************************************************************************/
415 :
416 : /**
417 : * \brief Add a point to a line string.
418 : *
419 : * The vertex count of the line string is increased by one, and assigned from
420 : * the passed location value.
421 : *
422 : * There is no SFCOM analog to this method.
423 : *
424 : * @param poPoint the point to assign to the new vertex.
425 : */
426 :
427 40 : void OGRLineString::addPoint( OGRPoint * poPoint )
428 :
429 : {
430 40 : setPoint( nPointCount, poPoint->getX(), poPoint->getY(), poPoint->getZ() );
431 40 : }
432 :
433 : /************************************************************************/
434 : /* addPoint() */
435 : /************************************************************************/
436 :
437 : /**
438 : * \brief Add a point to a line string.
439 : *
440 : * The vertex count of the line string is increased by one, and assigned from
441 : * the passed location value.
442 : *
443 : * There is no SFCOM analog to this method.
444 : *
445 : * @param x the X coordinate to assign to the new point.
446 : * @param y the Y coordinate to assign to the new point.
447 : * @param z the Z coordinate to assign to the new point (defaults to zero).
448 : */
449 :
450 519 : void OGRLineString::addPoint( double x, double y, double z )
451 :
452 : {
453 519 : setPoint( nPointCount, x, y, z );
454 519 : }
455 :
456 14394 : void OGRLineString::addPoint( double x, double y )
457 :
458 : {
459 14394 : setPoint( nPointCount, x, y );
460 14394 : }
461 :
462 : /************************************************************************/
463 : /* setPoints() */
464 : /************************************************************************/
465 :
466 : /**
467 : * \brief Assign all points in a line string.
468 : *
469 : * This method clears any existing points assigned to this line string,
470 : * and assigns a whole new set. It is the most efficient way of assigning
471 : * the value of a line string.
472 : *
473 : * There is no SFCOM analog to this method.
474 : *
475 : * @param nPointsIn number of points being passed in paoPointsIn
476 : * @param paoPointsIn list of points being assigned.
477 : * @param padfZ the Z values that go with the points (optional, may be NULL).
478 : */
479 :
480 : void OGRLineString::setPoints( int nPointsIn, OGRRawPoint * paoPointsIn,
481 2735 : double * padfZ )
482 :
483 : {
484 2735 : setNumPoints( nPointsIn );
485 2735 : memcpy( paoPoints, paoPointsIn, sizeof(OGRRawPoint) * nPointsIn);
486 :
487 : /* -------------------------------------------------------------------- */
488 : /* Check 2D/3D. */
489 : /* -------------------------------------------------------------------- */
490 2735 : if( padfZ == NULL && getCoordinateDimension() > 2 )
491 : {
492 0 : Make2D();
493 : }
494 2735 : else if( padfZ )
495 : {
496 1483 : Make3D();
497 1483 : memcpy( this->padfZ, padfZ, sizeof(double) * nPointsIn );
498 : }
499 2735 : }
500 :
501 : /************************************************************************/
502 : /* setPoints() */
503 : /************************************************************************/
504 :
505 : /**
506 : * \brief Assign all points in a line string.
507 : *
508 : * This method clear any existing points assigned to this line string,
509 : * and assigns a whole new set.
510 : *
511 : * There is no SFCOM analog to this method.
512 : *
513 : * @param nPointsIn number of points being passed in padfX and padfY.
514 : * @param padfX list of X coordinates of points being assigned.
515 : * @param padfY list of Y coordinates of points being assigned.
516 : * @param padfZ list of Z coordinates of points being assigned (defaults to
517 : * NULL for 2D objects).
518 : */
519 :
520 : void OGRLineString::setPoints( int nPointsIn, double * padfX, double * padfY,
521 2731 : double * padfZ )
522 :
523 : {
524 : int i;
525 :
526 : /* -------------------------------------------------------------------- */
527 : /* Check 2D/3D. */
528 : /* -------------------------------------------------------------------- */
529 2731 : if( padfZ == NULL )
530 24 : Make2D();
531 : else
532 2707 : Make3D();
533 :
534 : /* -------------------------------------------------------------------- */
535 : /* Assign values. */
536 : /* -------------------------------------------------------------------- */
537 2731 : setNumPoints( nPointsIn );
538 :
539 72616 : for( i = 0; i < nPointsIn; i++ )
540 : {
541 69885 : paoPoints[i].x = padfX[i];
542 69885 : paoPoints[i].y = padfY[i];
543 : }
544 :
545 2731 : if( this->padfZ != NULL )
546 2707 : memcpy( this->padfZ, padfZ, sizeof(double) * nPointsIn );
547 2731 : }
548 :
549 : /************************************************************************/
550 : /* getPoints() */
551 : /************************************************************************/
552 :
553 : /**
554 : * \brief Returns all points of line string.
555 : *
556 : * This method copies all points into user list. This list must be at
557 : * least sizeof(OGRRawPoint) * OGRGeometry::getNumPoints() byte in size.
558 : * It also copies all Z coordinates.
559 : *
560 : * There is no SFCOM analog to this method.
561 : *
562 : * @param paoPointsOut a buffer into which the points is written.
563 : * @param padfZ the Z values that go with the points (optional, may be NULL).
564 : */
565 :
566 0 : void OGRLineString::getPoints( OGRRawPoint * paoPointsOut, double * padfZ ) const
567 : {
568 0 : if ( ! paoPointsOut )
569 0 : return;
570 :
571 0 : memcpy( paoPointsOut, paoPoints, sizeof(OGRRawPoint) * nPointCount );
572 :
573 : /* -------------------------------------------------------------------- */
574 : /* Check 2D/3D. */
575 : /* -------------------------------------------------------------------- */
576 0 : if( padfZ )
577 : {
578 0 : if ( this->padfZ )
579 0 : memcpy( padfZ, this->padfZ, sizeof(double) * nPointCount );
580 : else
581 0 : memset( padfZ, 0, sizeof(double) * nPointCount );
582 : }
583 : }
584 :
585 :
586 : /************************************************************************/
587 : /* addSubLineString() */
588 : /************************************************************************/
589 :
590 : /**
591 : * \brief Add a segment of another linestring to this one.
592 : *
593 : * Adds the request range of vertices to the end of this line string
594 : * in an efficient manner. If the nStartVertex is larger than the
595 : * nEndVertex then the vertices will be reversed as they are copied.
596 : *
597 : * @param poOtherLine the other OGRLineString.
598 : * @param nStartVertex the first vertex to copy, defaults to 0 to start
599 : * with the first vertex in the other linestring.
600 : * @param nEndVertex the last vertex to copy, defaults to -1 indicating
601 : * the last vertex of the other line string.
602 : */
603 :
604 : void OGRLineString::addSubLineString( const OGRLineString *poOtherLine,
605 53 : int nStartVertex, int nEndVertex )
606 :
607 : {
608 : /* -------------------------------------------------------------------- */
609 : /* Do a bit of argument defaulting and validation. */
610 : /* -------------------------------------------------------------------- */
611 53 : if( nEndVertex == -1 )
612 28 : nEndVertex = poOtherLine->getNumPoints() - 1;
613 :
614 53 : if( nStartVertex < 0 || nEndVertex < 0
615 : || nStartVertex >= poOtherLine->getNumPoints()
616 : || nEndVertex >= poOtherLine->getNumPoints() )
617 : {
618 0 : CPLAssert( FALSE );
619 0 : return;
620 : }
621 :
622 : /* -------------------------------------------------------------------- */
623 : /* Grow this linestring to hold the additional points. */
624 : /* -------------------------------------------------------------------- */
625 53 : int nOldPoints = nPointCount;
626 53 : int nPointsToAdd = ABS(nEndVertex-nStartVertex) + 1;
627 :
628 53 : setNumPoints( nPointsToAdd + nOldPoints );
629 :
630 : /* -------------------------------------------------------------------- */
631 : /* Copy the x/y points - forward copies use memcpy. */
632 : /* -------------------------------------------------------------------- */
633 53 : if( nEndVertex >= nStartVertex )
634 : {
635 : memcpy( paoPoints + nOldPoints,
636 : poOtherLine->paoPoints + nStartVertex,
637 47 : sizeof(OGRRawPoint) * nPointsToAdd );
638 47 : if( poOtherLine->padfZ != NULL )
639 : {
640 9 : Make3D();
641 : memcpy( padfZ + nOldPoints, poOtherLine->padfZ + nStartVertex,
642 9 : sizeof(double) * nPointsToAdd );
643 : }
644 : }
645 :
646 : /* -------------------------------------------------------------------- */
647 : /* Copy the x/y points - reverse copies done double by double. */
648 : /* -------------------------------------------------------------------- */
649 : else
650 : {
651 : int i;
652 :
653 26 : for( i = 0; i < nPointsToAdd; i++ )
654 : {
655 : paoPoints[i+nOldPoints].x =
656 20 : poOtherLine->paoPoints[nStartVertex-i].x;
657 : paoPoints[i+nOldPoints].y =
658 20 : poOtherLine->paoPoints[nStartVertex-i].y;
659 : }
660 :
661 6 : if( poOtherLine->padfZ != NULL )
662 : {
663 0 : Make3D();
664 :
665 0 : for( i = 0; i < nPointsToAdd; i++ )
666 : {
667 0 : padfZ[i+nOldPoints] = poOtherLine->padfZ[nStartVertex-i];
668 : }
669 : }
670 : }
671 : }
672 :
673 : /************************************************************************/
674 : /* importFromWkb() */
675 : /* */
676 : /* Initialize from serialized stream in well known binary */
677 : /* format. */
678 : /************************************************************************/
679 :
680 : OGRErr OGRLineString::importFromWkb( unsigned char * pabyData,
681 144 : int nSize )
682 :
683 : {
684 : OGRwkbByteOrder eByteOrder;
685 :
686 144 : if( nSize < 9 && nSize != -1 )
687 0 : return OGRERR_NOT_ENOUGH_DATA;
688 :
689 : /* -------------------------------------------------------------------- */
690 : /* Get the byte order byte. */
691 : /* -------------------------------------------------------------------- */
692 144 : eByteOrder = DB2_V72_FIX_BYTE_ORDER((OGRwkbByteOrder) *pabyData);
693 144 : if (!( eByteOrder == wkbXDR || eByteOrder == wkbNDR ))
694 0 : return OGRERR_CORRUPT_DATA;
695 :
696 : /* -------------------------------------------------------------------- */
697 : /* Get the geometry feature type. For now we assume that */
698 : /* geometry type is between 0 and 255 so we only have to fetch */
699 : /* one byte. */
700 : /* -------------------------------------------------------------------- */
701 : OGRwkbGeometryType eGeometryType;
702 144 : int bIs3D = FALSE;
703 :
704 144 : if( eByteOrder == wkbNDR )
705 : {
706 132 : eGeometryType = (OGRwkbGeometryType) pabyData[1];
707 132 : bIs3D = pabyData[4] & 0x80 || pabyData[2] & 0x80;
708 : }
709 : else
710 : {
711 12 : eGeometryType = (OGRwkbGeometryType) pabyData[4];
712 12 : bIs3D = pabyData[1] & 0x80 || pabyData[3] & 0x80;
713 : }
714 :
715 144 : if( eGeometryType != wkbLineString )
716 0 : return OGRERR_CORRUPT_DATA;
717 :
718 : /* -------------------------------------------------------------------- */
719 : /* Get the vertex count. */
720 : /* -------------------------------------------------------------------- */
721 : int nNewNumPoints;
722 :
723 144 : memcpy( &nNewNumPoints, pabyData + 5, 4 );
724 :
725 144 : if( OGR_SWAP( eByteOrder ) )
726 12 : nNewNumPoints = CPL_SWAP32(nNewNumPoints);
727 :
728 : /* Check if the wkb stream buffer is big enough to store
729 : * fetched number of points.
730 : * 16 or 24 - size of point structure
731 : */
732 144 : int nPointSize = (bIs3D ? 24 : 16);
733 144 : if (nNewNumPoints < 0 || nNewNumPoints > INT_MAX / nPointSize)
734 0 : return OGRERR_CORRUPT_DATA;
735 144 : int nBufferMinSize = nPointSize * nNewNumPoints;
736 :
737 144 : if( nSize != -1 && nBufferMinSize > nSize-9 )
738 : {
739 : CPLError( CE_Failure, CPLE_AppDefined,
740 0 : "Length of input WKB is too small" );
741 0 : return OGRERR_NOT_ENOUGH_DATA;
742 : }
743 :
744 144 : setNumPoints( nNewNumPoints );
745 :
746 144 : if( bIs3D )
747 24 : Make3D();
748 : else
749 120 : Make2D();
750 :
751 : /* -------------------------------------------------------------------- */
752 : /* Get the vertex. */
753 : /* -------------------------------------------------------------------- */
754 144 : int i = 0;
755 :
756 144 : if( bIs3D )
757 : {
758 98 : for( i = 0; i < nPointCount; i++ )
759 : {
760 74 : memcpy( paoPoints + i, pabyData + 9 + i*24, 16 );
761 74 : memcpy( padfZ + i, pabyData + 9 + 16 + i*24, 8 );
762 : }
763 : }
764 : else
765 : {
766 120 : memcpy( paoPoints, pabyData + 9, 16 * nPointCount );
767 : }
768 :
769 : /* -------------------------------------------------------------------- */
770 : /* Byte swap if needed. */
771 : /* -------------------------------------------------------------------- */
772 144 : if( OGR_SWAP( eByteOrder ) )
773 : {
774 82 : for( i = 0; i < nPointCount; i++ )
775 : {
776 70 : CPL_SWAPDOUBLE( &(paoPoints[i].x) );
777 70 : CPL_SWAPDOUBLE( &(paoPoints[i].y) );
778 : }
779 :
780 12 : if( bIs3D )
781 : {
782 8 : for( i = 0; i < nPointCount; i++ )
783 : {
784 6 : CPL_SWAPDOUBLE( padfZ + i );
785 : }
786 : }
787 : }
788 :
789 144 : return OGRERR_NONE;
790 : }
791 :
792 : /************************************************************************/
793 : /* exportToWkb() */
794 : /* */
795 : /* Build a well known binary representation of this object. */
796 : /************************************************************************/
797 :
798 : OGRErr OGRLineString::exportToWkb( OGRwkbByteOrder eByteOrder,
799 72 : unsigned char * pabyData ) const
800 :
801 : {
802 : /* -------------------------------------------------------------------- */
803 : /* Set the byte order. */
804 : /* -------------------------------------------------------------------- */
805 72 : pabyData[0] = DB2_V72_UNFIX_BYTE_ORDER((unsigned char) eByteOrder);
806 :
807 : /* -------------------------------------------------------------------- */
808 : /* Set the geometry feature type. */
809 : /* -------------------------------------------------------------------- */
810 72 : GUInt32 nGType = getGeometryType();
811 :
812 72 : if( eByteOrder == wkbNDR )
813 61 : nGType = CPL_LSBWORD32( nGType );
814 : else
815 11 : nGType = CPL_MSBWORD32( nGType );
816 :
817 72 : memcpy( pabyData + 1, &nGType, 4 );
818 :
819 : /* -------------------------------------------------------------------- */
820 : /* Copy in the data count. */
821 : /* -------------------------------------------------------------------- */
822 72 : memcpy( pabyData+5, &nPointCount, 4 );
823 :
824 : /* -------------------------------------------------------------------- */
825 : /* Copy in the raw data. */
826 : /* -------------------------------------------------------------------- */
827 : int i;
828 :
829 72 : if( getCoordinateDimension() == 3 )
830 : {
831 36 : for( i = 0; i < nPointCount; i++ )
832 : {
833 28 : memcpy( pabyData + 9 + 24*i, paoPoints+i, 16 );
834 28 : memcpy( pabyData + 9 + 16 + 24*i, padfZ+i, 8 );
835 : }
836 : }
837 : else
838 64 : memcpy( pabyData+9, paoPoints, 16 * nPointCount );
839 :
840 : /* -------------------------------------------------------------------- */
841 : /* Swap if needed. */
842 : /* -------------------------------------------------------------------- */
843 72 : if( OGR_SWAP( eByteOrder ) )
844 : {
845 : int nCount;
846 :
847 11 : nCount = CPL_SWAP32( nPointCount );
848 11 : memcpy( pabyData+5, &nCount, 4 );
849 :
850 149 : for( i = getCoordinateDimension() * nPointCount - 1; i >= 0; i-- )
851 : {
852 138 : CPL_SWAP64PTR( pabyData + 9 + 8 * i );
853 : }
854 : }
855 :
856 72 : return OGRERR_NONE;
857 : }
858 :
859 : /************************************************************************/
860 : /* importFromWkt() */
861 : /* */
862 : /* Instantiate from well known text format. Currently this is */
863 : /* `LINESTRING ( x y, x y, ...)', */
864 : /************************************************************************/
865 :
866 182 : OGRErr OGRLineString::importFromWkt( char ** ppszInput )
867 :
868 : {
869 : char szToken[OGR_WKT_TOKEN_MAX];
870 182 : const char *pszInput = *ppszInput;
871 :
872 182 : if( paoPoints != NULL )
873 : {
874 0 : nPointCount = 0;
875 :
876 0 : CPLFree( paoPoints );
877 0 : paoPoints = NULL;
878 :
879 0 : CPLFree( padfZ );
880 0 : padfZ = NULL;
881 : }
882 :
883 : /* -------------------------------------------------------------------- */
884 : /* Read and verify the ``LINESTRING'' keyword token. */
885 : /* -------------------------------------------------------------------- */
886 182 : pszInput = OGRWktReadToken( pszInput, szToken );
887 :
888 182 : if( !EQUAL(szToken,getGeometryName()) )
889 0 : return OGRERR_CORRUPT_DATA;
890 :
891 : /* -------------------------------------------------------------------- */
892 : /* Check for EMPTY */
893 : /* -------------------------------------------------------------------- */
894 : const char *pszPreScan;
895 182 : int bHasZ = FALSE, bHasM = FALSE;
896 :
897 182 : pszPreScan = OGRWktReadToken( pszInput, szToken );
898 182 : if( EQUAL(szToken,"EMPTY") )
899 : {
900 11 : *ppszInput = (char *) pszPreScan;
901 11 : return OGRERR_NONE;
902 : }
903 :
904 : /* -------------------------------------------------------------------- */
905 : /* Check for Z, M or ZM. Will ignore the Measure */
906 : /* -------------------------------------------------------------------- */
907 171 : else if( EQUAL(szToken,"Z") )
908 : {
909 12 : bHasZ = TRUE;
910 : }
911 159 : else if( EQUAL(szToken,"M") )
912 : {
913 3 : bHasM = TRUE;
914 : }
915 156 : else if( EQUAL(szToken,"ZM") )
916 : {
917 3 : bHasZ = TRUE;
918 3 : bHasM = TRUE;
919 : }
920 :
921 171 : if (bHasZ || bHasM)
922 : {
923 18 : pszInput = pszPreScan;
924 18 : pszPreScan = OGRWktReadToken( pszInput, szToken );
925 18 : if( EQUAL(szToken,"EMPTY") )
926 : {
927 4 : *ppszInput = (char *) pszPreScan;
928 4 : empty();
929 : /* FIXME?: In theory we should store the dimension and M presence */
930 : /* if we want to allow round-trip with ExportToWKT v1.2 */
931 4 : return OGRERR_NONE;
932 : }
933 : }
934 :
935 167 : if( !EQUAL(szToken,"(") )
936 4 : return OGRERR_CORRUPT_DATA;
937 :
938 163 : if ( !bHasZ && !bHasM )
939 : {
940 : /* Test for old-style LINESTRING(EMPTY) */
941 151 : pszPreScan = OGRWktReadToken( pszPreScan, szToken );
942 151 : if( EQUAL(szToken,"EMPTY") )
943 : {
944 3 : pszInput = OGRWktReadToken( pszPreScan, szToken );
945 :
946 3 : if( !EQUAL(szToken,")") )
947 1 : return OGRERR_CORRUPT_DATA;
948 : else
949 : {
950 2 : *ppszInput = (char *) pszInput;
951 2 : empty();
952 2 : return OGRERR_NONE;
953 : }
954 : }
955 : }
956 :
957 : /* -------------------------------------------------------------------- */
958 : /* Read the point list. */
959 : /* -------------------------------------------------------------------- */
960 160 : int nMaxPoint = 0;
961 :
962 160 : nPointCount = 0;
963 :
964 : pszInput = OGRWktReadPoints( pszInput, &paoPoints, &padfZ, &nMaxPoint,
965 160 : &nPointCount );
966 160 : if( pszInput == NULL )
967 15 : return OGRERR_CORRUPT_DATA;
968 :
969 145 : *ppszInput = (char *) pszInput;
970 :
971 145 : if( padfZ == NULL )
972 108 : nCoordDimension = 2;
973 : else
974 : {
975 : /* Ignore Z array when we have a LINESTRING M */
976 39 : if (bHasM && !bHasZ)
977 : {
978 2 : nCoordDimension = 2;
979 2 : CPLFree(padfZ);
980 2 : padfZ = NULL;
981 : }
982 : else
983 35 : nCoordDimension = 3;
984 : }
985 :
986 145 : return OGRERR_NONE;
987 : }
988 :
989 : /************************************************************************/
990 : /* exportToWkt() */
991 : /* */
992 : /* Translate this structure into it's well known text format */
993 : /* equivelent. This could be made alot more CPU efficient! */
994 : /************************************************************************/
995 :
996 452 : OGRErr OGRLineString::exportToWkt( char ** ppszDstText ) const
997 :
998 : {
999 452 : int nMaxString = nPointCount * 40 * 3 + 20;
1000 452 : int nRetLen = 0;
1001 :
1002 : /* -------------------------------------------------------------------- */
1003 : /* Handle special empty case. */
1004 : /* -------------------------------------------------------------------- */
1005 452 : if( nPointCount == 0 )
1006 : {
1007 22 : CPLString osEmpty;
1008 22 : osEmpty.Printf("%s EMPTY",getGeometryName());
1009 22 : *ppszDstText = CPLStrdup(osEmpty);
1010 22 : return OGRERR_NONE;
1011 : }
1012 :
1013 : /* -------------------------------------------------------------------- */
1014 : /* General case. */
1015 : /* -------------------------------------------------------------------- */
1016 430 : *ppszDstText = (char *) VSIMalloc( nMaxString );
1017 430 : if( *ppszDstText == NULL )
1018 0 : return OGRERR_NOT_ENOUGH_MEMORY;
1019 :
1020 430 : sprintf( *ppszDstText, "%s (", getGeometryName() );
1021 :
1022 5446 : for( int i = 0; i < nPointCount; i++ )
1023 : {
1024 5016 : if( nMaxString <= (int) strlen(*ppszDstText+nRetLen) + 32 + nRetLen )
1025 : {
1026 : CPLDebug( "OGR",
1027 : "OGRLineString::exportToWkt() ... buffer overflow.\n"
1028 : "nMaxString=%d, strlen(*ppszDstText) = %d, i=%d\n"
1029 : "*ppszDstText = %s",
1030 0 : nMaxString, (int) strlen(*ppszDstText), i, *ppszDstText );
1031 :
1032 0 : VSIFree( *ppszDstText );
1033 0 : *ppszDstText = NULL;
1034 0 : return OGRERR_NOT_ENOUGH_MEMORY;
1035 : }
1036 :
1037 5016 : if( i > 0 )
1038 4586 : strcat( *ppszDstText + nRetLen, "," );
1039 :
1040 5016 : nRetLen += strlen(*ppszDstText + nRetLen);
1041 5016 : if( getCoordinateDimension() == 3 )
1042 : OGRMakeWktCoordinate( *ppszDstText + nRetLen,
1043 : paoPoints[i].x,
1044 : paoPoints[i].y,
1045 : padfZ[i],
1046 578 : nCoordDimension );
1047 : else
1048 : OGRMakeWktCoordinate( *ppszDstText + nRetLen,
1049 : paoPoints[i].x,
1050 : paoPoints[i].y,
1051 : 0.0,
1052 4438 : nCoordDimension );
1053 :
1054 5016 : nRetLen += strlen(*ppszDstText + nRetLen);
1055 : }
1056 :
1057 430 : strcat( *ppszDstText+nRetLen, ")" );
1058 :
1059 430 : return OGRERR_NONE;
1060 : }
1061 :
1062 : /************************************************************************/
1063 : /* get_Length() */
1064 : /* */
1065 : /* For now we return a simple euclidian 2D distance. */
1066 : /************************************************************************/
1067 :
1068 0 : double OGRLineString::get_Length() const
1069 :
1070 : {
1071 0 : double dfLength = 0;
1072 : int i;
1073 :
1074 0 : for( i = 0; i < nPointCount-1; i++ )
1075 : {
1076 : double dfDeltaX, dfDeltaY;
1077 :
1078 0 : dfDeltaX = paoPoints[i+1].x - paoPoints[i].x;
1079 0 : dfDeltaY = paoPoints[i+1].y - paoPoints[i].y;
1080 0 : dfLength += sqrt(dfDeltaX*dfDeltaX + dfDeltaY*dfDeltaY);
1081 : }
1082 :
1083 0 : return dfLength;
1084 : }
1085 :
1086 : /************************************************************************/
1087 : /* StartPoint() */
1088 : /************************************************************************/
1089 :
1090 0 : void OGRLineString::StartPoint( OGRPoint * poPoint ) const
1091 :
1092 : {
1093 0 : getPoint( 0, poPoint );
1094 0 : }
1095 :
1096 : /************************************************************************/
1097 : /* EndPoint() */
1098 : /************************************************************************/
1099 :
1100 0 : void OGRLineString::EndPoint( OGRPoint * poPoint ) const
1101 :
1102 : {
1103 0 : getPoint( nPointCount-1, poPoint );
1104 0 : }
1105 :
1106 : /************************************************************************/
1107 : /* Value() */
1108 : /* */
1109 : /* Get an interpolated point at some distance along the curve. */
1110 : /************************************************************************/
1111 :
1112 0 : void OGRLineString::Value( double dfDistance, OGRPoint * poPoint ) const
1113 :
1114 : {
1115 0 : double dfLength = 0;
1116 : int i;
1117 :
1118 0 : if( dfDistance < 0 )
1119 : {
1120 0 : StartPoint( poPoint );
1121 0 : return;
1122 : }
1123 :
1124 0 : for( i = 0; i < nPointCount-1; i++ )
1125 : {
1126 : double dfDeltaX, dfDeltaY, dfSegLength;
1127 :
1128 0 : dfDeltaX = paoPoints[i+1].x - paoPoints[i].x;
1129 0 : dfDeltaY = paoPoints[i+1].y - paoPoints[i].y;
1130 0 : dfSegLength = sqrt(dfDeltaX*dfDeltaX + dfDeltaY*dfDeltaY);
1131 :
1132 0 : if (dfSegLength > 0)
1133 : {
1134 0 : if( (dfLength <= dfDistance) && ((dfLength + dfSegLength) >=
1135 : dfDistance) )
1136 : {
1137 : double dfRatio;
1138 :
1139 0 : dfRatio = (dfDistance - dfLength) / dfSegLength;
1140 :
1141 : poPoint->setX( paoPoints[i].x * (1 - dfRatio)
1142 0 : + paoPoints[i+1].x * dfRatio );
1143 : poPoint->setY( paoPoints[i].y * (1 - dfRatio)
1144 0 : + paoPoints[i+1].y * dfRatio );
1145 :
1146 0 : if( getCoordinateDimension() == 3 )
1147 : poPoint->setZ( padfZ[i] * (1 - dfRatio)
1148 0 : + padfZ[i] * dfRatio );
1149 :
1150 0 : return;
1151 : }
1152 :
1153 0 : dfLength += dfSegLength;
1154 : }
1155 : }
1156 :
1157 0 : EndPoint( poPoint );
1158 : }
1159 :
1160 : /************************************************************************/
1161 : /* getEnvelope() */
1162 : /************************************************************************/
1163 :
1164 1038 : void OGRLineString::getEnvelope( OGREnvelope * psEnvelope ) const
1165 :
1166 : {
1167 : double dfMinX, dfMinY, dfMaxX, dfMaxY;
1168 :
1169 1038 : if( nPointCount == 0 )
1170 : {
1171 1 : psEnvelope->MinX = 0;
1172 1 : psEnvelope->MaxX = 0;
1173 1 : psEnvelope->MinY = 0;
1174 1 : psEnvelope->MaxY = 0;
1175 1 : return;
1176 : }
1177 :
1178 1037 : dfMinX = dfMaxX = paoPoints[0].x;
1179 1037 : dfMinY = dfMaxY = paoPoints[0].y;
1180 :
1181 90561 : for( int iPoint = 1; iPoint < nPointCount; iPoint++ )
1182 : {
1183 89524 : if( dfMaxX < paoPoints[iPoint].x )
1184 11706 : dfMaxX = paoPoints[iPoint].x;
1185 89524 : if( dfMaxY < paoPoints[iPoint].y )
1186 11649 : dfMaxY = paoPoints[iPoint].y;
1187 89524 : if( dfMinX > paoPoints[iPoint].x )
1188 3371 : dfMinX = paoPoints[iPoint].x;
1189 89524 : if( dfMinY > paoPoints[iPoint].y )
1190 6137 : dfMinY = paoPoints[iPoint].y;
1191 : }
1192 :
1193 1037 : psEnvelope->MinX = dfMinX;
1194 1037 : psEnvelope->MaxX = dfMaxX;
1195 1037 : psEnvelope->MinY = dfMinY;
1196 1037 : psEnvelope->MaxY = dfMaxY;
1197 : }
1198 :
1199 : /************************************************************************/
1200 : /* Equals() */
1201 : /************************************************************************/
1202 :
1203 3 : OGRBoolean OGRLineString::Equals( OGRGeometry * poOther ) const
1204 :
1205 : {
1206 3 : OGRLineString *poOLine = (OGRLineString *) poOther;
1207 :
1208 3 : if( poOLine == this )
1209 0 : return TRUE;
1210 :
1211 3 : if( poOther->getGeometryType() != getGeometryType() )
1212 0 : return FALSE;
1213 :
1214 : // we should eventually test the SRS.
1215 :
1216 3 : if( getNumPoints() != poOLine->getNumPoints() )
1217 0 : return FALSE;
1218 :
1219 15 : for( int iPoint = 0; iPoint < getNumPoints(); iPoint++ )
1220 : {
1221 12 : if( getX(iPoint) != poOLine->getX(iPoint)
1222 : || getY(iPoint) != poOLine->getY(iPoint)
1223 : || getZ(iPoint) != poOLine->getZ(iPoint) )
1224 0 : return FALSE;
1225 : }
1226 :
1227 3 : return TRUE;
1228 : }
1229 :
1230 : /************************************************************************/
1231 : /* transform() */
1232 : /************************************************************************/
1233 :
1234 25 : OGRErr OGRLineString::transform( OGRCoordinateTransformation *poCT )
1235 :
1236 : {
1237 : #ifdef DISABLE_OGRGEOM_TRANSFORM
1238 : return OGRERR_FAILURE;
1239 : #else
1240 : double *xyz;
1241 : int i;
1242 :
1243 : /* -------------------------------------------------------------------- */
1244 : /* Because we don't want to partially transform this geometry */
1245 : /* (if some points fail after some have succeeded) we will */
1246 : /* instead make a copy of the points to operate on. */
1247 : /* -------------------------------------------------------------------- */
1248 25 : xyz = (double *) CPLMalloc(sizeof(double) * nPointCount * 3);
1249 25 : if( xyz == NULL )
1250 0 : return OGRERR_NOT_ENOUGH_MEMORY;
1251 :
1252 538 : for( i = 0; i < nPointCount; i++ )
1253 : {
1254 513 : xyz[i ] = paoPoints[i].x;
1255 513 : xyz[i+nPointCount] = paoPoints[i].y;
1256 513 : if( padfZ )
1257 3 : xyz[i+nPointCount*2] = padfZ[i];
1258 : else
1259 510 : xyz[i+nPointCount*2] = 0.0;
1260 : }
1261 :
1262 : /* -------------------------------------------------------------------- */
1263 : /* Transform and reapply. */
1264 : /* -------------------------------------------------------------------- */
1265 25 : if( !poCT->Transform( nPointCount, xyz, xyz + nPointCount,
1266 : xyz+nPointCount*2 ) )
1267 : {
1268 0 : CPLFree( xyz );
1269 0 : return OGRERR_FAILURE;
1270 : }
1271 : else
1272 : {
1273 : setPoints( nPointCount, xyz, xyz+nPointCount,
1274 25 : ( padfZ ) ? xyz+nPointCount*2 : NULL);
1275 25 : CPLFree( xyz );
1276 :
1277 25 : assignSpatialReference( poCT->GetTargetCS() );
1278 :
1279 25 : return OGRERR_NONE;
1280 : }
1281 : #endif
1282 : }
1283 :
1284 : /************************************************************************/
1285 : /* IsEmpty() */
1286 : /************************************************************************/
1287 :
1288 2951 : OGRBoolean OGRLineString::IsEmpty( ) const
1289 : {
1290 2951 : return (nPointCount == 0);
1291 : }
1292 :
1293 : /************************************************************************/
1294 : /* OGRLineString::segmentize() */
1295 : /************************************************************************/
1296 :
1297 11 : void OGRLineString::segmentize( double dfMaxLength )
1298 : {
1299 11 : if (dfMaxLength <= 0)
1300 : {
1301 : CPLError(CE_Failure, CPLE_AppDefined,
1302 0 : "dfMaxLength must be strictly positive");
1303 0 : return;
1304 : }
1305 :
1306 : int i;
1307 11 : OGRRawPoint* paoNewPoints = NULL;
1308 11 : double* padfNewZ = NULL;
1309 11 : int nNewPointCount = 0;
1310 11 : double dfSquareMaxLength = dfMaxLength * dfMaxLength;
1311 :
1312 247 : for( i = 0; i < nPointCount; i++ )
1313 : {
1314 : paoNewPoints = (OGRRawPoint *)
1315 247 : OGRRealloc(paoNewPoints, sizeof(OGRRawPoint) * (nNewPointCount + 1));
1316 247 : paoNewPoints[nNewPointCount] = paoPoints[i];
1317 :
1318 247 : if( getCoordinateDimension() == 3 )
1319 : {
1320 : padfNewZ = (double *)
1321 0 : OGRRealloc(padfNewZ, sizeof(double) * (nNewPointCount + 1));
1322 0 : padfNewZ[nNewPointCount] = padfZ[i];
1323 : }
1324 :
1325 247 : nNewPointCount++;
1326 :
1327 247 : if (i == nPointCount - 1)
1328 11 : break;
1329 :
1330 236 : double dfX = paoPoints[i+1].x - paoPoints[i].x;
1331 236 : double dfY = paoPoints[i+1].y - paoPoints[i].y;
1332 236 : double dfSquareDist = dfX * dfX + dfY * dfY;
1333 236 : if (dfSquareDist > dfSquareMaxLength)
1334 : {
1335 97 : int nIntermediatePoints = (int)floor(sqrt(dfSquareDist / dfSquareMaxLength));
1336 : int j;
1337 :
1338 : paoNewPoints = (OGRRawPoint *)
1339 97 : OGRRealloc(paoNewPoints, sizeof(OGRRawPoint) * (nNewPointCount + nIntermediatePoints));
1340 97 : if( getCoordinateDimension() == 3 )
1341 : {
1342 : padfNewZ = (double *)
1343 0 : OGRRealloc(padfNewZ, sizeof(double) * (nNewPointCount + nIntermediatePoints));
1344 : }
1345 :
1346 273 : for(j=1;j<=nIntermediatePoints;j++)
1347 : {
1348 176 : paoNewPoints[nNewPointCount + j - 1].x = paoPoints[i].x + j * dfX / (nIntermediatePoints + 1);
1349 176 : paoNewPoints[nNewPointCount + j - 1].y = paoPoints[i].y + j * dfY / (nIntermediatePoints + 1);
1350 176 : if( getCoordinateDimension() == 3 )
1351 : {
1352 : /* No interpolation */
1353 0 : padfNewZ[nNewPointCount + j - 1] = 0;
1354 : }
1355 : }
1356 :
1357 97 : nNewPointCount += nIntermediatePoints;
1358 : }
1359 : }
1360 :
1361 11 : OGRFree(paoPoints);
1362 11 : paoPoints = paoNewPoints;
1363 11 : nPointCount = nNewPointCount;
1364 :
1365 11 : if( getCoordinateDimension() == 3 )
1366 : {
1367 0 : OGRFree(padfZ);
1368 0 : padfZ = padfNewZ;
1369 : }
1370 : }
|