9#include <unordered_map>
23using PolygonNeighbours = SweepLine<BoundingBoxWrapper<P>,std::vector<std::pair<P,P>>,HorizontalAABBOrdering<BoundingBoxWrapper<P>>,
true>;
26struct PolygonNeighboursInsertEvent :
public PolygonNeighbours<P>::DefaultInsertEvent {
27 PolygonNeighboursInsertEvent(
const BoundingBoxWrapper<P> & box):PolygonNeighbours<P>::
DefaultInsertEvent(box){}
29 return this->
obj->getBoundingBox().top();
39struct PolygonNeighboursRemoveEvent:
public PolygonNeighbours<P>::RemoveEvent {
40 util::BiPredicate_t<BoundingBoxWrapper<P>> neighbouringPredicate;
42 PolygonNeighboursRemoveEvent(
const BoundingBoxWrapper<P> & bbPptr, util::BiPredicate<BoundingBoxWrapper<P>>
auto const & neighbouringBiPredicate,
size_t maxNeighbours):PolygonNeighbours<P>::
RemoveEvent(bbPptr),neighbouringPredicate(neighbouringBiPredicate),maxNeighbours(maxNeighbours){}
45 return this->
obj->getBoundingBox().bottom();
48 virtual void process(PolygonNeighbours<P> & sweepLine, std::vector<std::pair<P,P>> & output)
const {
49 const auto & sls = sweepLine.getSLS();
50 const auto & current = *this->
obj;
51 auto distanceMapper = [¤t](
const auto & p){
58 auto closestNeighbours = util::FixedSizeBuffer<P,std::invoke_result_t<
decltype(distanceMapper),P>>(maxNeighbours,distanceMapper);
59 bool skippedSameObject =
false;
60 for(
auto it = sls.lower_bound(this->obj); it != sls.end(); --it){
61 const auto & neighbour = *(*it);
62 if(skippedSameObject && neighbouringPredicate(current,neighbour)){
63 closestNeighbours.push(neighbour.getPolygon());
66 skippedSameObject =
true;
70 for(
auto it = sls.upper_bound(this->obj); it != sls.end();++it){
71 const auto & neighbour = *(*it);
72 if(neighbouringPredicate(current,neighbour))
73 closestNeighbours.push(neighbour.getPolygon());
76 for(
auto && neighbour: closestNeighbours) {
77 output.emplace_back(current.getPolygon(),std::move(neighbour));
79 sweepLine.removeSLS(this->
obj);
83template<PolygonRange R, IPolygon P = std::ranges::range_value_t<R>>
84static std::vector<std::pair<P,P>> polygonNeighboursDelaunay(
const R & polygons, util::BiPredicate<P>
auto const & neighbouringPredicate,
double tolerance = 0.0,
bool onlyEdges =
true) {
86 std::vector<Vec2DReal> centroids;
88 std::unordered_map<Vec2DReal, P, std::hash<Vec2DReal>, std::equal_to<Vec2DReal>> centroidToPolygon;
89 for (
const auto & polygon : polygons) {
90 auto c = polygon.centroid();
91 centroids.push_back(c);
92 centroidToPolygon.emplace(c, polygon);
99 return delaunay.edges().transform([&](
const auto & edges) {
100 std::vector<std::pair<P,P>> adjacencies;
101 for (
const auto & edge : edges) {
102 auto it1 = centroidToPolygon.find(edge.p());
103 auto it2 = centroidToPolygon.find(edge.q());
104 if (it1 != centroidToPolygon.end() && it2 != centroidToPolygon.end() && neighbouringPredicate(it1->second, it2->second)) {
105 adjacencies.emplace_back(it1->second, it2->second);
109 }).value_or(std::vector<std::pair<P,P>>{});
112template<PolygonRange R, IPolygon P = std::ranges::range_value_t<R>>
113static std::vector<std::pair<P,P>> polygonNeighboursSweep(
const R & polygons, util::BiPredicate<BoundingBoxWrapper<P>>
auto const & neighbouringPredicate,util::UnaryFunction<P,BoundingBoxWrapper<P>>
auto const & wrapper,
size_t maxNeighbours) {
114 using SweepLine_t =
typename __impl::PolygonNeighbours<P>;
115 SweepLine_t sweepLine;
116 std::vector<std::pair<P,P>> output;
117 std::vector<BoundingBoxWrapper<P>> boundingBoxPolygons;
118 boundingBoxPolygons.reserve(
util::size(polygons));
119 std::ranges::for_each(polygons,[&boundingBoxPolygons,&wrapper](
const auto & p){
120 boundingBoxPolygons.push_back(wrapper(p));
122 std::ranges::for_each(boundingBoxPolygons,[&sweepLine,&neighbouringPredicate,maxNeighbours](
const auto & bbPptr){
123 sweepLine.addEvent(std::make_unique<__impl::PolygonNeighboursInsertEvent<P>>(bbPptr));
124 sweepLine.addEvent(std::make_unique<__impl::PolygonNeighboursRemoveEvent<P>>(bbPptr,neighbouringPredicate,maxNeighbours));
126 return sweepLine.sweep(output);
147template<PolygonRange R, IPolygon P = std::ranges::range_value_t<R>>
148static std::vector<std::pair<P,P>>
delaunay(
const R & polygons,
util::BiPredicate<P> auto const & neighbouringPredicate,
double tolerance = 0.0,
bool onlyEdges =
true) {
149 return __impl::polygonNeighboursDelaunay(polygons,neighbouringPredicate, tolerance, onlyEdges);
156template<PolygonRange R, IPolygon P = std::ranges::range_value_t<R>>
157static std::vector<std::pair<P,P>>
delaunay(
const R & polygons) {
171template<PolygonRange R, IPolygon P = std::ranges::range_value_t<R>>
173 return __impl::polygonNeighboursSweep(polygons,neighbouringPredicate,wrapper,maxNeighbours);
186template<PolygonRange R, IPolygon P = std::ranges::range_value_t<R>>
190 },wrapper,maxNeighbours);
202template<PolygonRange R, IPolygon P = std::ranges::range_value_t<R>>
203static std::vector<std::pair<P,P>>
sweep(
const R & polygons,
util::BiPredicate<P> auto const & neighbouringPredicate,
size_t maxNeighbours) {
215template<PolygonRange R>
217 if (bufferMultiplier <= 1)
218 throw std::invalid_argument(
"Buffer range multiplier has to be greater than 1");
219 using P = std::ranges::range_value_t<R>;
225 auto scaledWrapper = [bufferMultiplier](
const P & polygon) {
229 return sweep(polygons, crossesOrContainedInBoundingBox,scaledWrapper,maxNeighbours);
Wrapper for Polygon objects, which stores a (custom) bounding box.
Definition BoundingBoxWrapper.hpp:13
const Rectangle< fishnet::math::DEFAULT_NUMERIC > & getBoundingBox() const noexcept
Definition BoundingBoxWrapper.hpp:36
auto getPolygon() const noexcept
Definition BoundingBoxWrapper.hpp:40
Implementation of a rectangle Stores top,right,bottom and left point of the rectangle.
Definition Rectangle.hpp:15
constexpr bool contains(IPoint auto const &point) const noexcept
Definition Ring.hpp:196
virtual fishnet::math::DEFAULT_NUMERIC eventPoint() const noexcept=0
const Input * obj
Definition SweepLine.hpp:38
virtual void process(SweepLine< Input, Output, SLSLess, InsertEventsFirst, EventQueueGreater > &sweepLine, Output &output) const =0
Definition FunctionalConcepts.hpp:42
Definition FunctionalConcepts.hpp:9
Definition BoundingBoxWrapper.hpp:5
DelaunayTriangulation(R const &) -> DelaunayTriangulation< std::ranges::range_value_t< R > >
static fishnet::math::DEFAULT_FLOATING_POINT shapeDistance(Shape auto const &lhs, Shape auto const &rhs, util::BiFunction< Vec2DReal, Vec2DReal, fishnet::math::DEFAULT_FLOATING_POINT > auto const &distanceFunction) noexcept
Compute the distance between two shapes, with custom distance function.
Definition PolygonDistance.hpp:465
double DEFAULT_NUMERIC
Definition NumericConcepts.hpp:13
constexpr size_t size(std::ranges::range auto &&range) noexcept
Definition CollectionConcepts.hpp:50
Definition PolygonNeighbours.hpp:131
static std::vector< std::pair< P, P > > delaunay(const R &polygons)
Overload without predicate — returns all Delaunay edges.
Definition PolygonNeighbours.hpp:157
static std::vector< std::pair< P, P > > sweep(const R &polygons, util::BiPredicate< P > auto const &neighbouringPredicate, size_t maxNeighbours)
Overload with wrapper into default BoundingBoxWrappers (no custom bounding box allowed)
Definition PolygonNeighbours.hpp:203
static std::vector< std::pair< P, P > > sweepTemplate(const R &polygons, util::BiPredicate< BoundingBoxWrapper< P > > auto const &neighbouringPredicate, util::UnaryFunction< P, BoundingBoxWrapper< P > > auto const &wrapper, size_t maxNeighbours)
Generic findNeighbouringPolygons function, which returns a list of pairs indicating the adjacencies o...
Definition PolygonNeighbours.hpp:172
static std::vector< std::pair< P, P > > sweep(const R &polygons, util::BiPredicate< P > auto &&neighbouringPredicate, util::UnaryFunction< P, BoundingBoxWrapper< P > > auto const &wrapper, size_t maxNeighbours)
Finding neighbours of polygons using a sweepline, returns a list of pairs indicating the adjacencies ...
Definition PolygonNeighbours.hpp:187
static std::vector< std::pair< std::ranges::range_value_t< R >, std::ranges::range_value_t< R > > > sweepWithFixedBuffer(const R &polygons, fishnet::math::DEFAULT_NUMERIC bufferMultiplier, size_t maxNeighbours)
Overload for finding neighbouring polygons with a custom buffer multiplier for the bounding boxes.
Definition PolygonNeighbours.hpp:216
static std::vector< std::pair< P, P > > delaunay(const R &polygons, util::BiPredicate< P > auto const &neighbouringPredicate, double tolerance=0.0, bool onlyEdges=true)
Find neighbouring polygons using Delaunay triangulation on centroids.
Definition PolygonNeighbours.hpp:148
DefaultInsertEvent(const Input &obj)
Definition SweepLine.hpp:71
RemoveEvent(const Input &obj)
Definition SweepLine.hpp:64
Definition FunctionalConcepts.hpp:83