Skip to content

Commit

Permalink
#757 geos_overlay_polygon added, WIP
Browse files Browse the repository at this point in the history
  • Loading branch information
MaartenHilferink committed Aug 5, 2024
1 parent f276bcd commit 89144a5
Show file tree
Hide file tree
Showing 8 changed files with 233 additions and 8 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -25,3 +25,4 @@ todo*.txt
/rtc/dll/obj
/rtc/dll/obj/x64/Debug
/vcpkg_installed
/obj.OLD
1 change: 1 addition & 0 deletions geo/dll/GeoDLL.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@
<ClInclude Include="src\GeoBase.h" />
<ClInclude Include="src\GeoInterface.h" />
<ClInclude Include="src\GeoPCH.h" />
<ClInclude Include="src\GEOS_Traits.h" />
<ClInclude Include="src\IppBase.h" />
<ClInclude Include="src\IppiUtils.h" />
<ClInclude Include="src\minkowski.h" />
Expand Down
3 changes: 3 additions & 0 deletions geo/dll/GeoDLL.vcxproj.filters
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,9 @@
<ClInclude Include="src\CGAL_60\Polygon_repair\repair.h">
<Filter>Geo Header Files</Filter>
</ClInclude>
<ClInclude Include="src\GEOS_Traits.h">
<Filter>Geo Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="src\Canyon.cpp">
Expand Down
2 changes: 0 additions & 2 deletions geo/dll/src/BoostGeometry.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1014,7 +1014,5 @@ namespace

template <typename P> using CGAL_SymmetricDifferenceMultiPolygonOperator = CGAL_MultiPolygonOperator<P, cgal_sym_difference>;
tl_oper::inst_tuple_templ<typelists::points, CGAL_SymmetricDifferenceMultiPolygonOperator, AbstrOperGroup&> cgalSymmetricDifferenceMultiPolygonOperatorsNamed(grcgalXOR);


}

32 changes: 30 additions & 2 deletions geo/dll/src/BoostPolygon.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,9 +36,9 @@

#include "BoostGeometry.h"
#include "CGAL_Traits.h"
#include "GEOS_Traits.h"


enum class geometry_library { boost_polygon, boost_geometry, cgal };
enum class geometry_library { boost_polygon, boost_geometry, cgal, geos };

const Int32 MAX_COORD = (1 << 26);

Expand Down Expand Up @@ -387,6 +387,31 @@ class PolygonOverlayOperator : public AbstrPolygonOverlayOperator
back.m_OrgRel.first = p1_rel;
back.m_OrgRel.second = p2Offset + (((*iter)->get_ptr()) - poly2Array.begin());

leveled_critical_section::scoped_lock resLock(resLocalAdditionSection);
resTileData->push_back(std::move(back));
}
}
else if constexpr (GL == geometry_library::geos)
{
auto mp1 = geos_create_multi_polygon(*polyPtr);


for (box_iter_type iter = spIndexPtr->begin(bbox); iter; ++iter)
{
CGAL_Traits::Polygon_set poly2;
auto mp2 = geos_create_multi_polygon(*((*iter)->get_ptr()));

auto res = mp1->intersection(mp2.get());

if (!res || res->isEmpty())
continue;

res_data_elem_type back;
geos_assign_mp(back.m_Geometry, *debug_cast<const geos::geom::MultiPolygon*>(res.get()));

back.m_OrgRel.first = p1_rel;
back.m_OrgRel.second = p2Offset + (((*iter)->get_ptr()) - poly2Array.begin());

leveled_critical_section::scoped_lock resLock(resLocalAdditionSection);
resTileData->push_back(std::move(back));
}
Expand Down Expand Up @@ -1673,16 +1698,19 @@ namespace
static CommonOperGroup grBgOverlayPolygon("bg_overlay_polygon", oper_policy::dynamic_result_class | oper_policy::better_not_in_meta_scripting);
static CommonOperGroup grBpOverlayPolygon("bp_overlay_polygon", oper_policy::dynamic_result_class | oper_policy::better_not_in_meta_scripting);
static CommonOperGroup grCGALOverlayPolygon("cgal_overlay_polygon", oper_policy::dynamic_result_class | oper_policy::better_not_in_meta_scripting);
static CommonOperGroup grGEOSOverlayPolygon("geos_overlay_polygon", oper_policy::dynamic_result_class | oper_policy::better_not_in_meta_scripting);


template <typename P> using BoostPolygonOverlayOperator = PolygonOverlayOperator<P, geometry_library::boost_polygon>;
template <typename P> using BoostGeometryOverlayOperator = PolygonOverlayOperator<P, geometry_library::boost_geometry>;
template <typename P> using CGAL_OverlayOperator = PolygonOverlayOperator<P, geometry_library::cgal>;
template <typename P> using GEOS_OverlayOperator = PolygonOverlayOperator<P, geometry_library::geos>;
tl_oper::inst_tuple_templ<typelists::sint_points , BoostPolygonOverlayOperator , AbstrOperGroup&> boostPolygonOverlayOperators (grOverlayPolygon);
tl_oper::inst_tuple_templ<typelists::sint_points , BoostPolygonOverlayOperator , AbstrOperGroup&> boostPolygonBpOverlayOperators (grBpOverlayPolygon);
tl_oper::inst_tuple_templ<typelists::float_points, BoostGeometryOverlayOperator, AbstrOperGroup&> boostGeometryOverlayOperators (grOverlayPolygon);
tl_oper::inst_tuple_templ<typelists::points , BoostGeometryOverlayOperator, AbstrOperGroup&> boostGeometryBgOverlayOperators(grBgOverlayPolygon);
tl_oper::inst_tuple_templ<typelists::points, CGAL_OverlayOperator, AbstrOperGroup&> cgalOverlayOperators(grCGALOverlayPolygon);
tl_oper::inst_tuple_templ<typelists::points, GEOS_OverlayOperator, AbstrOperGroup&> geosOverlayOperators(grGEOSOverlayPolygon);

tl_oper::inst_tuple_templ<typelists::sint_points, PolygonConnectivityOperator> polygonConnectivityOperators;
tl_oper::inst_tuple_templ<typelists::points, BoxConnectivityOperator> boxConnectivityOperators;
Expand Down
4 changes: 2 additions & 2 deletions geo/dll/src/CGAL_Traits.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,8 @@

struct CGAL_Traits
{
using Kernel = CGAL::Exact_predicates_exact_constructions_kernel;
// using Kernel = CGAL::Exact_predicates_inexact_constructions_kernel;
// using Kernel = CGAL::Exact_predicates_exact_constructions_kernel;
using Kernel = CGAL::Exact_predicates_inexact_constructions_kernel;
// fails on simple intersections, such as identifying a crossing point
// 112894,685301784 403381,743493082
//
Expand Down
193 changes: 193 additions & 0 deletions geo/dll/src/GEOS_Traits.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,193 @@
// Copyright (C) 1998-2024 Object Vision b.v.
// License: GNU GPL 3
/////////////////////////////////////////////////////////////////////////////

#if defined(_MSC_VER)
#pragma once
#endif

#if !defined(DMS_GEO_GEOS_TRAITS_H)
#define DMS_GEO_GEOS_TRAITS_H

#include "geo/RingIterator.h"


#include "RemoveAdjacentsAndSpikes.h"

//============================ GEOS ============================
#include <geos/geom/GeometryFactory.h>
#include <geos/geom/Geometry.h>
#include <geos/geom/Polygon.h>
#include <geos/geom/LinearRing.h>
#include <geos/algorithm/Orientation.h>



template <typename DmsPointType>
auto geos_create_multi_polygon(SA_ConstReference<DmsPointType> polyRef, bool mustInsertInnerRings = true)
-> std::unique_ptr<geos::geom::MultiPolygon>
{
// std::unique_ptr< geos::geom::MultiPolygon> resMP.clear();

SA_ConstRingIterator<DmsPointType> rb(polyRef, 0), re(polyRef, -1);
if (rb == re)
return;
auto ri = rb;


static auto factory = geos::geom::GeometryFactory::create();

std::vector< geos::geom::Polygon> resPolygons;
geos::geom::LinearRing helperRing, currRing;
std::vector< geos::geom::LinearRing> currInnerRings;
std::vector<geos::geom::Coordinate> helperRingCoords;

SA_ConstRingIterator<DmsPointType>
rb(polyRef, 0),
re(polyRef, -1);
auto ri = rb;
// dbg_assert(ri != re);
if (ri == re)
return;

bool outerOrientationCW = true;
for (; ri != re; ++ri)
{
assert((*ri).begin() != (*ri).end());
assert((*ri).begin()[0] == (*ri).end()[-1]); // closed ?

helperRingCoords.clear();
for (const auto& p : *ri)
{
helperRingCoords.emplace_back(geos::geom::Coordinate(p.x, p.y));
}
helperRing = geos::geom::LinearRing(std::move(helperRingCoords), factory);
MG_CHECK(helperRing.isClosed());

bool currOrientationCW = !geos::algorithm::Orientation::isCCW(helperRing.getCoordinatesRO());
MG_CHECK(ri != rb || currOrientationCW);

if (ri == rb || currOrientationCW == outerOrientationCW)
{
if (ri != rb && !currRing.isEmpty())
{
resPolygons.emplace_back(factory->createPolygon(std::move(currRing), std::move(currInnerRings)));
currInnerRings.clear();
}
currRing = helperRing;
outerOrientationCW = currOrientationCW;

/* NYI
// skip outer rings that intersect with a previous outer ring if innerRings are skipped
if (!mustInsertInnerRings)
{
SizeT polygonIndex = 0;
while (polygonIndex < resMP.size())
{
auto currPolygon = resMP.begin() + polygonIndex;
if (boost::geometry::intersects(currPolygon->outer(), helperPolygon.outer()))
{
if (boost::geometry::within(currPolygon->outer(), helperPolygon.outer()))
{
resMP.erase(currPolygon);
continue;
}
if (boost::geometry::within(helperPolygon.outer(), currPolygon->outer()))
{
helperPolygon.clear();
assert(helperPolygon.outer().empty() && helperPolygon.inners().empty());
break;
}
if (boost::geometry::overlaps(currPolygon->outer(), helperPolygon.outer()))
throwDmsErrF("OuterPolygon: unexpected overlap of two outer rings in %s", AsString(polyRef).c_str());
// a combination of touching outer rings such as in an 8 shape is
}
polygonIndex++;
}
}
*/
}
else if (mustInsertInnerRings)
{
currInnerRings.emplace_back(helperRing);
}
}
if (!currRing.isEmpty())
{
resPolygons.emplace_back(factory->createPolygon(std::move(currRing), std::move(currInnerRings)));
}
return factory->createMultiPolygon(std::move(resPolygons));
}


template <dms_sequence E>
void geos_assign(E&& ref, const geos::geom::Coordinate& c)
{
ref.emplace_back(shp2dms_order(c.x, c.y));

}

template <dms_sequence E>
void geos_assign(E&& ref, const geos::geom::LinearRing& ringData)
{
for (const auto& c : ringData.getCoordinatesRO())
geos_assign(ref, c);
}

template <dms_sequence E>
void geos_assign(E&& ref, const geos::geom::Polygon& poly)
{
geos_assign(ref, poly.getExteriorRing());
SizeT irCount = poly.getNumInteriorRing();
for (SizeT ir = 0; ir != irCount; ++ir)
geos_assign(ref, poly.getInteriorRingN(ir));

if (irCount)
{
--irCount;
while (irCount)
geos_assign(ref, poly.getInteriorRingN(--irCount).back());

geos_assign(ref, poly.getExteriorRing().back());
}
}


template <dms_sequence E>
void geos_assign_mp(E&& ref, const geos::geom::MultiPolygon& mpData)
{
ref.clear();

if (mpData.isEmpty())
return;

SizeT i = 0, n = mpData.getNumGeometries();
assert(n != 0); // follows from poly.size()
SizeT count = n - 1;

for (; i != n; ++i)
{
const auto* poly = mpData.getGeometryN(i);
count += poly->getExteriorRing()->getNumPoints();
for (SizeT ir=0, irCount = poly->getNumInteriorRing(); ir != irCount; ++ir)
count += poly->getInteriorRingN(ir)->getNumPoints() + 1;
}

ref.reserve(count);

for (const auto& p : mpData)
{
geos_assign(ref, p);
}
while (--n)
{
geos_assign (ref, mpData.getGeometryN(n).getExteriorRing().back());
}

assert(ref.size() == count);
}


#endif //!defined(DMS_GEO_GEOS_TRAITS_H)
5 changes: 3 additions & 2 deletions vcpkg.json
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
{
"dependencies": [
"boost",
"cgal",
"gdal",
"openssl",
{
"name": "sqlite3",
"features": [
"rtree"
]
},
"gdal",
"cgal"
"geos"
]
}

0 comments on commit 89144a5

Please sign in to comment.