Skip to content

Commit

Permalink
OGR: Add OGRLayer::GetExtent3D()
Browse files Browse the repository at this point in the history
Fix #8570
  • Loading branch information
elpaso committed Nov 24, 2023
1 parent 0fe09b6 commit 602933f
Show file tree
Hide file tree
Showing 7 changed files with 145 additions and 0 deletions.
21 changes: 21 additions & 0 deletions autotest/ogr/ogr_csv.py
Original file line number Diff line number Diff line change
Expand Up @@ -2915,6 +2915,27 @@ def test_ogr_csv_separator_open_option(tmp_vsimem, sep, sep_opt_value, other_sep
assert f["baz"] == "3"


def test_ogr_csv_getextent3d(tmp_vsimem):

gdal.FileFromMemBuffer(
tmp_vsimem / "test.csv",
"id,WKT\n1,POINT Z(1 1 1)\n1,POINT Z(2 2 2)",
)

gdal.ErrorReset()
ds = gdal.OpenEx(
tmp_vsimem / "test.csv", gdal.OF_VECTOR, open_options=["SEPARATOR=COMMA"]
)
assert gdal.GetLastErrorMsg() == ""
lyr = ds.GetLayer(0)
dfn = lyr.GetLayerDefn()
assert dfn.GetGeomFieldCount() == 1
ext2d = lyr.GetExtent()
assert ext2d == (1.0, 2.0, 1.0, 2.0)
ext3d = lyr.GetExtent3D()
assert ext3d == (1.0, 2.0, 1.0, 2.0, 1.0, 2.0)


###############################################################################


Expand Down
2 changes: 2 additions & 0 deletions ogr/ogr_api.h
Original file line number Diff line number Diff line change
Expand Up @@ -765,6 +765,8 @@ GIntBig CPL_DLL OGR_L_GetFeatureCount(OGRLayerH, int);
OGRErr CPL_DLL OGR_L_GetExtent(OGRLayerH, OGREnvelope *, int);
OGRErr CPL_DLL OGR_L_GetExtentEx(OGRLayerH, int iGeomField,
OGREnvelope *psExtent, int bForce);
OGRErr CPL_DLL OGR_L_GetExtent3D(OGRLayerH, int iGeomField,
OGREnvelope3D *psExtent3D, int bForce);
int CPL_DLL OGR_L_TestCapability(OGRLayerH, const char *);
OGRErr CPL_DLL OGR_L_CreateField(OGRLayerH, OGRFieldDefnH, int);
OGRErr CPL_DLL OGR_L_CreateGeomField(OGRLayerH hLayer,
Expand Down
9 changes: 9 additions & 0 deletions ogr/ograpispy.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -790,6 +790,15 @@ void OGRAPISpy_L_GetExtentEx(OGRLayerH hLayer, int iGeomField, int bForce)
OGRAPISpyFileClose();
}

void OGRAPISpy_L_GetExtent3D(OGRLayerH hLayer, int iGeomField, int bForce)
{
CPLMutexHolderD(&hMutex);
OGRAPISpyFlushDefered();
fprintf(fpSpyFile, "%s.GetExtent3D(geom_field=%d, force=%d)\n",
OGRAPISpyGetLayerVar(hLayer).c_str(), iGeomField, bForce);
OGRAPISpyFileClose();
}

void OGRAPISpy_L_SetAttributeFilter(OGRLayerH hLayer, const char *pszFilter)
{
CPLMutexHolderD(&hMutex);
Expand Down
1 change: 1 addition & 0 deletions ogr/ograpispy.h
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,7 @@ void OGRAPISpy_Dataset_RollbackTransaction(GDALDatasetH hDS);
void OGRAPISpy_L_GetFeatureCount(OGRLayerH hLayer, int bForce);
void OGRAPISpy_L_GetExtent(OGRLayerH hLayer, int bForce);
void OGRAPISpy_L_GetExtentEx(OGRLayerH hLayer, int iGeomField, int bForce);
void OGRAPISpy_L_GetExtent3D(OGRLayerH hLayer, int iGeomField, int bForce);
void OGRAPISpy_L_SetAttributeFilter(OGRLayerH hLayer, const char *pszFilter);
void OGRAPISpy_L_GetFeature(OGRLayerH hLayer, GIntBig nFeatureId);
void OGRAPISpy_L_SetNextByIndex(OGRLayerH hLayer, GIntBig nIndex);
Expand Down
99 changes: 99 additions & 0 deletions ogr/ogrsf_frmts/generic/ogrlayer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -227,6 +227,85 @@ OGRErr OGRLayer::GetExtent(int iGeomField, OGREnvelope *psExtent, int bForce)
return GetExtentInternal(iGeomField, psExtent, bForce);
}

OGRErr OGRLayer::GetExtent3D(int iGeomField, OGREnvelope3D *psExtent3D,
int bForce)

{
psExtent3D->MinX = 0.0;
psExtent3D->MaxX = 0.0;
psExtent3D->MinY = 0.0;
psExtent3D->MaxY = 0.0;
psExtent3D->MinZ = 0.0;
psExtent3D->MaxZ = 0.0;

/* -------------------------------------------------------------------- */
/* If this layer has a none geometry type, then we can */
/* reasonably assume there are not extents available. */
/* -------------------------------------------------------------------- */
if (iGeomField < 0 || iGeomField >= GetLayerDefn()->GetGeomFieldCount() ||
GetLayerDefn()->GetGeomFieldDefn(iGeomField)->GetType() == wkbNone)
{
if (iGeomField != 0)
{
CPLError(CE_Failure, CPLE_AppDefined,
"Invalid geometry field index : %d", iGeomField);
}
return OGRERR_FAILURE;
}

/* -------------------------------------------------------------------- */
/* If not forced, we should avoid having to scan all the */
/* features and just return a failure. */
/* -------------------------------------------------------------------- */
if (!bForce)
return OGRERR_FAILURE;

/* -------------------------------------------------------------------- */
/* OK, we hate to do this, but go ahead and read through all */
/* the features to collect geometries and build extents. */
/* -------------------------------------------------------------------- */
OGREnvelope3D oEnv;
bool bExtentSet = false;

for (auto &&poFeature : *this)
{
OGRGeometry *poGeom = poFeature->GetGeomFieldRef(iGeomField);
if (poGeom == nullptr || poGeom->IsEmpty())
{
/* Do nothing */
}
else if (!bExtentSet)
{
poGeom->getEnvelope(psExtent3D);
if (!(CPLIsNan(psExtent3D->MinX) || CPLIsNan(psExtent3D->MinY) ||
CPLIsNan(psExtent3D->MaxX) || CPLIsNan(psExtent3D->MaxY)) ||
CPLIsNan(psExtent3D->MinZ) || CPLIsNan(psExtent3D->MaxZ))
{
bExtentSet = true;
}
}
else
{
poGeom->getEnvelope(&oEnv);
if (oEnv.MinX < psExtent3D->MinX)
psExtent3D->MinX = oEnv.MinX;
if (oEnv.MinY < psExtent3D->MinY)
psExtent3D->MinY = oEnv.MinY;
if (oEnv.MinZ < psExtent3D->MinZ)
psExtent3D->MinZ = oEnv.MinZ;
if (oEnv.MaxX > psExtent3D->MaxX)
psExtent3D->MaxX = oEnv.MaxX;
if (oEnv.MaxY > psExtent3D->MaxY)
psExtent3D->MaxY = oEnv.MaxY;
if (oEnv.MaxZ > psExtent3D->MaxZ)
psExtent3D->MaxZ = oEnv.MaxZ;
}
}
ResetReading();

return bExtentSet ? OGRERR_NONE : OGRERR_FAILURE;
}

//! @cond Doxygen_Suppress
OGRErr OGRLayer::GetExtentInternal(int iGeomField, OGREnvelope *psExtent,
int bForce)
Expand Down Expand Up @@ -299,6 +378,7 @@ OGRErr OGRLayer::GetExtentInternal(int iGeomField, OGREnvelope *psExtent,

return bExtentSet ? OGRERR_NONE : OGRERR_FAILURE;
}

//! @endcond

/************************************************************************/
Expand Down Expand Up @@ -337,6 +417,25 @@ OGRErr OGR_L_GetExtentEx(OGRLayerH hLayer, int iGeomField,
bForce);
}

/************************************************************************/
/* OGR_L_GetExtent3D() */
/************************************************************************/

OGRErr OGR_L_GetExtent3D(OGRLayerH hLayer, int iGeomField,
OGREnvelope3D *psExtent3D, int bForce)

{
VALIDATE_POINTER1(hLayer, "OGR_L_GetExtent3D", OGRERR_INVALID_HANDLE);

#ifdef OGRAPISPY_ENABLED
if (bOGRAPISpyEnabled)
OGRAPISpy_L_GetExtent3D(hLayer, iGeomField, bForce);
#endif

return OGRLayer::FromHandle(hLayer)->GetExtent3D(iGeomField, psExtent3D,
bForce);
}

/************************************************************************/
/* SetAttributeFilter() */
/************************************************************************/
Expand Down
4 changes: 4 additions & 0 deletions ogr/ogrsf_frmts/ogrsf_frmts.h
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,8 @@ class CPL_DLL OGRLayer : public GDALMajorObject
int InstallFilter(OGRGeometry *);

OGRErr GetExtentInternal(int iGeomField, OGREnvelope *psExtent, int bForce);
OGRErr GetExtent3DInternal(int iGeomField, OGREnvelope3D *psExtent3D,
int bForce);
//! @endcond

virtual OGRErr ISetFeature(OGRFeature *poFeature) CPL_WARN_UNUSED_RESULT;
Expand Down Expand Up @@ -257,6 +259,8 @@ class CPL_DLL OGRLayer : public GDALMajorObject
int bForce = TRUE) CPL_WARN_UNUSED_RESULT;
virtual OGRErr GetExtent(int iGeomField, OGREnvelope *psExtent,
int bForce = TRUE) CPL_WARN_UNUSED_RESULT;
virtual OGRErr GetExtent3D(int iGeomField, OGREnvelope3D *psExtent3D,
int bForce = TRUE) CPL_WARN_UNUSED_RESULT;

virtual int TestCapability(const char *) = 0;

Expand Down
9 changes: 9 additions & 0 deletions swig/include/ogr.i
Original file line number Diff line number Diff line change
Expand Up @@ -1304,6 +1304,15 @@ public:
*isvalid = TRUE;
return;
}
%feature( "kwargs" ) GetExtent3D;
void GetExtent3D(double argout[6], int* isvalid = NULL, int force = 1, int can_return_null = 0, int geom_field = 0 ) {
OGRErr eErr = OGR_L_GetExtent3D(self, geom_field, (OGREnvelope3D*)argout, force);
if (can_return_null)
*isvalid = (eErr == OGRERR_NONE);
else
*isvalid = TRUE;
return;
}
#else
#ifndef SWIGJAVA
%feature( "kwargs" ) GetExtent;
Expand Down

0 comments on commit 602933f

Please sign in to comment.