1 : /******************************************************************************
2 : * $Id: gdalrasterize.cpp 19078 2010-03-14 16:36:42Z chaitanya $
3 : *
4 : * Project: GDAL
5 : * Purpose: Vector rasterization.
6 : * Author: Frank Warmerdam, warmerdam@pobox.com
7 : *
8 : ******************************************************************************
9 : * Copyright (c) 2005, 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 <vector>
31 :
32 : #include "gdal_alg.h"
33 : #include "gdal_alg_priv.h"
34 : #include "gdal_priv.h"
35 : #include "ogr_api.h"
36 : #include "ogr_geometry.h"
37 : #include "ogr_spatialref.h"
38 :
39 : #ifdef OGR_ENABLED
40 : #include "ogrsf_frmts.h"
41 : #endif
42 :
43 : /************************************************************************/
44 : /* gvBurnScanline() */
45 : /************************************************************************/
46 :
47 : void gvBurnScanline( void *pCBData, int nY, int nXStart, int nXEnd,
48 412 : double dfVariant )
49 :
50 : {
51 412 : GDALRasterizeInfo *psInfo = (GDALRasterizeInfo *) pCBData;
52 : int iBand;
53 :
54 412 : if( nXStart > nXEnd )
55 2 : return;
56 :
57 410 : CPLAssert( nY >= 0 && nY < psInfo->nYSize );
58 410 : CPLAssert( nXStart <= nXEnd );
59 410 : CPLAssert( nXStart < psInfo->nXSize );
60 410 : CPLAssert( nXEnd >= 0 );
61 :
62 410 : if( nXStart < 0 )
63 0 : nXStart = 0;
64 410 : if( nXEnd >= psInfo->nXSize )
65 0 : nXEnd = psInfo->nXSize - 1;
66 :
67 410 : if( psInfo->eType == GDT_Byte )
68 : {
69 1104 : for( iBand = 0; iBand < psInfo->nBands; iBand++ )
70 : {
71 : unsigned char *pabyInsert;
72 : unsigned char nBurnValue = (unsigned char)
73 : ( psInfo->padfBurnValue[iBand] +
74 : ( (psInfo->eBurnValueSource == GBV_UserBurnValue)?
75 694 : 0 : dfVariant ) );
76 :
77 : pabyInsert = psInfo->pabyChunkBuf
78 : + iBand * psInfo->nXSize * psInfo->nYSize
79 694 : + nY * psInfo->nXSize + nXStart;
80 :
81 694 : memset( pabyInsert, nBurnValue, nXEnd - nXStart + 1 );
82 : }
83 : }
84 : else
85 : {
86 0 : for( iBand = 0; iBand < psInfo->nBands; iBand++ )
87 : {
88 0 : int nPixels = nXEnd - nXStart + 1;
89 : float *pafInsert;
90 : float fBurnValue = (float)
91 : ( psInfo->padfBurnValue[iBand] +
92 : ( (psInfo->eBurnValueSource == GBV_UserBurnValue)?
93 0 : 0 : dfVariant ) );
94 :
95 : pafInsert = ((float *) psInfo->pabyChunkBuf)
96 : + iBand * psInfo->nXSize * psInfo->nYSize
97 0 : + nY * psInfo->nXSize + nXStart;
98 :
99 0 : while( nPixels-- > 0 )
100 0 : *(pafInsert++) = fBurnValue;
101 : }
102 : }
103 : }
104 :
105 : /************************************************************************/
106 : /* gvBurnPoint() */
107 : /************************************************************************/
108 :
109 57550 : void gvBurnPoint( void *pCBData, int nY, int nX, double dfVariant )
110 :
111 : {
112 57550 : GDALRasterizeInfo *psInfo = (GDALRasterizeInfo *) pCBData;
113 : int iBand;
114 :
115 57550 : CPLAssert( nY >= 0 && nY < psInfo->nYSize );
116 57550 : CPLAssert( nX >= 0 && nX < psInfo->nXSize );
117 :
118 57550 : if( psInfo->eType == GDT_Byte )
119 : {
120 3144 : for( iBand = 0; iBand < psInfo->nBands; iBand++ )
121 : {
122 : unsigned char *pbyInsert = psInfo->pabyChunkBuf
123 : + iBand * psInfo->nXSize * psInfo->nYSize
124 2272 : + nY * psInfo->nXSize + nX;
125 :
126 : *pbyInsert = (unsigned char)( psInfo->padfBurnValue[iBand] +
127 : ( (psInfo->eBurnValueSource == GBV_UserBurnValue)?
128 2272 : 0 : dfVariant ) );
129 : }
130 : }
131 : else
132 : {
133 113356 : for( iBand = 0; iBand < psInfo->nBands; iBand++ )
134 : {
135 : float *pfInsert = ((float *) psInfo->pabyChunkBuf)
136 : + iBand * psInfo->nXSize * psInfo->nYSize
137 56678 : + nY * psInfo->nXSize + nX;
138 :
139 : *pfInsert = (float)( psInfo->padfBurnValue[iBand] +
140 : ( (psInfo->eBurnValueSource == GBV_UserBurnValue)?
141 56678 : 0 : dfVariant ) );
142 : }
143 : }
144 57550 : }
145 :
146 : /************************************************************************/
147 : /* GDALCollectRingsFromGeometry() */
148 : /************************************************************************/
149 :
150 : static void GDALCollectRingsFromGeometry(
151 : OGRGeometry *poShape,
152 : std::vector<double> &aPointX, std::vector<double> &aPointY,
153 : std::vector<double> &aPointVariant,
154 1291 : std::vector<int> &aPartSize, GDALBurnValueSrc eBurnValueSrc)
155 :
156 : {
157 1291 : if( poShape == NULL )
158 0 : return;
159 :
160 1291 : OGRwkbGeometryType eFlatType = wkbFlatten(poShape->getGeometryType());
161 : int i;
162 :
163 1291 : if ( eFlatType == wkbPoint )
164 : {
165 0 : OGRPoint *poPoint = (OGRPoint *) poShape;
166 0 : int nNewCount = aPointX.size() + 1;
167 :
168 0 : aPointX.reserve( nNewCount );
169 0 : aPointY.reserve( nNewCount );
170 0 : aPointX.push_back( poPoint->getX() );
171 0 : aPointY.push_back( poPoint->getY() );
172 0 : aPartSize.push_back( 1 );
173 0 : if( eBurnValueSrc != GBV_UserBurnValue )
174 : {
175 : /*switch( eBurnValueSrc )
176 : {
177 : case GBV_Z:*/
178 0 : aPointVariant.reserve( nNewCount );
179 0 : aPointVariant.push_back( poPoint->getZ() );
180 : /*break;
181 : case GBV_M:
182 : aPointVariant.reserve( nNewCount );
183 : aPointVariant.push_back( poPoint->getM() );
184 : }*/
185 : }
186 : }
187 1291 : else if ( eFlatType == wkbLineString )
188 : {
189 1266 : OGRLineString *poLine = (OGRLineString *) poShape;
190 1266 : int nCount = poLine->getNumPoints();
191 1266 : int nNewCount = aPointX.size() + nCount;
192 :
193 1266 : aPointX.reserve( nNewCount );
194 1266 : aPointY.reserve( nNewCount );
195 1266 : if( eBurnValueSrc != GBV_UserBurnValue )
196 1242 : aPointVariant.reserve( nNewCount );
197 33801 : for ( i = nCount - 1; i >= 0; i-- )
198 : {
199 32535 : aPointX.push_back( poLine->getX(i) );
200 32535 : aPointY.push_back( poLine->getY(i) );
201 32535 : if( eBurnValueSrc != GBV_UserBurnValue )
202 : {
203 : /*switch( eBurnValueSrc )
204 : {
205 : case GBV_Z:*/
206 32431 : aPointVariant.push_back( poLine->getZ(i) );
207 : /*break;
208 : case GBV_M:
209 : aPointVariant.push_back( poLine->getM(i) );
210 : }*/
211 : }
212 : }
213 1266 : aPartSize.push_back( nCount );
214 : }
215 25 : else if ( EQUAL(poShape->getGeometryName(),"LINEARRING") )
216 : {
217 0 : OGRLinearRing *poRing = (OGRLinearRing *) poShape;
218 0 : int nCount = poRing->getNumPoints();
219 0 : int nNewCount = aPointX.size() + nCount;
220 :
221 0 : aPointX.reserve( nNewCount );
222 0 : aPointY.reserve( nNewCount );
223 0 : if( eBurnValueSrc != GBV_UserBurnValue )
224 0 : aPointVariant.reserve( nNewCount );
225 0 : for ( i = nCount - 1; i >= 0; i-- )
226 : {
227 0 : aPointX.push_back( poRing->getX(i) );
228 0 : aPointY.push_back( poRing->getY(i) );
229 : }
230 0 : if( eBurnValueSrc != GBV_UserBurnValue )
231 : {
232 : /*switch( eBurnValueSrc )
233 : {
234 : case GBV_Z:*/
235 0 : aPointVariant.push_back( poRing->getZ(i) );
236 : /*break;
237 : case GBV_M:
238 : aPointVariant.push_back( poRing->getM(i) );
239 : }*/
240 : }
241 0 : aPartSize.push_back( nCount );
242 : }
243 25 : else if( eFlatType == wkbPolygon )
244 : {
245 21 : OGRPolygon *poPolygon = (OGRPolygon *) poShape;
246 :
247 : GDALCollectRingsFromGeometry( poPolygon->getExteriorRing(),
248 : aPointX, aPointY, aPointVariant,
249 21 : aPartSize, eBurnValueSrc );
250 :
251 24 : for( i = 0; i < poPolygon->getNumInteriorRings(); i++ )
252 : GDALCollectRingsFromGeometry( poPolygon->getInteriorRing(i),
253 : aPointX, aPointY, aPointVariant,
254 3 : aPartSize, eBurnValueSrc );
255 : }
256 :
257 8 : else if( eFlatType == wkbMultiPoint
258 : || eFlatType == wkbMultiLineString
259 : || eFlatType == wkbMultiPolygon
260 : || eFlatType == wkbGeometryCollection )
261 : {
262 4 : OGRGeometryCollection *poGC = (OGRGeometryCollection *) poShape;
263 :
264 9 : for( i = 0; i < poGC->getNumGeometries(); i++ )
265 : GDALCollectRingsFromGeometry( poGC->getGeometryRef(i),
266 : aPointX, aPointY, aPointVariant,
267 5 : aPartSize, eBurnValueSrc );
268 : }
269 : else
270 : {
271 0 : CPLDebug( "GDAL", "Rasterizer ignoring non-polygonal geometry." );
272 : }
273 : }
274 :
275 : /************************************************************************/
276 : /* gv_rasterize_one_shape() */
277 : /************************************************************************/
278 : static void
279 : gv_rasterize_one_shape( unsigned char *pabyChunkBuf, int nYOff,
280 : int nXSize, int nYSize,
281 : int nBands, GDALDataType eType, int bAllTouched,
282 : OGRGeometry *poShape, double *padfBurnValue,
283 : GDALBurnValueSrc eBurnValueSrc,
284 : GDALTransformerFunc pfnTransformer,
285 1262 : void *pTransformArg )
286 :
287 : {
288 : GDALRasterizeInfo sInfo;
289 :
290 1262 : if (poShape == NULL)
291 0 : return;
292 :
293 1262 : sInfo.nXSize = nXSize;
294 1262 : sInfo.nYSize = nYSize;
295 1262 : sInfo.nBands = nBands;
296 1262 : sInfo.pabyChunkBuf = pabyChunkBuf;
297 1262 : sInfo.eType = eType;
298 1262 : sInfo.padfBurnValue = padfBurnValue;
299 1262 : sInfo.eBurnValueSource = eBurnValueSrc;
300 :
301 : /* -------------------------------------------------------------------- */
302 : /* Transform polygon geometries into a set of rings and a part */
303 : /* size list. */
304 : /* -------------------------------------------------------------------- */
305 1262 : std::vector<double> aPointX;
306 2524 : std::vector<double> aPointY;
307 2524 : std::vector<double> aPointVariant;
308 2524 : std::vector<int> aPartSize;
309 :
310 : GDALCollectRingsFromGeometry( poShape, aPointX, aPointY, aPointVariant,
311 1262 : aPartSize, eBurnValueSrc );
312 :
313 : /* -------------------------------------------------------------------- */
314 : /* Transform points if needed. */
315 : /* -------------------------------------------------------------------- */
316 1262 : if( pfnTransformer != NULL )
317 : {
318 1262 : int *panSuccess = (int *) CPLCalloc(sizeof(int),aPointX.size());
319 :
320 : // TODO: we need to add all appropriate error checking at some point.
321 : pfnTransformer( pTransformArg, FALSE, aPointX.size(),
322 1262 : &(aPointX[0]), &(aPointY[0]), NULL, panSuccess );
323 1262 : CPLFree( panSuccess );
324 : }
325 :
326 : /* -------------------------------------------------------------------- */
327 : /* Shift to account for the buffer offset of this buffer. */
328 : /* -------------------------------------------------------------------- */
329 : unsigned int i;
330 :
331 33797 : for( i = 0; i < aPointY.size(); i++ )
332 32535 : aPointY[i] -= nYOff;
333 :
334 : /* -------------------------------------------------------------------- */
335 : /* Perform the rasterization. */
336 : /* According to the C++ Standard/23.2.4, elements of a vector are */
337 : /* stored in continuous memory block. */
338 : /* -------------------------------------------------------------------- */
339 : unsigned int j,n;
340 :
341 : // TODO - mloskot: Check if vectors are empty, otherwise it may
342 : // lead to undefined behavior by returning non-referencable pointer.
343 : // if (!aPointX.empty())
344 : // /* fill polygon */
345 : // else
346 : // /* How to report this problem? */
347 1262 : switch ( wkbFlatten(poShape->getGeometryType()) )
348 : {
349 : case wkbPoint:
350 : case wkbMultiPoint:
351 : GDALdllImagePoint( sInfo.nXSize, nYSize,
352 : aPartSize.size(), &(aPartSize[0]),
353 : &(aPointX[0]), &(aPointY[0]),
354 : (eBurnValueSrc == GBV_UserBurnValue)?
355 : NULL : &(aPointVariant[0]),
356 0 : gvBurnPoint, &sInfo );
357 0 : break;
358 : case wkbLineString:
359 : case wkbMultiLineString:
360 : {
361 1242 : if( bAllTouched )
362 : GDALdllImageLineAllTouched( sInfo.nXSize, nYSize,
363 : aPartSize.size(), &(aPartSize[0]),
364 : &(aPointX[0]), &(aPointY[0]),
365 : (eBurnValueSrc == GBV_UserBurnValue)?
366 : NULL : &(aPointVariant[0]),
367 0 : gvBurnPoint, &sInfo );
368 : else
369 : GDALdllImageLine( sInfo.nXSize, nYSize,
370 : aPartSize.size(), &(aPartSize[0]),
371 : &(aPointX[0]), &(aPointY[0]),
372 : (eBurnValueSrc == GBV_UserBurnValue)?
373 : NULL : &(aPointVariant[0]),
374 1242 : gvBurnPoint, &sInfo );
375 : }
376 1242 : break;
377 :
378 : default:
379 : {
380 : GDALdllImageFilledPolygon( sInfo.nXSize, nYSize,
381 : aPartSize.size(), &(aPartSize[0]),
382 : &(aPointX[0]), &(aPointY[0]),
383 : (eBurnValueSrc == GBV_UserBurnValue)?
384 : NULL : &(aPointVariant[0]),
385 20 : gvBurnScanline, &sInfo );
386 20 : if( bAllTouched )
387 : {
388 : /* Reverting the variants to the first value because the
389 : polygon is filled using the variant from the first point of
390 : the first segment. Should be removed when the code to full
391 : polygons more appropriately is added. */
392 7 : if(eBurnValueSrc == GBV_UserBurnValue)
393 : {
394 : GDALdllImageLineAllTouched( sInfo.nXSize, nYSize,
395 : aPartSize.size(), &(aPartSize[0]),
396 : &(aPointX[0]), &(aPointY[0]),
397 : NULL,
398 7 : gvBurnPoint, &sInfo );
399 : }
400 : else
401 : {
402 0 : for( i = 0, n = 0; i < aPartSize.size(); i++ )
403 0 : for( j = 0; j < aPartSize[i]; j++ )
404 0 : aPointVariant[n++] = aPointVariant[0];
405 :
406 : GDALdllImageLineAllTouched( sInfo.nXSize, nYSize,
407 : aPartSize.size(), &(aPartSize[0]),
408 : &(aPointX[0]), &(aPointY[0]),
409 : &(aPointVariant[0]),
410 0 : gvBurnPoint, &sInfo );
411 : }
412 : }
413 : }
414 : break;
415 1262 : }
416 : }
417 :
418 : /************************************************************************/
419 : /* GDALRasterizeGeometries() */
420 : /************************************************************************/
421 :
422 : /**
423 : * Burn geometries into raster.
424 : *
425 : * Rasterize a list of geometric objects into a raster dataset. The
426 : * geometries are passed as an array of OGRGeometryH handlers.
427 : *
428 : * If the geometries are in the georferenced coordinates of the raster
429 : * dataset, then the pfnTransform may be passed in NULL and one will be
430 : * derived internally from the geotransform of the dataset. The transform
431 : * needs to transform the geometry locations into pixel/line coordinates
432 : * on the raster dataset.
433 : *
434 : * The output raster may be of any GDAL supported datatype, though currently
435 : * internally the burning is done either as GDT_Byte or GDT_Float32. This
436 : * may be improved in the future. An explicit list of burn values for
437 : * each geometry for each band must be passed in.
438 : *
439 : * The papszOption list of options currently only supports one option. The
440 : * "ALL_TOUCHED" option may be enabled by setting it to "TRUE".
441 : *
442 : * @param hDS output data, must be opened in update mode.
443 : * @param nBandCount the number of bands to be updated.
444 : * @param panBandList the list of bands to be updated.
445 : * @param nGeomCount the number of geometries being passed in pahGeometries.
446 : * @param pahGeometries the array of geometries to burn in.
447 : * @param pfnTransformer transformation to apply to geometries to put into
448 : * pixel/line coordinates on raster. If NULL a geotransform based one will
449 : * be created internally.
450 : * @param pTransformerArg callback data for transformer.
451 : * @param padfGeomBurnValue the array of values to burn into the raster.
452 : * There should be nBandCount values for each geometry.
453 : * @param papszOptions special options controlling rasterization
454 : * <dl>
455 : * <dt>"ALL_TOUCHED":</dt> <dd>May be set to TRUE to set all pixels touched
456 : * by the line or polygons, not just those whose center is within the polygon
457 : * or that are selected by brezenhams line algorithm. Defaults to FALSE.</dd>
458 : * <dt>"BURN_VALUE_FROM":</dt> <dd>May be set to "Z" to use the Z values of the
459 : * geometries. dfBurnValue is added to this before burning.
460 : * Defaults to GDALBurnValueSrc.GBV_UserBurnValue in which case just the
461 : * dfBurnValue is burned. This is implemented only for points and lines for
462 : * now. The M value may be supported in the future.</dd>
463 : * </dl>
464 : * @param pfnProgress the progress function to report completion.
465 : * @param pProgressArg callback data for progress function.
466 : *
467 : * @return CE_None on success or CE_Failure on error.
468 : */
469 :
470 : CPLErr GDALRasterizeGeometries( GDALDatasetH hDS,
471 : int nBandCount, int *panBandList,
472 : int nGeomCount, OGRGeometryH *pahGeometries,
473 : GDALTransformerFunc pfnTransformer,
474 : void *pTransformArg,
475 : double *padfGeomBurnValue,
476 : char **papszOptions,
477 : GDALProgressFunc pfnProgress,
478 10 : void *pProgressArg )
479 :
480 : {
481 : GDALDataType eType;
482 : int nYChunkSize, nScanlineBytes;
483 : unsigned char *pabyChunkBuf;
484 : int iY;
485 10 : GDALDataset *poDS = (GDALDataset *) hDS;
486 :
487 10 : if( pfnProgress == NULL )
488 6 : pfnProgress = GDALDummyProgress;
489 :
490 : /* -------------------------------------------------------------------- */
491 : /* Do some rudimentary arg checking. */
492 : /* -------------------------------------------------------------------- */
493 10 : if( nBandCount == 0 || nGeomCount == 0 )
494 0 : return CE_None;
495 :
496 : // prototype band.
497 10 : GDALRasterBand *poBand = poDS->GetRasterBand( panBandList[0] );
498 10 : if (poBand == NULL)
499 0 : return CE_Failure;
500 :
501 10 : int bAllTouched = CSLFetchBoolean( papszOptions, "ALL_TOUCHED", FALSE );
502 10 : const char *pszOpt = CSLFetchNameValue( papszOptions, "BURN_VALUE_FROM" );
503 10 : GDALBurnValueSrc eBurnValueSource = GBV_UserBurnValue;
504 10 : if( pszOpt )
505 : {
506 2 : if( EQUAL(pszOpt,"Z"))
507 2 : eBurnValueSource = GBV_Z;
508 : /*else if( EQUAL(pszOpt,"M"))
509 : eBurnValueSource = GBV_M;*/
510 : }
511 :
512 : /* -------------------------------------------------------------------- */
513 : /* If we have no transformer, assume the geometries are in file */
514 : /* georeferenced coordinates, and create a transformer to */
515 : /* convert that to pixel/line coordinates. */
516 : /* */
517 : /* We really just need to apply an affine transform, but for */
518 : /* simplicity we use the more general GenImgProjTransformer. */
519 : /* -------------------------------------------------------------------- */
520 10 : int bNeedToFreeTransformer = FALSE;
521 :
522 10 : if( pfnTransformer == NULL )
523 : {
524 4 : bNeedToFreeTransformer = TRUE;
525 :
526 : pTransformArg =
527 : GDALCreateGenImgProjTransformer( NULL, NULL, hDS, NULL,
528 4 : FALSE, 0.0, 0);
529 4 : pfnTransformer = GDALGenImgProjTransform;
530 : }
531 :
532 : /* -------------------------------------------------------------------- */
533 : /* Establish a chunksize to operate on. The larger the chunk */
534 : /* size the less times we need to make a pass through all the */
535 : /* shapes. */
536 : /* -------------------------------------------------------------------- */
537 10 : if( poBand->GetRasterDataType() == GDT_Byte )
538 8 : eType = GDT_Byte;
539 : else
540 2 : eType = GDT_Float32;
541 :
542 : nScanlineBytes = nBandCount * poDS->GetRasterXSize()
543 10 : * (GDALGetDataTypeSize(eType)/8);
544 10 : nYChunkSize = 10000000 / nScanlineBytes;
545 10 : if( nYChunkSize > poDS->GetRasterYSize() )
546 10 : nYChunkSize = poDS->GetRasterYSize();
547 :
548 10 : pabyChunkBuf = (unsigned char *) VSIMalloc(nYChunkSize * nScanlineBytes);
549 10 : if( pabyChunkBuf == NULL )
550 : {
551 : CPLError( CE_Failure, CPLE_OutOfMemory,
552 0 : "Unable to allocate rasterization buffer." );
553 0 : return CE_Failure;
554 : }
555 :
556 : /* ==================================================================== */
557 : /* Loop over image in designated chunks. */
558 : /* ==================================================================== */
559 10 : CPLErr eErr = CE_None;
560 :
561 10 : pfnProgress( 0.0, NULL, pProgressArg );
562 :
563 20 : for( iY = 0;
564 : iY < poDS->GetRasterYSize() && eErr == CE_None;
565 : iY += nYChunkSize )
566 : {
567 : int nThisYChunkSize;
568 : int iShape;
569 :
570 10 : nThisYChunkSize = nYChunkSize;
571 10 : if( nThisYChunkSize + iY > poDS->GetRasterYSize() )
572 0 : nThisYChunkSize = poDS->GetRasterYSize() - iY;
573 :
574 : eErr =
575 : poDS->RasterIO(GF_Read,
576 : 0, iY, poDS->GetRasterXSize(), nThisYChunkSize,
577 : pabyChunkBuf,poDS->GetRasterXSize(),nThisYChunkSize,
578 : eType, nBandCount, panBandList,
579 10 : 0, 0, 0 );
580 10 : if( eErr != CE_None )
581 0 : break;
582 :
583 1257 : for( iShape = 0; iShape < nGeomCount; iShape++ )
584 : {
585 : gv_rasterize_one_shape( pabyChunkBuf, iY,
586 : poDS->GetRasterXSize(), nThisYChunkSize,
587 : nBandCount, eType, bAllTouched,
588 : (OGRGeometry *) pahGeometries[iShape],
589 : padfGeomBurnValue + iShape*nBandCount,
590 : eBurnValueSource,
591 1247 : pfnTransformer, pTransformArg );
592 : }
593 :
594 : eErr =
595 : poDS->RasterIO( GF_Write, 0, iY,
596 : poDS->GetRasterXSize(), nThisYChunkSize,
597 : pabyChunkBuf,
598 : poDS->GetRasterXSize(), nThisYChunkSize,
599 10 : eType, nBandCount, panBandList, 0, 0, 0 );
600 :
601 10 : if( !pfnProgress((iY+nThisYChunkSize)/((double)poDS->GetRasterYSize()),
602 : "", pProgressArg ) )
603 : {
604 0 : CPLError( CE_Failure, CPLE_UserInterrupt, "User terminated" );
605 0 : eErr = CE_Failure;
606 : }
607 : }
608 :
609 : /* -------------------------------------------------------------------- */
610 : /* cleanup */
611 : /* -------------------------------------------------------------------- */
612 10 : VSIFree( pabyChunkBuf );
613 :
614 10 : if( bNeedToFreeTransformer )
615 4 : GDALDestroyTransformer( pTransformArg );
616 :
617 10 : return eErr;
618 : }
619 :
620 : /************************************************************************/
621 : /* GDALRasterizeLayers() */
622 : /************************************************************************/
623 :
624 : /**
625 : * Burn geometries from the specified list of layers into raster.
626 : *
627 : * Rasterize all the geometric objects from a list of layers into a raster
628 : * dataset. The layers are passed as an array of OGRLayerH handlers.
629 : *
630 : * If the geometries are in the georferenced coordinates of the raster
631 : * dataset, then the pfnTransform may be passed in NULL and one will be
632 : * derived internally from the geotransform of the dataset. The transform
633 : * needs to transform the geometry locations into pixel/line coordinates
634 : * on the raster dataset.
635 : *
636 : * The output raster may be of any GDAL supported datatype, though currently
637 : * internally the burning is done either as GDT_Byte or GDT_Float32. This
638 : * may be improved in the future. An explicit list of burn values for
639 : * each layer for each band must be passed in.
640 : *
641 : * @param hDS output data, must be opened in update mode.
642 : * @param nBandCount the number of bands to be updated.
643 : * @param panBandList the list of bands to be updated.
644 : * @param nLayerCount the number of layers being passed in pahLayers array.
645 : * @param pahLayers the array of layers to burn in.
646 : * @param pfnTransformer transformation to apply to geometries to put into
647 : * pixel/line coordinates on raster. If NULL a geotransform based one will
648 : * be created internally.
649 : * @param pTransformerArg callback data for transformer.
650 : * @param padfLayerBurnValues the array of values to burn into the raster.
651 : * There should be nBandCount values for each layer.
652 : * @param papszOption special options controlling rasterization:
653 : * <dl>
654 : * <dt>"ATTRIBUTE":</dt> <dd>Identifies an attribute field on the features to be
655 : * used for a burn in value. The value will be burned into all output
656 : * bands. If specified, padfLayerBurnValues will not be used and can be a NULL
657 : * pointer.</dd>
658 : * <dt>"CHUNKYSIZE":</dt> <dd>The height in lines of the chunk to operate on.
659 : * The larger the chunk size the less times we need to make a pass through all
660 : * the shapes. If it is not set or set to zero the default chunk size will be
661 : * used. Default size will be estimated based on the GDAL cache buffer size
662 : * using formula: cache_size_bytes/scanline_size_bytes, so the chunk will
663 : * not exceed the cache.</dd>
664 : * <dt>"ALL_TOUCHED":</dt> <dd>May be set to TRUE to set all pixels touched
665 : * by the line or polygons, not just those whose center is within the polygon
666 : * or that are selected by brezenhams line algorithm. Defaults to FALSE.</dd>
667 : * <dt>"BURN_VALUE_FROM":</dt> <dd>May be set to "Z" to use the Z values of the
668 : * geometries. The value from padfLayerBurnValues or the attribute field value
669 : * is added to this before burning. In default case dfBurnValue is burned as it
670 : * is. This is implemented properly only for points and lines for now. Polygons
671 : * will be burned using the Z value from the first point. The M value may be
672 : * supported in the future.</dd>
673 : * @param pfnProgress the progress function to report completion.
674 : * @param pProgressArg callback data for progress function.
675 : *
676 : * @return CE_None on success or CE_Failure on error.
677 : */
678 :
679 : #ifdef OGR_ENABLED
680 :
681 : CPLErr GDALRasterizeLayers( GDALDatasetH hDS,
682 : int nBandCount, int *panBandList,
683 : int nLayerCount, OGRLayerH *pahLayers,
684 : GDALTransformerFunc pfnTransformer,
685 : void *pTransformArg,
686 : double *padfLayerBurnValues,
687 : char **papszOptions,
688 : GDALProgressFunc pfnProgress,
689 4 : void *pProgressArg )
690 :
691 : {
692 : GDALDataType eType;
693 : unsigned char *pabyChunkBuf;
694 4 : GDALDataset *poDS = (GDALDataset *) hDS;
695 :
696 4 : if( pfnProgress == NULL )
697 4 : pfnProgress = GDALDummyProgress;
698 :
699 : /* -------------------------------------------------------------------- */
700 : /* Do some rudimentary arg checking. */
701 : /* -------------------------------------------------------------------- */
702 4 : if( nBandCount == 0 || nLayerCount == 0 )
703 0 : return CE_None;
704 :
705 : // prototype band.
706 4 : GDALRasterBand *poBand = poDS->GetRasterBand( panBandList[0] );
707 4 : if (poBand == NULL)
708 0 : return CE_Failure;
709 :
710 4 : int bAllTouched = CSLFetchBoolean( papszOptions, "ALL_TOUCHED", FALSE );
711 4 : const char *pszOpt = CSLFetchNameValue( papszOptions, "BURN_VALUE_FROM" );
712 4 : GDALBurnValueSrc eBurnValueSource = GBV_UserBurnValue;
713 4 : if( pszOpt )
714 : {
715 1 : if( EQUAL(pszOpt,"Z"))
716 1 : eBurnValueSource = GBV_Z;
717 : /*else if( EQUAL(pszOpt,"M"))
718 : eBurnValueSource = GBV_M;*/
719 : }
720 :
721 : /* -------------------------------------------------------------------- */
722 : /* Establish a chunksize to operate on. The larger the chunk */
723 : /* size the less times we need to make a pass through all the */
724 : /* shapes. */
725 : /* -------------------------------------------------------------------- */
726 : int nYChunkSize, nScanlineBytes;
727 : const char *pszYChunkSize =
728 4 : CSLFetchNameValue( papszOptions, "CHUNKYSIZE" );
729 :
730 4 : if( poBand->GetRasterDataType() == GDT_Byte )
731 4 : eType = GDT_Byte;
732 : else
733 0 : eType = GDT_Float32;
734 :
735 : nScanlineBytes = nBandCount * poDS->GetRasterXSize()
736 4 : * (GDALGetDataTypeSize(eType)/8);
737 :
738 4 : if ( pszYChunkSize && (nYChunkSize = atoi(pszYChunkSize)) )
739 : ;
740 : else
741 4 : nYChunkSize = GDALGetCacheMax() / nScanlineBytes;
742 :
743 4 : if( nYChunkSize < 1 )
744 0 : nYChunkSize = 1;
745 4 : if( nYChunkSize > poDS->GetRasterYSize() )
746 4 : nYChunkSize = poDS->GetRasterYSize();
747 :
748 4 : pabyChunkBuf = (unsigned char *) VSIMalloc(nYChunkSize * nScanlineBytes);
749 4 : if( pabyChunkBuf == NULL )
750 : {
751 : CPLError( CE_Failure, CPLE_OutOfMemory,
752 0 : "Unable to allocate rasterization buffer." );
753 0 : return CE_Failure;
754 : }
755 :
756 : /* -------------------------------------------------------------------- */
757 : /* Read the image once for all layers if user requested to render */
758 : /* the whole raster in single chunk. */
759 : /* -------------------------------------------------------------------- */
760 4 : if ( nYChunkSize == poDS->GetRasterYSize() )
761 : {
762 4 : if ( poDS->RasterIO( GF_Read, 0, 0, poDS->GetRasterXSize(),
763 : nYChunkSize, pabyChunkBuf,
764 : poDS->GetRasterXSize(), nYChunkSize,
765 : eType, nBandCount, panBandList, 0, 0, 0 )
766 : != CE_None )
767 : {
768 : CPLError( CE_Failure, CPLE_OutOfMemory,
769 0 : "Unable to read buffer." );
770 0 : CPLFree( pabyChunkBuf );
771 0 : return CE_Failure;
772 : }
773 : }
774 :
775 : /* ==================================================================== */
776 : /* Read the specified layers transfoming and rasterizing */
777 : /* geometries. */
778 : /* ==================================================================== */
779 4 : CPLErr eErr = CE_None;
780 : int iLayer;
781 : const char *pszBurnAttribute =
782 4 : CSLFetchNameValue( papszOptions, "ATTRIBUTE" );
783 :
784 4 : pfnProgress( 0.0, NULL, pProgressArg );
785 :
786 8 : for( iLayer = 0; iLayer < nLayerCount; iLayer++ )
787 : {
788 4 : int iBurnField = -1;
789 4 : double *padfBurnValues = NULL;
790 4 : OGRLayer *poLayer = (OGRLayer *) pahLayers[iLayer];
791 :
792 4 : if ( !poLayer )
793 : {
794 : CPLError( CE_Warning, CPLE_AppDefined,
795 0 : "Layer element number %d is NULL, skipping.\n", iLayer );
796 0 : continue;
797 : }
798 :
799 : /* -------------------------------------------------------------------- */
800 : /* If the layer does not contain any features just skip it. */
801 : /* Do not force the feature count, so if driver doesn't know */
802 : /* exact number of features, go down the normal way. */
803 : /* -------------------------------------------------------------------- */
804 4 : if ( poLayer->GetFeatureCount(FALSE) == 0 )
805 0 : continue;
806 :
807 4 : if ( pszBurnAttribute )
808 : {
809 : iBurnField =
810 1 : poLayer->GetLayerDefn()->GetFieldIndex( pszBurnAttribute );
811 1 : if ( iBurnField == -1 )
812 : {
813 : CPLError( CE_Warning, CPLE_AppDefined,
814 : "Failed to find field %s on layer %s, skipping.\n",
815 : pszBurnAttribute,
816 0 : poLayer->GetLayerDefn()->GetName() );
817 0 : continue;
818 : }
819 : }
820 : else
821 3 : padfBurnValues = padfLayerBurnValues + iLayer * nBandCount;
822 :
823 : /* -------------------------------------------------------------------- */
824 : /* If we have no transformer, create the one from input file */
825 : /* projection. Note that each layer can be georefernced */
826 : /* separately. */
827 : /* -------------------------------------------------------------------- */
828 4 : int bNeedToFreeTransformer = FALSE;
829 :
830 4 : if( pfnTransformer == NULL )
831 : {
832 4 : char *pszProjection = NULL;
833 4 : bNeedToFreeTransformer = TRUE;
834 :
835 4 : OGRSpatialReference *poSRS = poLayer->GetSpatialRef();
836 4 : if ( !poSRS )
837 : {
838 : CPLError( CE_Warning, CPLE_AppDefined,
839 : "Failed to fetch spatial reference on layer %s "
840 : "to build transformer, assuming matching coordinate systems.\n",
841 1 : poLayer->GetLayerDefn()->GetName() );
842 : }
843 : else
844 3 : poSRS->exportToWkt( &pszProjection );
845 :
846 : pTransformArg =
847 : GDALCreateGenImgProjTransformer( NULL, pszProjection,
848 4 : hDS, NULL, FALSE, 0.0, 0 );
849 4 : pfnTransformer = GDALGenImgProjTransform;
850 :
851 4 : CPLFree( pszProjection );
852 : }
853 :
854 : OGRFeature *poFeat;
855 :
856 4 : poLayer->ResetReading();
857 :
858 : /* -------------------------------------------------------------------- */
859 : /* Loop over image in designated chunks. */
860 : /* -------------------------------------------------------------------- */
861 : int iY;
862 8 : for( iY = 0;
863 : iY < poDS->GetRasterYSize() && eErr == CE_None;
864 : iY += nYChunkSize )
865 : {
866 : int nThisYChunkSize;
867 :
868 4 : nThisYChunkSize = nYChunkSize;
869 4 : if( nThisYChunkSize + iY > poDS->GetRasterYSize() )
870 0 : nThisYChunkSize = poDS->GetRasterYSize() - iY;
871 :
872 : // Only re-read image if not a single chunk is being rendered
873 4 : if ( nYChunkSize < poDS->GetRasterYSize() )
874 : {
875 : eErr =
876 : poDS->RasterIO( GF_Read, 0, iY,
877 : poDS->GetRasterXSize(), nThisYChunkSize,
878 : pabyChunkBuf,
879 : poDS->GetRasterXSize(), nThisYChunkSize,
880 0 : eType, nBandCount, panBandList, 0, 0, 0 );
881 0 : if( eErr != CE_None )
882 0 : break;
883 : }
884 :
885 4 : double *padfAttrValues = (double *) VSIMalloc(sizeof(double) * nBandCount);
886 23 : while( (poFeat = poLayer->GetNextFeature()) != NULL )
887 : {
888 15 : OGRGeometry *poGeom = poFeat->GetGeometryRef();
889 :
890 15 : if ( pszBurnAttribute )
891 : {
892 : int iBand;
893 : double dfAttrValue;
894 :
895 5 : dfAttrValue = poFeat->GetFieldAsDouble( iBurnField );
896 20 : for (iBand = 0 ; iBand < nBandCount ; iBand++)
897 15 : padfAttrValues[iBand] = dfAttrValue;
898 :
899 5 : padfBurnValues = padfAttrValues;
900 : }
901 :
902 : gv_rasterize_one_shape( pabyChunkBuf, iY,
903 : poDS->GetRasterXSize(),
904 : nThisYChunkSize,
905 : nBandCount, eType, bAllTouched, poGeom,
906 : padfBurnValues, eBurnValueSource,
907 15 : pfnTransformer, pTransformArg );
908 :
909 15 : delete poFeat;
910 : }
911 4 : VSIFree( padfAttrValues );
912 :
913 : // Only write image if not a single chunk is being rendered
914 4 : if ( nYChunkSize < poDS->GetRasterYSize() )
915 : {
916 : eErr =
917 : poDS->RasterIO( GF_Write, 0, iY,
918 : poDS->GetRasterXSize(), nThisYChunkSize,
919 : pabyChunkBuf,
920 : poDS->GetRasterXSize(), nThisYChunkSize,
921 0 : eType, nBandCount, panBandList, 0, 0, 0 );
922 : }
923 :
924 4 : poLayer->ResetReading();
925 :
926 4 : if( !pfnProgress((iY+nThisYChunkSize)/((double)poDS->GetRasterYSize()),
927 : "", pProgressArg) )
928 : {
929 0 : CPLError( CE_Failure, CPLE_UserInterrupt, "User terminated" );
930 0 : eErr = CE_Failure;
931 : }
932 : }
933 :
934 4 : if ( bNeedToFreeTransformer )
935 : {
936 4 : GDALDestroyTransformer( pTransformArg );
937 4 : pTransformArg = NULL;
938 4 : pfnTransformer = NULL;
939 : }
940 : }
941 :
942 : /* -------------------------------------------------------------------- */
943 : /* Write out the image once for all layers if user requested */
944 : /* to render the whole raster in single chunk. */
945 : /* -------------------------------------------------------------------- */
946 4 : if ( nYChunkSize == poDS->GetRasterYSize() )
947 : {
948 : poDS->RasterIO( GF_Write, 0, 0,
949 : poDS->GetRasterXSize(), nYChunkSize,
950 : pabyChunkBuf,
951 : poDS->GetRasterXSize(), nYChunkSize,
952 4 : eType, nBandCount, panBandList, 0, 0, 0 );
953 : }
954 :
955 : /* -------------------------------------------------------------------- */
956 : /* cleanup */
957 : /* -------------------------------------------------------------------- */
958 4 : VSIFree( pabyChunkBuf );
959 :
960 4 : return eErr;
961 : }
962 :
963 : #endif /* def OGR_ENABLED */
964 :
965 : /************************************************************************/
966 : /* GDALRasterizeLayersBuf() */
967 : /************************************************************************/
968 :
969 : /**
970 : * Burn geometries from the specified list of layer into raster.
971 : *
972 : * Rasterize all the geometric objects from a list of layers into supplied
973 : * raster buffer. The layers are passed as an array of OGRLayerH handlers.
974 : *
975 : * If the geometries are in the georferenced coordinates of the raster
976 : * dataset, then the pfnTransform may be passed in NULL and one will be
977 : * derived internally from the geotransform of the dataset. The transform
978 : * needs to transform the geometry locations into pixel/line coordinates
979 : * of the target raster.
980 : *
981 : * The output raster may be of any GDAL supported datatype, though currently
982 : * internally the burning is done either as GDT_Byte or GDT_Float32. This
983 : * may be improved in the future.
984 : *
985 : * @param pData pointer to the output data array.
986 : *
987 : * @param nBufXSize width of the output data array in pixels.
988 : *
989 : * @param nBufYSize height of the output data array in pixels.
990 : *
991 : * @param eBufType data type of the output data array.
992 : *
993 : * @param nPixelSpace The byte offset from the start of one pixel value in
994 : * pData to the start of the next pixel value within a scanline. If defaulted
995 : * (0) the size of the datatype eBufType is used.
996 : *
997 : * @param nLineSpace The byte offset from the start of one scanline in
998 : * pData to the start of the next. If defaulted the size of the datatype
999 : * eBufType * nBufXSize is used.
1000 : *
1001 : * @param nLayerCount the number of layers being passed in pahLayers array.
1002 : *
1003 : * @param pahLayers the array of layers to burn in.
1004 : *
1005 : * @param pszDstProjection WKT defining the coordinate system of the target
1006 : * raster.
1007 : *
1008 : * @param padfDstGeoTransform geotransformation matrix of the target raster.
1009 : *
1010 : * @param pfnTransformer transformation to apply to geometries to put into
1011 : * pixel/line coordinates on raster. If NULL a geotransform based one will
1012 : * be created internally.
1013 : *
1014 : * @param pTransformerArg callback data for transformer.
1015 : *
1016 : * @param dfBurnValue the value to burn into the raster.
1017 : *
1018 : * @param papszOption special options controlling rasterization:
1019 : * <dl>
1020 : * <dt>"ATTRIBUTE":</dt> <dd>Identifies an attribute field on the features to be
1021 : * used for a burn in value. The value will be burned into all output
1022 : * bands. If specified, padfLayerBurnValues will not be used and can be a NULL
1023 : * pointer.</dd>
1024 : * <dt>"ALL_TOUCHED":</dt> <dd>May be set to TRUE to set all pixels touched
1025 : * by the line or polygons, not just those whose center is within the polygon
1026 : * or that are selected by brezenhams line algorithm. Defaults to FALSE.</dd>
1027 : * </dl>
1028 : * <dt>"BURN_VALUE_FROM":</dt> <dd>May be set to "Z" to use
1029 : * the Z values of the geometries. dfBurnValue or the attribute field value is
1030 : * added to this before burning. In default case dfBurnValue is burned as it
1031 : * is. This is implemented properly only for points and lines for now. Polygons
1032 : * will be burned using the Z value from the first point. The M value may
1033 : * be supported in the future.</dd>
1034 : * </dl>
1035 : *
1036 : * @param pfnProgress the progress function to report completion.
1037 : *
1038 : * @param pProgressArg callback data for progress function.
1039 : *
1040 : *
1041 : * @return CE_None on success or CE_Failure on error.
1042 : */
1043 :
1044 : #ifdef OGR_ENABLED
1045 :
1046 : CPLErr GDALRasterizeLayersBuf( void *pData, int nBufXSize, int nBufYSize,
1047 : GDALDataType eBufType,
1048 : int nPixelSpace, int nLineSpace,
1049 : int nLayerCount, OGRLayerH *pahLayers,
1050 : const char *pszDstProjection,
1051 : double *padfDstGeoTransform,
1052 : GDALTransformerFunc pfnTransformer,
1053 : void *pTransformArg, double dfBurnValue,
1054 : char **papszOptions,
1055 : GDALProgressFunc pfnProgress,
1056 0 : void *pProgressArg )
1057 :
1058 : {
1059 : /* -------------------------------------------------------------------- */
1060 : /* If pixel and line spaceing are defaulted assign reasonable */
1061 : /* value assuming a packed buffer. */
1062 : /* -------------------------------------------------------------------- */
1063 0 : if( nPixelSpace == 0 )
1064 0 : nPixelSpace = GDALGetDataTypeSize( eBufType ) / 8;
1065 :
1066 0 : if( nLineSpace == 0 )
1067 0 : nLineSpace = nPixelSpace * nBufXSize;
1068 :
1069 0 : if( pfnProgress == NULL )
1070 0 : pfnProgress = GDALDummyProgress;
1071 :
1072 : /* -------------------------------------------------------------------- */
1073 : /* Do some rudimentary arg checking. */
1074 : /* -------------------------------------------------------------------- */
1075 0 : if( nLayerCount == 0 )
1076 0 : return CE_None;
1077 :
1078 0 : int bAllTouched = CSLFetchBoolean( papszOptions, "ALL_TOUCHED", FALSE );
1079 0 : const char *pszOpt = CSLFetchNameValue( papszOptions, "BURN_VALUE_FROM" );
1080 0 : GDALBurnValueSrc eBurnValueSource = GBV_UserBurnValue;
1081 0 : if( pszOpt )
1082 : {
1083 0 : if( EQUAL(pszOpt,"Z"))
1084 0 : eBurnValueSource = GBV_Z;
1085 : /*else if( EQUAL(pszOpt,"M"))
1086 : eBurnValueSource = GBV_M;*/
1087 : }
1088 :
1089 : /* ==================================================================== */
1090 : /* Read thes pecified layers transfoming and rasterizing */
1091 : /* geometries. */
1092 : /* ==================================================================== */
1093 0 : CPLErr eErr = CE_None;
1094 : int iLayer;
1095 : const char *pszBurnAttribute =
1096 0 : CSLFetchNameValue( papszOptions, "ATTRIBUTE" );
1097 :
1098 0 : pfnProgress( 0.0, NULL, pProgressArg );
1099 :
1100 0 : for( iLayer = 0; iLayer < nLayerCount; iLayer++ )
1101 : {
1102 0 : int iBurnField = -1;
1103 0 : OGRLayer *poLayer = (OGRLayer *) pahLayers[iLayer];
1104 :
1105 0 : if ( !poLayer )
1106 : {
1107 : CPLError( CE_Warning, CPLE_AppDefined,
1108 0 : "Layer element number %d is NULL, skipping.\n", iLayer );
1109 0 : continue;
1110 : }
1111 :
1112 : /* -------------------------------------------------------------------- */
1113 : /* If the layer does not contain any features just skip it. */
1114 : /* Do not force the feature count, so if driver doesn't know */
1115 : /* exact number of features, go down the normal way. */
1116 : /* -------------------------------------------------------------------- */
1117 0 : if ( poLayer->GetFeatureCount(FALSE) == 0 )
1118 0 : continue;
1119 :
1120 0 : if ( pszBurnAttribute )
1121 : {
1122 : iBurnField =
1123 0 : poLayer->GetLayerDefn()->GetFieldIndex( pszBurnAttribute );
1124 0 : if ( iBurnField == -1 )
1125 : {
1126 : CPLError( CE_Warning, CPLE_AppDefined,
1127 : "Failed to find field %s on layer %s, skipping.\n",
1128 : pszBurnAttribute,
1129 0 : poLayer->GetLayerDefn()->GetName() );
1130 0 : continue;
1131 : }
1132 : }
1133 :
1134 : /* -------------------------------------------------------------------- */
1135 : /* If we have no transformer, create the one from input file */
1136 : /* projection. Note that each layer can be georefernced */
1137 : /* separately. */
1138 : /* -------------------------------------------------------------------- */
1139 0 : int bNeedToFreeTransformer = FALSE;
1140 :
1141 0 : if( pfnTransformer == NULL )
1142 : {
1143 0 : char *pszProjection = NULL;
1144 0 : bNeedToFreeTransformer = TRUE;
1145 :
1146 0 : OGRSpatialReference *poSRS = poLayer->GetSpatialRef();
1147 0 : if ( !poSRS )
1148 : {
1149 : CPLError( CE_Warning, CPLE_AppDefined,
1150 : "Failed to fetch spatial reference on layer %s "
1151 : "to build transformer, assuming matching coordinate systems.\n",
1152 0 : poLayer->GetLayerDefn()->GetName() );
1153 : }
1154 : else
1155 0 : poSRS->exportToWkt( &pszProjection );
1156 :
1157 : pTransformArg =
1158 : GDALCreateGenImgProjTransformer3( pszProjection, NULL,
1159 : pszDstProjection,
1160 0 : padfDstGeoTransform );
1161 0 : pfnTransformer = GDALGenImgProjTransform;
1162 :
1163 0 : CPLFree( pszProjection );
1164 : }
1165 :
1166 : OGRFeature *poFeat;
1167 :
1168 0 : poLayer->ResetReading();
1169 :
1170 0 : while( (poFeat = poLayer->GetNextFeature()) != NULL )
1171 : {
1172 0 : OGRGeometry *poGeom = poFeat->GetGeometryRef();
1173 :
1174 0 : if ( pszBurnAttribute )
1175 0 : dfBurnValue = poFeat->GetFieldAsDouble( iBurnField );
1176 :
1177 : gv_rasterize_one_shape( (unsigned char *) pData, 0,
1178 : nBufXSize, nBufYSize,
1179 : 1, eBufType, bAllTouched, poGeom,
1180 : &dfBurnValue, eBurnValueSource,
1181 0 : pfnTransformer, pTransformArg );
1182 :
1183 0 : delete poFeat;
1184 : }
1185 :
1186 0 : poLayer->ResetReading();
1187 :
1188 0 : if( !pfnProgress(1, "", pProgressArg) )
1189 : {
1190 0 : CPLError( CE_Failure, CPLE_UserInterrupt, "User terminated" );
1191 0 : eErr = CE_Failure;
1192 : }
1193 :
1194 0 : if ( bNeedToFreeTransformer )
1195 : {
1196 0 : GDALDestroyTransformer( pTransformArg );
1197 0 : pTransformArg = NULL;
1198 0 : pfnTransformer = NULL;
1199 : }
1200 : }
1201 :
1202 0 : return eErr;
1203 : }
1204 :
1205 : #endif /* def OGR_ENABLED */
|