LCOV - code coverage report
Current view: directory - alg - llrasterize.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 239 178 74.5 %
Date: 2010-01-09 Functions: 6 5 83.3 %

       1                 : /******************************************************************************
       2                 :  * $Id: llrasterize.cpp 18340 2009-12-19 04:41:45Z chaitanya $
       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             415 : static int llCompareInt(const void *a, const void *b)
      34                 : {
      35             415 :   return (*(const int *)a) - (*(const int *)b);
      36                 : }
      37                 : 
      38              41 : static void llSwapDouble(double *a, double *b)
      39                 : {
      40              41 :   double temp = *a;
      41              41 :   *a = *b;
      42              41 :   *b = temp;
      43              41 : }
      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              17 : 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              17 :     if (!nPartCount) {
     118               0 :         return;
     119                 :     }
     120                 : 
     121              17 :     n = 0;
     122              37 :     for( part = 0; part < nPartCount; part++ )
     123              20 :         n += panPartSize[part];
     124                 :     
     125              17 :     polyInts = (int *) malloc(sizeof(int) * n);
     126              17 :     polyAllocated = n;
     127                 :     
     128              17 :     dminy = padfY[0];
     129              17 :     dmaxy = padfY[0];
     130              95 :     for (i=1; (i < n); i++) {
     131                 : 
     132              78 :         if (padfY[i] < dminy) {
     133              18 :             dminy = padfY[i];
     134                 :         }
     135              78 :         if (padfY[i] > dmaxy) {
     136               8 :             dmaxy = padfY[i];
     137                 :         }
     138                 :     }
     139              17 :     miny = (int) dminy;
     140              17 :     maxy = (int) dmaxy;
     141                 :     
     142                 :     
     143              17 :     if( miny < 0 )
     144               0 :         miny = 0;
     145              17 :     if( maxy >= nRasterYSize )
     146               1 :         maxy = nRasterYSize-1;
     147                 :    
     148                 :     
     149              17 :     minx = 0;
     150              17 :     maxx = nRasterXSize - 1;
     151                 : 
     152                 :     /* Fix in 1.3: count a vertex only once */
     153             393 :     for (y=miny; y <= maxy; y++) {
     154             376 :         int partoffset = 0;
     155                 : 
     156             376 :         dy = y +0.5; /* center height of line*/
     157                 :          
     158                 : 
     159             376 :         part = 0;
     160             376 :         ints = 0;
     161                 : 
     162                 :         /*Initialize polyInts, otherwise it can sometimes causes a seg fault */
     163             376 :         memset(polyInts, -1, sizeof(int) * n);
     164                 : 
     165            3053 :         for (i=0; (i < n); i++) {
     166                 :         
     167                 :             
     168            2677 :             if( i == partoffset + panPartSize[part] ) {
     169             195 :                 partoffset += panPartSize[part];
     170             195 :                 part++;
     171                 :             }
     172                 : 
     173            2677 :             if( i == partoffset ) {
     174             571 :                 ind1 = partoffset + panPartSize[part] - 1;
     175             571 :                 ind2 = partoffset;
     176                 :             } else {
     177            2106 :                 ind1 = i-1;
     178            2106 :                 ind2 = i;
     179                 :             }
     180                 :       
     181                 : 
     182            2677 :             dy1 = padfY[ind1];
     183            2677 :             dy2 = padfY[ind2];
     184                 :             
     185                 : 
     186            2677 :             if( (dy1 < dy && dy2 < dy) || (dy1 > dy && dy2 > dy) )
     187            1955 :                 continue;
     188                 : 
     189             722 :             if (dy1 < dy2) {
     190             361 :                 dx1 = padfX[ind1];
     191             361 :                 dx2 = padfX[ind2];
     192             361 :             } else if (dy1 > dy2) {
     193             361 :                 dy2 = padfY[ind1];
     194             361 :                 dy1 = padfY[ind2];
     195             361 :                 dx2 = padfX[ind1];
     196             361 :                 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             722 :             if(( dy < dy2 ) && (dy >= dy1))
     221                 :             {
     222                 :                 
     223             722 :                 intersect = (dy-dy1) * (dx2-dx1) / (dy2-dy1) + dx1;
     224                 : 
     225             722 :     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             376 :         qsort(polyInts, ints, sizeof(int), llCompareInt);
     237                 : 
     238                 : 
     239             737 :         for (i=0; (i < (ints)); i+=2)
     240                 :         {
     241             361 :             if( polyInts[i] <= maxx && polyInts[i+1] > minx )
     242                 :             {
     243             361 :                 pfnScanlineFunc( pCBData, y, polyInts[i], polyInts[i+1] - 1, (dfVariant == NULL)?0:dfVariant[0] );
     244                 :             }
     245                 :         }
     246                 :     }
     247                 : 
     248              17 :     free( polyInts );
     249                 : }
     250                 : 
     251                 : /************************************************************************/
     252                 : /*                         GDALdllImagePoint()                          */
     253                 : /************************************************************************/
     254                 : 
     255               0 : 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               0 :     for ( i = 0; i < nPartCount; i++ )
     263                 :     {
     264               0 :         int nX = (int)floor( padfX[i] + 0.5 );
     265               0 :         int nY = (int)floor( padfY[i] + 0.5 );
     266               0 :         double dfVariant = 0;
     267               0 :         if( padfVariant != NULL )
     268               0 :             dfVariant = padfVariant[i];
     269                 : 
     270               0 :         if ( 0 <= nX && nX < nRasterXSize && 0 <= nY && nY < nRasterYSize )
     271               0 :             pfnPointFunc( pCBData, nY, nX, dfVariant );
     272                 :     }
     273               0 : }
     274                 : 
     275                 : /************************************************************************/
     276                 : /*                         GDALdllImageLine()                           */
     277                 : /************************************************************************/
     278                 : 
     279               4 : 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               4 :     if ( !nPartCount )
     287               0 :         return;
     288                 : 
     289               8 :     for ( i = 0, n = 0; i < nPartCount; n += panPartSize[i++] )
     290                 :     {
     291                 :         int j;
     292                 : 
     293               9 :         for ( j = 1; j < panPartSize[i]; j++ )
     294                 :         {
     295               5 :             int iX = (int)floor( padfX[n + j - 1] + 0.5 );
     296               5 :             int iY = (int)floor( padfY[n + j - 1] + 0.5 );
     297                 : 
     298               5 :             const int iX1 = (int)floor( padfX[n + j] + 0.5 );
     299               5 :             const int iY1 = (int)floor( padfY[n + j] + 0.5 );
     300                 : 
     301               5 :             double dfVariant = 0, dfVariant1 = 0;
     302               5 :             if( padfVariant != NULL && 
     303                 :                 ((GDALRasterizeInfo *)pCBData)->eBurnValueSource !=
     304                 :                     GBV_UserBurnValue )
     305                 :             {
     306               3 :                 dfVariant = padfVariant[n + j - 1];
     307               3 :                 dfVariant1 = padfVariant[n + j];
     308                 :             }
     309                 : 
     310               5 :             int nDeltaX = ABS( iX1 - iX );
     311               5 :             int nDeltaY = ABS( iY1 - iY );
     312                 : 
     313                 :             // Step direction depends on line direction.
     314               5 :             const int nXStep = ( iX > iX1 ) ? -1 : 1;
     315               5 :             const int nYStep = ( iY > iY1 ) ? -1 : 1;
     316                 : 
     317                 :             // Determine the line slope.
     318               5 :             if ( nDeltaX >= nDeltaY )
     319                 :             {           
     320               4 :                 const int nXError = nDeltaY << 1;
     321               4 :                 const int nYError = nXError - (nDeltaX << 1);
     322               4 :                 int nError = nXError - nDeltaX;
     323                 :                 double dfDeltaVariant = (dfVariant1 - dfVariant) /
     324               4 :                                                            (double)nDeltaX;
     325                 : 
     326             402 :                 while ( nDeltaX-- >= 0 )
     327                 :                 {
     328             394 :                     if ( 0 <= iX && iX < nRasterXSize
     329                 :                          && 0 <= iY && iY < nRasterYSize )
     330             387 :                         pfnPointFunc( pCBData, iY, iX, dfVariant );
     331                 : 
     332             394 :                     dfVariant += dfDeltaVariant;
     333             394 :                     iX += nXStep;
     334             394 :                     if ( nError > 0 )
     335                 :                     { 
     336             202 :                         iY += nYStep;
     337             202 :                         nError += nYError;
     338                 :                     }
     339                 :                     else
     340             192 :                         nError += nXError;
     341                 :                 }   
     342                 :             }
     343                 :             else
     344                 :             {
     345               1 :                 const int nXError = nDeltaX << 1;
     346               1 :                 const int nYError = nXError - (nDeltaY << 1);
     347               1 :                 int nError = nXError - nDeltaY;
     348                 :                 double dfDeltaVariant = (dfVariant1 - dfVariant) /
     349               1 :                                                            (double)nDeltaY;
     350                 : 
     351              33 :                 while ( nDeltaY-- >= 0 )
     352                 :                 {
     353              31 :                     if ( 0 <= iX && iX < nRasterXSize
     354                 :                          && 0 <= iY && iY < nRasterYSize )
     355              31 :                         pfnPointFunc( pCBData, iY, iX, dfVariant );
     356                 : 
     357              31 :                     dfVariant += dfDeltaVariant;
     358              31 :                     iY += nYStep;
     359              31 :                     if ( nError > 0 )
     360                 :                     { 
     361              15 :                         iX += nXStep;
     362              15 :                         nError += nYError;
     363                 :                     }
     364                 :                     else
     365              16 :                         nError += nXError;
     366                 :                 }
     367                 :             }
     368                 :         }
     369                 :     }
     370                 : }
     371                 : 
     372                 : /************************************************************************/
     373                 : /*                     GDALdllImageLineAllTouched()                     */
     374                 : /*                                                                      */
     375                 : /*      This alternate line drawing algorithm attempts to ensure        */
     376                 : /*      that every pixel touched at all by the line will get set.       */
     377                 : /*      @param padfVariant should contain the values that are to be     */
     378                 : /*      added to the burn value.  The values along the line between the */
     379                 : /*      points will be linearly interpolated. These values are used     */
     380                 : /*      only if pCBData->eBurnValueSource is set to something other     */
     381                 : /*      than GBV_UserBurnValue. If NULL is passed, a monotonous line    */
     382                 : /*      will be drawn with the burn value.                              */
     383                 : /************************************************************************/
     384                 : 
     385                 : void 
     386               7 : GDALdllImageLineAllTouched(int nRasterXSize, int nRasterYSize, 
     387                 :                            int nPartCount, int *panPartSize,
     388                 :                            double *padfX, double *padfY, double *padfVariant,
     389                 :                            llPointFunc pfnPointFunc, void *pCBData )
     390                 : 
     391                 : {
     392                 :     int     i, n;
     393                 : 
     394               7 :     if ( !nPartCount )
     395               0 :         return;
     396                 : 
     397              14 :     for ( i = 0, n = 0; i < nPartCount; n += panPartSize[i++] )
     398                 :     {
     399                 :         int j;
     400                 : 
     401              33 :         for ( j = 1; j < panPartSize[i]; j++ )
     402                 :         {
     403              26 :             double dfX = padfX[n + j - 1];
     404              26 :             double dfY = padfY[n + j - 1];
     405                 : 
     406              26 :             double dfXEnd = padfX[n + j];
     407              26 :             double dfYEnd = padfY[n + j];
     408                 : 
     409              26 :             double dfVariant = 0, dfVariantEnd = 0;
     410              26 :             if( padfVariant != NULL &&
     411                 :                 ((GDALRasterizeInfo *)pCBData)->eBurnValueSource !=
     412                 :                     GBV_UserBurnValue )
     413                 :             {
     414               0 :                 dfVariant = padfVariant[n + j - 1];
     415               0 :                 dfVariantEnd = padfVariant[n + j];
     416                 :             }
     417                 : 
     418                 :             // Skip segments that are off the target region.
     419              26 :             if( (dfY < 0 && dfYEnd < 0)
     420                 :                 || (dfY > nRasterYSize && dfYEnd > nRasterYSize)
     421                 :                 || (dfX < 0 && dfXEnd < 0)
     422                 :                 || (dfX > nRasterXSize && dfXEnd > nRasterXSize) )
     423               0 :                 continue;
     424                 : 
     425                 :             // Swap if needed so we can proceed from left2right (X increasing)
     426              26 :             if( dfX > dfXEnd )
     427                 :             {
     428               9 :                 llSwapDouble( &dfX, &dfXEnd );
     429               9 :                 llSwapDouble( &dfY, &dfYEnd );
     430               9 :                 llSwapDouble( &dfVariant, &dfVariantEnd );
     431                 :             }
     432                 :             
     433                 :             // Special case for vertical lines.
     434              26 :             if( floor(dfX) == floor(dfXEnd) )
     435                 :             {
     436              12 :                 if( dfYEnd < dfY )
     437                 :                 {
     438               7 :                     llSwapDouble( &dfY, &dfYEnd );
     439               7 :                     llSwapDouble( &dfVariant, &dfVariantEnd );
     440                 :                 }
     441                 : 
     442              12 :                 int iX = (int) floor(dfX);
     443              12 :                 int iY = (int) floor(dfY);
     444              12 :                 int iYEnd = (int) floor(dfYEnd);
     445                 : 
     446              12 :                 if( iX >= nRasterXSize )
     447               0 :                     continue;
     448                 : 
     449              12 :                 double dfDeltaVariant = 0;
     450              12 :                 if(( dfYEnd - dfY ) > 0)
     451                 :                     dfDeltaVariant = ( dfVariantEnd - dfVariant )
     452              12 :                                      / ( dfYEnd - dfY );//per unit change in iY
     453                 : 
     454                 :                 // Clip to the borders of the target region
     455              12 :                 if( iY < 0 )
     456               0 :                     iY = 0;
     457              12 :                 if( iYEnd >= nRasterYSize )
     458               0 :                     iYEnd = nRasterYSize - 1;
     459              12 :                 dfVariant += dfDeltaVariant * ( (double)iY - dfY );
     460                 : 
     461              12 :                 if( padfVariant == NULL )
     462             112 :                     for( ; iY <= iYEnd; iY++ )
     463             100 :                         pfnPointFunc( pCBData, iY, iX, 0.0 );
     464                 :                 else
     465               0 :                     for( ; iY <= iYEnd; iY++, dfVariant +=  dfDeltaVariant )
     466               0 :                         pfnPointFunc( pCBData, iY, iX, dfVariant );
     467                 : 
     468              12 :                 continue; // next segment
     469                 :             }
     470                 : 
     471                 :             double dfDeltaVariant = ( dfVariantEnd - dfVariant )
     472              14 :                                     / ( dfXEnd - dfX );//per unit change in iX
     473                 : 
     474                 :             // special case for horizontal lines
     475              14 :             if( floor(dfY) == floor(dfYEnd) )
     476                 :             {
     477              12 :                 if( dfXEnd < dfX )
     478                 :                 {
     479               0 :                     llSwapDouble( &dfX, &dfXEnd );
     480               0 :                     llSwapDouble( &dfVariant, &dfVariantEnd );
     481                 :                 }
     482                 : 
     483              12 :                 int iX = (int) floor(dfX);
     484              12 :                 int iY = (int) floor(dfY);
     485              12 :                 int iXEnd = (int) floor(dfXEnd);
     486                 :                 
     487              12 :                 if( iY >= nRasterYSize )
     488               0 :                     continue;
     489                 : 
     490                 :                 // Clip to the borders of the target region
     491              12 :                 if( iX < 0 )
     492               0 :                     iX = 0;
     493              12 :                 if( iXEnd >= nRasterXSize )
     494               0 :                     iXEnd = nRasterXSize - 1;
     495              12 :                 dfVariant += dfDeltaVariant * ( (double)iX - dfX );
     496                 : 
     497              12 :                 if( padfVariant == NULL )
     498             136 :                     for( ; iX <= iXEnd; iX++ )
     499             124 :                         pfnPointFunc( pCBData, iY, iX, 0.0 );
     500                 :                 else
     501               0 :                     for( ; iX <= iXEnd; iX++, dfVariant +=  dfDeltaVariant )
     502               0 :                         pfnPointFunc( pCBData, iY, iX, dfVariant );
     503                 : 
     504              12 :                 continue; // next segment
     505                 :             }
     506                 : 
     507                 : /* -------------------------------------------------------------------- */
     508                 : /*      General case - left to right sloped.                            */
     509                 : /* -------------------------------------------------------------------- */
     510               2 :             double dfSlope = (dfYEnd - dfY) / (dfXEnd - dfX);
     511                 : 
     512                 :             // clip segment in X
     513               2 :             if( dfXEnd > nRasterXSize )
     514                 :             {
     515               0 :                 dfYEnd -= ( dfXEnd - (double)nRasterXSize ) * dfSlope;
     516               0 :                 dfXEnd = nRasterXSize;
     517                 :             }
     518               2 :             if( dfX < 0 )
     519                 :             {
     520               0 :                 dfY += (0 - dfX) * dfSlope;
     521               0 :                 dfVariant += dfDeltaVariant * (0.0 - dfX);
     522               0 :                 dfX = 0.0;
     523                 :             }
     524                 : 
     525                 :             // clip segment in Y
     526                 :             double dfDiffX;
     527               2 :             if( dfYEnd > dfY )
     528                 :             {
     529               0 :                 if( dfY < 0 )
     530                 :                 {
     531               0 :                     dfX += (dfDiffX = (0 - dfY) / dfSlope);
     532               0 :                     dfVariant += dfDeltaVariant * dfDiffX;
     533               0 :                     dfY = 0.0;
     534                 :                 }
     535               0 :                 if( dfYEnd >= nRasterYSize )
     536                 :                 {
     537               0 :                     dfXEnd += ( dfYEnd - (double)nRasterYSize ) / dfSlope;
     538               0 :                     dfYEnd = nRasterXSize;
     539                 :                 }
     540                 :             }
     541                 :             else
     542                 :             {
     543               2 :                 if( dfY >= nRasterYSize )
     544                 :                 {
     545               0 :                     dfX += (dfDiffX = ((double)nRasterYSize - dfY) / dfSlope);
     546               0 :                     dfVariant += dfDeltaVariant * dfDiffX;
     547               0 :                     dfY = nRasterYSize;
     548                 :                 }
     549               2 :                 if( dfYEnd < 0 )
     550                 :                 {
     551               0 :                     dfXEnd -= ( dfYEnd - 0 ) / dfSlope;
     552               0 :                     dfYEnd = 0;
     553                 :                 }
     554                 :             }
     555                 : 
     556                 :             // step from pixel to pixel.
     557              14 :             while( dfX < dfXEnd )
     558                 :             {
     559              10 :                 int iX = (int) floor(dfX);
     560              10 :                 int iY = (int) floor(dfY);
     561                 : 
     562                 :                 // burn in the current point.
     563                 :                 // We should be able to drop the Y check because we cliped in Y,
     564                 :                 // but there may be some error with all the small steps.
     565              10 :                 if( iY >= 0 && iY < nRasterYSize )
     566              10 :                     pfnPointFunc( pCBData, iY, iX, dfVariant );
     567                 : 
     568              10 :                 double dfStepX = floor(dfX+1.0) - dfX;
     569              10 :                 double dfStepY = dfStepX * dfSlope;
     570                 : 
     571                 :                 // step to right pixel without changing scanline?
     572              10 :                 if( (int) floor(dfY + dfStepY) == iY )
     573                 :                 {
     574               6 :                     dfX += dfStepX;
     575               6 :                     dfY += dfStepY;
     576               6 :                     dfVariant += dfDeltaVariant * dfStepX;
     577                 :                 }
     578               4 :                 else if( dfSlope < 0 )
     579                 :                 {
     580               4 :                     dfStepY = iY - dfY;
     581               4 :                     if( dfStepY > -0.000000001 )
     582               4 :                         dfStepY = -0.000000001;
     583                 : 
     584               4 :                     dfStepX = dfStepY / dfSlope;
     585               4 :                     dfX += dfStepX;
     586               4 :                     dfY += dfStepY;
     587               4 :                     dfVariant += dfDeltaVariant * dfStepX;
     588                 :                 }
     589                 :                 else
     590                 :                 {
     591               0 :                     dfStepY = (iY + 1) - dfY;
     592               0 :                     if( dfStepY < 0.000000001 )
     593               0 :                         dfStepY = 0.000000001;
     594                 : 
     595               0 :                     dfStepX = dfStepY / dfSlope;
     596               0 :                     dfX += dfStepX;
     597               0 :                     dfY += dfStepY;
     598               0 :                     dfVariant += dfDeltaVariant * dfStepX;
     599                 :                 }
     600                 :             } // next step along sement.
     601                 : 
     602                 :         } // next segment
     603                 :     } // next part
     604                 : }
     605                 : 

Generated by: LCOV version 1.7