LTP GCOV extension - code coverage report
Current view: directory - ogr - ogrlinestring.cpp
Test: gdal_filtered.info
Date: 2010-07-12 Instrumented lines: 427
Code covered: 80.6 % Executed lines: 344

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

Generated by: LTP GCOV extension version 1.5