18template<fishnet::math::Number T>
30template<fishnet::math::Number T>
33 std::vector<Segment<T>> segments;
42 std::vector<Segment<T>> segments {};
45 segments.reserve(points.size());
46 for(
size_t i = 0; i < points.size()-1 ; ++i){
47 if(points[i]==points[i+1])
49 segments.emplace_back(points[i],points[i+1]);
51 auto const& first = points[0];
52 auto const& last = points[points.size()-1];
54 segments.emplace_back(last,first);
63 constexpr void makeValid()
noexcept {
64 for(
size_t i =0; i < segments.size(); ++i){
65 if(segments[i].q() != segments[(i+1)%segments.size()].p()){
66 auto & s = segments[(i+1)%segments.size()];
81 u_int16_t intersectionCounter = 0;
83 for(
const auto & segment: segments){
84 if(point==segment.p() or point==segment.q() or segment.contains(point))
86 std::optional<Vec2DReal> interOpt = segment.intersection(horizontalRay);
89 const Vec2DReal & inter = interOpt.value();
90 if (inter == segment.lowerEndpoint())
92 ++intersectionCounter;
103 verifyPolygonalRing<T>(this->segments);
110 verifyPolygonalRing<T>(this->segments);
115 std::vector<Vec2D<T>> pointsInVector {points};
116 this->segments = std::move(toSegments(pointsInVector));
117 verifyPolygonalRing<T>(this->segments);
120 template<fishnet::math::Number U>
121 constexpr operator Ring<U> () const noexcept {
122 std::vector<Vec2D<U>> points {};
123 std::ranges::transform(
getPoints(),std::back_inserter(points),[](
const auto & p){
134 return std::ranges::empty_view<Ring<T>>();
138 return std::views::all(segments);
143 | std::views::transform([](
const auto & s){
return s.p();});
153 for(
size_t i = 0; i < segments.size(); i++){
154 area += segments[i].p().cross(segments[(i+1)%segments.size()].p());
156 return 0.5 * fabs(
area);
166 for(
const auto & s : segments){
178 T high = this->segments.at(0).p().y;
180 T right = this->segments.at(0).p().x;
220 template<LinearGeometry L>
221 constexpr bool intersects(
const L & linearFeature)
const noexcept {
226 std::unordered_set<Vec2D<double>> intersectionSet {};
228 | std::views::transform([linearFeature](
const auto & segment){
return segment.intersection(linearFeature);})
229 | std::views::filter([](
const auto & optIntersection){
return optIntersection.has_value();});
230 for(
auto && optInter : intersectionView){
231 intersectionSet.insert(optInter.value());
233 return intersectionSet;
244 [[unlikely]]
if(not segment.isValid())
246 std::vector<Vec2DReal> splittingPoints;
247 splittingPoints.push_back(segment.p());
248 for(
const auto & s : segments){
249 [[unlikely]]
if (s.contains(segment))
251 auto inter = s.intersection(segment);
252 if(inter and not s.isEndpoint(inter.value()) and not segment.isEndpoint(inter.value())){
253 splittingPoints.push_back(inter.value());
256 splittingPoints.push_back(segment.q());
257 std::ranges::sort(splittingPoints,[segment](
const Vec2DReal & a,
const Vec2DReal & b ){
258 return segment.p().
distance(a) < segment.p().distance(b);
260 for(
size_t i = 0; i < splittingPoints.size()-1; i++){
261 auto middlePointOfPartialSegment = splittingPoints[i] + (splittingPoints[i+1]-splittingPoints[i]) * 0.5;
262 if(not
contains(middlePointOfPartialSegment))
269 template<fishnet::math::Number U>
271 if(this->segments.size() != other.getSegments().size())
273 size_t size = segments.size();
275 Segment<T> const & start = this->segments.front();
276 auto segmentViewOther = other.getSegments();
277 size_t indexOfStart = segmentViewOther.size();
278 for(
size_t i = 0; i < segmentViewOther.size(); ++i){
279 if(segmentViewOther[i] == start){
284 if(indexOfStart == segmentViewOther.size())
287 auto nextIndex = [size,indexOfStart](
size_t index){
return (indexOfStart+index) % size;};
288 bool allMatch =
true;
289 for(
size_t i = 0; i < this->segments.size(); ++i){
290 if(this->segments[i] != segmentViewOther[nextIndex(i)])
293 if(allMatch)
return true;
295 auto prevIndex = [size,indexOfStart](
size_t index) {
296 return (indexOfStart-index+size) % size;
298 for(
size_t i = 0; i < this->segments.size(); ++i){
299 if(this->segments[i]!=segmentViewOther[prevIndex(i)])
return false;
305 if(not this->
aaBB().overlap(other.aaBB()))
307 return std::ranges::any_of(segments,[&other](
const auto & s){
return other.intersects(s);})
308 || std::ranges::any_of(other.getSegments(),[
this](
const auto & s){return this->intersects(s);});
312 return std::ranges::all_of(other.getSegments(), [
this](
const auto & s){
313 return this->contains(s);
318 if(not this->
aaBB().overlap(other.aaBB()))
320 if(this->
crosses(other))
return false;
321 if(this->
contains(other) || other.contains(*
this))
return false;
322 for(
const auto & p : other.getPoints()){
334 if(this->
aaBB().overlap(other.aaBB()) && (this->contains(other) or other.contains(*
this) or this->crosses(other)))
339 constexpr size_t hash() const noexcept {
340 auto segmentsHashView = this->
getSegments() | std::views::transform([](
const auto & segment){
return segment.hash();});
342 return std::accumulate(std::ranges::begin(segmentsHashView),std::ranges::end(segmentsHashView),centroidHash);
346 std::ostringstream oss;
348 for (
const auto & s: this->segments){
349 if(!first) oss <<
",";
358template<std::ranges::random_access_range R>
Implementation of a ray A ray consist of an origin and the direction of the ray.
Definition Ray.hpp:13
static constexpr Ray< T > right(Vec2D< T > origin) noexcept
Definition Ray.hpp:29
Implementation of a rectangle Stores top,right,bottom and left point of the rectangle.
Definition Rectangle.hpp:15
Implementation of a ring.
Definition Ring.hpp:31
constexpr bool contains(IPoint auto const &point) const noexcept
Definition Ring.hpp:196
constexpr std::unordered_set< Vec2DReal > intersections(LinearGeometry auto const &linearFeature) const noexcept
Definition Ring.hpp:225
constexpr Vec2DReal centroid() const noexcept
Calculate centroid point of the ring https://en.wikipedia.org/wiki/Centroid.
Definition Ring.hpp:164
constexpr PointLocation getPointLocation(IPoint auto const &point) const noexcept
Get the location of a point with regard to the ring (INSIDE | OUTSIDE | BOUNDARY) Uses the Ray-Castin...
Definition Ring.hpp:80
static constexpr GeometryType type
Definition Ring.hpp:99
constexpr std::string toString() const noexcept
Definition Ring.hpp:345
constexpr fishnet::math::DEFAULT_FLOATING_POINT area() const noexcept
Calculate the area of the ring Uses Shoelace formula: https://en.wikipedia.org/wiki/Shoelace_formula.
Definition Ring.hpp:151
constexpr util::view_of< Vec2D< T > > auto getPoints() const noexcept
Definition Ring.hpp:141
T numeric_type
Definition Ring.hpp:98
constexpr bool isInside(IPoint auto const &point) const noexcept
Definition Ring.hpp:200
constexpr bool intersects(const L &linearFeature) const noexcept
test whether a linear feature intersects the ring
Definition Ring.hpp:221
Ring(util::random_access_range_of< Vec2D< T > > auto const &points, bool checked=false)
Definition Ring.hpp:101
constexpr Rectangle< T > aaBB() const noexcept
Computes the axis-aligned bounding box of the ring Calculated be computing the extreme points in ever...
Definition Ring.hpp:177
constexpr bool contains(IRing auto const &other) const noexcept
Definition Ring.hpp:311
constexpr bool contains(ISegment auto const &segment) const noexcept
Test whether a segment is fully contained inside the boundary of the ring Collect all intersections o...
Definition Ring.hpp:243
constexpr size_t hash() const noexcept
Definition Ring.hpp:339
Ring(std::initializer_list< Vec2D< T > > &&points)
Definition Ring.hpp:114
constexpr util::view_of< Segment< T > > auto getSegments() const noexcept
Definition Ring.hpp:137
constexpr bool isOnBoundary(IPoint auto const &point) const noexcept
Definition Ring.hpp:204
constexpr bool operator==(const Ring< U > &other) const noexcept
Definition Ring.hpp:270
constexpr fishnet::math::DEFAULT_FLOATING_POINT distance(IRing auto const &other) const noexcept
Distance between the two rings.
Definition Ring.hpp:333
constexpr auto getHoles() const noexcept
Definition Ring.hpp:133
constexpr bool touches(IRing auto const &other) const noexcept
Definition Ring.hpp:317
constexpr bool isOutside(IPoint auto const &point) const noexcept
Definition Ring.hpp:208
constexpr bool crosses(IRing auto const &other) const noexcept
Definition Ring.hpp:304
Ring(util::random_access_range_of< Segment< T > > auto &&segments, bool checked=false)
Definition Ring.hpp:107
constexpr const Ring< T > & getBoundary() const noexcept
Definition Ring.hpp:129
Implementation of a segment.
Definition Segment.hpp:14
Implementation of a two-dimensional vector.
Definition Vec2D.hpp:16
constexpr size_t hash() const noexcept
Definition Vec2D.hpp:179
Interface for a point.
Definition IPoint.hpp:92
Interface for a ring A ring is a closed loop of segments, forming a boundary of a shape.
Definition IRing.hpp:143
Interface for a segment A segment is formed between two points p and q, containing only the points on...
Definition ISegment.hpp:105
Definition IGeometry.hpp:13
Definition CollectionConcepts.hpp:39
Definition CollectionConcepts.hpp:45
Definition BoundingBoxWrapper.hpp:5
PointLocation
Definition Ring.hpp:21
GeometryType
Definition GeometryBase.hpp:6
Rectangle(const S &) -> Rectangle< typename S::numeric_type >
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
static constexpr bool ringIntersects(const R &ring, const L &linearFeature) noexcept
test whether a linear feature intersects a ring Check every intersection of the linear feature with t...
Definition RingIntersection.hpp:28
double DEFAULT_FLOATING_POINT
Definition NumericConcepts.hpp:12