BoundaryChainNoder.h
/**********************************************************************
*
* GEOS - Geometry Engine Open Source
* http://geos.osgeo.org
*
* Copyright (c) Martin Davis 2022
*
* This is free software; you can redistribute and/or modify it under
* the terms of the GNU Lesser General Public Licence as published
* by the Free Software Foundation.
* See the COPYING file for more information.
*
**********************************************************************/
#pragma once
#include <geos/noding/Noder.h> // for composition
#include <geos/noding/SegmentString.h> // for composition
#include <geos/geom/LineSegment.h> // for composition
#include <geos/noding/BasicSegmentString.h>
#include <unordered_set>
// Forward declarations
namespace geos {
namespace geom {
class CoordinateSequence;
class Coordinate;
}
namespace noding {
class NodedSegmentString;
}
}
namespace geos { // geos
namespace noding { // geos::noding
class GEOS_DLL BoundaryChainNoder : public Noder {
using Coordinate = geos::geom::Coordinate;
private:
class BoundaryChainMap {
private:
// Members
SegmentString* segString;
std::vector<bool> isBoundary;
static SegmentString* createChain(
const SegmentString* segString,
std::size_t startIndex,
std::size_t endIndex,
bool constructZ,
bool constructM);
std::size_t findChainStart(std::size_t index) const;
std::size_t findChainEnd(std::size_t index) const;
public:
BoundaryChainMap(SegmentString* ss)
: segString(ss) {
isBoundary.resize(ss->size()-1, false);
};
void setBoundarySegment(std::size_t index);
void createChains(std::vector<SegmentString*>& chains, bool constructZ, bool constructM);
};
class Segment {
public:
Segment(const geom::CoordinateSequence& seq,
BoundaryChainMap& segMap,
std::size_t index)
: m_seq(seq)
, m_segMap(segMap)
, m_index(index)
, m_flip(seq.getAt<geom::CoordinateXY>(index).compareTo(seq.getAt<geom::CoordinateXY>(index + 1)) < 0)
{}
const geom::CoordinateXY& p0() const {
return m_seq.getAt<geom::CoordinateXY>(m_flip ? m_index : m_index + 1);
}
const geom::CoordinateXY& p1() const {
return m_seq.getAt<geom::CoordinateXY>(m_flip ? m_index + 1 : m_index);
}
void markBoundary() const {
m_segMap.setBoundarySegment(m_index);
};
bool operator==(const Segment& other) const {
return p0().equals2D(other.p0()) && p1().equals2D(other.p1());
}
struct HashCode {
std::size_t operator()(const Segment& s) const {
std::size_t h = std::hash<double>{}(s.p0().x);
h ^= (std::hash<double>{}(s.p0().y) << 1);
h ^= (std::hash<double>{}(s.p1().x) << 1);
h ^= (std::hash<double>{}(s.p1().y) << 1);
return h;
}
};
private:
const geom::CoordinateSequence& m_seq;
BoundaryChainMap& m_segMap;
std::size_t m_index;
bool m_flip;
};
public:
using SegmentSet = std::unordered_set<Segment, Segment::HashCode>;
BoundaryChainNoder()
: m_chainList(nullptr)
, m_constructZ(false)
, m_constructM(false)
{};
// Noder virtual methods
std::vector<SegmentString*>* getNodedSubstrings() const override;
void computeNodes(std::vector<SegmentString*>* inputSegStrings) override;
private:
// Members
std::vector<SegmentString*>* m_chainList;
std::vector<std::unique_ptr<geom::CoordinateSequence>> m_substrings;
bool m_constructZ;
bool m_constructM;
// Methods
void addSegments(std::vector<SegmentString*>* segStrings,
SegmentSet& segSet,
std::vector<BoundaryChainMap>& includedSegs);
static void addSegments(SegmentString* segString,
BoundaryChainMap& segInclude,
SegmentSet& segSet);
static bool segSetContains(
SegmentSet& segSet, Segment& seg);
static void markBoundarySegments(SegmentSet& segSet);
std::vector<SegmentString*>* extractChains(std::vector<BoundaryChainMap>& sections) const;
Coordinate::UnorderedSet findNodePts(
const std::vector<SegmentString*>* segStrings) const;
std::vector<SegmentString*>* nodeChains(
const std::vector<SegmentString*>* chains,
const Coordinate::UnorderedSet& nodePts);
void nodeChain(
SegmentString* chain,
const Coordinate::UnorderedSet& nodePts,
std::vector<SegmentString*>* nodedChains);
std::size_t findNodeIndex(
const SegmentString* chain,
std::size_t start,
const Coordinate::UnorderedSet& nodePts) const;
noding::BasicSegmentString* substring(
const SegmentString* segString,
std::size_t start, std::size_t end);
// Declared as non-copyable
BoundaryChainNoder(const BoundaryChainNoder& other);
BoundaryChainNoder& operator=(const BoundaryChainNoder& rhs);
};
} // namespace geos::noding
} // namespace geos
geos::geom::CoordinateSequence
The internal representation of a list of coordinates inside a Geometry.
Definition CoordinateSequence.h:56
geos::geom::Coordinate
Coordinate is the lightweight class used to store coordinates.
Definition Coordinate.h:217
geos::noding::BasicSegmentString
Represents a list of contiguous line segments, and supports noding the segments.
Definition BasicSegmentString.h:44
geos::noding::BoundaryChainNoder::getNodedSubstrings
std::vector< SegmentString * > * getNodedSubstrings() const override
Returns a collection of fully noded SegmentStrings. The SegmentStrings have the same context as their...
geos::noding::BoundaryChainNoder::computeNodes
void computeNodes(std::vector< SegmentString * > *inputSegStrings) override
Computes the noding for a collection of SegmentStrings.
geos::noding::NodedSegmentString
Represents a list of contiguous line segments, and supports noding the segments.
Definition NodedSegmentString.h:58
geos::noding::SegmentString
An interface for classes which represent a sequence of contiguous line segments.
Definition SegmentString.h:47
geos::geom::CoordinateSequence::getAt
const T & getAt(std::size_t i) const
Returns a read-only reference to Coordinate at position i.
Definition CoordinateSequence.h:249
geos::geom
Definition Angle.h:26
geos::index
Provides classes for various kinds of spatial indexes.
Definition CleanCoverage.h:39
geos::noding
Classes to compute nodings for arrangements of line segments and line segment sequences.
Definition CoverageCleaner.h:42
geos
Basic namespace for all GEOS functionalities.
Definition geos.h:38