LCOV - code coverage report
Current view: directory - alg - llrasterize.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 239 187 78.2 %
Date: 2012-04-28 Functions: 6 6 100.0 %

       1                 : /******************************************************************************
       2                 :  * $Id: llrasterize.cpp 22998 2011-08-28 12:23:29Z rouault $
       3                 :  *
       4                 :  * Project:  GDAL
       5                 :  * Purpose:  Vector polygon rasterization code.
       6                 :  * Author:   Frank Warmerdam, warmerdam@pobox.com
       7                 :  *
       8                 :  ******************************************************************************
       9                 :  * Copyright (c) 2000, Frank Warmerdam <warmerdam@pobox.com>
      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 "gdal_alg.h"
      31                 : #include "gdal_alg_priv.h"
      32                 : 
      33             980 : static int llCompareInt(const void *a, const void *b)
      34                 : {
      35             980 :   return (*(const int *)a) - (*(const int *)b);
      36                 : }
      37                 : 
      38              70 : static void llSwapDouble(double *a, double *b)
      39                 : {
      40              70 :   double temp = *a;
      41              70 :   *a = *b;
      42              70 :   *b = temp;
      43              70 : }
      44                 : 
      45                 : /************************************************************************/
      46                 : /*                       dllImageFilledPolygon()                        */
      47                 : /*                                                                      */
      48                 : /*      Perform scanline conversion of the passed multi-ring            */
      49                 : /*      polygon.  Note the polygon does not need to be explicitly       */
      50                 : /*      closed.  The scanline function will be called with              */
      51                 : /*      horizontal scanline chunks which may not be entirely            */
      52                 : /*      contained within the valid raster area (in the X                */
      53                 : /*      direction).                                                     */
      54                 : /*                                                                      */
      55                 : /*      NEW: Nodes' coordinate are kept as double  in order             */
      56                 : /*      to compute accurately the intersections with the lines          */
      57                 : /*                                                                      */
      58                 : /*      Two methods for determining the border pixels:                  */
      59                 : /*                                                                      */
      60                 : /*      1) method = 0                                                   */
      61                 : /*         Inherits algorithm from version above but with several bugs  */
      62                 : /*         fixed except for the cone facing down.                       */
      63                 : /*         A pixel on which a line intersects a segment of a            */
      64                 : /*         polygon will always be considered as inside the shape.       */
      65                 : /*         Note that we only compute intersections with lines that      */
      66                 : /*         passes through the middle of a pixel (line coord = 0.5,      */
      67                 : /*         1.5, 2.5, etc.)                                              */
      68                 : /*                                                                      */
      69                 : /*      2) method = 1:                                                  */
      70                 : /*         A pixel is considered inside a polygon if its center         */
      71                 : /*         falls inside the polygon. This is somehow more robust unless */
      72                 : /*         the nodes are placed in the center of the pixels in which    */
      73                 : /*         case, due to numerical inaccuracies, it's hard to predict    */
      74                 : /*         if the pixel will be considered inside or outside the shape. */
      75                 : /************************************************************************/
      76                 : 
      77                 : /*
      78                 :  * NOTE: This code was originally adapted from the gdImageFilledPolygon() 
      79                 :  * function in libgd.  
      80                 :  * 
      81                 :  * http://www.boutell.com/gd/
      82                 :  *
      83                 :  * It was later adapted for direct inclusion in GDAL and relicensed under
      84                 :  * the GDAL MIT/X license (pulled from the OpenEV distribution). 
      85                 :  */
      86                 : 
      87              40 : void GDALdllImageFilledPolygon(int nRasterXSize, int nRasterYSize, 
      88                 :                                int nPartCount, int *panPartSize,
      89                 :                                double *padfX, double *padfY,
      90                 :                                double *dfVariant,
      91                 :                                llScanlineFunc pfnScanlineFunc, void *pCBData )
      92                 : {
      93                 : /*************************************************************************
      94                 : 2nd Method (method=1):
      95                 : =====================
      96                 : No known bug
      97                 : *************************************************************************/
      98                 : 
      99                 :     int i;
     100                 :     int y;
     101                 :     int miny, maxy,minx,maxx;
     102                 :     double dminy, dmaxy;
     103                 :     double dx1, dy1;
     104                 :     double dx2, dy2;
     105                 :     double dy;
     106                 :     double intersect;
     107                 :     
     108                 : 
     109                 :     int ind1, ind2;
     110                 :     int ints, n, part;
     111                 :     int *polyInts, polyAllocated;
     112                 : 
     113                 :   
     114                 :     int horizontal_x1, horizontal_x2;
     115                 : 
     116                 : 
     117              40 :     if (!nPartCount) {
     118               0 :         return;
     119                 :     }
     120                 : 
     121              40 :     n = 0;
     122              88 :     for( part = 0; part < nPartCount; part++ )
     123              48 :         n += panPartSize[part];
     124                 :     
     125              40 :     polyInts = (int *) malloc(sizeof(int) * n);
     126              40 :     polyAllocated = n;
     127                 :     
     128              40 :     dminy = padfY[0];
     129              40 :     dmaxy = padfY[0];
     130             230 :     for (i=1; (i < n); i++) {
     131                 : 
     132             190 :         if (padfY[i] < dminy) {
     133              46 :             dminy = padfY[i];
     134                 :         }
     135             190 :         if (padfY[i] > dmaxy) {
     136              10 :             dmaxy = padfY[i];
     137                 :         }
     138                 :     }
     139              40 :     miny = (int) dminy;
     140              40 :     maxy = (int) dmaxy;
     141                 :     
     142                 :     
     143              40 :     if( miny < 0 )
     144               0 :         miny = 0;
     145              40 :     if( maxy >= nRasterYSize )
     146               2 :         maxy = nRasterYSize-1;
     147                 :    
     148                 :     
     149              40 :     minx = 0;
     150              40 :     maxx = nRasterXSize - 1;
     151                 : 
     152                 :     /* Fix in 1.3: count a vertex only once */
     153             884 :     for (y=miny; y <= maxy; y++) {
     154             844 :         int partoffset = 0;
     155                 : 
     156             844 :         dy = y +0.5; /* center height of line*/
     157                 :          
     158                 : 
     159             844 :         part = 0;
     160             844 :         ints = 0;
     161                 : 
     162                 :         /*Initialize polyInts, otherwise it can sometimes causes a seg fault */
     163             844 :         memset(polyInts, -1, sizeof(int) * n);
     164                 : 
     165            6808 :         for (i=0; (i < n); i++) {
     166                 :         
     167                 :             
     168            5964 :             if( i == partoffset + panPartSize[part] ) {
     169             420 :                 partoffset += panPartSize[part];
     170             420 :                 part++;
     171                 :             }
     172                 : 
     173            5964 :             if( i == partoffset ) {
     174            1264 :                 ind1 = partoffset + panPartSize[part] - 1;
     175            1264 :                 ind2 = partoffset;
     176                 :             } else {
     177            4700 :                 ind1 = i-1;
     178            4700 :                 ind2 = i;
     179                 :             }
     180                 :       
     181                 : 
     182            5964 :             dy1 = padfY[ind1];
     183            5964 :             dy2 = padfY[ind2];
     184                 :             
     185                 : 
     186            5964 :             if( (dy1 < dy && dy2 < dy) || (dy1 > dy && dy2 > dy) )
     187            4316 :                 continue;
     188                 : 
     189            1648 :             if (dy1 < dy2) {
     190             824 :                 dx1 = padfX[ind1];
     191             824 :                 dx2 = padfX[ind2];
     192             824 :             } else if (dy1 > dy2) {
     193             824 :                 dy2 = padfY[ind1];
     194             824 :                 dy1 = padfY[ind2];
     195             824 :                 dx2 = padfX[ind1];
     196             824 :                 dx1 = padfX[ind2];
     197                 :             } else /* if (fabs(dy1-dy2)< 1.e-6) */
     198                 :             {
     199                 :                 
     200                 :                 /*AE: DO NOT skip bottom horizontal segments 
     201                 :                   -Fill them separately- 
     202                 :                   They are not taken into account twice.*/
     203               0 :                 if (padfX[ind1] > padfX[ind2])
     204                 :                 {
     205               0 :                     horizontal_x1 = (int) floor(padfX[ind2]+0.5);
     206               0 :                     horizontal_x2 = (int) floor(padfX[ind1]+0.5);
     207                 :     
     208               0 :                     if  ( (horizontal_x1 >  maxx) ||  (horizontal_x2 <= minx) )
     209               0 :                         continue;
     210                 : 
     211                 :                     /*fill the horizontal segment (separately from the rest)*/
     212               0 :                     pfnScanlineFunc( pCBData, y, horizontal_x1, horizontal_x2 - 1, (dfVariant == NULL)?0:dfVariant[0] );
     213               0 :                     continue;
     214                 :                 }
     215                 :                 else /*skip top horizontal segments (they are already filled in the regular loop)*/
     216               0 :                     continue;
     217                 : 
     218                 :             }
     219                 : 
     220            1648 :             if(( dy < dy2 ) && (dy >= dy1))
     221                 :             {
     222                 :                 
     223            1648 :                 intersect = (dy-dy1) * (dx2-dx1) / (dy2-dy1) + dx1;
     224                 : 
     225            1648 :                 polyInts[ints++] = (int) floor(intersect+0.5);
     226                 :             }
     227                 :         }
     228                 : 
     229                 :         /* 
     230                 :          * It would be more efficient to do this inline, to avoid 
     231                 :          * a function call for each comparison.
     232                 :          * NOTE - mloskot: make llCompareInt a functor and use std
     233                 :          * algorithm and it will be optimized and expanded
     234                 :          * automatically in compile-time, with modularity preserved.
     235                 :          */
     236             844 :         qsort(polyInts, ints, sizeof(int), llCompareInt);
     237                 : 
     238                 : 
     239            1668 :         for (i=0; (i < (ints)); i+=2)
     240                 :         {
     241             824 :             if( polyInts[i] <= maxx && polyInts[i+1] > minx )
     242                 :             {
     243             824 :                 pfnScanlineFunc( pCBData, y, polyInts[i], polyInts[i+1] - 1, (dfVariant == NULL)?0:dfVariant[0] );
     244                 :             }
     245                 :         }
     246                 :     }
     247                 : 
     248              40 :     free( polyInts );
     249                 : }
     250                 : 
     251                 : /************************************************************************/
     252                 : /*                         GDALdllImagePoint()                          */
     253                 : /************************************************************************/
     254                 : 
     255              10 : void GDALdllImagePoint( int nRasterXSize, int nRasterYSize, 
     256                 :                         int nPartCount, int *panPartSize,
     257                 :                         double *padfX, double *padfY, double *padfVariant,
     258                 :                         llPointFunc pfnPointFunc, void *pCBData )
     259                 : {
     260                 :     int     i;
     261                 :  
     262              20 :     for ( i = 0; i < nPartCount; i++ )
     263                 :     {
     264              10 :         int nX = (int)floor( padfX[i] );
     265              10 :         int nY = (int)floor( padfY[i] );
     266              10 :         double dfVariant = 0;
     267              10 :         if( padfVariant != NULL )
     268               0 :             dfVariant = padfVariant[i];
     269                 : 
     270              10 :         if ( 0 <= nX && nX < nRasterXSize && 0 <= nY && nY < nRasterYSize )
     271              10 :             pfnPointFunc( pCBData, nY, nX, dfVariant );
     272                 :     }
     273              10 : }
     274                 : 
     275                 : /************************************************************************/
     276                 : /*                         GDALdllImageLine()                           */
     277                 : /************************************************************************/
     278                 : 
     279            2484 : void GDALdllImageLine( int nRasterXSize, int nRasterYSize, 
     280                 :                        int nPartCount, int *panPartSize,
     281                 :                        double *padfX, double *padfY, double *padfVariant,
     282                 :                        llPointFunc pfnPointFunc, void *pCBData )
     283                 : {
     284                 :     int     i, n;
     285                 : 
     286            2484 :     if ( !nPartCount )
     287               0 :         return;
     288                 : 
     289            4968 :     for ( i = 0, n = 0; i < nPartCount; n += panPartSize[i++] )
     290                 :     {
     291                 :         int j;
     292                 : 
     293           64840 :         for ( j = 1; j < panPartSize[i]; j++ )
     294                 :         {
     295           62356 :             int iX = (int)floor( padfX[n + j - 1] );
     296           62356 :             int iY = (int)floor( padfY[n + j - 1] );
     297                 : 
     298           62356 :             const int iX1 = (int)floor( padfX[n + j] );
     299           62356 :             const int iY1 = (int)floor( padfY[n + j] );
     300                 : 
     301           62356 :             double dfVariant = 0, dfVariant1 = 0;
     302           62356 :             if( padfVariant != NULL && 
     303                 :                 ((GDALRasterizeInfo *)pCBData)->eBurnValueSource !=
     304                 :                     GBV_UserBurnValue )
     305                 :             {
     306           62346 :                 dfVariant = padfVariant[n + j - 1];
     307           62346 :                 dfVariant1 = padfVariant[n + j];
     308                 :             }
     309                 : 
     310           62356 :             int nDeltaX = ABS( iX1 - iX );
     311           62356 :             int nDeltaY = ABS( iY1 - iY );
     312                 : 
     313                 :             // Step direction depends on line direction.
     314           62356 :             const int nXStep = ( iX > iX1 ) ? -1 : 1;
     315           62356 :             const int nYStep = ( iY > iY1 ) ? -1 : 1;
     316                 : 
     317                 :             // Determine the line slope.
     318           62356 :             if ( nDeltaX >= nDeltaY )
     319                 :             {           
     320           54614 :                 const int nXError = nDeltaY << 1;
     321           54614 :                 const int nYError = nXError - (nDeltaX << 1);
     322           54614 :                 int nError = nXError - nDeltaX;
     323                 :                 /* == 0 makes clang -fcatch-undefined-behavior -ftrapv happy, but if */
     324                 :                 /* it is == 0, dfDeltaVariant is not really used, so any value is OK */
     325                 :                 double dfDeltaVariant = (nDeltaX == 0) ? 0 : (dfVariant1 - dfVariant) /
     326           54614 :                                                            (double)nDeltaX;
     327                 : 
     328          198070 :                 while ( nDeltaX-- >= 0 )
     329                 :                 {
     330           88842 :                     if ( 0 <= iX && iX < nRasterXSize
     331                 :                          && 0 <= iY && iY < nRasterYSize )
     332           88492 :                         pfnPointFunc( pCBData, iY, iX, dfVariant );
     333                 : 
     334           88842 :                     dfVariant += dfDeltaVariant;
     335           88842 :                     iX += nXStep;
     336           88842 :                     if ( nError > 0 )
     337                 :                     { 
     338           31712 :                         iY += nYStep;
     339           31712 :                         nError += nYError;
     340                 :                     }
     341                 :                     else
     342           57130 :                         nError += nXError;
     343                 :                 }   
     344                 :             }
     345                 :             else
     346                 :             {
     347            7742 :                 const int nXError = nDeltaX << 1;
     348            7742 :                 const int nYError = nXError - (nDeltaY << 1);
     349            7742 :                 int nError = nXError - nDeltaY;
     350                 :                 /* == 0 makes clang -fcatch-undefined-behavior -ftrapv happy, but if */
     351                 :                 /* it is == 0, dfDeltaVariant is not really used, so any value is OK */
     352                 :                 double dfDeltaVariant = (nDeltaY == 0) ? 0 : (dfVariant1 - dfVariant) /
     353            7742 :                                                            (double)nDeltaY;
     354                 : 
     355           31084 :                 while ( nDeltaY-- >= 0 )
     356                 :                 {
     357           15600 :                     if ( 0 <= iX && iX < nRasterXSize
     358                 :                          && 0 <= iY && iY < nRasterYSize )
     359           15424 :                         pfnPointFunc( pCBData, iY, iX, dfVariant );
     360                 : 
     361           15600 :                     dfVariant += dfDeltaVariant;
     362           15600 :                     iY += nYStep;
     363           15600 :                     if ( nError > 0 )
     364                 :                     { 
     365              60 :                         iX += nXStep;
     366              60 :                         nError += nYError;
     367                 :                     }
     368                 :                     else
     369           15540 :                         nError += nXError;
     370                 :                 }
     371                 :             }
     372                 :         }
     373                 :     }
     374                 : }
     375                 : 
     376                 : /************************************************************************/
     377                 : /*                     GDALdllImageLineAllTouched()                     */
     378                 : /*                                                                      */
     379                 : /*      This alternate line drawing algorithm attempts to ensure        */
     380                 : /*      that every pixel touched at all by the line will get set.       */
     381                 : /*      @param padfVariant should contain the values that are to be     */
     382                 : /*      added to the burn value.  The values along the line between the */
     383                 : /*      points will be linearly interpolated. These values are used     */
     384                 : /*      only if pCBData->eBurnValueSource is set to something other     */
     385                 : /*      than GBV_UserBurnValue. If NULL is passed, a monotonous line    */
     386                 : /*      will be drawn with the burn value.                              */
     387                 : /************************************************************************/
     388                 : 
     389                 : void 
     390              14 : GDALdllImageLineAllTouched(int nRasterXSize, int nRasterYSize, 
     391                 :                            int nPartCount, int *panPartSize,
     392                 :                            double *padfX, double *padfY, double *padfVariant,
     393                 :                            llPointFunc pfnPointFunc, void *pCBData )
     394                 : 
     395                 : {
     396                 :     int     i, n;
     397                 : 
     398              14 :     if ( !nPartCount )
     399               0 :         return;
     400                 : 
     401              28 :     for ( i = 0, n = 0; i < nPartCount; n += panPartSize[i++] )
     402                 :     {
     403                 :         int j;
     404                 : 
     405              66 :         for ( j = 1; j < panPartSize[i]; j++ )
     406                 :         {
     407              52 :             double dfX = padfX[n + j - 1];
     408              52 :             double dfY = padfY[n + j - 1];
     409                 : 
     410              52 :             double dfXEnd = padfX[n + j];
     411              52 :             double dfYEnd = padfY[n + j];
     412                 : 
     413              52 :             double dfVariant = 0, dfVariantEnd = 0;
     414              52 :             if( padfVariant != NULL &&
     415                 :                 ((GDALRasterizeInfo *)pCBData)->eBurnValueSource !=
     416                 :                     GBV_UserBurnValue )
     417                 :             {
     418               0 :                 dfVariant = padfVariant[n + j - 1];
     419               0 :                 dfVariantEnd = padfVariant[n + j];
     420                 :             }
     421                 : 
     422                 :             // Skip segments that are off the target region.
     423              52 :             if( (dfY < 0 && dfYEnd < 0)
     424                 :                 || (dfY > nRasterYSize && dfYEnd > nRasterYSize)
     425                 :                 || (dfX < 0 && dfXEnd < 0)
     426                 :                 || (dfX > nRasterXSize && dfXEnd > nRasterXSize) )
     427               0 :                 continue;
     428                 : 
     429                 :             // Swap if needed so we can proceed from left2right (X increasing)
     430              52 :             if( dfX > dfXEnd )
     431                 :             {
     432              14 :                 llSwapDouble( &dfX, &dfXEnd );
     433              14 :                 llSwapDouble( &dfY, &dfYEnd );
     434              14 :                 llSwapDouble( &dfVariant, &dfVariantEnd );
     435                 :             }
     436                 :             
     437                 :             // Special case for vertical lines.
     438              52 :             if( floor(dfX) == floor(dfXEnd) )
     439                 :             {
     440              24 :                 if( dfYEnd < dfY )
     441                 :                 {
     442              14 :                     llSwapDouble( &dfY, &dfYEnd );
     443              14 :                     llSwapDouble( &dfVariant, &dfVariantEnd );
     444                 :                 }
     445                 : 
     446              24 :                 int iX = (int) floor(dfX);
     447              24 :                 int iY = (int) floor(dfY);
     448              24 :                 int iYEnd = (int) floor(dfYEnd);
     449                 : 
     450              24 :                 if( iX >= nRasterXSize )
     451               0 :                     continue;
     452                 : 
     453              24 :                 double dfDeltaVariant = 0;
     454              24 :                 if(( dfYEnd - dfY ) > 0)
     455                 :                     dfDeltaVariant = ( dfVariantEnd - dfVariant )
     456              24 :                                      / ( dfYEnd - dfY );//per unit change in iY
     457                 : 
     458                 :                 // Clip to the borders of the target region
     459              24 :                 if( iY < 0 )
     460               0 :                     iY = 0;
     461              24 :                 if( iYEnd >= nRasterYSize )
     462               0 :                     iYEnd = nRasterYSize - 1;
     463              24 :                 dfVariant += dfDeltaVariant * ( (double)iY - dfY );
     464                 : 
     465              24 :                 if( padfVariant == NULL )
     466             224 :                     for( ; iY <= iYEnd; iY++ )
     467             200 :                         pfnPointFunc( pCBData, iY, iX, 0.0 );
     468                 :                 else
     469               0 :                     for( ; iY <= iYEnd; iY++, dfVariant +=  dfDeltaVariant )
     470               0 :                         pfnPointFunc( pCBData, iY, iX, dfVariant );
     471                 : 
     472              24 :                 continue; // next segment
     473                 :             }
     474                 : 
     475                 :             double dfDeltaVariant = ( dfVariantEnd - dfVariant )
     476              28 :                                     / ( dfXEnd - dfX );//per unit change in iX
     477                 : 
     478                 :             // special case for horizontal lines
     479              28 :             if( floor(dfY) == floor(dfYEnd) )
     480                 :             {
     481              24 :                 if( dfXEnd < dfX )
     482                 :                 {
     483               0 :                     llSwapDouble( &dfX, &dfXEnd );
     484               0 :                     llSwapDouble( &dfVariant, &dfVariantEnd );
     485                 :                 }
     486                 : 
     487              24 :                 int iX = (int) floor(dfX);
     488              24 :                 int iY = (int) floor(dfY);
     489              24 :                 int iXEnd = (int) floor(dfXEnd);
     490                 :                 
     491              24 :                 if( iY >= nRasterYSize )
     492               0 :                     continue;
     493                 : 
     494                 :                 // Clip to the borders of the target region
     495              24 :                 if( iX < 0 )
     496               0 :                     iX = 0;
     497              24 :                 if( iXEnd >= nRasterXSize )
     498               0 :                     iXEnd = nRasterXSize - 1;
     499              24 :                 dfVariant += dfDeltaVariant * ( (double)iX - dfX );
     500                 : 
     501              24 :                 if( padfVariant == NULL )
     502             272 :                     for( ; iX <= iXEnd; iX++ )
     503             248 :                         pfnPointFunc( pCBData, iY, iX, 0.0 );
     504                 :                 else
     505               0 :                     for( ; iX <= iXEnd; iX++, dfVariant +=  dfDeltaVariant )
     506               0 :                         pfnPointFunc( pCBData, iY, iX, dfVariant );
     507                 : 
     508              24 :                 continue; // next segment
     509                 :             }
     510                 : 
     511                 : /* -------------------------------------------------------------------- */
     512                 : /*      General case - left to right sloped.                            */
     513                 : /* -------------------------------------------------------------------- */
     514               4 :             double dfSlope = (dfYEnd - dfY) / (dfXEnd - dfX);
     515                 : 
     516                 :             // clip segment in X
     517               4 :             if( dfXEnd > nRasterXSize )
     518                 :             {
     519               0 :                 dfYEnd -= ( dfXEnd - (double)nRasterXSize ) * dfSlope;
     520               0 :                 dfXEnd = nRasterXSize;
     521                 :             }
     522               4 :             if( dfX < 0 )
     523                 :             {
     524               0 :                 dfY += (0 - dfX) * dfSlope;
     525               0 :                 dfVariant += dfDeltaVariant * (0.0 - dfX);
     526               0 :                 dfX = 0.0;
     527                 :             }
     528                 : 
     529                 :             // clip segment in Y
     530                 :             double dfDiffX;
     531               4 :             if( dfYEnd > dfY )
     532                 :             {
     533               0 :                 if( dfY < 0 )
     534                 :                 {
     535               0 :                     dfX += (dfDiffX = (0 - dfY) / dfSlope);
     536               0 :                     dfVariant += dfDeltaVariant * dfDiffX;
     537               0 :                     dfY = 0.0;
     538                 :                 }
     539               0 :                 if( dfYEnd >= nRasterYSize )
     540                 :                 {
     541               0 :                     dfXEnd += ( dfYEnd - (double)nRasterYSize ) / dfSlope;
     542               0 :                     dfYEnd = nRasterXSize;
     543                 :                 }
     544                 :             }
     545                 :             else
     546                 :             {
     547               4 :                 if( dfY >= nRasterYSize )
     548                 :                 {
     549               0 :                     dfX += (dfDiffX = ((double)nRasterYSize - dfY) / dfSlope);
     550               0 :                     dfVariant += dfDeltaVariant * dfDiffX;
     551               0 :                     dfY = nRasterYSize;
     552                 :                 }
     553               4 :                 if( dfYEnd < 0 )
     554                 :                 {
     555               0 :                     dfXEnd -= ( dfYEnd - 0 ) / dfSlope;
     556               0 :                     dfYEnd = 0;
     557                 :                 }
     558                 :             }
     559                 : 
     560                 :             // step from pixel to pixel.
     561              28 :             while( dfX < dfXEnd )
     562                 :             {
     563              20 :                 int iX = (int) floor(dfX);
     564              20 :                 int iY = (int) floor(dfY);
     565                 : 
     566                 :                 // burn in the current point.
     567                 :                 // We should be able to drop the Y check because we cliped in Y,
     568                 :                 // but there may be some error with all the small steps.
     569              20 :                 if( iY >= 0 && iY < nRasterYSize )
     570              20 :                     pfnPointFunc( pCBData, iY, iX, dfVariant );
     571                 : 
     572              20 :                 double dfStepX = floor(dfX+1.0) - dfX;
     573              20 :                 double dfStepY = dfStepX * dfSlope;
     574                 : 
     575                 :                 // step to right pixel without changing scanline?
     576              20 :                 if( (int) floor(dfY + dfStepY) == iY )
     577                 :                 {
     578              12 :                     dfX += dfStepX;
     579              12 :                     dfY += dfStepY;
     580              12 :                     dfVariant += dfDeltaVariant * dfStepX;
     581                 :                 }
     582               8 :                 else if( dfSlope < 0 )
     583                 :                 {
     584               8 :                     dfStepY = iY - dfY;
     585               8 :                     if( dfStepY > -0.000000001 )
     586               8 :                         dfStepY = -0.000000001;
     587                 : 
     588               8 :                     dfStepX = dfStepY / dfSlope;
     589               8 :                     dfX += dfStepX;
     590               8 :                     dfY += dfStepY;
     591               8 :                     dfVariant += dfDeltaVariant * dfStepX;
     592                 :                 }
     593                 :                 else
     594                 :                 {
     595               0 :                     dfStepY = (iY + 1) - dfY;
     596               0 :                     if( dfStepY < 0.000000001 )
     597               0 :                         dfStepY = 0.000000001;
     598                 : 
     599               0 :                     dfStepX = dfStepY / dfSlope;
     600               0 :                     dfX += dfStepX;
     601               0 :                     dfY += dfStepY;
     602               0 :                     dfVariant += dfDeltaVariant * dfStepX;
     603                 :                 }
     604                 :             } // next step along sement.
     605                 : 
     606                 :         } // next segment
     607                 :     } // next part
     608                 : }
     609                 : 

Generated by: LCOV version 1.7