Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[pull] master from OSGeo:master #107

Merged
merged 11 commits into from
Dec 5, 2024
Merged
4 changes: 4 additions & 0 deletions .github/workflows/alpine/build.sh
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,10 @@ cmake ${GDAL_SOURCE_DIR:=..} \
-DIconv_INCLUDE_DIR=/usr/include/gnu-libiconv \
-DIconv_LIBRARY=/usr/lib/libiconv.so \
-DADD_EXTERNAL_DEFERRED_PLUGIN_FOO=/tmp/foo.cpp \
-DGDAL_ENABLE_PLUGINS=ON \
-DGDAL_ENABLE_PLUGINS_NO_DEPS=ON \
-DOGR_ENABLE_DRIVER_TAB_PLUGIN=OFF \
-DOGR_ENABLE_DRIVER_GEOJSON_PLUGIN=OFF \
-DCMAKE_CXX_STANDARD=23 \
-DCMAKE_C_FLAGS=-Werror -DCMAKE_CXX_FLAGS="-Werror" -DWERROR_DEV_FLAG="-Werror=dev"
make -j$(nproc)
Expand Down
11 changes: 5 additions & 6 deletions apps/ogr2ogr_lib.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4099,12 +4099,11 @@ bool SetupTargetLayer::CanUseWriteArrowBatch(
{
return false;
}
auto poSrcSRS = m_poUserSourceSRS ? m_poUserSourceSRS
: poSrcLayer->GetLayerDefn()
->GetGeomFieldDefn(0)
->GetSpatialRef();
if (!poSrcSRS ||
!OGRGeometryFactory::isTransformWithOptionsRegularTransform(
const auto poSrcSRS = m_poUserSourceSRS ? m_poUserSourceSRS
: poSrcLayer->GetLayerDefn()
->GetGeomFieldDefn(0)
->GetSpatialRef();
if (!OGRGeometryFactory::isTransformWithOptionsRegularTransform(
poSrcSRS, m_poOutputSRS, nullptr))
{
return false;
Expand Down
38 changes: 38 additions & 0 deletions autotest/ogr/ogr_flatgeobuf.py
Original file line number Diff line number Diff line change
Expand Up @@ -1612,3 +1612,41 @@ def test_ogr_flatgeobuf_arrow_stream_numpy_datetime_as_string(tmp_vsimem):
assert batch["datetime"][1] == b"2022-05-31T12:34:56.789Z"
assert batch["datetime"][2] == b"2022-05-31T12:34:56"
assert batch["datetime"][3] == b"2022-05-31T12:34:56+12:30"


def test_ogr_flatgeobuf_write_empty_geometries_no_spatial_index(tmp_vsimem):
# Verify empty geom handling without spatial index
out_filename = str(tmp_vsimem / "out.fgb")
with ogr.GetDriverByName("FlatGeobuf").CreateDataSource(out_filename) as ds:
lyr = ds.CreateLayer(
"test", geom_type=ogr.wkbPolygon, options=["SPATIAL_INDEX=NO"]
)

f = ogr.Feature(lyr.GetLayerDefn())
f.SetGeometry(ogr.CreateGeometryFromWkt("POLYGON EMPTY"))
lyr.CreateFeature(f)
f = ogr.Feature(lyr.GetLayerDefn())
lyr.CreateFeature(f)

with gdal.OpenEx(out_filename) as ds:
lyr = ds.GetLayer(0)
f = lyr.GetNextFeature()
g = f.GetGeometryRef()
assert g is None


def test_ogr_flatgeobuf_write_empty_file_no_spatial_index(tmp_vsimem):
# Verify empty geom handling without spatial index
out_filename = str(tmp_vsimem / "out.fgb")
with ogr.GetDriverByName("FlatGeobuf").CreateDataSource(out_filename) as ds:
srs = osr.SpatialReference()
srs.ImportFromEPSG(32631)
ds.CreateLayer(
"test", geom_type=ogr.wkbPolygon, srs=srs, options=["SPATIAL_INDEX=NO"]
)

with gdal.OpenEx(out_filename) as ds:
lyr = ds.GetLayer(0)
assert lyr.GetFeatureCount() == 0
assert lyr.GetExtent(can_return_null=True) is None
assert lyr.GetSpatialRef().GetAuthorityCode(None) == "32631"
40 changes: 40 additions & 0 deletions autotest/utilities/test_ogr2ogr_lib.py
Original file line number Diff line number Diff line change
Expand Up @@ -2924,6 +2924,46 @@ def my_handler(errorClass, errno, msg):
assert f.GetGeometryRef().GetGeometryCount() == 2


###############################################################################
# Test -ct in Arrow code path
# Cf https://github.com/OSGeo/gdal/issues/11438


@gdaltest.enable_exceptions()
def test_ogr2ogr_lib_reproject_arrow_optim_ct(tmp_vsimem):

srcDS = gdal.GetDriverByName("Memory").Create("", 0, 0, 0, gdal.GDT_Unknown)
srs = osr.SpatialReference()
srs.ImportFromEPSG(32632)
srcLayer = srcDS.CreateLayer("test", srs=srs)
f = ogr.Feature(srcLayer.GetLayerDefn())
f.SetGeometry(ogr.CreateGeometryFromWkt("POINT (1 2)"))
srcLayer.CreateFeature(f)

got_msg = []

def my_handler(errorClass, errno, msg):
got_msg.append(msg)
return

config_options = {"CPL_DEBUG": "ON", "OGR2OGR_USE_ARROW_API": "YES"}
with gdaltest.error_handler(my_handler), gdaltest.config_options(config_options):
ds = gdal.VectorTranslate(
"",
srcDS,
format="Memory",
reproject=True,
coordinateOperation="+proj=affine +s11=-1",
)

assert "OGR2OGR: Using WriteArrowBatch()" in got_msg

lyr = ds.GetLayer(0)
assert lyr.GetSpatialRef().GetAuthorityCode(None) == "32632"
f = lyr.GetNextFeature()
assert f.GetGeometryRef().ExportToWkt() == "POINT (-1 2)"


###############################################################################
# Test -explodecollections on empty geometries

Expand Down
2 changes: 1 addition & 1 deletion cmake/helpers/GdalCMakeMinimumRequired.cmake
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
set(GDAL_CMAKE_VERSION_MIN 3.16)
set(GDAL_CMAKE_VERSION_MAX 3.28)
set(GDAL_CMAKE_VERSION_MAX 3.31)
3 changes: 2 additions & 1 deletion ogr/ogrgeometryfactory.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3886,7 +3886,8 @@ bool OGRGeometryFactory::isTransformWithOptionsRegularTransform(
return false;

#ifdef HAVE_GEOS
if (poSourceCRS->IsProjected() && poTargetCRS->IsGeographic() &&
if (poSourceCRS && poTargetCRS && poSourceCRS->IsProjected() &&
poTargetCRS->IsGeographic() &&
poTargetCRS->GetAxisMappingStrategy() == OAMS_TRADITIONAL_GIS_ORDER &&
// check that angular units is degree
std::fabs(poTargetCRS->GetAngularUnits(nullptr) -
Expand Down
30 changes: 21 additions & 9 deletions ogr/ogrsf_frmts/flatgeobuf/ogrflatgeobuflayer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
#include "geometrywriter.h"

#include <algorithm>
#include <cmath>
#include <limits>
#include <new>
#include <stdexcept>
Expand Down Expand Up @@ -71,7 +72,9 @@ OGRFlatGeobufLayer::OGRFlatGeobufLayer(const Header *poHeader, GByte *headerBuf,
m_hasM = m_poHeader->has_m();
m_hasT = m_poHeader->has_t();
const auto envelope = m_poHeader->envelope();
if (envelope && envelope->size() == 4)
if (envelope && envelope->size() == 4 && std::isfinite((*envelope)[0]) &&
std::isfinite((*envelope)[1]) && std::isfinite((*envelope)[2]) &&
std::isfinite((*envelope)[3]))
{
m_sExtent.MinX = (*envelope)[0];
m_sExtent.MinY = (*envelope)[1];
Expand Down Expand Up @@ -536,8 +539,7 @@ bool OGRFlatGeobufLayer::CreateFinalFile()
// no spatial index requested, we are (almost) done
if (!m_bCreateSpatialIndexAtClose)
{
if (m_poFpWrite == nullptr || m_featuresCount == 0 ||
!SupportsSeekWhileWriting(m_osFilename))
if (m_poFpWrite == nullptr || !SupportsSeekWhileWriting(m_osFilename))
{
return true;
}
Expand All @@ -546,14 +548,24 @@ bool OGRFlatGeobufLayer::CreateFinalFile()
VSIFSeekL(m_poFpWrite, 0, SEEK_SET);
m_writeOffset = 0;
std::vector<double> extentVector;
extentVector.push_back(m_sExtent.MinX);
extentVector.push_back(m_sExtent.MinY);
extentVector.push_back(m_sExtent.MaxX);
extentVector.push_back(m_sExtent.MaxY);
if (!m_sExtent.IsInit())
{
extentVector.resize(4, std::numeric_limits<double>::quiet_NaN());
}
else
{
extentVector.push_back(m_sExtent.MinX);
extentVector.push_back(m_sExtent.MinY);
extentVector.push_back(m_sExtent.MaxX);
extentVector.push_back(m_sExtent.MaxY);
}
writeHeader(m_poFpWrite, m_featuresCount, &extentVector);
// Sanity check to verify that the dummy header and the real header
// have the same size.
CPLAssert(m_writeOffset == m_offsetAfterHeader);
if (m_featuresCount)
{
CPLAssert(m_writeOffset == m_offsetAfterHeader);
}
CPL_IGNORE_RET_VAL(m_writeOffset); // otherwise checkers might tell the
// member is not used
return true;
Expand Down Expand Up @@ -2295,7 +2307,7 @@ OGRErr OGRFlatGeobufLayer::ICreateFeature(OGRFeature *poNewFeature)
// the size of the FlatBuffer, but WKB might be a good approximation.
// Takes an extra security margin of 10%
flatbuffers::Offset<FlatGeobuf::Geometry> geometryOffset = 0;
if (ogrGeometry != nullptr)
if (ogrGeometry && !ogrGeometry->IsEmpty())
{
const auto nWKBSize = ogrGeometry->WkbSize();
if (nWKBSize > feature_max_buffer_size - nWKBSize / 10)
Expand Down
52 changes: 26 additions & 26 deletions ogr/ogrsf_frmts/openfilegdb/filegdbtable.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2545,21 +2545,21 @@ int FileGDBTable::GetIndexCount()
GUInt32 i;
for (i = 0; i < nIndexCount; i++)
{
returnErrorAndCleanupIf(static_cast<GUInt32>(pabyEnd - pabyCur) <
returnErrorAndCleanupIf(static_cast<size_t>(pabyEnd - pabyCur) <
sizeof(GUInt32),
VSIFree(pabyIdx));
const GUInt32 nIdxNameCarCount = GetUInt32(pabyCur, 0);
const GUInt32 nIdxNameCharCount = GetUInt32(pabyCur, 0);
pabyCur += sizeof(GUInt32);
returnErrorAndCleanupIf(nIdxNameCarCount > 1024, VSIFree(pabyIdx));
returnErrorAndCleanupIf(static_cast<GUInt32>(pabyEnd - pabyCur) <
2 * nIdxNameCarCount,
returnErrorAndCleanupIf(nIdxNameCharCount > 1024, VSIFree(pabyIdx));
returnErrorAndCleanupIf(static_cast<size_t>(pabyEnd - pabyCur) <
2 * nIdxNameCharCount,
VSIFree(pabyIdx));
const std::string osIndexName(
ReadUTF16String(pabyCur, nIdxNameCarCount));
pabyCur += 2 * nIdxNameCarCount;
ReadUTF16String(pabyCur, nIdxNameCharCount));
pabyCur += 2 * nIdxNameCharCount;

// 4 "magic fields"
returnErrorAndCleanupIf(static_cast<GUInt32>(pabyEnd - pabyCur) <
returnErrorAndCleanupIf(static_cast<size_t>(pabyEnd - pabyCur) <
sizeof(GUInt16) + sizeof(GUInt32) +
sizeof(GUInt16) + sizeof(GUInt32),
VSIFree(pabyIdx));
Expand All @@ -2583,16 +2583,16 @@ int FileGDBTable::GetIndexCount()
// Skip magic fields
pabyCur += sizeof(GUInt16);

const GUInt32 nColNameCarCount = nMagic2;
const GUInt32 nColNameCharCount = nMagic2;
pabyCur += sizeof(GUInt32);
returnErrorAndCleanupIf(nColNameCarCount > 1024, VSIFree(pabyIdx));
returnErrorAndCleanupIf(static_cast<GUInt32>(pabyEnd - pabyCur) <
2 * nColNameCarCount,
returnErrorAndCleanupIf(nColNameCharCount > 1024, VSIFree(pabyIdx));
returnErrorAndCleanupIf(static_cast<size_t>(pabyEnd - pabyCur) <
2 * nColNameCharCount,
VSIFree(pabyIdx));
pabyCur += 2 * nColNameCarCount;
pabyCur += 2 * nColNameCharCount;

// Skip magic field
returnErrorAndCleanupIf(static_cast<GUInt32>(pabyEnd - pabyCur) <
returnErrorAndCleanupIf(static_cast<size_t>(pabyEnd - pabyCur) <
sizeof(GUInt16),
VSIFree(pabyIdx));
pabyCur += sizeof(GUInt16);
Expand All @@ -2604,21 +2604,21 @@ int FileGDBTable::GetIndexCount()
pabyCur += sizeof(GUInt16) + sizeof(GUInt32) + sizeof(GUInt16) +
sizeof(GUInt32);

returnErrorAndCleanupIf(static_cast<GUInt32>(pabyEnd - pabyCur) <
returnErrorAndCleanupIf(static_cast<size_t>(pabyEnd - pabyCur) <
sizeof(GUInt32),
VSIFree(pabyIdx));
const GUInt32 nColNameCarCount = GetUInt32(pabyCur, 0);
const GUInt32 nColNameCharCount = GetUInt32(pabyCur, 0);
pabyCur += sizeof(GUInt32);
returnErrorAndCleanupIf(nColNameCarCount > 1024, VSIFree(pabyIdx));
returnErrorAndCleanupIf(static_cast<GUInt32>(pabyEnd - pabyCur) <
2 * nColNameCarCount,
returnErrorAndCleanupIf(nColNameCharCount > 1024, VSIFree(pabyIdx));
returnErrorAndCleanupIf(static_cast<size_t>(pabyEnd - pabyCur) <
2 * nColNameCharCount,
VSIFree(pabyIdx));
const std::string osExpression(
ReadUTF16String(pabyCur, nColNameCarCount));
pabyCur += 2 * nColNameCarCount;
ReadUTF16String(pabyCur, nColNameCharCount));
pabyCur += 2 * nColNameCharCount;

// Skip magic field
returnErrorAndCleanupIf(static_cast<GUInt32>(pabyEnd - pabyCur) <
returnErrorAndCleanupIf(static_cast<size_t>(pabyEnd - pabyCur) <
sizeof(GUInt16),
VSIFree(pabyIdx));
pabyCur += sizeof(GUInt16);
Expand Down Expand Up @@ -3284,16 +3284,16 @@ bool FileGDBOGRGeometryConverterImpl::ReadPartDefs(
nCurves = 0;
return true;
}
returnErrorIf(nPoints > static_cast<GUInt32>(pabyEnd - pabyCur));
returnErrorIf(nPoints > static_cast<size_t>(pabyEnd - pabyCur));
if (bIsMultiPatch)
returnErrorIf(!SkipVarUInt(pabyCur, pabyEnd));
returnErrorIf(!ReadVarUInt32(pabyCur, pabyEnd, nParts));
returnErrorIf(nParts > static_cast<GUInt32>(pabyEnd - pabyCur));
returnErrorIf(nParts > static_cast<size_t>(pabyEnd - pabyCur));
returnErrorIf(nParts > static_cast<GUInt32>(INT_MAX) / sizeof(GUInt32));
if (bHasCurveDesc)
{
returnErrorIf(!ReadVarUInt32(pabyCur, pabyEnd, nCurves));
returnErrorIf(nCurves > static_cast<GUInt32>(pabyEnd - pabyCur));
returnErrorIf(nCurves > static_cast<size_t>(pabyEnd - pabyCur));
}
else
nCurves = 0;
Expand All @@ -3314,7 +3314,7 @@ bool FileGDBOGRGeometryConverterImpl::ReadPartDefs(
{
GUInt32 nTmp;
returnErrorIf(!ReadVarUInt32(pabyCur, pabyEnd, nTmp));
returnErrorIf(nTmp > static_cast<GUInt32>(pabyEnd - pabyCur));
returnErrorIf(nTmp > static_cast<size_t>(pabyEnd - pabyCur));
panPointCount[i] = nTmp;
nSumNPartsM1 += nTmp;
}
Expand Down
Loading