LCOV - code coverage report
Current view: directory - ogr - ogrlinestring.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 530 421 79.4 %
Date: 2012-12-26 Functions: 45 42 93.3 %

       1                 : /******************************************************************************
       2                 :  * $Id: ogrlinestring.cpp 24519 2012-05-30 21:28:53Z 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 24519 2012-05-30 21:28:53Z rouault $");
      35                 : 
      36                 : /************************************************************************/
      37                 : /*                           OGRLineString()                            */
      38                 : /************************************************************************/
      39                 : 
      40                 : /**
      41                 :  * \brief Create an empty line string.
      42                 :  */
      43                 : 
      44          801190 : OGRLineString::OGRLineString()
      45                 : 
      46                 : {
      47          801190 :     nPointCount = 0;
      48          801190 :     paoPoints = NULL;
      49          801190 :     padfZ = NULL;
      50          801190 : }
      51                 : 
      52                 : /************************************************************************/
      53                 : /*                           ~OGRLineString()                           */
      54                 : /************************************************************************/
      55                 : 
      56          801190 : OGRLineString::~OGRLineString()
      57                 : 
      58                 : {
      59          801190 :     if( paoPoints != NULL )
      60          800760 :         OGRFree( paoPoints );
      61          801190 :     if( padfZ != NULL )
      62          340725 :         OGRFree( padfZ );
      63          801190 : }
      64                 : 
      65                 : /************************************************************************/
      66                 : /*                          getGeometryType()                           */
      67                 : /************************************************************************/
      68                 : 
      69          371916 : OGRwkbGeometryType OGRLineString::getGeometryType() const
      70                 : 
      71                 : {
      72          371916 :     if( getCoordinateDimension() == 3 )
      73           32815 :         return wkbLineString25D;
      74                 :     else
      75          339101 :         return wkbLineString;
      76                 : }
      77                 : 
      78                 : /************************************************************************/
      79                 : /*                            flattenTo2D()                             */
      80                 : /************************************************************************/
      81                 : 
      82              31 : void OGRLineString::flattenTo2D()
      83                 : 
      84                 : {
      85              31 :     Make2D();
      86              31 : }
      87                 : 
      88                 : /************************************************************************/
      89                 : /*                          getGeometryName()                           */
      90                 : /************************************************************************/
      91                 : 
      92            1160 : const char * OGRLineString::getGeometryName() const
      93                 : 
      94                 : {
      95            1160 :     return "LINESTRING";
      96                 : }
      97                 : 
      98                 : /************************************************************************/
      99                 : /*                               clone()                                */
     100                 : /************************************************************************/
     101                 : 
     102           62204 : OGRGeometry *OGRLineString::clone() const
     103                 : 
     104                 : {
     105                 :     OGRLineString       *poNewLineString;
     106                 : 
     107           62204 :     poNewLineString = new OGRLineString();
     108                 : 
     109           62204 :     poNewLineString->assignSpatialReference( getSpatialReference() );
     110           62204 :     poNewLineString->setPoints( nPointCount, paoPoints, padfZ );
     111           62204 :     poNewLineString->setCoordinateDimension( getCoordinateDimension() );
     112                 :     
     113           62204 :     return poNewLineString;
     114                 : }
     115                 : 
     116                 : /************************************************************************/
     117                 : /*                               empty()                                */
     118                 : /************************************************************************/
     119                 : 
     120             543 : void OGRLineString::empty()
     121                 : 
     122                 : {
     123             543 :     setNumPoints( 0 );
     124             543 : }
     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          337030 : void OGRLineString::setCoordinateDimension( int nNewDimension )
     141                 : 
     142                 : {
     143          337030 :     nCoordDimension = nNewDimension;
     144          337030 :     if( nNewDimension == 2 )
     145            5536 :         Make2D();
     146          331494 :     else if( nNewDimension == 3 )
     147          331494 :         Make3D();
     148          337030 : }
     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            1905 : int OGRLineString::WkbSize() const
     158                 : 
     159                 : {
     160            1905 :     return 5 + 4 + 8 * nPointCount * getCoordinateDimension();
     161                 : }
     162                 : 
     163                 : /************************************************************************/
     164                 : /*                               Make2D()                               */
     165                 : /************************************************************************/
     166                 : 
     167           63948 : void OGRLineString::Make2D()
     168                 : 
     169                 : {
     170           63948 :     if( padfZ != NULL )
     171                 :     {
     172             382 :         OGRFree( padfZ );
     173             382 :         padfZ = NULL;
     174                 :     }
     175           63948 :     nCoordDimension = 2;
     176           63948 : }
     177                 : 
     178                 : /************************************************************************/
     179                 : /*                               Make3D()                               */
     180                 : /************************************************************************/
     181                 : 
     182          700707 : void OGRLineString::Make3D()
     183                 : 
     184                 : {
     185          700707 :     if( padfZ == NULL )
     186                 :     {
     187          341024 :         if( nPointCount == 0 )
     188          276554 :             padfZ = (double *) OGRCalloc(sizeof(double),1);
     189                 :         else
     190           64470 :             padfZ = (double *) OGRCalloc(sizeof(double),nPointCount);
     191                 :     }
     192          700707 :     nCoordDimension = 3;
     193          700707 : }
     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            2919 : void    OGRLineString::getPoint( int i, OGRPoint * poPoint ) const
     209                 : 
     210                 : {
     211            2919 :     assert( i >= 0 );
     212            2919 :     assert( i < nPointCount );
     213            2919 :     assert( poPoint != NULL );
     214                 : 
     215            2919 :     poPoint->setX( paoPoints[i].x );
     216            2919 :     poPoint->setY( paoPoints[i].y );
     217                 : 
     218            2919 :     if( getCoordinateDimension() == 3 && padfZ != NULL )
     219             123 :         poPoint->setZ( padfZ[i] );
     220            2919 : }
     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          760377 : double OGRLineString::getZ( int iVertex ) const
     275                 : 
     276                 : {
     277          760377 :     if( padfZ != NULL && iVertex >= 0 && iVertex < nPointCount 
     278                 :         && nCoordDimension >= 3 )
     279           60388 :         return( padfZ[iVertex] );
     280                 :     else
     281          699989 :         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         4157233 : void OGRLineString::setNumPoints( int nNewPointCount )
     301                 : 
     302                 : {
     303         4157233 :     if( nNewPointCount == 0 )
     304                 :     {
     305             658 :         OGRFree( paoPoints );
     306             658 :         paoPoints = NULL;
     307                 :         
     308             658 :         OGRFree( padfZ );
     309             658 :         padfZ = NULL;
     310                 :         
     311             658 :         nPointCount = 0;
     312             658 :         return;
     313                 :     }
     314                 : 
     315         4156575 :     if( nNewPointCount > nPointCount )
     316                 :     {
     317                 :         OGRRawPoint* paoNewPoints = (OGRRawPoint *)
     318         4147639 :             VSIRealloc(paoPoints, sizeof(OGRRawPoint) * nNewPointCount);
     319         4147639 :         if (paoNewPoints == NULL)
     320                 :         {
     321                 :             CPLError(CE_Failure, CPLE_OutOfMemory,
     322               0 :                      "Could not allocate array for %d points", nNewPointCount);
     323               0 :             return;
     324                 :         }
     325         4147639 :         paoPoints = paoNewPoints;
     326                 :         
     327                 :         memset( paoPoints + nPointCount,
     328         4147639 :                 0, sizeof(OGRRawPoint) * (nNewPointCount - nPointCount) );
     329                 :         
     330         4147639 :         if( getCoordinateDimension() == 3 )
     331                 :         {
     332                 :             double* padfNewZ = (double *)
     333          286012 :                 VSIRealloc( padfZ, sizeof(double)*nNewPointCount );
     334          286012 :             if (padfNewZ == NULL)
     335                 :             {
     336                 :                 CPLError(CE_Failure, CPLE_OutOfMemory,
     337               0 :                      "Could not allocate array for %d points", nNewPointCount);
     338               0 :                 return;
     339                 :             }
     340          286012 :             padfZ = padfNewZ;
     341                 :             memset( padfZ + nPointCount, 0,
     342          286012 :                     sizeof(double) * (nNewPointCount - nPointCount) );
     343                 :         }
     344                 :     }
     345                 : 
     346         4156575 :     nPointCount = nNewPointCount;
     347                 : }
     348                 : 
     349                 : /************************************************************************/
     350                 : /*                              setPoint()                              */
     351                 : /************************************************************************/
     352                 : 
     353                 : /**
     354                 :  * \brief Set the location of a vertex in line string.
     355                 :  *
     356                 :  * If iPoint is larger than the number of necessary the number of existing
     357                 :  * points in the line string, the point count will be increased to
     358                 :  * accomodate the request.
     359                 :  *
     360                 :  * There is no SFCOM analog to this method.
     361                 :  * 
     362                 :  * @param iPoint the index of the vertex to assign (zero based).
     363                 :  * @param poPoint the value to assign to the vertex.
     364                 :  */
     365                 : 
     366             562 : void OGRLineString::setPoint( int iPoint, OGRPoint * poPoint )
     367                 : 
     368                 : {
     369             562 :     if (poPoint->getCoordinateDimension() < 3)
     370             562 :         setPoint( iPoint, poPoint->getX(), poPoint->getY() );
     371                 :     else
     372               0 :         setPoint( iPoint, poPoint->getX(), poPoint->getY(), poPoint->getZ() );
     373             562 : }
     374                 : 
     375                 : /************************************************************************/
     376                 : /*                              setPoint()                              */
     377                 : /************************************************************************/
     378                 : 
     379                 : /**
     380                 :  * \brief Set the location of a vertex in line string.
     381                 :  *
     382                 :  * If iPoint is larger than the number of necessary the number of existing
     383                 :  * points in the line string, the point count will be increased to
     384                 :  * accomodate the request.
     385                 :  * 
     386                 :  * There is no SFCOM analog to this method.
     387                 :  *
     388                 :  * @param iPoint the index of the vertex to assign (zero based).
     389                 :  * @param xIn input X coordinate to assign.
     390                 :  * @param yIn input Y coordinate to assign.
     391                 :  * @param zIn input Z coordinate to assign (defaults to zero).
     392                 :  */
     393                 : 
     394          135905 : void OGRLineString::setPoint( int iPoint, double xIn, double yIn, double zIn )
     395                 : 
     396                 : {
     397          135905 :     if( getCoordinateDimension() == 2 )
     398            7092 :         Make3D();
     399                 : 
     400          135905 :     if( iPoint >= nPointCount )
     401                 :     {
     402           10801 :         setNumPoints( iPoint+1 );
     403           10801 :         if (nPointCount < iPoint + 1)
     404               0 :             return;
     405                 :     }
     406                 : 
     407          135905 :     paoPoints[iPoint].x = xIn;
     408          135905 :     paoPoints[iPoint].y = yIn;
     409                 : 
     410          135905 :     if( zIn != 0.0 )
     411                 :     {
     412           28231 :         Make3D();
     413           28231 :         padfZ[iPoint] = zIn;
     414                 :     }
     415          107674 :     else if( getCoordinateDimension() == 3 )
     416                 :     {
     417          107674 :         padfZ[iPoint] = 0.0;
     418                 :     }
     419                 : }
     420                 : 
     421         6209337 : void OGRLineString::setPoint( int iPoint, double xIn, double yIn )
     422                 : 
     423                 : {
     424         6209337 :     if( iPoint >= nPointCount )
     425                 :     {
     426         3609720 :         setNumPoints( iPoint+1 );
     427         3609720 :         if (nPointCount < iPoint + 1)
     428               0 :             return;
     429                 :     }
     430                 : 
     431         6209337 :     paoPoints[iPoint].x = xIn;
     432         6209337 :     paoPoints[iPoint].y = yIn;
     433                 : }
     434                 : 
     435                 : /************************************************************************/
     436                 : /*                              addPoint()                              */
     437                 : /************************************************************************/
     438                 : 
     439                 : /**
     440                 :  * \brief Add a point to a line string.
     441                 :  *
     442                 :  * The vertex count of the line string is increased by one, and assigned from
     443                 :  * the passed location value.
     444                 :  *
     445                 :  * There is no SFCOM analog to this method.
     446                 :  *
     447                 :  * @param poPoint the point to assign to the new vertex.
     448                 :  */
     449                 : 
     450             740 : void OGRLineString::addPoint( OGRPoint * poPoint )
     451                 : 
     452                 : {
     453             740 :     if ( poPoint->getCoordinateDimension() < 3 )
     454             739 :         setPoint( nPointCount, poPoint->getX(), poPoint->getY() );
     455                 :     else
     456               1 :         setPoint( nPointCount, poPoint->getX(), poPoint->getY(), poPoint->getZ() );
     457             740 : }
     458                 : 
     459                 : /************************************************************************/
     460                 : /*                              addPoint()                              */
     461                 : /************************************************************************/
     462                 : 
     463                 : /**
     464                 :  * \brief Add a point to a line string.
     465                 :  *
     466                 :  * The vertex count of the line string is increased by one, and assigned from
     467                 :  * the passed location value.
     468                 :  *
     469                 :  * There is no SFCOM analog to this method.
     470                 :  *
     471                 :  * @param x the X coordinate to assign to the new point.
     472                 :  * @param y the Y coordinate to assign to the new point.
     473                 :  * @param z the Z coordinate to assign to the new point (defaults to zero).
     474                 :  */
     475                 : 
     476            9002 : void OGRLineString::addPoint( double x, double y, double z )
     477                 : 
     478                 : {
     479            9002 :     setPoint( nPointCount, x, y, z );
     480            9002 : }
     481                 : 
     482         3357585 : void OGRLineString::addPoint( double x, double y )
     483                 : 
     484                 : {
     485         3357585 :     setPoint( nPointCount, x, y );
     486         3357585 : }
     487                 : 
     488                 : /************************************************************************/
     489                 : /*                             setPoints()                              */
     490                 : /************************************************************************/
     491                 : 
     492                 : /**
     493                 :  * \brief Assign all points in a line string.
     494                 :  *
     495                 :  * This method clears any existing points assigned to this line string,
     496                 :  * and assigns a whole new set.  It is the most efficient way of assigning
     497                 :  * the value of a line string.
     498                 :  *
     499                 :  * There is no SFCOM analog to this method.
     500                 :  *
     501                 :  * @param nPointsIn number of points being passed in paoPointsIn
     502                 :  * @param paoPointsIn list of points being assigned.
     503                 :  * @param padfZ the Z values that go with the points (optional, may be NULL).
     504                 :  */
     505                 : 
     506           75816 : void OGRLineString::setPoints( int nPointsIn, OGRRawPoint * paoPointsIn,
     507                 :                                double * padfZ )
     508                 : 
     509                 : {
     510           75816 :     setNumPoints( nPointsIn );
     511           75816 :     if (nPointCount < nPointsIn)
     512               0 :         return;
     513                 : 
     514           75816 :     memcpy( paoPoints, paoPointsIn, sizeof(OGRRawPoint) * nPointsIn);
     515                 : 
     516                 : /* -------------------------------------------------------------------- */
     517                 : /*      Check 2D/3D.                                                    */
     518                 : /* -------------------------------------------------------------------- */
     519           75816 :     if( padfZ == NULL && getCoordinateDimension() > 2 )
     520                 :     {
     521               0 :         Make2D();
     522                 :     }
     523           75816 :     else if( padfZ )
     524                 :     {
     525           58108 :         Make3D();
     526           58108 :         memcpy( this->padfZ, padfZ, sizeof(double) * nPointsIn );
     527                 :     }
     528                 : }
     529                 : 
     530                 : /************************************************************************/
     531                 : /*                             setPoints()                              */
     532                 : /************************************************************************/
     533                 : 
     534                 : /**
     535                 :  * \brief Assign all points in a line string.
     536                 :  *
     537                 :  * This method clear any existing points assigned to this line string,
     538                 :  * and assigns a whole new set.
     539                 :  *
     540                 :  * There is no SFCOM analog to this method.
     541                 :  *
     542                 :  * @param nPointsIn number of points being passed in padfX and padfY.
     543                 :  * @param padfX list of X coordinates of points being assigned.
     544                 :  * @param padfY list of Y coordinates of points being assigned.
     545                 :  * @param padfZ list of Z coordinates of points being assigned (defaults to
     546                 :  * NULL for 2D objects).
     547                 :  */
     548                 : 
     549          331893 : void OGRLineString::setPoints( int nPointsIn, double * padfX, double * padfY,
     550                 :                                double * padfZ )
     551                 : 
     552                 : {
     553                 :     int         i;
     554                 : 
     555                 : /* -------------------------------------------------------------------- */
     556                 : /*      Check 2D/3D.                                                    */
     557                 : /* -------------------------------------------------------------------- */
     558          331893 :     if( padfZ == NULL )
     559           56736 :         Make2D();
     560                 :     else
     561          275157 :         Make3D();
     562                 :     
     563                 : /* -------------------------------------------------------------------- */
     564                 : /*      Assign values.                                                  */
     565                 : /* -------------------------------------------------------------------- */
     566          331893 :     setNumPoints( nPointsIn );
     567          331893 :     if (nPointCount < nPointsIn)
     568               0 :         return;
     569                 : 
     570         3590607 :     for( i = 0; i < nPointsIn; i++ )
     571                 :     {
     572         3258714 :         paoPoints[i].x = padfX[i];
     573         3258714 :         paoPoints[i].y = padfY[i];
     574                 :     }
     575                 : 
     576          331893 :     if( this->padfZ != NULL )
     577          275157 :         memcpy( this->padfZ, padfZ, sizeof(double) * nPointsIn );
     578                 : }
     579                 : 
     580                 : /************************************************************************/
     581                 : /*                          getPoints()                                 */
     582                 : /************************************************************************/
     583                 : 
     584                 : /**
     585                 :  * \brief Returns all points of line string.
     586                 :  *
     587                 :  * This method copies all points into user list. This list must be at
     588                 :  * least sizeof(OGRRawPoint) * OGRGeometry::getNumPoints() byte in size.
     589                 :  * It also copies all Z coordinates.
     590                 :  *
     591                 :  * There is no SFCOM analog to this method.
     592                 :  *
     593                 :  * @param paoPointsOut a buffer into which the points is written.
     594                 :  * @param padfZ the Z values that go with the points (optional, may be NULL).
     595                 :  */
     596                 : 
     597             104 : void OGRLineString::getPoints( OGRRawPoint * paoPointsOut, double * padfZ ) const
     598                 : {
     599             104 :     if ( ! paoPointsOut )
     600               0 :         return;
     601                 :         
     602             104 :     memcpy( paoPointsOut, paoPoints, sizeof(OGRRawPoint) * nPointCount );
     603                 : 
     604                 : /* -------------------------------------------------------------------- */
     605                 : /*      Check 2D/3D.                                                    */
     606                 : /* -------------------------------------------------------------------- */
     607             104 :     if( padfZ )
     608                 :     {
     609              45 :         if ( this->padfZ )
     610              44 :             memcpy( padfZ, this->padfZ, sizeof(double) * nPointCount );
     611                 :         else
     612               1 :             memset( padfZ, 0, sizeof(double) * nPointCount );
     613                 :     }
     614                 : }
     615                 : 
     616                 : 
     617                 : /************************************************************************/
     618                 : /*                          getPoints()                                 */
     619                 : /************************************************************************/
     620                 : 
     621                 : /**
     622                 :  * \brief Returns all points of line string.
     623                 :  *
     624                 :  * This method copies all points into user arrays. The user provides the
     625                 :  * stride between 2 consecutives elements of the array.
     626                 :  *
     627                 :  * On some CPU architectures, care must be taken so that the arrays are properly aligned.
     628                 :  *
     629                 :  * There is no SFCOM analog to this method.
     630                 :  *
     631                 :  * @param pabyX a buffer of at least (sizeof(double) * nXStride * nPointCount) bytes, may be NULL.
     632                 :  * @param nXStride the number of bytes between 2 elements of pabyX.
     633                 :  * @param pabyY a buffer of at least (sizeof(double) * nYStride * nPointCount) bytes, may be NULL.
     634                 :  * @param nYStride the number of bytes between 2 elements of pabyY.
     635                 :  * @param pabyZ a buffer of at last size (sizeof(double) * nZStride * nPointCount) bytes, may be NULL.
     636                 :  * @param nZStride the number of bytes between 2 elements of pabyZ.
     637                 :  *
     638                 :  * @since OGR 1.9.0
     639                 :  */
     640                 : 
     641               9 : void OGRLineString::getPoints( void* pabyX, int nXStride,
     642                 :                                void* pabyY, int nYStride,
     643                 :                                void* pabyZ, int nZStride)  const
     644                 : {
     645                 :     int i;
     646               9 :     if (pabyX != NULL && nXStride == 0)
     647               0 :         return;
     648               9 :     if (pabyY != NULL && nYStride == 0)
     649               0 :         return;
     650               9 :     if (pabyZ != NULL && nZStride == 0)
     651               0 :         return;
     652               9 :     if (nXStride == 2 * sizeof(double) &&
     653                 :         nYStride == 2 * sizeof(double) &&
     654                 :         (char*)pabyY == (char*)pabyX + sizeof(double) &&
     655                 :         (pabyZ == NULL || nZStride == sizeof(double)))
     656                 :     {
     657               9 :         getPoints((OGRRawPoint *)pabyX, (double*)pabyZ);
     658               9 :         return;
     659                 :     }
     660               0 :     for(i=0;i<nPointCount;i++)
     661                 :     {
     662               0 :         if (pabyX) *(double*)((char*)pabyX + i * nXStride) = paoPoints[i].x;
     663               0 :         if (pabyY) *(double*)((char*)pabyY + i * nYStride) = paoPoints[i].y;
     664                 :     }
     665                 : 
     666               0 :     if (pabyZ)
     667                 :     {
     668               0 :         for(i=0;i<nPointCount;i++)
     669                 :         {
     670               0 :             *(double*)((char*)pabyZ + i * nZStride) = (padfZ) ? padfZ[i] : 0.0;
     671                 :         }
     672                 :     }
     673                 : }
     674                 : 
     675                 : /************************************************************************/
     676                 : /*                           reversePoints()                            */
     677                 : /************************************************************************/
     678                 : 
     679                 : /**
     680                 :  * \brief Reverse point order. 
     681                 :  *
     682                 :  * This method updates the points in this line string in place 
     683                 :  * reversing the point ordering (first for last, etc).  
     684                 :  */
     685                 : 
     686               0 : void OGRLineString::reversePoints()
     687                 : 
     688                 : {
     689                 :     int i;
     690                 : 
     691               0 :     for( i = 0; i < nPointCount/2; i++ )
     692                 :     {
     693               0 :         OGRRawPoint sPointTemp = paoPoints[i];
     694                 : 
     695               0 :         paoPoints[i] = paoPoints[nPointCount-i-1];
     696               0 :         paoPoints[nPointCount-i-1] = sPointTemp;
     697                 : 
     698               0 :         if( padfZ )
     699                 :         {
     700               0 :             double dfZTemp = padfZ[i];
     701                 : 
     702               0 :             padfZ[i] = padfZ[nPointCount-i-1];
     703               0 :             padfZ[nPointCount-i-1] = dfZTemp;
     704                 :         }
     705                 :     }
     706               0 : }
     707                 : 
     708                 : /************************************************************************/
     709                 : /*                          addSubLineString()                          */
     710                 : /************************************************************************/
     711                 : 
     712                 : /**
     713                 :  * \brief Add a segment of another linestring to this one.
     714                 :  *
     715                 :  * Adds the request range of vertices to the end of this line string
     716                 :  * in an efficient manner.  If the nStartVertex is larger than the
     717                 :  * nEndVertex then the vertices will be reversed as they are copied. 
     718                 :  *
     719                 :  * @param poOtherLine the other OGRLineString. 
     720                 :  * @param nStartVertex the first vertex to copy, defaults to 0 to start
     721                 :  * with the first vertex in the other linestring. 
     722                 :  * @param nEndVertex the last vertex to copy, defaults to -1 indicating 
     723                 :  * the last vertex of the other line string. 
     724                 :  */
     725                 : 
     726            6279 : void OGRLineString::addSubLineString( const OGRLineString *poOtherLine, 
     727                 :                                       int nStartVertex, int nEndVertex )
     728                 : 
     729                 : {
     730            6279 :     int nOtherLineNumPoints = poOtherLine->getNumPoints();
     731            6279 :     if (nOtherLineNumPoints == 0)
     732               0 :         return;
     733                 : 
     734                 : /* -------------------------------------------------------------------- */
     735                 : /*      Do a bit of argument defaulting and validation.                 */
     736                 : /* -------------------------------------------------------------------- */
     737            6279 :     if( nEndVertex == -1 )
     738            6240 :         nEndVertex = nOtherLineNumPoints - 1;
     739                 : 
     740            6279 :     if( nStartVertex < 0 || nEndVertex < 0 
     741                 :         || nStartVertex >= nOtherLineNumPoints 
     742                 :         || nEndVertex >= nOtherLineNumPoints )
     743                 :     {
     744               0 :         CPLAssert( FALSE );
     745               0 :         return;
     746                 :     }
     747                 : 
     748                 : /* -------------------------------------------------------------------- */
     749                 : /*      Grow this linestring to hold the additional points.             */
     750                 : /* -------------------------------------------------------------------- */
     751            6279 :     int nOldPoints = nPointCount;
     752            6279 :     int nPointsToAdd = ABS(nEndVertex-nStartVertex) + 1;
     753                 : 
     754            6279 :     setNumPoints( nPointsToAdd + nOldPoints );
     755            6279 :     if (nPointCount < nPointsToAdd + nOldPoints)
     756               0 :         return;
     757                 : 
     758                 : /* -------------------------------------------------------------------- */
     759                 : /*      Copy the x/y points - forward copies use memcpy.                */
     760                 : /* -------------------------------------------------------------------- */
     761            6279 :     if( nEndVertex >= nStartVertex )
     762                 :     {
     763                 :         memcpy( paoPoints + nOldPoints, 
     764                 :                 poOtherLine->paoPoints + nStartVertex, 
     765            6273 :                 sizeof(OGRRawPoint) * nPointsToAdd );
     766            6273 :         if( poOtherLine->padfZ != NULL )
     767                 :         {
     768               9 :             Make3D();
     769                 :             memcpy( padfZ + nOldPoints, poOtherLine->padfZ + nStartVertex,
     770               9 :                     sizeof(double) * nPointsToAdd );
     771                 :         }
     772                 :     }
     773                 :     
     774                 : /* -------------------------------------------------------------------- */
     775                 : /*      Copy the x/y points - reverse copies done double by double.     */
     776                 : /* -------------------------------------------------------------------- */
     777                 :     else
     778                 :     {
     779                 :         int i;
     780                 : 
     781              26 :         for( i = 0; i < nPointsToAdd; i++ )
     782                 :         {
     783              20 :             paoPoints[i+nOldPoints].x = 
     784              20 :                 poOtherLine->paoPoints[nStartVertex-i].x;
     785              20 :             paoPoints[i+nOldPoints].y = 
     786              20 :                 poOtherLine->paoPoints[nStartVertex-i].y;
     787                 :         }
     788                 : 
     789               6 :         if( poOtherLine->padfZ != NULL )
     790                 :         {
     791               0 :             Make3D();
     792                 : 
     793               0 :             for( i = 0; i < nPointsToAdd; i++ )
     794                 :             {
     795               0 :                 padfZ[i+nOldPoints] = poOtherLine->padfZ[nStartVertex-i];
     796                 :             }
     797                 :         }
     798                 :     }
     799                 : }
     800                 : 
     801                 : /************************************************************************/
     802                 : /*                           importFromWkb()                            */
     803                 : /*                                                                      */
     804                 : /*      Initialize from serialized stream in well known binary          */
     805                 : /*      format.                                                         */
     806                 : /************************************************************************/
     807                 : 
     808             386 : OGRErr OGRLineString::importFromWkb( unsigned char * pabyData,
     809                 :                                      int nSize )
     810                 : 
     811                 : {
     812                 :     OGRwkbByteOrder     eByteOrder;
     813                 :     
     814             386 :     if( nSize < 9 && nSize != -1 )
     815               0 :         return OGRERR_NOT_ENOUGH_DATA;
     816                 : 
     817                 : /* -------------------------------------------------------------------- */
     818                 : /*      Get the byte order byte.                                        */
     819                 : /* -------------------------------------------------------------------- */
     820             386 :     eByteOrder = DB2_V72_FIX_BYTE_ORDER((OGRwkbByteOrder) *pabyData);
     821             386 :     if (!( eByteOrder == wkbXDR || eByteOrder == wkbNDR ))
     822               0 :         return OGRERR_CORRUPT_DATA;
     823                 : 
     824                 : /* -------------------------------------------------------------------- */
     825                 : /*      Get the geometry feature type.  For now we assume that          */
     826                 : /*      geometry type is between 0 and 255 so we only have to fetch     */
     827                 : /*      one byte.                                                       */
     828                 : /* -------------------------------------------------------------------- */
     829                 :     OGRwkbGeometryType eGeometryType;
     830             386 :     int bIs3D = FALSE;
     831                 : 
     832             386 :     if( eByteOrder == wkbNDR )
     833                 :     {
     834             372 :         eGeometryType = (OGRwkbGeometryType) pabyData[1];
     835             372 :         bIs3D = pabyData[4] & 0x80 || pabyData[2] & 0x80;
     836                 :     }
     837                 :     else
     838                 :     {
     839              14 :         eGeometryType = (OGRwkbGeometryType) pabyData[4];
     840              14 :         bIs3D = pabyData[1] & 0x80 || pabyData[3] & 0x80;
     841                 :     }
     842                 : 
     843             386 :     if( eGeometryType != wkbLineString )
     844               0 :         return OGRERR_CORRUPT_DATA;
     845                 : 
     846                 : /* -------------------------------------------------------------------- */
     847                 : /*      Get the vertex count.                                           */
     848                 : /* -------------------------------------------------------------------- */
     849                 :     int         nNewNumPoints;
     850                 :     
     851             386 :     memcpy( &nNewNumPoints, pabyData + 5, 4 );
     852                 :     
     853             386 :     if( OGR_SWAP( eByteOrder ) )
     854              14 :         nNewNumPoints = CPL_SWAP32(nNewNumPoints);
     855                 :     
     856                 :     /* Check if the wkb stream buffer is big enough to store
     857                 :      * fetched number of points.
     858                 :      * 16 or 24 - size of point structure
     859                 :      */
     860             386 :     int nPointSize = (bIs3D ? 24 : 16);
     861             386 :     if (nNewNumPoints < 0 || nNewNumPoints > INT_MAX / nPointSize)
     862               0 :         return OGRERR_CORRUPT_DATA;
     863             386 :     int nBufferMinSize = nPointSize * nNewNumPoints;
     864                 : 
     865             386 :     if( nSize != -1 && nBufferMinSize > nSize-9 )
     866                 :     {
     867                 :         CPLError( CE_Failure, CPLE_AppDefined,
     868               0 :                   "Length of input WKB is too small" );
     869               0 :         return OGRERR_NOT_ENOUGH_DATA;
     870                 :     }
     871                 : 
     872             386 :     setNumPoints( nNewNumPoints );
     873             386 :     if (nPointCount < nNewNumPoints)
     874               0 :         return OGRERR_FAILURE;
     875                 :     
     876             386 :     if( bIs3D )
     877             125 :         Make3D();
     878                 :     else
     879             261 :         Make2D();
     880                 :     
     881                 : /* -------------------------------------------------------------------- */
     882                 : /*      Get the vertex.                                                 */
     883                 : /* -------------------------------------------------------------------- */
     884             386 :     int i = 0;
     885                 :     
     886             386 :     if( bIs3D )
     887                 :     {
     888             486 :         for( i = 0; i < nPointCount; i++ )
     889                 :         {
     890             361 :             memcpy( paoPoints + i, pabyData + 9 + i*24, 16 );
     891             361 :             memcpy( padfZ + i, pabyData + 9 + 16 + i*24, 8 );
     892                 :         }
     893                 :     }
     894                 :     else
     895                 :     {
     896             261 :         memcpy( paoPoints, pabyData + 9, 16 * nPointCount );
     897                 :     }
     898                 :     
     899                 : /* -------------------------------------------------------------------- */
     900                 : /*      Byte swap if needed.                                            */
     901                 : /* -------------------------------------------------------------------- */
     902             386 :     if( OGR_SWAP( eByteOrder ) )
     903                 :     {
     904              88 :         for( i = 0; i < nPointCount; i++ )
     905                 :         {
     906              74 :             CPL_SWAPDOUBLE( &(paoPoints[i].x) );
     907              74 :             CPL_SWAPDOUBLE( &(paoPoints[i].y) );
     908                 :         }
     909                 : 
     910              14 :         if( bIs3D )
     911                 :         {
     912               8 :             for( i = 0; i < nPointCount; i++ )
     913                 :             {
     914               6 :                 CPL_SWAPDOUBLE( padfZ + i );
     915                 :             }
     916                 :         }
     917                 :     }
     918                 :     
     919             386 :     return OGRERR_NONE;
     920                 : }
     921                 : 
     922                 : /************************************************************************/
     923                 : /*                            exportToWkb()                             */
     924                 : /*                                                                      */
     925                 : /*      Build a well known binary representation of this object.        */
     926                 : /************************************************************************/
     927                 : 
     928            1530 : OGRErr  OGRLineString::exportToWkb( OGRwkbByteOrder eByteOrder,
     929                 :                                unsigned char * pabyData ) const
     930                 : 
     931                 : {
     932                 : /* -------------------------------------------------------------------- */
     933                 : /*      Set the byte order.                                             */
     934                 : /* -------------------------------------------------------------------- */
     935            1530 :     pabyData[0] = DB2_V72_UNFIX_BYTE_ORDER((unsigned char) eByteOrder);
     936                 : 
     937                 : /* -------------------------------------------------------------------- */
     938                 : /*      Set the geometry feature type.                                  */
     939                 : /* -------------------------------------------------------------------- */
     940            1530 :     GUInt32 nGType = getGeometryType();
     941                 :     
     942            1530 :     if( eByteOrder == wkbNDR )
     943            1517 :         nGType = CPL_LSBWORD32( nGType );
     944                 :     else
     945              13 :         nGType = CPL_MSBWORD32( nGType );
     946                 : 
     947            1530 :     memcpy( pabyData + 1, &nGType, 4 );
     948                 :     
     949                 : /* -------------------------------------------------------------------- */
     950                 : /*      Copy in the data count.                                         */
     951                 : /* -------------------------------------------------------------------- */
     952            1530 :     memcpy( pabyData+5, &nPointCount, 4 );
     953                 : 
     954                 : /* -------------------------------------------------------------------- */
     955                 : /*      Copy in the raw data.                                           */
     956                 : /* -------------------------------------------------------------------- */
     957                 :     int         i;
     958                 :     
     959            1530 :     if( getCoordinateDimension() == 3 )
     960                 :     {
     961              72 :         for( i = 0; i < nPointCount; i++ )
     962                 :         {
     963              55 :             memcpy( pabyData + 9 + 24*i, paoPoints+i, 16 );
     964              55 :             memcpy( pabyData + 9 + 16 + 24*i, padfZ+i, 8 );
     965                 :         }
     966                 :     }
     967                 :     else
     968            1513 :         memcpy( pabyData+9, paoPoints, 16 * nPointCount );
     969                 : 
     970                 : /* -------------------------------------------------------------------- */
     971                 : /*      Swap if needed.                                                 */
     972                 : /* -------------------------------------------------------------------- */
     973            1530 :     if( OGR_SWAP( eByteOrder ) )
     974                 :     {
     975                 :         int     nCount;
     976                 : 
     977              13 :         nCount = CPL_SWAP32( nPointCount );
     978              13 :         memcpy( pabyData+5, &nCount, 4 );
     979                 : 
     980             159 :         for( i = getCoordinateDimension() * nPointCount - 1; i >= 0; i-- )
     981                 :         {
     982             146 :             CPL_SWAP64PTR( pabyData + 9 + 8 * i );
     983                 :         }
     984                 :     }
     985                 :     
     986            1530 :     return OGRERR_NONE;
     987                 : }
     988                 : 
     989                 : /************************************************************************/
     990                 : /*                           importFromWkt()                            */
     991                 : /*                                                                      */
     992                 : /*      Instantiate from well known text format.  Currently this is     */
     993                 : /*      `LINESTRING ( x y, x y, ...)',                                  */
     994                 : /************************************************************************/
     995                 : 
     996             378 : OGRErr OGRLineString::importFromWkt( char ** ppszInput )
     997                 : 
     998                 : {
     999                 :     char        szToken[OGR_WKT_TOKEN_MAX];
    1000             378 :     const char  *pszInput = *ppszInput;
    1001                 : 
    1002             378 :     empty();
    1003                 : 
    1004                 : /* -------------------------------------------------------------------- */
    1005                 : /*      Read and verify the ``LINESTRING'' keyword token.               */
    1006                 : /* -------------------------------------------------------------------- */
    1007             378 :     pszInput = OGRWktReadToken( pszInput, szToken );
    1008                 : 
    1009             378 :     if( !EQUAL(szToken,getGeometryName()) )
    1010               0 :         return OGRERR_CORRUPT_DATA;
    1011                 : 
    1012                 : /* -------------------------------------------------------------------- */
    1013                 : /*      Check for EMPTY                                                 */
    1014                 : /* -------------------------------------------------------------------- */
    1015                 :     const char *pszPreScan;
    1016             378 :     int bHasZ = FALSE, bHasM = FALSE;
    1017                 : 
    1018             378 :     pszPreScan = OGRWktReadToken( pszInput, szToken );
    1019             378 :     if( EQUAL(szToken,"EMPTY") )
    1020                 :     {
    1021              18 :         *ppszInput = (char *) pszPreScan;
    1022              18 :         return OGRERR_NONE;
    1023                 :     }
    1024                 : 
    1025                 : /* -------------------------------------------------------------------- */
    1026                 : /*      Check for Z, M or ZM. Will ignore the Measure                   */
    1027                 : /* -------------------------------------------------------------------- */
    1028             360 :     else if( EQUAL(szToken,"Z") )
    1029                 :     {
    1030              12 :         bHasZ = TRUE;
    1031                 :     }
    1032             348 :     else if( EQUAL(szToken,"M") )
    1033                 :     {
    1034               3 :         bHasM = TRUE;
    1035                 :     }
    1036             345 :     else if( EQUAL(szToken,"ZM") )
    1037                 :     {
    1038               3 :         bHasZ = TRUE;
    1039               3 :         bHasM = TRUE;
    1040                 :     }
    1041                 : 
    1042             360 :     if (bHasZ || bHasM)
    1043                 :     {
    1044              18 :         pszInput = pszPreScan;
    1045              18 :         pszPreScan = OGRWktReadToken( pszInput, szToken );
    1046              18 :         if( EQUAL(szToken,"EMPTY") )
    1047                 :         {
    1048               4 :             *ppszInput = (char *) pszPreScan;
    1049               4 :             empty();
    1050                 :             /* FIXME?: In theory we should store the dimension and M presence */
    1051                 :             /* if we want to allow round-trip with ExportToWKT v1.2 */
    1052               4 :             return OGRERR_NONE;
    1053                 :         }
    1054                 :     }
    1055                 : 
    1056             356 :     if( !EQUAL(szToken,"(") )
    1057               4 :         return OGRERR_CORRUPT_DATA;
    1058                 : 
    1059             352 :     if ( !bHasZ && !bHasM )
    1060                 :     {
    1061                 :         /* Test for old-style LINESTRING(EMPTY) */
    1062             340 :         pszPreScan = OGRWktReadToken( pszPreScan, szToken );
    1063             340 :         if( EQUAL(szToken,"EMPTY") )
    1064                 :         {
    1065               3 :             pszInput = OGRWktReadToken( pszPreScan, szToken );
    1066                 : 
    1067               3 :             if( !EQUAL(szToken,")") )
    1068               1 :                 return OGRERR_CORRUPT_DATA;
    1069                 :             else
    1070                 :             {
    1071               2 :                 *ppszInput = (char *) pszInput;
    1072               2 :                 empty();
    1073               2 :                 return OGRERR_NONE;
    1074                 :             }
    1075                 :         }
    1076                 :     }
    1077                 : 
    1078                 : /* -------------------------------------------------------------------- */
    1079                 : /*      Read the point list.                                            */
    1080                 : /* -------------------------------------------------------------------- */
    1081             349 :     int      nMaxPoint = 0;
    1082                 : 
    1083             349 :     nPointCount = 0;
    1084                 : 
    1085                 :     pszInput = OGRWktReadPoints( pszInput, &paoPoints, &padfZ, &nMaxPoint,
    1086             349 :                                  &nPointCount );
    1087             349 :     if( pszInput == NULL )
    1088              15 :         return OGRERR_CORRUPT_DATA;
    1089                 : 
    1090             334 :     *ppszInput = (char *) pszInput;
    1091                 : 
    1092             334 :     if( padfZ == NULL )
    1093             249 :         nCoordDimension = 2;
    1094                 :     else
    1095                 :     {
    1096                 :         /* Ignore Z array when we have a LINESTRING M */
    1097              87 :         if (bHasM && !bHasZ)
    1098                 :         {
    1099               2 :             nCoordDimension = 2;
    1100               2 :             CPLFree(padfZ);
    1101               2 :             padfZ = NULL;
    1102                 :         }
    1103                 :         else
    1104              83 :             nCoordDimension = 3;
    1105                 :     }
    1106                 :     
    1107             334 :     return OGRERR_NONE;
    1108                 : }
    1109                 : 
    1110                 : /************************************************************************/
    1111                 : /*                            exportToWkt()                             */
    1112                 : /*                                                                      */
    1113                 : /*      Translate this structure into it's well known text format       */
    1114                 : /*      equivelent.  This could be made alot more CPU efficient!        */
    1115                 : /************************************************************************/
    1116                 : 
    1117             735 : OGRErr OGRLineString::exportToWkt( char ** ppszDstText ) const
    1118                 : 
    1119                 : {
    1120             735 :     int         nMaxString = nPointCount * 40 * 3 + 20;
    1121             735 :     int         nRetLen = 0;
    1122                 : 
    1123                 : /* -------------------------------------------------------------------- */
    1124                 : /*      Handle special empty case.                                      */
    1125                 : /* -------------------------------------------------------------------- */
    1126             735 :     if( nPointCount == 0 )
    1127                 :     {
    1128              36 :         CPLString osEmpty;
    1129              36 :         osEmpty.Printf("%s EMPTY",getGeometryName());
    1130              36 :         *ppszDstText = CPLStrdup(osEmpty);
    1131              36 :         return OGRERR_NONE;
    1132                 :     }
    1133                 : 
    1134                 : /* -------------------------------------------------------------------- */
    1135                 : /*      General case.                                                   */
    1136                 : /* -------------------------------------------------------------------- */
    1137             699 :     *ppszDstText = (char *) VSIMalloc( nMaxString );
    1138             699 :     if( *ppszDstText == NULL )
    1139               0 :         return OGRERR_NOT_ENOUGH_MEMORY;
    1140                 : 
    1141             699 :     sprintf( *ppszDstText, "%s (", getGeometryName() );
    1142                 : 
    1143            6633 :     for( int i = 0; i < nPointCount; i++ )
    1144                 :     {
    1145            5934 :         if( nMaxString <= (int) strlen(*ppszDstText+nRetLen) + 32 + nRetLen )
    1146                 :         {
    1147                 :             CPLDebug( "OGR", 
    1148                 :                       "OGRLineString::exportToWkt() ... buffer overflow.\n"
    1149                 :                       "nMaxString=%d, strlen(*ppszDstText) = %d, i=%d\n"
    1150                 :                       "*ppszDstText = %s", 
    1151               0 :                       nMaxString, (int) strlen(*ppszDstText), i, *ppszDstText );
    1152                 : 
    1153               0 :             VSIFree( *ppszDstText );
    1154               0 :             *ppszDstText = NULL;
    1155               0 :             return OGRERR_NOT_ENOUGH_MEMORY;
    1156                 :         }
    1157                 :         
    1158            5934 :         if( i > 0 )
    1159            5235 :             strcat( *ppszDstText + nRetLen, "," );
    1160                 : 
    1161            5934 :         nRetLen += strlen(*ppszDstText + nRetLen);
    1162            5934 :         if( getCoordinateDimension() == 3 )
    1163                 :             OGRMakeWktCoordinate( *ppszDstText + nRetLen,
    1164             500 :                                   paoPoints[i].x,
    1165             500 :                                   paoPoints[i].y,
    1166                 :                                   padfZ[i],
    1167            1500 :                                   nCoordDimension );
    1168                 :         else
    1169                 :             OGRMakeWktCoordinate( *ppszDstText + nRetLen,
    1170            5434 :                                   paoPoints[i].x,
    1171            5434 :                                   paoPoints[i].y,
    1172                 :                                   0.0,
    1173           16302 :                                   nCoordDimension );
    1174                 : 
    1175            5934 :         nRetLen += strlen(*ppszDstText + nRetLen);
    1176                 :     }
    1177                 : 
    1178             699 :     strcat( *ppszDstText+nRetLen, ")" );
    1179                 : 
    1180             699 :     return OGRERR_NONE;
    1181                 : }
    1182                 : 
    1183                 : /************************************************************************/
    1184                 : /*                             get_Length()                             */
    1185                 : /*                                                                      */
    1186                 : /*      For now we return a simple euclidian 2D distance.               */
    1187                 : /************************************************************************/
    1188                 : 
    1189              13 : double OGRLineString::get_Length() const
    1190                 : 
    1191                 : {
    1192              13 :     double      dfLength = 0;
    1193                 :     int         i;
    1194                 : 
    1195             956 :     for( i = 0; i < nPointCount-1; i++ )
    1196                 :     {
    1197                 :         double      dfDeltaX, dfDeltaY;
    1198                 : 
    1199             943 :         dfDeltaX = paoPoints[i+1].x - paoPoints[i].x;
    1200             943 :         dfDeltaY = paoPoints[i+1].y - paoPoints[i].y;
    1201             943 :         dfLength += sqrt(dfDeltaX*dfDeltaX + dfDeltaY*dfDeltaY);
    1202                 :     }
    1203                 :     
    1204              13 :     return dfLength;
    1205                 : }
    1206                 : 
    1207                 : /************************************************************************/
    1208                 : /*                             StartPoint()                             */
    1209                 : /************************************************************************/
    1210                 : 
    1211              68 : void OGRLineString::StartPoint( OGRPoint * poPoint ) const
    1212                 : 
    1213                 : {
    1214              68 :     getPoint( 0, poPoint );
    1215              68 : }
    1216                 : 
    1217                 : /************************************************************************/
    1218                 : /*                              EndPoint()                              */
    1219                 : /************************************************************************/
    1220                 : 
    1221              68 : void OGRLineString::EndPoint( OGRPoint * poPoint ) const
    1222                 : 
    1223                 : {
    1224              68 :     getPoint( nPointCount-1, poPoint );
    1225              68 : }
    1226                 : 
    1227                 : /************************************************************************/
    1228                 : /*                               Value()                                */
    1229                 : /*                                                                      */
    1230                 : /*      Get an interpolated point at some distance along the curve.     */
    1231                 : /************************************************************************/
    1232                 : 
    1233               0 : void OGRLineString::Value( double dfDistance, OGRPoint * poPoint ) const
    1234                 : 
    1235                 : {
    1236               0 :     double      dfLength = 0;
    1237                 :     int         i;
    1238                 : 
    1239               0 :     if( dfDistance < 0 )
    1240                 :     {
    1241               0 :         StartPoint( poPoint );
    1242               0 :         return;
    1243                 :     }
    1244                 : 
    1245               0 :     for( i = 0; i < nPointCount-1; i++ )
    1246                 :     {
    1247                 :         double      dfDeltaX, dfDeltaY, dfSegLength;
    1248                 : 
    1249               0 :         dfDeltaX = paoPoints[i+1].x - paoPoints[i].x;
    1250               0 :         dfDeltaY = paoPoints[i+1].y - paoPoints[i].y;
    1251               0 :         dfSegLength = sqrt(dfDeltaX*dfDeltaX + dfDeltaY*dfDeltaY);
    1252                 : 
    1253               0 :         if (dfSegLength > 0)
    1254                 :         {
    1255               0 :             if( (dfLength <= dfDistance) && ((dfLength + dfSegLength) >= 
    1256                 :                                              dfDistance) )
    1257                 :             {
    1258                 :                 double      dfRatio;
    1259                 : 
    1260               0 :                 dfRatio = (dfDistance - dfLength) / dfSegLength;
    1261                 : 
    1262               0 :                 poPoint->setX( paoPoints[i].x * (1 - dfRatio)
    1263               0 :                                + paoPoints[i+1].x * dfRatio );
    1264               0 :                 poPoint->setY( paoPoints[i].y * (1 - dfRatio)
    1265               0 :                                + paoPoints[i+1].y * dfRatio );
    1266                 : 
    1267               0 :                 if( getCoordinateDimension() == 3 )
    1268               0 :                     poPoint->setZ( padfZ[i] * (1 - dfRatio)
    1269               0 :                                    + padfZ[i] * dfRatio );
    1270                 :                 
    1271               0 :                 return;
    1272                 :             }
    1273                 : 
    1274               0 :             dfLength += dfSegLength;
    1275                 :         }
    1276                 :     }
    1277                 :     
    1278               0 :     EndPoint( poPoint );
    1279                 : }
    1280                 : 
    1281                 : /************************************************************************/
    1282                 : /*                            getEnvelope()                             */
    1283                 : /************************************************************************/
    1284                 : 
    1285          279086 : void OGRLineString::getEnvelope( OGREnvelope * psEnvelope ) const
    1286                 : 
    1287                 : {
    1288                 :     double      dfMinX, dfMinY, dfMaxX, dfMaxY;
    1289                 : 
    1290          279086 :     if( nPointCount == 0 )
    1291                 :     {
    1292               4 :         psEnvelope->MinX = 0;
    1293               4 :         psEnvelope->MaxX = 0;
    1294               4 :         psEnvelope->MinY = 0;
    1295               4 :         psEnvelope->MaxY = 0;
    1296               4 :         return;
    1297                 :     }
    1298                 :     
    1299          279082 :     dfMinX = dfMaxX = paoPoints[0].x;
    1300          279082 :     dfMinY = dfMaxY = paoPoints[0].y;
    1301                 : 
    1302         5011433 :     for( int iPoint = 1; iPoint < nPointCount; iPoint++ )
    1303                 :     {
    1304         4732351 :         if( dfMaxX < paoPoints[iPoint].x )
    1305         1251250 :             dfMaxX = paoPoints[iPoint].x;
    1306         4732351 :         if( dfMaxY < paoPoints[iPoint].y )
    1307         1461892 :             dfMaxY = paoPoints[iPoint].y;
    1308         4732351 :         if( dfMinX > paoPoints[iPoint].x )
    1309         1334003 :             dfMinX = paoPoints[iPoint].x;
    1310         4732351 :         if( dfMinY > paoPoints[iPoint].y )
    1311         1106733 :             dfMinY = paoPoints[iPoint].y;
    1312                 :     }
    1313                 : 
    1314          279082 :     psEnvelope->MinX = dfMinX;
    1315          279082 :     psEnvelope->MaxX = dfMaxX;
    1316          279082 :     psEnvelope->MinY = dfMinY;
    1317          279082 :     psEnvelope->MaxY = dfMaxY;
    1318                 : }
    1319                 : 
    1320                 : 
    1321                 : /************************************************************************/
    1322                 : /*                            getEnvelope()                             */
    1323                 : /************************************************************************/
    1324                 : 
    1325             141 : void OGRLineString::getEnvelope( OGREnvelope3D * psEnvelope ) const
    1326                 : 
    1327                 : {
    1328             141 :     getEnvelope((OGREnvelope*)psEnvelope);
    1329                 : 
    1330                 :     double      dfMinZ, dfMaxZ;
    1331                 : 
    1332             141 :     if( nPointCount == 0 || padfZ == NULL )
    1333                 :     {
    1334              78 :         psEnvelope->MinZ = 0;
    1335              78 :         psEnvelope->MaxZ = 0;
    1336              78 :         return;
    1337                 :     }
    1338                 : 
    1339              63 :     dfMinZ = dfMaxZ = padfZ[0];
    1340                 : 
    1341             645 :     for( int iPoint = 1; iPoint < nPointCount; iPoint++ )
    1342                 :     {
    1343             582 :         if( dfMinZ > padfZ[iPoint] )
    1344              20 :             dfMinZ = padfZ[iPoint];
    1345             582 :         if( dfMaxZ < padfZ[iPoint] )
    1346               0 :             dfMaxZ = padfZ[iPoint];
    1347                 :     }
    1348                 : 
    1349              63 :     psEnvelope->MinZ = dfMinZ;
    1350              63 :     psEnvelope->MaxZ = dfMaxZ;
    1351                 : }
    1352                 : 
    1353                 : /************************************************************************/
    1354                 : /*                               Equals()                                */
    1355                 : /************************************************************************/
    1356                 : 
    1357           50846 : OGRBoolean OGRLineString::Equals( OGRGeometry * poOther ) const
    1358                 : 
    1359                 : {
    1360           50846 :     OGRLineString       *poOLine = (OGRLineString *) poOther;
    1361                 :     
    1362           50846 :     if( poOLine == this )
    1363               0 :         return TRUE;
    1364                 :     
    1365           50846 :     if( poOther->getGeometryType() != getGeometryType() )
    1366               0 :         return FALSE;
    1367                 : 
    1368                 :     // we should eventually test the SRS.
    1369                 : 
    1370           50846 :     if( getNumPoints() != poOLine->getNumPoints() )
    1371           14788 :         return FALSE;
    1372                 : 
    1373          338249 :     for( int iPoint = 0; iPoint < getNumPoints(); iPoint++ )
    1374                 :     {
    1375          321566 :         if( getX(iPoint) != poOLine->getX(iPoint)
    1376                 :             || getY(iPoint) != poOLine->getY(iPoint) 
    1377                 :             || getZ(iPoint) != poOLine->getZ(iPoint) )
    1378           19375 :             return FALSE;
    1379                 :     }
    1380                 : 
    1381           16683 :     return TRUE;
    1382                 : }
    1383                 : 
    1384                 : /************************************************************************/
    1385                 : /*                             transform()                              */
    1386                 : /************************************************************************/
    1387                 : 
    1388              53 : OGRErr OGRLineString::transform( OGRCoordinateTransformation *poCT )
    1389                 : 
    1390                 : {
    1391                 : #ifdef DISABLE_OGRGEOM_TRANSFORM
    1392                 :     return OGRERR_FAILURE;
    1393                 : #else
    1394                 :     double      *xyz;
    1395                 :     int         *pabSuccess;
    1396                 :     int         i, j;
    1397                 : 
    1398                 : /* -------------------------------------------------------------------- */
    1399                 : /*   Make a copy of the points to operate on, so as to be able to       */
    1400                 : /*   keep only valid reprojected points if partial reprojection enabled */
    1401                 : /*   or keeping intact the original geometry if only full reprojection  */
    1402                 : /*   allowed.                                                           */
    1403                 : /* -------------------------------------------------------------------- */
    1404              53 :     xyz = (double *) VSIMalloc(sizeof(double) * nPointCount * 3);
    1405              53 :     pabSuccess = (int *) VSICalloc(sizeof(int), nPointCount);
    1406              53 :     if( xyz == NULL || pabSuccess == NULL )
    1407                 :     {
    1408               0 :         VSIFree(xyz);
    1409               0 :         VSIFree(pabSuccess);
    1410               0 :         return OGRERR_NOT_ENOUGH_MEMORY;
    1411                 :     }
    1412                 : 
    1413             632 :     for( i = 0; i < nPointCount; i++ )
    1414                 :     {
    1415             579 :         xyz[i  ] = paoPoints[i].x;
    1416             579 :         xyz[i+nPointCount] = paoPoints[i].y;
    1417             579 :         if( padfZ )
    1418              43 :             xyz[i+nPointCount*2] = padfZ[i];
    1419                 :         else
    1420             536 :             xyz[i+nPointCount*2] = 0.0;
    1421                 :     }
    1422                 : 
    1423                 : /* -------------------------------------------------------------------- */
    1424                 : /*      Transform and reapply.                                          */
    1425                 : /* -------------------------------------------------------------------- */
    1426                 :     poCT->TransformEx( nPointCount, xyz, xyz + nPointCount,
    1427              53 :                        xyz+nPointCount*2, pabSuccess );
    1428                 : 
    1429              53 :     const char* pszEnablePartialReprojection = NULL;
    1430                 : 
    1431             632 :     for( i = 0, j = 0; i < nPointCount; i++ )
    1432                 :     {
    1433             579 :         if (pabSuccess[i])
    1434                 :         {
    1435             579 :             xyz[j] = xyz[i];
    1436             579 :             xyz[j+nPointCount] = xyz[i+nPointCount];
    1437             579 :             xyz[j+2*nPointCount] = xyz[i+2*nPointCount];
    1438             579 :             j ++;
    1439                 :         }
    1440                 :         else
    1441                 :         {
    1442               0 :             if (pszEnablePartialReprojection == NULL)
    1443                 :                 pszEnablePartialReprojection =
    1444               0 :                     CPLGetConfigOption("OGR_ENABLE_PARTIAL_REPROJECTION", NULL);
    1445               0 :             if (pszEnablePartialReprojection == NULL)
    1446                 :             {
    1447                 :                 static int bHasWarned = FALSE;
    1448               0 :                 if (!bHasWarned)
    1449                 :                 {
    1450                 :                     /* Check that there is at least one valid reprojected point */
    1451                 :                     /* and issue an error giving an hint to use OGR_ENABLE_PARTIAL_REPROJECTION */
    1452               0 :                     int bHasOneValidPoint = (j != 0);
    1453               0 :                     for( ; i < nPointCount && !bHasOneValidPoint; i++ )
    1454                 :                     {
    1455               0 :                         if (pabSuccess[i])
    1456               0 :                             bHasOneValidPoint = TRUE;
    1457                 :                     }
    1458               0 :                     if (bHasOneValidPoint)
    1459                 :                     {
    1460               0 :                         bHasWarned = TRUE;
    1461                 :                         CPLError(CE_Failure, CPLE_AppDefined,
    1462                 :                                 "Full reprojection failed, but partial is possible if you define "
    1463               0 :                                 "OGR_ENABLE_PARTIAL_REPROJECTION configuration option to TRUE");
    1464                 :                     }
    1465                 :                 }
    1466                 : 
    1467               0 :                 CPLFree( xyz );
    1468               0 :                 CPLFree( pabSuccess );
    1469               0 :                 return OGRERR_FAILURE;
    1470                 :             }
    1471               0 :             else if (!CSLTestBoolean(pszEnablePartialReprojection))
    1472                 :             {
    1473               0 :                 CPLFree( xyz );
    1474               0 :                 CPLFree( pabSuccess );
    1475               0 :                 return OGRERR_FAILURE;
    1476                 :             }
    1477                 :         }
    1478                 :     }
    1479                 : 
    1480              53 :     if (j == 0 && nPointCount != 0)
    1481                 :     {
    1482               0 :         CPLFree( xyz );
    1483               0 :         CPLFree( pabSuccess );
    1484               0 :         return OGRERR_FAILURE;
    1485                 :     }
    1486                 : 
    1487                 :     setPoints( j, xyz, xyz+nPointCount,
    1488              53 :             ( padfZ ) ? xyz+nPointCount*2 : NULL);
    1489              53 :     CPLFree( xyz );
    1490              53 :     CPLFree( pabSuccess );
    1491                 : 
    1492              53 :     assignSpatialReference( poCT->GetTargetCS() );
    1493                 : 
    1494              53 :     return OGRERR_NONE;
    1495                 : #endif
    1496                 : }
    1497                 : 
    1498                 : /************************************************************************/
    1499                 : /*                               IsEmpty()                              */
    1500                 : /************************************************************************/
    1501                 : 
    1502          165422 : OGRBoolean OGRLineString::IsEmpty(  ) const
    1503                 : {
    1504          165422 :     return (nPointCount == 0);
    1505                 : }
    1506                 : 
    1507                 : /************************************************************************/
    1508                 : /*                     OGRLineString::segmentize()                      */
    1509                 : /************************************************************************/
    1510                 : 
    1511              11 : void OGRLineString::segmentize( double dfMaxLength )
    1512                 : {
    1513              11 :     if (dfMaxLength <= 0)
    1514                 :     {
    1515                 :         CPLError(CE_Failure, CPLE_AppDefined,
    1516               0 :                  "dfMaxLength must be strictly positive");
    1517               0 :         return;
    1518                 :     }
    1519                 : 
    1520                 :     int i;
    1521              11 :     OGRRawPoint* paoNewPoints = NULL;
    1522              11 :     double* padfNewZ = NULL;
    1523              11 :     int nNewPointCount = 0;
    1524              11 :     double dfSquareMaxLength = dfMaxLength * dfMaxLength;
    1525                 : 
    1526             247 :     for( i = 0; i < nPointCount; i++ )
    1527                 :     {
    1528                 :         paoNewPoints = (OGRRawPoint *)
    1529             247 :             OGRRealloc(paoNewPoints, sizeof(OGRRawPoint) * (nNewPointCount + 1));
    1530             247 :         paoNewPoints[nNewPointCount] = paoPoints[i];
    1531                 : 
    1532             247 :         if( getCoordinateDimension() == 3 )
    1533                 :         {
    1534                 :             padfNewZ = (double *)
    1535               0 :                 OGRRealloc(padfNewZ, sizeof(double) * (nNewPointCount + 1));
    1536               0 :             padfNewZ[nNewPointCount] = padfZ[i];
    1537                 :         }
    1538                 : 
    1539             247 :         nNewPointCount++;
    1540                 : 
    1541             247 :         if (i == nPointCount - 1)
    1542              11 :             break;
    1543                 : 
    1544             236 :         double dfX = paoPoints[i+1].x - paoPoints[i].x;
    1545             236 :         double dfY = paoPoints[i+1].y - paoPoints[i].y;
    1546             236 :         double dfSquareDist = dfX * dfX + dfY * dfY;
    1547             236 :         if (dfSquareDist > dfSquareMaxLength)
    1548                 :         {
    1549              97 :             int nIntermediatePoints = (int)floor(sqrt(dfSquareDist / dfSquareMaxLength));
    1550                 :             int j;
    1551                 : 
    1552                 :             paoNewPoints = (OGRRawPoint *)
    1553              97 :                 OGRRealloc(paoNewPoints, sizeof(OGRRawPoint) * (nNewPointCount + nIntermediatePoints));
    1554              97 :             if( getCoordinateDimension() == 3 )
    1555                 :             {
    1556                 :                 padfNewZ = (double *)
    1557               0 :                     OGRRealloc(padfNewZ, sizeof(double) * (nNewPointCount + nIntermediatePoints));
    1558                 :             }
    1559                 : 
    1560             273 :             for(j=1;j<=nIntermediatePoints;j++)
    1561                 :             {
    1562             176 :                 paoNewPoints[nNewPointCount + j - 1].x = paoPoints[i].x + j * dfX / (nIntermediatePoints + 1);
    1563             176 :                 paoNewPoints[nNewPointCount + j - 1].y = paoPoints[i].y + j * dfY / (nIntermediatePoints + 1);
    1564             176 :                 if( getCoordinateDimension() == 3 )
    1565                 :                 {
    1566                 :                     /* No interpolation */
    1567               0 :                     padfNewZ[nNewPointCount + j - 1] = 0;
    1568                 :                 }
    1569                 :             }
    1570                 : 
    1571              97 :             nNewPointCount += nIntermediatePoints;
    1572                 :         }
    1573                 :     }
    1574                 : 
    1575              11 :     OGRFree(paoPoints);
    1576              11 :     paoPoints = paoNewPoints;
    1577              11 :     nPointCount = nNewPointCount;
    1578                 : 
    1579              11 :     if( getCoordinateDimension() == 3 )
    1580                 :     {
    1581               0 :         OGRFree(padfZ);
    1582               0 :         padfZ = padfNewZ;
    1583                 :     }
    1584                 : }
    1585                 : 
    1586                 : /************************************************************************/
    1587                 : /*                               swapXY()                               */
    1588                 : /************************************************************************/
    1589                 : 
    1590              40 : void OGRLineString::swapXY()
    1591                 : {
    1592                 :     int i;
    1593             208 :     for( i = 0; i < nPointCount; i++ )
    1594                 :     {
    1595             168 :         double dfTemp = paoPoints[i].x;
    1596             168 :         paoPoints[i].x = paoPoints[i].y;
    1597             168 :         paoPoints[i].y = dfTemp;
    1598                 :     }
    1599              40 : }

Generated by: LCOV version 1.7