Skip to content

Commit

Permalink
Merge pull request OSGeo#8983 from rouault/vrttileindex
Browse files Browse the repository at this point in the history
Add GDAL Raster Tile Index (GTI) driver, and associated gdaltindex improvements
  • Loading branch information
rouault authored Jan 23, 2024
2 parents 527b897 + c624f2b commit 5f9ffa3
Show file tree
Hide file tree
Showing 41 changed files with 10,069 additions and 1,051 deletions.
5 changes: 3 additions & 2 deletions apps/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@ add_library(
nearblack_lib_floodfill.cpp
gdal_footprint_lib.cpp
gdalmdiminfo_lib.cpp
gdalmdimtranslate_lib.cpp)
gdalmdimtranslate_lib.cpp
gdaltindex_lib.cpp)
add_dependencies(appslib generate_gdal_version_h)
target_sources(${GDAL_LIB_TARGET_NAME} PRIVATE $<TARGET_OBJECTS:appslib>)
gdal_standard_includes(appslib)
Expand Down Expand Up @@ -55,7 +56,7 @@ if (BUILD_APPS)
add_executable(gdalmanage gdalmanage.cpp)
add_executable(gdalsrsinfo gdalsrsinfo.cpp)
target_link_libraries(gdalsrsinfo PRIVATE PROJ::proj)
add_executable(gdaltindex gdaltindex.cpp)
add_executable(gdaltindex gdal_utils_priv.h gdaltindex_bin.cpp)
add_executable(gdal_rasterize gdal_rasterize_bin.cpp)
add_executable(gdaldem gdaldem_bin.cpp)
add_executable(gdaltransform gdaltransform.cpp)
Expand Down
17 changes: 17 additions & 0 deletions apps/gdal_utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -307,6 +307,23 @@ void CPL_DLL GDALVectorInfoOptionsFree(GDALVectorInfoOptions *psOptions);
char CPL_DLL *GDALVectorInfo(GDALDatasetH hDataset,
const GDALVectorInfoOptions *psOptions);

/*! Options for GDALTileIndex(). Opaque type */
typedef struct GDALTileIndexOptions GDALTileIndexOptions;

/** Opaque type */
typedef struct GDALTileIndexOptionsForBinary GDALTileIndexOptionsForBinary;

GDALTileIndexOptions CPL_DLL *
GDALTileIndexOptionsNew(char **papszArgv,
GDALTileIndexOptionsForBinary *psOptionsForBinary);

void CPL_DLL GDALTileIndexOptionsFree(GDALTileIndexOptions *psOptions);

GDALDatasetH CPL_DLL GDALTileIndex(const char *pszDest, int nSrcCount,
const char *const *papszSrcDSNames,
const GDALTileIndexOptions *psOptions,
int *pbUsageError);

CPL_C_END

#endif /* GDAL_UTILS_H_INCLUDED */
8 changes: 8 additions & 0 deletions apps/gdal_utils_priv.h
Original file line number Diff line number Diff line change
Expand Up @@ -222,6 +222,14 @@ struct GDALFootprintOptionsForBinary
std::string osDestLayerName{};
};

struct GDALTileIndexOptionsForBinary
{
CPLStringList aosSrcFiles{};
bool bDestSpecified = false;
std::string osDest{};
bool bQuiet = false;
};

#endif /* #ifndef DOXYGEN_SKIP */

#endif /* GDAL_UTILS_PRIV_H_INCLUDED */
161 changes: 83 additions & 78 deletions apps/gdaladdo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
#include "gdal_priv.h"
#include "commonutils.h"
#include "vrtdataset.h"
#include "vrt_priv.h"

#include <algorithm>

Expand Down Expand Up @@ -275,15 +276,6 @@ static bool PartialRefreshFromSourceTimestamp(
bool bMinSizeSpecified, int nMinSize, GDALProgressFunc pfnProgress,
void *pProgressArg)
{
auto poVRTDS = dynamic_cast<VRTDataset *>(poDS);
if (!poVRTDS)
{
CPLError(CE_Failure, CPLE_AppDefined,
"--partial-refresh-from-source-timestamp only works on a VRT "
"dataset");
return false;
}

std::vector<int> anOvrIndices;
if (!GetOvrIndices(poDS, nLevelCount, panLevels, bMinSizeSpecified,
nMinSize, anOvrIndices))
Expand All @@ -304,82 +296,95 @@ static bool PartialRefreshFromSourceTimestamp(
return false;
}

auto poVRTBand =
dynamic_cast<VRTSourcedRasterBand *>(poDS->GetRasterBand(1));
if (!poVRTBand)
{
CPLError(CE_Failure, CPLE_AppDefined,
"Band is not a VRTSourcedRasterBand");
return false;
}

struct Region
{
std::string osFileName;
int nXOff;
int nYOff;
int nXSize;
int nYSize;
};
std::vector<Region> regions;
std::vector<GTISourceDesc> regions;

double dfTotalPixels = 0;
for (int i = 0; i < poVRTBand->nSources; ++i)

if (dynamic_cast<VRTDataset *>(poDS))
{
auto poSource =
dynamic_cast<VRTSimpleSource *>(poVRTBand->papoSources[i]);
if (poSource)
auto poVRTBand =
dynamic_cast<VRTSourcedRasterBand *>(poDS->GetRasterBand(1));
if (!poVRTBand)
{
VSIStatBufL sStatSource;
if (VSIStatL(poSource->GetSourceDatasetName().c_str(),
&sStatSource) == 0)
CPLError(CE_Failure, CPLE_AppDefined,
"Band is not a VRTSourcedRasterBand");
return false;
}

for (int i = 0; i < poVRTBand->nSources; ++i)
{
auto poSource =
dynamic_cast<VRTSimpleSource *>(poVRTBand->papoSources[i]);
if (poSource)
{
if (sStatSource.st_mtime > sStatVRTOvr.st_mtime)
VSIStatBufL sStatSource;
if (VSIStatL(poSource->GetSourceDatasetName().c_str(),
&sStatSource) == 0)
{
double dfXOff, dfYOff, dfXSize, dfYSize;
poSource->GetDstWindow(dfXOff, dfYOff, dfXSize, dfYSize);
constexpr double EPS = 1e-8;
int nXOff = static_cast<int>(dfXOff + EPS);
int nYOff = static_cast<int>(dfYOff + EPS);
int nXSize = static_cast<int>(dfXSize + 0.5);
int nYSize = static_cast<int>(dfYSize + 0.5);
if (nXOff > poDS->GetRasterXSize() ||
nYOff > poDS->GetRasterYSize() || nXSize <= 0 ||
nYSize <= 0)
if (sStatSource.st_mtime > sStatVRTOvr.st_mtime)
{
continue;
}
if (nXOff < 0)
{
nXSize += nXOff;
nXOff = 0;
}
if (nXOff > poDS->GetRasterXSize() - nXSize)
{
nXSize = poDS->GetRasterXSize() - nXOff;
}
if (nYOff < 0)
{
nYSize += nYOff;
nYOff = 0;
}
if (nYOff > poDS->GetRasterYSize() - nYSize)
{
nYSize = poDS->GetRasterYSize() - nYOff;
}
double dfXOff, dfYOff, dfXSize, dfYSize;
poSource->GetDstWindow(dfXOff, dfYOff, dfXSize,
dfYSize);
constexpr double EPS = 1e-8;
int nXOff = static_cast<int>(dfXOff + EPS);
int nYOff = static_cast<int>(dfYOff + EPS);
int nXSize = static_cast<int>(dfXSize + 0.5);
int nYSize = static_cast<int>(dfYSize + 0.5);
if (nXOff > poDS->GetRasterXSize() ||
nYOff > poDS->GetRasterYSize() || nXSize <= 0 ||
nYSize <= 0)
{
continue;
}
if (nXOff < 0)
{
nXSize += nXOff;
nXOff = 0;
}
if (nXOff > poDS->GetRasterXSize() - nXSize)
{
nXSize = poDS->GetRasterXSize() - nXOff;
}
if (nYOff < 0)
{
nYSize += nYOff;
nYOff = 0;
}
if (nYOff > poDS->GetRasterYSize() - nYSize)
{
nYSize = poDS->GetRasterYSize() - nYOff;
}

dfTotalPixels += static_cast<double>(nXSize) * nYSize;
Region region;
region.osFileName = poSource->GetSourceDatasetName();
region.nXOff = nXOff;
region.nYOff = nYOff;
region.nXSize = nXSize;
region.nYSize = nYSize;
regions.push_back(std::move(region));
dfTotalPixels += static_cast<double>(nXSize) * nYSize;
GTISourceDesc region;
region.osFilename = poSource->GetSourceDatasetName();
region.nDstXOff = nXOff;
region.nDstYOff = nYOff;
region.nDstXSize = nXSize;
region.nDstYSize = nYSize;
regions.push_back(std::move(region));
}
}
}
}
}
else if (auto poGTIDS = GDALDatasetCastToGTIDataset(poDS))
{
regions = GTIGetSourcesMoreRecentThan(poGTIDS, sStatVRTOvr.st_mtime);
for (const auto &region : regions)
{
dfTotalPixels +=
static_cast<double>(region.nDstXSize) * region.nDstYSize;
}
}
else
{
CPLError(CE_Failure, CPLE_AppDefined,
"--partial-refresh-from-source-timestamp only works on a VRT "
"dataset");
return false;
}

if (!regions.empty())
{
Expand All @@ -389,22 +394,22 @@ static bool PartialRefreshFromSourceTimestamp(
if (pfnProgress == GDALDummyProgress)
{
CPLDebug("GDAL", "Refresh from source %s",
region.osFileName.c_str());
region.osFilename.c_str());
}
else
{
printf("Refresh from source %s.\n", region.osFileName.c_str());
printf("Refresh from source %s.\n", region.osFilename.c_str());
}
double dfNextCurPixels =
dfCurPixels +
static_cast<double>(region.nXSize) * region.nYSize;
static_cast<double>(region.nDstXSize) * region.nDstYSize;
void *pScaledProgress = GDALCreateScaledProgress(
dfCurPixels / dfTotalPixels, dfNextCurPixels / dfTotalPixels,
pfnProgress, pProgressArg);
bool bRet = PartialRefresh(
poDS, anOvrIndices, nBandCount, panBandList, pszResampling,
region.nXOff, region.nYOff, region.nXSize, region.nYSize,
GDALScaledProgress, pScaledProgress);
region.nDstXOff, region.nDstYOff, region.nDstXSize,
region.nDstYSize, GDALScaledProgress, pScaledProgress);
GDALDestroyScaledProgress(pScaledProgress);
if (!bRet)
return false;
Expand Down
Loading

0 comments on commit 5f9ffa3

Please sign in to comment.