1
/******************************************************************************
4
* Project: KmlSuperOverlay
5
* Purpose: Implements write support for KML superoverlay - KMZ.
6
* Author: Harsh Govind, harsh.govind@spadac.com
8
******************************************************************************
9
* Copyright (c) 2010, SPADAC Inc. <harsh.govind@spadac.com>
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:
18
* The above copyright notice and this permission notice shall be included
19
* in all copies or substantial portions of the Software.
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
****************************************************************************/
30
#include "kmlsuperoverlaydataset.h"
32
#include <cmath> /* fabs */
33
#include <cstring> /* strdup */
40
#include "cpl_error.h"
41
#include "cpl_string.h"
44
#include "ogr_spatialref.h"
48
/************************************************************************/
50
/************************************************************************/
51
void GenerateTiles(std::string filename,
53
int rysize, int ix, int iy,
54
int rx, int ry, int dxsize,
55
int dysize, int bands,
57
GDALDriver* poOutputTileDriver,
58
GDALDriver* poMemDriver,
61
GDALDataset* poTmpDataset = NULL;
62
GDALRasterBand* alphaBand = NULL;
64
GByte* pafScanline = new GByte[dxsize];
65
bool* hadnoData = new bool[dxsize];
67
if (isJpegDriver && bands == 4)
70
poTmpDataset = poMemDriver->Create("", dxsize, dysize, bands, GDT_Byte, NULL);
72
if (isJpegDriver == false)//Jpeg dataset only has one or three bands
74
if (bands < 4)//add transparency to files with one band or three bands
76
poTmpDataset->AddBand(GDT_Byte);
77
alphaBand = poTmpDataset->GetRasterBand(poTmpDataset->GetRasterCount());
81
int rowOffset = rysize/dysize;
82
int loopCount = rysize/rowOffset;
83
for (int row = 0; row < loopCount; row++)
85
if (isJpegDriver == false)
87
for (int i = 0; i < dxsize; i++)
93
for (int band = 1; band <= bands; band++)
95
GDALRasterBand* poBand = poSrcDs->GetRasterBand(band);
98
bool isSigned = false;
99
double noDataValue = poBand->GetNoDataValue(&hasNoData);
100
const char* pixelType = poBand->GetMetadataItem("PIXELTYPE", "IMAGE_STRUCTURE");
103
if (strcmp(pixelType, "SIGNEDBYTE") == 0)
109
GDALRasterBand* poBandtmp = NULL;
112
poBandtmp = poTmpDataset->GetRasterBand(band);
115
int yOffset = ry + row * rowOffset;
116
bool bReadFailed = false;
120
poBand->RasterIO( GF_Read, rx, yOffset, rxsize, rowOffset, pafScanline, dxsize, 1, GDT_Byte, 0, 0);
122
if ( errTest == CE_Failure )
130
//fill the true or false for hadnoData array if the source data has nodata value
131
if (isJpegDriver == false)
135
for (int j = 0; j < dxsize; j++)
137
double v = pafScanline[j];
143
if (tmpv == noDataValue || bReadFailed == true)
151
if (poBandtmp && bReadFailed == false)
153
poBandtmp->RasterIO(GF_Write, 0, row, dxsize, 1, pafScanline, dxsize, 1, GDT_Byte,
158
//fill the values for alpha band
159
if (isJpegDriver == false)
163
for (int i = 0; i < dxsize; i++)
165
if (hadnoData[i] == true)
171
pafScanline[i] = 255;
175
alphaBand->RasterIO(GF_Write, 0, row, dxsize, 1, pafScanline, dxsize, 1, GDT_Byte,
181
delete [] pafScanline;
184
GDALDataset* outDs = poOutputTileDriver->CreateCopy(filename.c_str(), poTmpDataset, FALSE, NULL, NULL, NULL);
186
GDALClose(poTmpDataset);
191
/************************************************************************/
192
/* GenerateRootKml() */
193
/************************************************************************/
196
int GenerateRootKml(const char* filename,
197
const char* kmlfilename,
204
VSILFILE* fp = VSIFOpenL(filename, "wb");
207
CPLError(CE_Failure, CPLE_AppDefined, "Cannot create %s",
211
int minlodpixels = tilesize/2;
213
const char* tmpfilename = CPLGetBasename(kmlfilename);
214
// If we haven't writen any features yet, output the layer's schema
215
VSIFPrintfL(fp, "<kml xmlns=\"http://earth.google.com/kml/2.1\">\n");
216
VSIFPrintfL(fp, "\t<Document>\n");
217
VSIFPrintfL(fp, "\t\t<name>%s</name>\n", tmpfilename);
218
VSIFPrintfL(fp, "\t\t<description></description>\n");
219
VSIFPrintfL(fp, "\t\t<Style>\n");
220
VSIFPrintfL(fp, "\t\t\t<ListStyle id=\"hideChildren\">\n");
221
VSIFPrintfL(fp, "\t\t\t\t<listItemType>checkHideChildren</listItemType>\n");
222
VSIFPrintfL(fp, "\t\t\t</ListStyle>\n");
223
VSIFPrintfL(fp, "\t\t</Style>\n");
224
VSIFPrintfL(fp, "\t\t<Region>\n \t\t<LatLonAltBox>\n");
225
VSIFPrintfL(fp, "\t\t\t\t<north>%f</north>\n", north);
226
VSIFPrintfL(fp, "\t\t\t\t<south>%f</south>\n", south);
227
VSIFPrintfL(fp, "\t\t\t\t<east>%f</east>\n", east);
228
VSIFPrintfL(fp, "\t\t\t\t<west>%f</west>\n", west);
229
VSIFPrintfL(fp, "\t\t\t</LatLonAltBox>\n");
230
VSIFPrintfL(fp, "\t\t</Region>\n");
231
VSIFPrintfL(fp, "\t\t<NetworkLink>\n");
232
VSIFPrintfL(fp, "\t\t\t<open>1</open>\n");
233
VSIFPrintfL(fp, "\t\t\t<Region>\n");
234
VSIFPrintfL(fp, "\t\t\t\t<Lod>\n");
235
VSIFPrintfL(fp, "\t\t\t\t\t<minLodPixels>%d</minLodPixels>\n", minlodpixels);
236
VSIFPrintfL(fp, "\t\t\t\t\t<maxLodPixels>-1</maxLodPixels>\n");
237
VSIFPrintfL(fp, "\t\t\t\t</Lod>\n");
238
VSIFPrintfL(fp, "\t\t\t\t<LatLonAltBox>\n");
239
VSIFPrintfL(fp, "\t\t\t\t\t<north>%f</north>\n", north);
240
VSIFPrintfL(fp, "\t\t\t\t\t<south>%f</south>\n", south);
241
VSIFPrintfL(fp, "\t\t\t\t\t<east>%f</east>\n", east);
242
VSIFPrintfL(fp, "\t\t\t\t\t<west>%f</west>\n", west);
243
VSIFPrintfL(fp, "\t\t\t\t</LatLonAltBox>\n");
244
VSIFPrintfL(fp, "\t\t\t</Region>\n");
245
VSIFPrintfL(fp, "\t\t\t<Link>\n");
246
VSIFPrintfL(fp, "\t\t\t\t<href>0/0/0.kml</href>\n");
247
VSIFPrintfL(fp, "\t\t\t\t<viewRefreshMode>onRegion</viewRefreshMode>\n");
248
VSIFPrintfL(fp, "\t\t\t</Link>\n");
249
VSIFPrintfL(fp, "\t\t</NetworkLink>\n");
250
VSIFPrintfL(fp, "\t</Document>\n");
251
VSIFPrintfL(fp, "</kml>\n");
257
/************************************************************************/
258
/* GenerateChildKml() */
259
/************************************************************************/
262
int GenerateChildKml(std::string filename,
263
int zoom, int ix, int iy,
264
double zoomxpixel, double zoomypixel, int dxsize, int dysize,
265
double south, double west, int xsize,
266
int ysize, int maxzoom,
267
OGRCoordinateTransformation * poTransform,
270
double tnorth = south + zoomypixel *((iy + 1)*dysize);
271
double tsouth = south + zoomypixel *(iy*dysize);
272
double teast = west + zoomxpixel*((ix+1)*dxsize);
273
double twest = west + zoomxpixel*ix*dxsize;
275
double upperleftT = twest;
276
double lowerleftT = twest;
278
double rightbottomT = tsouth;
279
double leftbottomT = tsouth;
281
double lefttopT = tnorth;
282
double righttopT = tnorth;
284
double lowerrightT = teast;
285
double upperrightT = teast;
289
poTransform->Transform(1, &twest, &tsouth);
290
poTransform->Transform(1, &teast, &tnorth);
292
poTransform->Transform(1, &upperleftT, &lefttopT);
293
poTransform->Transform(1, &upperrightT, &righttopT);
294
poTransform->Transform(1, &lowerrightT, &rightbottomT);
295
poTransform->Transform(1, &lowerleftT, &leftbottomT);
298
std::vector<int> xchildren;
299
std::vector<int> ychildern;
302
if ( zoom < maxzoom )
304
double zareasize = pow(2.0, (maxzoom - zoom - 1))*dxsize;
305
double zareasize1 = pow(2.0, (maxzoom - zoom - 1))*dysize;
306
xchildren.push_back(ix*2);
308
int tmp1 = (int)ceil(xsize / zareasize);
311
xchildren.push_back(ix*2+1);
313
ychildern.push_back(iy*2);
315
tmp1 = (int)ceil(ysize / zareasize1);
318
ychildern.push_back(iy*2+1);
323
VSILFILE* fp = VSIFOpenL(filename.c_str(), "wb");
326
CPLError(CE_Failure, CPLE_AppDefined, "Cannot create %s",
331
VSIFPrintfL(fp, "<kml xmlns=\"http://earth.google.com/kml/2.1\" xmlns:gx=\"http://www.google.com/kml/ext/2.2\">\n");
332
VSIFPrintfL(fp, "\t<Document>\n");
333
VSIFPrintfL(fp, "\t\t<name>%d/%d/%d.kml</name>\n", zoom, ix, iy);
334
VSIFPrintfL(fp, "\t\t<Style>\n");
335
VSIFPrintfL(fp, "\t\t\t<ListStyle id=\"hideChildren\">\n");
336
VSIFPrintfL(fp, "\t\t\t\t<listItemType>checkHideChildren</listItemType>\n");
337
VSIFPrintfL(fp, "\t\t\t</ListStyle>\n");
338
VSIFPrintfL(fp, "\t\t</Style>\n");
339
VSIFPrintfL(fp, "\t\t<Region>\n");
340
VSIFPrintfL(fp, "\t\t\t<Lod>\n");
341
VSIFPrintfL(fp, "\t\t\t\t<minLodPixels>%d</minLodPixels>\n", 128);
342
VSIFPrintfL(fp, "\t\t\t\t<maxLodPixels>%d</maxLodPixels>\n", maxLodPix);
343
VSIFPrintfL(fp, "\t\t\t</Lod>\n");
344
VSIFPrintfL(fp, "\t\t\t<LatLonAltBox>\n");
345
VSIFPrintfL(fp, "\t\t\t\t<north>%f</north>\n", tnorth);
346
VSIFPrintfL(fp, "\t\t\t\t<south>%f</south>\n", tsouth);
347
VSIFPrintfL(fp, "\t\t\t\t<east>%f</east>\n", teast);
348
VSIFPrintfL(fp, "\t\t\t\t<west>%f</west>\n", twest);
349
VSIFPrintfL(fp, "\t\t\t</LatLonAltBox>\n");
350
VSIFPrintfL(fp, "\t\t</Region>\n");
351
VSIFPrintfL(fp, "\t\t<GroundOverlay>\n");
352
VSIFPrintfL(fp, "\t\t\t<drawOrder>%d</drawOrder>\n", zoom);
353
VSIFPrintfL(fp, "\t\t\t<Icon>\n");
354
VSIFPrintfL(fp, "\t\t\t\t<href>%d%s</href>\n", iy, fileExt.c_str());
355
VSIFPrintfL(fp, "\t\t\t</Icon>\n");
356
VSIFPrintfL(fp, "\t\t\t<gx:LatLonQuad>\n");
357
VSIFPrintfL(fp, "\t\t\t\t<coordinates>\n");
358
VSIFPrintfL(fp, "\t\t\t\t\t%f,%f,0\n", lowerleftT, leftbottomT);
359
VSIFPrintfL(fp, "\t\t\t\t\t%f,%f,0\n", lowerrightT, rightbottomT);
360
VSIFPrintfL(fp, "\t\t\t\t\t%f,%f,0\n", upperrightT, righttopT);
361
VSIFPrintfL(fp, "\t\t\t\t\t%f,%f,0\n", upperleftT, lefttopT);
362
VSIFPrintfL(fp, "\t\t\t\t</coordinates>\n");
363
VSIFPrintfL(fp, "\t\t\t</gx:LatLonQuad>\n");
364
VSIFPrintfL(fp, "\t\t</GroundOverlay>\n");
366
for (unsigned int i = 0; i < xchildren.size(); i++)
368
int cx = xchildren[i];
369
for (unsigned int j = 0; j < ychildern.size(); j++)
371
int cy = ychildern[j];
373
double cnorth = south + zoomypixel/2 *((cy + 1)*dysize);
374
double csouth = south + zoomypixel/2 *(cy*dysize);
375
double ceast = west + zoomxpixel/2*((cx+1)*dxsize);
376
double cwest = west + zoomxpixel/2*cx*dxsize;
380
poTransform->Transform(1, &cwest, &csouth);
381
poTransform->Transform(1, &ceast, &cnorth);
384
VSIFPrintfL(fp, "\t\t<NetworkLink>\n");
385
VSIFPrintfL(fp, "\t\t\t<name>%d/%d/%d%s</name>\n", zoom+1, cx, cy, fileExt.c_str());
386
VSIFPrintfL(fp, "\t\t\t<Region>\n");
387
VSIFPrintfL(fp, "\t\t\t\t<Lod>\n");
388
VSIFPrintfL(fp, "\t\t\t\t\t<minLodPixels>128</minLodPixels>\n");
389
VSIFPrintfL(fp, "\t\t\t\t\t<maxLodPixels>-1</maxLodPixels>\n");
390
VSIFPrintfL(fp, "\t\t\t\t</Lod>\n");
391
VSIFPrintfL(fp, "\t\t\t\t<LatLonAltBox>\n");
392
VSIFPrintfL(fp, "\t\t\t\t\t<north>%f</north>\n", cnorth);
393
VSIFPrintfL(fp, "\t\t\t\t\t<south>%f</south>\n", csouth);
394
VSIFPrintfL(fp, "\t\t\t\t\t<east>%f</east>\n", ceast);
395
VSIFPrintfL(fp, "\t\t\t\t\t<west>%f</west>\n", cwest);
396
VSIFPrintfL(fp, "\t\t\t\t</LatLonAltBox>\n");
397
VSIFPrintfL(fp, "\t\t\t</Region>\n");
398
VSIFPrintfL(fp, "\t\t\t<Link>\n");
399
VSIFPrintfL(fp, "\t\t\t\t<href>../../%d/%d/%d.kml</href>\n", zoom+1, cx, cy);
400
VSIFPrintfL(fp, "\t\t\t\t<viewRefreshMode>onRegion</viewRefreshMode>\n");
401
VSIFPrintfL(fp, "\t\t\t\t<viewFormat/>\n");
402
VSIFPrintfL(fp, "\t\t\t</Link>\n");
403
VSIFPrintfL(fp, "\t\t</NetworkLink>\n");
407
VSIFPrintfL(fp, "\t</Document>\n");
408
VSIFPrintfL(fp, "</kml>\n");
414
/************************************************************************/
415
/* zipWithMinizip() */
416
/************************************************************************/
417
bool zipWithMinizip(std::vector<std::string> srcFiles, std::string srcDirectory, std::string targetFile)
419
void *zipfile = CPLCreateZip(targetFile.c_str(), NULL);
422
CPLError( CE_Failure, CPLE_FileIO,
423
"Unable to open target zip file.." );
427
std::vector <std::string>::iterator v1_Iter;
428
for(v1_Iter = srcFiles.begin(); v1_Iter != srcFiles.end(); v1_Iter++)
430
std::string fileRead = *v1_Iter;
432
// Find relative path and open new file with zip file
433
std::string relativeFileReadPath = fileRead;
434
int remNumChars = srcDirectory.size();
437
int f = fileRead.find(srcDirectory);
440
relativeFileReadPath.erase(f, remNumChars + 1); // 1 added for backslash at the end
444
std::basic_string<char>::iterator iter1;
445
for (iter1 = relativeFileReadPath.begin(); iter1 != relativeFileReadPath.end(); iter1++)
447
int f = relativeFileReadPath.find("\\");
450
relativeFileReadPath.replace(f, 1, "/");
457
if (CPLCreateFileInZip(zipfile, relativeFileReadPath.c_str(), NULL) != CE_None)
459
CPLError( CE_Failure, CPLE_FileIO,
460
"Unable to create file within the zip file.." );
464
// Read source file and write to zip file
465
VSILFILE* fp = VSIFOpenL(fileRead.c_str(), "rb");
468
CPLError( CE_Failure, CPLE_FileIO,
469
"Could not open source file.." );
473
// Read file in buffer
474
std::string fileData;
475
const unsigned int bufSize = 1024;
478
while((nRead = VSIFReadL(buf, 1, bufSize, fp)) != 0)
480
if ( CPLWriteFileInZip(zipfile, buf, nRead) != CE_None )
482
CPLError( CE_Failure, CPLE_FileIO,
483
"Could not write to file within zip file.." );
484
CPLCloseFileInZip(zipfile);
485
CPLCloseZip(zipfile);
493
// Close one src file zipped completely
494
if ( CPLCloseFileInZip(zipfile) != CE_None )
496
CPLError( CE_Failure, CPLE_FileIO,
497
"Could not close file written within zip file.." );
498
CPLCloseZip(zipfile);
503
CPLCloseZip(zipfile);
508
/************************************************************************/
509
/* KmlSuperOverlayDataset() */
510
/************************************************************************/
512
KmlSuperOverlayDataset::KmlSuperOverlayDataset()
515
bGeoTransformSet = FALSE;
518
/************************************************************************/
519
/* ~KmlSuperOverlayDataset() */
520
/************************************************************************/
522
KmlSuperOverlayDataset::~KmlSuperOverlayDataset()
528
/************************************************************************/
529
/* GetProjectionRef() */
530
/************************************************************************/
532
const char *KmlSuperOverlayDataset::GetProjectionRef()
535
return SRS_WKT_WGS84;
538
/************************************************************************/
539
/* KMLSuperOverlayRecursiveUnlink() */
540
/************************************************************************/
542
static void KMLSuperOverlayRecursiveUnlink( const char *pszName )
545
char **papszFileList;
548
papszFileList = CPLReadDir( pszName );
550
for( i = 0; papszFileList != NULL && papszFileList[i] != NULL; i++ )
552
VSIStatBufL sStatBuf;
554
if( EQUAL(papszFileList[i],".") || EQUAL(papszFileList[i],"..") )
557
CPLString osFullFilename =
558
CPLFormFilename( pszName, papszFileList[i], NULL );
560
VSIStatL( osFullFilename, &sStatBuf );
562
if( VSI_ISREG( sStatBuf.st_mode ) )
564
VSIUnlink( osFullFilename );
566
else if( VSI_ISDIR( sStatBuf.st_mode ) )
568
KMLSuperOverlayRecursiveUnlink( osFullFilename );
572
CSLDestroy( papszFileList );
577
/************************************************************************/
579
/************************************************************************/
581
GDALDataset *KmlSuperOverlayDataset::CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
582
int bStrict, char ** papszOptions, GDALProgressFunc pfnProgress, void * pProgressData)
586
int bands = poSrcDS->GetRasterCount();
587
if (bands != 1 && bands != 3 && bands != 4)
590
//correct the file and get the directory
591
char* output_dir = NULL;
592
if (pszFilename == NULL)
594
output_dir = CPLGetCurrentDir();
595
pszFilename = CPLFormFilename(output_dir, "doc", "kml");
599
const char* extension = CPLGetExtension(pszFilename);
600
if (!EQUAL(extension,"kml") && !EQUAL(extension,"kmz"))
602
CPLError( CE_Failure, CPLE_None,
603
"File extension should be kml or kmz." );
606
if (EQUAL(extension,"kmz"))
611
output_dir = CPLStrdup(CPLGetPath(pszFilename));
612
if (strcmp(output_dir, "") == 0)
615
output_dir = CPLGetCurrentDir();
618
CPLString outDir = output_dir;
622
KmlSuperOverlayDataset *poDsDummy = new KmlSuperOverlayDataset();
626
outDir = CPLFormFilename(outDir, CPLSPrintf("kmlsuperoverlaytmp_%p", poDsDummy) , NULL);
627
if (VSIMkdir(outDir, 0755) != 0)
629
CPLError( CE_Failure, CPLE_None,
630
"Cannot create %s", outDir.c_str() );
636
GDALDriver* poOutputTileDriver = NULL;
637
bool isJpegDriver = true;
639
const char* pszFormat = CSLFetchNameValueDef(papszOptions, "FORMAT", "JPEG");
640
if (EQUAL(pszFormat, "PNG"))
642
isJpegDriver = false;
645
GDALDriver* poMemDriver = GetGDALDriverManager()->GetDriverByName("MEM");
646
poOutputTileDriver = GetGDALDriverManager()->GetDriverByName(pszFormat);
648
if( poMemDriver == NULL || poOutputTileDriver == NULL)
650
CPLError( CE_Failure, CPLE_None,
651
"Image export driver was not found.." );
654
KMLSuperOverlayRecursiveUnlink(outDir);
658
int xsize = poSrcDS->GetRasterXSize();
659
int ysize = poSrcDS->GetRasterYSize();
666
double adfGeoTransform[6];
668
if( poSrcDS->GetGeoTransform(adfGeoTransform) == CE_None )
670
north = adfGeoTransform[3];
671
south = adfGeoTransform[3] + adfGeoTransform[5]*ysize;
672
east = adfGeoTransform[0] + adfGeoTransform[1]*xsize;
673
west = adfGeoTransform[0];
676
OGRCoordinateTransformation * poTransform = NULL;
677
if (poSrcDS->GetProjectionRef() != NULL)
679
OGRSpatialReference poDsUTM;
681
char* projStr = (char*)poSrcDS->GetProjectionRef();
683
if (poDsUTM.importFromWkt(&projStr) == OGRERR_NONE)
685
if (poDsUTM.IsProjected())
687
OGRSpatialReference poLatLong;
688
poLatLong.SetWellKnownGeogCS( "WGS84" );
690
poTransform = OGRCreateCoordinateTransformation( &poDsUTM, &poLatLong );
691
if( poTransform != NULL )
693
poTransform->Transform(1, &west, &south);
694
poTransform->Transform(1, &east, &north);
700
//Zoom levels of the pyramid.
704
// Let the longer side determine the max zoom level and x/y tilesizes.
705
if ( xsize >= ysize )
707
double dtilexsize = xsize;
708
while (dtilexsize > 400) //calculate x tile size
710
dtilexsize = dtilexsize/2;
713
maxzoom = static_cast<int>(log( (double)xsize / dtilexsize ) / log(2.0));
714
tilexsize = (int)dtilexsize;
715
tileysize = (int)( (double)(dtilexsize * ysize) / xsize );
719
double dtileysize = ysize;
720
while (dtileysize > 400) //calculate y tile size
722
dtileysize = dtileysize/2;
725
maxzoom = static_cast<int>(log( (double)ysize / dtileysize ) / log(2.0));
726
tileysize = (int)dtileysize;
727
tilexsize = (int)( (double)(dtileysize * xsize) / ysize );
731
std::vector<double> zoomxpixels;
732
std::vector<double> zoomypixels;
733
for (int zoom = 0; zoom < maxzoom + 1; zoom++)
735
zoomxpixels.push_back(adfGeoTransform[1] * pow(2.0, (maxzoom - zoom)));
736
// zoomypixels.push_back(abs(adfGeoTransform[5]) * pow(2.0, (maxzoom - zoom)));
737
zoomypixels.push_back(fabs(adfGeoTransform[5]) * pow(2.0, (maxzoom - zoom)));
740
std::string tmpFileName;
741
std::vector<std::string> fileVector;
745
tmpFileName = CPLFormFilename(outDir, "tmp.kml", NULL);
746
nRet = GenerateRootKml(tmpFileName.c_str(), pszFilename, north, south, east, west, (int)tilexsize);
747
fileVector.push_back(tmpFileName);
751
nRet = GenerateRootKml(pszFilename, pszFilename, north, south, east, west, (int)tilexsize);
756
OGRCoordinateTransformation::DestroyCT( poTransform );
759
KMLSuperOverlayRecursiveUnlink(outDir);
763
for (int zoom = maxzoom; zoom >= 0; --zoom)
765
int rmaxxsize = static_cast<int>(pow(2.0, (maxzoom-zoom)) * tilexsize);
766
int rmaxysize = static_cast<int>(pow(2.0, (maxzoom-zoom)) * tileysize);
768
int xloop = (int)xsize/rmaxxsize;
769
int yloop = (int)ysize/rmaxysize;
771
xloop = xloop>0 ? xloop : 1;
772
yloop = yloop>0 ? yloop : 1;
773
for (int ix = 0; ix < xloop; ix++)
775
int rxsize = (int)(rmaxxsize);
776
int rx = (int)(ix * rmaxxsize);
778
for (int iy = 0; iy < yloop; iy++)
780
int rysize = (int)(rmaxysize);
781
int ry = (int)(ysize - (iy * rmaxysize)) - rysize;
783
int dxsize = (int)(rxsize/rmaxxsize * tilexsize);
784
int dysize = (int)(rysize/rmaxysize * tileysize);
786
std::stringstream zoomStr;
787
std::stringstream ixStr;
788
std::stringstream iyStr;
794
std::string zoomDir = outDir;
795
zoomDir+= "/" + zoomStr.str();
796
VSIMkdir(zoomDir.c_str(), 0775);
799
zoomDir = zoomDir + "/" + ixStr.str();
800
VSIMkdir(zoomDir.c_str(), 0775);
802
std::string fileExt = ".jpg";
803
if (isJpegDriver == false)
807
std::string filename = zoomDir + "/" + iyStr.str() + fileExt;
810
fileVector.push_back(filename);
813
GenerateTiles(filename, zoom, rxsize, rysize, ix, iy, rx, ry, dxsize,
814
dysize, bands, poSrcDS, poOutputTileDriver, poMemDriver, isJpegDriver);
815
std::string childKmlfile = zoomDir + "/" + iyStr.str() + ".kml";
818
fileVector.push_back(childKmlfile);
821
double tmpSouth = adfGeoTransform[3] + adfGeoTransform[5]*ysize;
822
double zoomxpix = zoomxpixels[zoom];
823
double zoomypix = zoomypixels[zoom];
834
GenerateChildKml(childKmlfile, zoom, ix, iy, zoomxpix, zoomypix,
835
dxsize, dysize, tmpSouth, adfGeoTransform[0], xsize, ysize, maxzoom, poTransform, fileExt);
840
OGRCoordinateTransformation::DestroyCT( poTransform );
845
std::string outputfile = pszFilename;
847
if (zipWithMinizip(fileVector, outDir, outputfile) == false)
849
CPLError( CE_Failure, CPLE_FileIO,
850
"Unable to do zip.." );
854
KMLSuperOverlayRecursiveUnlink(outDir);
856
if (zipDone == false)
866
/************************************************************************/
868
/************************************************************************/
870
GDALDataset *KmlSuperOverlayDataset::Open(GDALOpenInfo *)
876
/************************************************************************/
877
/* KmlSuperOverlayDatasetDelete() */
878
/************************************************************************/
880
static CPLErr KmlSuperOverlayDatasetDelete(const char* fileName)
882
/* Null implementation, so that people can Delete("MEM:::") */
886
/************************************************************************/
887
/* GDALRegister_KMLSUPEROVERLAY() */
888
/************************************************************************/
890
void GDALRegister_KMLSUPEROVERLAY()
893
GDALDriver *poDriver;
895
if( GDALGetDriverByName( "KMLSUPEROVERLAY" ) == NULL )
897
poDriver = new GDALDriver();
899
poDriver->SetDescription( "KMLSUPEROVERLAY" );
900
poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
901
"Kml Super Overlay" );
902
poDriver->SetMetadataItem( GDAL_DMD_CREATIONDATATYPES,
903
"Byte Int16 UInt16 Int32 UInt32 Float32 Float64 CInt16 CInt32 CFloat32 CFloat64" );
905
poDriver->SetMetadataItem( GDAL_DMD_CREATIONOPTIONLIST,
906
"<CreationOptionList>"
907
" <Option name='FORMAT' type='string-select' default='JPEG' description='Force of the tiles'>"
908
" <Value>PNG</Value>"
909
" <Value>JPEG</Value>"
911
"</CreationOptionList>" );
913
poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
915
poDriver->pfnOpen = KmlSuperOverlayDataset::Open;
916
poDriver->pfnCreateCopy = KmlSuperOverlayDataset::CreateCopy;
917
poDriver->pfnDelete = KmlSuperOverlayDatasetDelete;
919
GetGDALDriverManager()->RegisterDriver( poDriver );