18#include <geos/export.h>
20#include <geos/geom/Coordinate.h>
21#include <geos/geom/CoordinateSequenceIterator.h>
33class CoordinateFilter;
63 using iterator = CoordinateSequenceIterator<CoordinateSequence, Coordinate>;
64 using const_iterator = CoordinateSequenceIterator<const CoordinateSequence, const Coordinate>;
66 typedef std::unique_ptr<CoordinateSequence> Ptr;
162 std::unique_ptr<CoordinateSequence>
clone()
const;
187 assert(stride() == 2 || stride() == 3 || stride() == 4);
189 case 2:
return m_vect.size() / 2;
190 case 4:
return m_vect.size() / 4;
191 default :
return m_vect.size() / 3;
197 return m_vect.empty();
217 return m_hasdim ? m_hasz : (m_vect.empty() || !std::isnan(m_vect[2]));
242 case 4:
return CoordinateType::XYZM;
243 case 2:
return CoordinateType::XY;
244 default:
return hasM() ? CoordinateType::XYM : CoordinateType::XYZ;
255 template<
typename T=Coordinate>
256 const T&
getAt(std::size_t i)
const {
257 static_assert(std::is_base_of<CoordinateXY, T>::value,
"Must be a Coordinate class");
258 assert(
sizeof(T) <=
sizeof(
double) * stride());
259 assert(i*stride() < m_vect.size());
260 const T* orig =
reinterpret_cast<const T*
>(&m_vect[i*stride()]);
267 template<
typename T=Coordinate>
269 static_assert(std::is_base_of<CoordinateXY, T>::value,
"Must be a Coordinate class");
270 assert(
sizeof(T) <=
sizeof(
double) * stride());
271 assert(i*stride() < m_vect.size());
272 T* orig =
reinterpret_cast<T*
>(&m_vect[i*stride()]);
280 void getAt(std::size_t i, T& c)
const {
281 switch(getCoordinateType()) {
282 case CoordinateType::XY: c = getAt<CoordinateXY>(i);
break;
283 case CoordinateType::XYZ: c = getAt<Coordinate>(i);
break;
284 case CoordinateType::XYZM: c = getAt<CoordinateXYZM>(i);
break;
285 case CoordinateType::XYM: c = getAt<CoordinateXYM>(i);
break;
286 default: getAt<Coordinate>(i);
290 void getAt(std::size_t i, CoordinateXY& c)
const {
291 c = getAt<CoordinateXY>(i);
323 double getOrdinate(std::size_t index, std::size_t ordinateIndex)
const;
331 double getX(std::size_t index)
const
333 return m_vect[index * stride()];
342 double getY(std::size_t index)
const
344 return m_vect[index * stride() + 1];
354 double getZ(std::size_t index)
const
356 return getOrdinate(index, Z);
366 double getM(std::size_t index)
const
368 return getOrdinate(index, M);
377 void setX(std::size_t index,
double x)
379 m_vect[index * stride()] = x;
388 void setY(std::size_t index,
double y)
390 m_vect[index * stride() + 1] = y;
401 void setZ(std::size_t index,
double z)
404 setOrdinate(index, Z, z);
415 void setM(std::size_t index,
double m)
418 setOrdinate(index, M, m);
422 template<
typename T=Coordinate>
425 return getAt<T>(size() - 1);
429 template<
typename T=Coordinate>
432 return getAt<T>(size() - 1);
436 template<
typename T=Coordinate>
439 return *(
reinterpret_cast<const T*
>(m_vect.data()));
443 template<
typename T=Coordinate>
446 return *(
reinterpret_cast<T*
>(m_vect.data()));
450 void toVector(std::vector<Coordinate>& coords)
const;
452 void toVector(std::vector<CoordinateXY>& coords)
const;
461 void setAt(
const T& c, std::size_t pos) {
462 switch(getCoordinateType()) {
463 case CoordinateType::XY: setAtImpl<CoordinateXY>(c, pos);
break;
464 case CoordinateType::XYZ: setAtImpl<Coordinate>(c, pos);
break;
465 case CoordinateType::XYZM: setAtImpl<CoordinateXYZM>(c, pos);
break;
466 case CoordinateType::XYM: setAtImpl<CoordinateXYM>(c, pos);
break;
467 default: setAtImpl<Coordinate>(c, pos);
479 void setOrdinate(std::size_t index, std::size_t ordinateIndex,
double value);
495 template<
typename T=Coordinate>
507 void add(
const T& c,
bool allowRepeated)
509 if(!allowRepeated && !isEmpty()) {
510 const CoordinateXY& last = back<CoordinateXY>();
511 if(last.equals2D(c)) {
528 void add(
const T& c, std::size_t pos)
530 static_assert(std::is_base_of<CoordinateXY, T>::value,
"Must be a Coordinate class");
534 if (m_vect.size() + stride() <= m_vect.capacity()) {
536 setAt(c,
static_cast<std::size_t
>(pos));
540 setAt(tmp,
static_cast<std::size_t
>(pos));
554 void add(std::size_t i,
const T& coord,
bool allowRepeated)
557 if(! allowRepeated) {
558 std::size_t sz = size();
561 const CoordinateXY& prev = getAt<CoordinateXY>(i - 1);
562 if(prev.equals2D(coord)) {
567 const CoordinateXY& next = getAt<CoordinateXY>(i);
568 if(next.equals2D(coord)) {
578 void add(
double x,
double y) {
579 CoordinateXY c(x, y);
583 void add(
const CoordinateSequence& cs);
585 void add(
const CoordinateSequence& cs,
bool allowRepeated);
587 void add(
const CoordinateSequence& cl,
bool allowRepeated,
bool forwardDirection);
595 template<
typename T,
typename... Args>
596 void add(T begin, T end, Args... args) {
597 for (
auto it = begin; it != end; ++it) {
603 void add(std::size_t i, T from, T to) {
604 auto npts =
static_cast<std::size_t
>(std::distance(from, to));
607 for (
auto it = from; it != to; ++it) {
621 void reserve(std::size_t capacity) {
622 m_vect.reserve(capacity * stride());
625 void resize(std::size_t capacity) {
626 m_vect.resize(capacity * stride());
653 static std::size_t
indexOf(
const CoordinateXY* coordinate,
673 void scroll(
const CoordinateXY* firstCoordinate);
674 void scroll(std::size_t firstCoordinateIndex);
701 void swap(std::size_t i, std::size_t j);
710 void closeRing(
bool allowRepeated =
false);
716 template<
typename Filter>
717 void apply_rw(
const Filter* filter) {
718 switch(getCoordinateType()) {
719 case CoordinateType::XY:
720 for (
auto& c : items<CoordinateXY>()) {
721 if (filter->isDone())
break;
722 filter->filter_rw(&c);
725 case CoordinateType::XYZ:
727 if (filter->isDone())
break;
728 filter->filter_rw(&c);
731 case CoordinateType::XYM:
732 for (
auto& c : items<CoordinateXYM>()) {
733 if (filter->isDone())
break;
734 filter->filter_rw(&c);
737 case CoordinateType::XYZM:
738 for (
auto& c : items<CoordinateXYZM>()) {
739 if (filter->isDone())
break;
740 filter->filter_rw(&c);
744 m_hasdim = m_hasz =
false;
747 template<
typename Filter>
748 void apply_ro(Filter* filter)
const {
749 switch(getCoordinateType()) {
750 case CoordinateType::XY:
751 for (
const auto& c : items<CoordinateXY>()) {
752 if (filter->isDone())
break;
753 filter->filter_ro(&c);
756 case CoordinateType::XYZ:
757 for (
const auto& c : items<Coordinate>()) {
758 if (filter->isDone())
break;
759 filter->filter_ro(&c);
762 case CoordinateType::XYM:
763 for (
const auto& c : items<CoordinateXYM>()) {
764 if (filter->isDone())
break;
765 filter->filter_ro(&c);
768 case CoordinateType::XYZM:
769 for (
const auto& c : items<CoordinateXYZM>()) {
770 if (filter->isDone())
break;
771 filter->filter_ro(&c);
778 auto applyAt(
size_t i, F&& fun)
const {
779 switch(getCoordinateType()) {
780 case CoordinateType::XYZ:
return fun(getAt<Coordinate>(i));
781 case CoordinateType::XYM:
return fun(getAt<CoordinateXYM>(i));
782 case CoordinateType::XYZM:
return fun(getAt<CoordinateXYZM>(i));
783 default:
return fun(getAt<CoordinateXY>(i));
788 void forEach(F&& fun)
const {
789 switch(getCoordinateType()) {
790 case CoordinateType::XY:
for (
const auto& c : items<CoordinateXY>()) { fun(c); }
break;
791 case CoordinateType::XYZ:
for (
const auto& c : items<Coordinate>()) { fun(c); }
break;
792 case CoordinateType::XYM:
for (
const auto& c : items<CoordinateXYM>()) { fun(c); }
break;
793 case CoordinateType::XYZM:
for (
const auto& c : items<CoordinateXYZM>()) { fun(c); }
break;
797 template<
typename T,
typename F>
798 void forEach(F&& fun)
const
800 for (std::size_t i = 0; i < size(); i++) {
806 void forEachSegment(F&& fun)
const {
807 switch(getCoordinateType()) {
808 case CoordinateType::XY: forEachSegmentImpl<CoordinateXY, F>(std::move(fun));
break;
809 case CoordinateType::XYZ: forEachSegmentImpl<Coordinate, F>(std::move(fun));
break;
810 case CoordinateType::XYM: forEachSegmentImpl<CoordinateXYM, F>(std::move(fun));
break;
811 case CoordinateType::XYZM: forEachSegmentImpl<CoordinateXYZM, F>(std::move(fun));
break;
815 template<
typename T,
typename F>
816 void forEach(std::size_t from, std::size_t to, F&& fun)
const
818 for (std::size_t i = from; i <= to; i++) {
826 using SequenceType =
typename std::conditional<std::is_const<T>::value,
const CoordinateSequence, CoordinateSequence>::type;
828 explicit Coordinates(SequenceType* seq) : m_seq(seq) {}
830 CoordinateSequenceIterator<SequenceType, T> begin() {
834 CoordinateSequenceIterator<SequenceType, T> end() {
835 return {m_seq, m_seq->getSize()};
838 CoordinateSequenceIterator<const SequenceType, typename std::add_const<T>::type>
840 return CoordinateSequenceIterator<const SequenceType, typename std::add_const<T>::type>{m_seq};
843 CoordinateSequenceIterator<const SequenceType, typename std::add_const<T>::type>
845 return CoordinateSequenceIterator<const SequenceType, typename std::add_const<T>::type>{m_seq, m_seq->getSize()};
848 CoordinateSequenceIterator<const SequenceType, typename std::add_const<T>::type>
850 return CoordinateSequenceIterator<const SequenceType, typename std::add_const<T>::type>{m_seq};
853 CoordinateSequenceIterator<const SequenceType, typename std::add_const<T>::type>
855 return CoordinateSequenceIterator<const SequenceType, typename std::add_const<T>::type>{m_seq, m_seq->getSize()};
863 Coordinates<typename std::add_const<T>::type> items()
const {
864 return Coordinates<typename std::add_const<T>::type>(
this);
868 Coordinates<T> items() {
869 return Coordinates<T>(
this);
876 return m_vect.data();
879 const double* data()
const {
880 return m_vect.data();
884 std::vector<double> m_vect;
888 mutable bool m_hasdim;
896 template<
typename T1,
typename T2>
897 void setAtImpl(
const T2& c, std::size_t pos) {
898 auto& orig = getAt<T1>(pos);
902 template<
typename CoordType,
typename F>
903 void forEachSegmentImpl(F&& fun)
const {
904 auto p0it = items<CoordType>().cbegin();
905 const auto end = items<CoordType>().end();
911 auto p1it = std::next(p0it);
913 while (p1it != end) {
920 void make_space(std::size_t pos, std::size_t n) {
921 m_vect.insert(std::next(m_vect.begin(),
static_cast<std::ptrdiff_t
>(pos * stride())),
926 std::uint8_t stride()
const {
932GEOS_DLL std::ostream& operator<< (std::ostream& os,
const CoordinateSequence& cs);
934GEOS_DLL
bool operator== (
const CoordinateSequence& s1,
const CoordinateSequence& s2);
936GEOS_DLL
bool operator!= (
const CoordinateSequence& s1,
const CoordinateSequence& s2);
The internal representation of a list of coordinates inside a Geometry.
Definition CoordinateSequence.h:56
Coordinate is the lightweight class used to store coordinates.
Definition Coordinate.h:220
An Envelope defines a rectangulare region of the 2D coordinate plane.
Definition Envelope.h:59
T & getAt(std::size_t i)
Returns a reference to Coordinate at position i.
Definition CoordinateSequence.h:268
Coordinate & operator[](std::size_t i)
Definition CoordinateSequence.h:308
void setM(std::size_t index, double m)
Definition CoordinateSequence.h:415
void toVector(std::vector< Coordinate > &coords) const
Pushes all Coordinates of this sequence into the provided vector.
double getOrdinate(std::size_t index, std::size_t ordinateIndex) const
const T & front() const
Return first Coordinate in the sequence.
Definition CoordinateSequence.h:437
void setX(std::size_t index, double x)
Definition CoordinateSequence.h:377
T & back()
Return last Coordinate in the sequence.
Definition CoordinateSequence.h:430
void getAt(std::size_t i, T &c) const
Write Coordinate at position i to given Coordinate.
Definition CoordinateSequence.h:280
const T & getAt(std::size_t i) const
Returns a read-only reference to Coordinate at position i.
Definition CoordinateSequence.h:256
T & front()
Return first Coordinate in the sequence.
Definition CoordinateSequence.h:444
double getZ(std::size_t index) const
Definition CoordinateSequence.h:354
double getX(std::size_t index) const
Definition CoordinateSequence.h:331
void setY(std::size_t index, double y)
Definition CoordinateSequence.h:388
double getY(std::size_t index) const
Definition CoordinateSequence.h:342
void setZ(std::size_t index, double z)
Definition CoordinateSequence.h:401
const Coordinate & operator[](std::size_t i) const
Definition CoordinateSequence.h:298
const T & back() const
Return last Coordinate in the sequence.
Definition CoordinateSequence.h:423
double getM(std::size_t index) const
Definition CoordinateSequence.h:366
void add(const CoordinateSequence &cs, std::size_t from, std::size_t to)
Add the portion of a CoordinateSequence between the specified indices (inclusive)
void add(const T &c, bool allowRepeated)
Definition CoordinateSequence.h:507
void add(std::size_t i, const T &coord, bool allowRepeated)
Inserts the specified coordinate at the specified position in this list.
Definition CoordinateSequence.h:554
void add(const T &c)
Definition CoordinateSequence.h:496
void add(const T &c, std::size_t pos)
Inserts the specified coordinate at the specified position in this sequence. If multiple coordinates ...
Definition CoordinateSequence.h:528
void add(const CoordinateSequence &cs, std::size_t from, std::size_t to, bool allowRepeated)
Add the portion of a CoordinateSequence between the specified indices (inclusive)
CoordinateSequence(const std::initializer_list< CoordinateXYZM > &)
static CoordinateSequence XYM(std::size_t size)
Definition CoordinateSequence.h:155
CoordinateSequence(const std::initializer_list< CoordinateXY > &)
std::unique_ptr< CoordinateSequence > clone() const
Returns a heap-allocated deep copy of this CoordinateSequence.
CoordinateSequence(std::size_t size, bool hasz, bool hasm, bool initialize=true)
static CoordinateSequence XYZM(std::size_t size)
Definition CoordinateSequence.h:146
static CoordinateSequence XYZ(std::size_t size)
Definition CoordinateSequence.h:137
static CoordinateSequence XY(std::size_t size)
Definition CoordinateSequence.h:128
CoordinateSequence(std::size_t size, std::size_t dim=0)
CoordinateSequence(const std::initializer_list< CoordinateXYM > &)
CoordinateSequence(const std::initializer_list< Coordinate > &)
void setOrdinate(std::size_t index, std::size_t ordinateIndex, double value)
void setPoints(const std::vector< Coordinate > &v)
Substitute Coordinate list with a copy of the given vector.
void setAt(const T &c, std::size_t pos)
Copy Coordinate c to position pos.
Definition CoordinateSequence.h:461
void setPoints(const std::vector< CoordinateXY > &v)
Substitute Coordinate list with a copy of the given vector.
std::size_t getSize() const
Returns the number of Coordinates.
Definition CoordinateSequence.h:178
Envelope getEnvelope() const
bool hasRepeatedOrInvalidPoints() const
Returns true if contains any NaN/Inf coordinates.
size_t size() const
Returns the number of Coordinates.
Definition CoordinateSequence.h:185
bool hasRepeatedPoints() const
Returns true if contains any two consecutive points.
void setZM(bool hasZ, bool hasM)
CoordinateType getCoordinateType() const
Definition CoordinateSequence.h:240
bool isEmpty() const
Returns true if list contains no coordinates.
Definition CoordinateSequence.h:196
bool isRing() const
Tests whether an a CoordinateSequence forms a ring, by checking length and closure....
std::size_t getDimension() const
bool equalsIdentical(const CoordinateSequence &other) const
Returns true if the two sequences are identical (pointwise equal in all dimensions,...
void reverse()
Reverse Coordinate order in given CoordinateSequence.
static void scroll(CoordinateSequence *cl, const CoordinateXY *firstCoordinate)
Scroll given CoordinateSequence so to start with given Coordinate.
const CoordinateXY * minCoordinate() const
static int increasingDirection(const CoordinateSequence &pts)
Determines which orientation of the Coordinate array is (overall) increasing.
void expandEnvelope(Envelope &env) const
static CoordinateSequence * atLeastNCoordinatesOrNothing(std::size_t n, CoordinateSequence *c)
Returns either the given CoordinateSequence if its length is greater than the given amount,...
std::size_t minCoordinateIndex() const
std::string toString() const
Get a string representation of CoordinateSequence.
static std::size_t indexOf(const CoordinateXY *coordinate, const CoordinateSequence *cl)
Return position of a Coordinate.
static bool equals(const CoordinateSequence *cl1, const CoordinateSequence *cl2)
Returns true if the two arrays are identical, both null, or pointwise equal in two dimensions.
void swap(std::size_t i, std::size_t j)
Swap the coordinates at two indices.
Basic namespace for all GEOS functionalities.
Definition geos.h:38