59 std::copy(v.begin(), v.end(), std::back_inserter(*
this));
64 std::copy(beg, end, std::back_inserter(*
this));
85 for (const_iterator i = begin(); i != end() - 1; i++) {
90 (*(i + 1)).x() - p.
x(),
91 (*(i + 1)).y() - p.
y());
95 (*(end() - 1)).x() - p.
x(),
96 (*(end() - 1)).y() - p.
y());
98 (*(begin())).x() - p.
x(),
99 (*(begin())).y() - p.
y());
101 return (!(fabs(angle) <
M_PI));
107 for (const_iterator i = begin(); i != end() - 1; i++) {
108 if (poly.
around(*i, offset)) {
120 for (const_iterator i = begin(); i != end() - 1; i++) {
123 if (fabs(closest.
z() - (*i).z()) < zThreshold) {
129 for (const_iterator i = poly.begin(); i != poly.end() - 1; i++) {
132 if (fabs(closest.
z() - (*i).z()) < zThreshold) {
146 for (const_iterator i = begin(); i != end() - 1; i++) {
160 for (const_iterator i = begin(); i != end() - 1; i++) {
171 for (const_iterator i = begin(); i != end() - 1; i++) {
173 if (
intersects(*i, *(i + 1), p1, p2, withinDist, &x, &y, &m)) {
183 for (const_iterator i = begin(); i != end() - 1; i++) {
197 return at((
int)size() + index);
207 return at((
int)size() + index);
215 const_iterator i = begin();
216 double seenLength = 0;
218 const double nextLength = (*i).distanceTo(*(i + 1));
219 if (seenLength + nextLength > pos) {
222 seenLength += nextLength;
223 }
while (++i != end() - 1);
224 if (lateralOffset == 0 || size() < 2) {
227 return positionAtOffset(*(end() - 2), *(end() - 1), (*(end() - 2)).distanceTo(*(end() - 1)), lateralOffset);
234 const_iterator i = begin();
235 double seenLength = 0;
237 const double nextLength = (*i).distanceTo2D(*(i + 1));
238 if (seenLength + nextLength > pos) {
241 seenLength += nextLength;
242 }
while (++i != end() - 1);
252 const_iterator i = begin();
253 double seenLength = 0;
258 if (seenLength + nextLength > pos) {
261 seenLength += nextLength;
262 }
while (++i != end() - 1);
277 const_iterator i = begin();
278 double seenLength = 0;
283 if (seenLength + nextLength > pos) {
286 seenLength += nextLength;
287 }
while (++i != end() - 1);
297 if (pos < 0 || dist < pos) {
300 if (lateralOffset != 0) {
305 return p1 + (p2 - p1) * (pos / dist) + offset;
310 return p1 + (p2 - p1) * (pos / dist);
317 if (pos < 0 || dist < pos) {
320 if (lateralOffset != 0) {
325 return p1 + (p2 - p1) * (pos / dist) + offset;
330 return p1 + (p2 - p1) * (pos / dist);
337 for (const_iterator i = begin(); i != end(); i++) {
349 for (const_iterator i = begin(); i != end(); i++) {
354 return Position(x / (
double) size(), y / (
double) size(), z / (
double)size());
362 tmp.push_back(tmp[0]);
364 const int endIndex = (int)tmp.size() - 1;
368 if (tmp.
area() != 0) {
370 for (
int i = 0; i < endIndex; i++) {
371 const double z = tmp[i].x() * tmp[i + 1].y() - tmp[i + 1].x() * tmp[i].y();
373 x += (tmp[i].x() + tmp[i + 1].x()) * z;
374 y += (tmp[i].y() + tmp[i + 1].y()) * z;
381 double lengthSum = 0;
382 for (
int i = 0; i < endIndex; i++) {
383 double length = tmp[i].distanceTo(tmp[i + 1]);
384 x += (tmp[i].x() + tmp[i + 1].x()) * length / 2;
385 y += (tmp[i].y() + tmp[i + 1].y()) * length / 2;
388 if (lengthSum == 0) {
392 return Position(x / lengthSum, y / lengthSum);
400 for (
int i = 0; i < static_cast<int>(size()); i++) {
401 (*this)[i] = centroid + (((*this)[i] - centroid) * factor);
409 for (
int i = 0; i < static_cast<int>(size()); i++) {
410 (*this)[i] = centroid + (((*this)[i] - centroid) + offset);
427 for (const_iterator i = begin(); i != end() - 1; i++) {
428 len += (*i).distanceTo(*(i + 1));
437 for (const_iterator i = begin(); i != end() - 1; i++) {
438 len += (*i).distanceTo2D(*(i + 1));
452 tmp.push_back(tmp[0]);
454 const int endIndex = (int)tmp.size() - 1;
456 for (
int i = 0; i < endIndex; i++) {
457 area += tmp[i].x() * tmp[i + 1].y() - tmp[i + 1].x() * tmp[i].y();
468 for (const_iterator i = begin(); i != end() - 1; i++) {
469 if (poly.
around(*i, offset)) {
483 std::pair<PositionVector, PositionVector>
492 first.push_back((*
this)[0]);
494 const_iterator it = begin() + 1;
495 double next = first.back().distanceTo(*it);
499 first.push_back(*it);
501 next = first.back().distanceTo(*it);
503 if (fabs(where - (seen + next)) >
POSITION_EPS || it == end() - 1) {
510 first.push_back(*it);
513 for (; it != end(); it++) {
514 second.push_back(*it);
516 assert(first.size() >= 2);
517 assert(second.size() >= 2);
518 assert(first.back() == second.front());
520 return std::pair<PositionVector, PositionVector>(first, second);
526 for (PositionVector::const_iterator i = geom.begin(); i != geom.end(); i++) {
527 if (i != geom.begin()) {
544 for (
int i = 0; i < static_cast<int>(size()); i++) {
545 (*this)[i].add(xoff, yoff, zoff);
552 add(offset.
x(), offset.
y(), offset.
z());
558 for (
int i = 0; i < static_cast<int>(size()); i++) {
559 (*this)[i].mul(1, -1);
569 return atan2(p1.
x(), p1.
y()) < atan2(p2.
x(), p2.
y());
585 if (p1.
x() != p2.
x()) {
586 return p1.
x() < p2.
x();
588 return p1.
y() < p2.
y();
594 return (P1.
x() - P0.
x()) * (P2.
y() - P0.
y()) - (P2.
x() - P0.
x()) * (P1.
y() - P0.
y());
608 if (size() > 0 && v.size() > 0 && back().distanceTo(v[0]) < sameThreshold) {
609 copy(v.begin() + 1, v.end(), back_inserter(*
this));
611 copy(v.begin(), v.end(), back_inserter(*
this));
627 ret.push_back(begPos);
630 const_iterator i = begin();
632 while ((i + 1) != end()
634 seen + (*i).distanceTo(*(i + 1)) < beginOffset) {
635 seen += (*i).distanceTo(*(i + 1));
639 while ((i + 1) != end()
641 seen + (*i).distanceTo(*(i + 1)) < endOffset) {
644 seen += (*i).distanceTo(*(i + 1));
649 if (ret.size() == 1) {
650 ret.push_back(endPos);
667 ret.push_back(begPos);
670 const_iterator i = begin();
672 while ((i + 1) != end()
674 seen + (*i).distanceTo2D(*(i + 1)) < beginOffset) {
675 seen += (*i).distanceTo2D(*(i + 1));
679 while ((i + 1) != end()
681 seen + (*i).distanceTo2D(*(i + 1)) < endOffset) {
684 seen += (*i).distanceTo2D(*(i + 1));
689 if (ret.size() == 1) {
690 ret.push_back(endPos);
698 if (beginIndex < 0) {
699 beginIndex += (int)size();
702 assert(beginIndex < (
int)size());
703 assert(beginIndex + count <= (
int)size());
705 for (
int i = beginIndex; i < beginIndex + count; ++i) {
706 result.push_back((*
this)[i]);
714 return front().angleTo2D(back());
723 for (const_iterator i = begin(); i != end() - 1; i++) {
727 if (dist < minDist) {
728 nearestPos = pos + seen;
734 if (cornerDist < minDist) {
739 if (pos1 == (*(i - 1)).distanceTo2D(*i) && pos2 == 0.) {
741 minDist = cornerDist;
745 seen += (*i).distanceTo2D(*(i + 1));
761 double nearestPos = -1;
764 for (const_iterator i = begin(); i != end() - 1; i++) {
768 if (dist < minDist) {
769 nearestPos = pos + seen;
771 sign =
isLeft(*i, *(i + 1), p) >= 0 ? -1 : 1;
776 if (cornerDist < minDist) {
781 if (pos1 == (*(i - 1)).distanceTo2D(*i) && pos2 == 0.) {
783 minDist = cornerDist;
784 sign =
isLeft(*(i - 1), *i, p) >= 0 ? -1 : 1;
788 seen += (*i).distanceTo2D(*(i + 1));
790 if (nearestPos != -1) {
791 return Position(nearestPos, sign * minDist);
804 for (
int i = 0; i < (int)size(); i++) {
806 if (dist < minDist) {
818 int insertionIndex = 1;
819 for (
int i = 0; i < (int)size() - 1; i++) {
823 if (dist < minDist) {
824 insertionIndex = i + 1;
828 insert(begin() + insertionIndex, p);
829 return insertionIndex;
839 int removalIndex = 0;
840 for (
int i = 0; i < (int)size(); i++) {
842 if (dist < minDist) {
847 erase(begin() + removalIndex);
854 std::vector<double> ret;
855 for (const_iterator i = other.begin(); i != other.end() - 1; i++) {
857 copy(atSegment.begin(), atSegment.end(), back_inserter(ret));
865 std::vector<double> ret;
867 for (const_iterator i = begin(); i != end() - 1; i++) {
871 if (
intersects(p1, p2, lp1, lp2, 0., &x, &y, &m)) {
872 ret.push_back(
Position(x, y).distanceTo2D(p1) + pos);
923 for (const_reverse_iterator i = rbegin(); i != rend(); i++) {
933 return Position((beg.
y() - end.
y()) * scale, (end.
x() - beg.
x()) * scale);
946 for (
int i = 0; i < static_cast<int>(size()); i++) {
949 const Position& to = (*this)[i + 1];
950 shape.push_back(from -
sideOffset(from, to, amount));
951 }
else if (i == static_cast<int>(size()) - 1) {
952 const Position& from = (*this)[i - 1];
954 shape.push_back(to -
sideOffset(from, to, amount));
956 const Position& from = (*this)[i - 1];
958 const Position& to = (*this)[i + 1];
961 const double extrapolateDev = fromMe[1].distanceTo2D(to);
964 shape.push_back(me -
sideOffset(from, to, amount));
969 shape.push_back(fromMe[1]);
980 shape.push_back(meNew);
983 shape.back().set(shape.back().x(), shape.back().y(), me.
z());
992 assert((
int)size() > pos + 1);
993 return (*
this)[pos].angleTo2D((*
this)[pos + 1]);
999 if (size() == 0 || (*
this)[0] == back()) {
1002 push_back((*
this)[0]);
1008 std::vector<double> ret;
1010 for (i = begin(); i != end(); i++) {
1011 const double dist = s.
distance2D(*i, perpendicular);
1013 ret.push_back(dist);
1016 for (i = s.begin(); i != s.end(); i++) {
1017 const double dist =
distance2D(*i, perpendicular);
1019 ret.push_back(dist);
1030 }
else if (size() == 1) {
1031 return front().distanceTo(p);
1060 return size() >= 2 && (*this)[0] == back();
1067 iterator last = begin();
1068 for (iterator i = begin() + 1; i != end() && (!assertLength || size() > 2);) {
1069 if (last->almostSame(*i, minDist)) {
1082 if (size() == v2.size()) {
1083 for (
int i = 0; i < (int)size(); i++) {
1084 if ((*
this)[i] != v2[i]) {
1100 for (const_iterator i = begin(); i != end() - 1; i++) {
1101 if ((*i).z() != (*(i + 1)).z()) {
1111 const double eps = std::numeric_limits<double>::epsilon();
1112 const double denominator = (p22.
y() - p21.
y()) * (p12.
x() - p11.
x()) - (p22.
x() - p21.
x()) * (p12.
y() - p11.
y());
1113 const double numera = (p22.
x() - p21.
x()) * (p11.
y() - p21.
y()) - (p22.
y() - p21.
y()) * (p11.
x() - p21.
x());
1114 const double numerb = (p12.
x() - p11.
x()) * (p11.
y() - p21.
y()) - (p12.
y() - p11.
y()) * (p11.
x() - p21.
x());
1116 if (fabs(numera) < eps && fabs(numerb) < eps && fabs(denominator) < eps) {
1122 if (p11.
x() != p12.
x()) {
1123 a1 = p11.
x() < p12.
x() ? p11.
x() : p12.
x();
1124 a2 = p11.
x() < p12.
x() ? p12.
x() : p11.
x();
1125 a3 = p21.
x() < p22.
x() ? p21.
x() : p22.
x();
1126 a4 = p21.
x() < p22.
x() ? p22.
x() : p21.
x();
1128 a1 = p11.
y() < p12.
y() ? p11.
y() : p12.
y();
1129 a2 = p11.
y() < p12.
y() ? p12.
y() : p11.
y();
1130 a3 = p21.
y() < p22.
y() ? p21.
y() : p22.
y();
1131 a4 = p21.
y() < p22.
y() ? p22.
y() : p21.
y();
1133 if (a1 <= a3 && a3 <= a2) {
1140 if (a3 <= a1 && a1 <= a4) {
1149 if (p11.
x() != p12.
x()) {
1150 *mu = (a - p11.
x()) / (p12.
x() - p11.
x());
1152 *y = p11.
y() + (*mu) * (p12.
y() - p11.
y());
1156 if (p12.
y() == p11.
y()) {
1159 *mu = (a - p11.
y()) / (p12.
y() - p11.
y());
1168 if (fabs(denominator) < eps) {
1172 double mua = numera / denominator;
1174 if (fabs(p12.
x() - p22.
x()) < eps && fabs(p12.
y() - p22.
y()) < eps) {
1177 const double offseta = withinDist / p11.
distanceTo2D(p12);
1178 const double offsetb = withinDist / p21.
distanceTo2D(p22);
1179 const double mub = numerb / denominator;
1180 if (mua < -offseta || mua > 1 + offseta || mub < -offsetb || mub > 1 + offsetb) {
1185 *x = p11.
x() + mua * (p12.
x() - p11.
x());
1186 *y = p11.
y() + mua * (p12.
y() - p11.
y());
1195 const double s = sin(angle);
1196 const double c = cos(angle);
1197 for (
int i = 0; i < (int)size(); i++) {
1198 const double x = (*this)[i].x();
1199 const double y = (*this)[i].y();
1200 const double z = (*this)[i].z();
1201 const double xnew = x * c - y * s;
1202 const double ynew = x * s + y * c;
1203 (*this)[i].set(xnew, ynew, z);
1211 bool changed =
true;
1212 while (changed && result.size() > 3) {
1214 for (
int i = 0; i < (int)result.size(); i++) {
1216 const Position& p2 = result[(i + 2) % result.size()];
1217 const int middleIndex = (i + 1) % result.size();
1218 const Position& p0 = result[middleIndex];
1220 const double triangleArea2 = fabs((p2.
y() - p1.
y()) * p0.
x() - (p2.
x() - p1.
x()) * p0.
y() + p2.
x() * p1.
y() - p2.
y() * p1.
x());
1224 result.erase(result.begin() + middleIndex);
1245 result.push_back(base);
1247 result.push_back(tmp[closestIndex]);
1248 }
else if (before) {
1250 if (closestIndex > 0) {
1251 result.push_back(tmp[closestIndex - 1]);
1253 result.push_back(tmp[1]);
1257 if (closestIndex < (
int)size() - 1) {
1258 result.push_back(tmp[closestIndex + 1]);
1260 result.push_back(tmp[-1]);
1265 result.
add(base * -1);
1275 const double z0 = (*this)[0].z();
1277 const double dz = (*this)[1].z() - z0;
1279 if (size() > 2 && dz != 0) {
1289 const double dz2 = result[iLast].z() - z0;
1291 for (
int i = 1; i < iLast; ++i) {
1292 seen += result[i].distanceTo2D(result[i - 1]);
1293 result[i].set(result[i].x(), result[i].y(), z0 + dz2 * seen / dist2);
1303 if (index < 0 || index >= (
int)size()) {
1307 for (
int i = 1; i <= index; ++i) {
1308 seen += (*this)[i].distanceTo2D((*
this)[i - 1]);
1317 for (
int i = 1; i < (int)size(); ++i) {
1318 const Position& p1 = (*this)[i - 1];
bool around(const Position &p, double offset=0) const
Returns the information whether the position vector describes a polygon lying around the given point...
clase for increasing Sorter
double rotationDegreeAtOffset(double pos) const
Returns the rotation at the given length.
int operator()(const Position &p1, const Position &p2) const
comparing operation
bool almostSame(const Position &p2, double maxDiv=POSITION_EPS) const
checki if two position is almost the sme as other
double length2D() const
Returns the length.
void append(const PositionVector &v, double sameThreshold=2.0)
PositionVector getOrthogonal(const Position &p, double extend, bool before, double length=1.0) const
return orthogonal through p (extending this vector if necessary)
double z() const
Returns the z-position.
void sortAsPolyCWByAngle()
short as polygon CV by angle
double distance2D(const Position &p, bool perpendicular=false) const
closest 2D-distance to point p (or -1 if perpendicular is true and the point is beyond this vector) ...
void add(const Position &pos)
Adds the given position to this one.
int indexOfClosest(const Position &p) const
index of the closest position to p
double distanceTo2D(const Position &p2) const
returns the euclidean distance in the x-y-plane
friend std::ostream & operator<<(std::ostream &os, const PositionVector &geom)
Position positionAtOffset2D(double pos, double lateralOffset=0) const
Returns the position at the given length.
Position intersectionPosition2D(const Position &p1, const Position &p2, const double withinDist=0.) const
Returns the position of the intersection.
double y() const
Returns the y-position.
double x() const
Returns the x-position.
double angleTo2D(const Position &other) const
returns the angle in the plane of the vector pointing from here to the other position ...
Position getCentroid() const
Returns the centroid (closes the polygon if unclosed)
bool partialWithin(const AbstractPoly &poly, double offset=0) const
Returns the information whether this polygon lies partially within the given polygon.
PositionVector reverse() const
reverse position vector
double rotationAtOffset(double pos) const
Returns the rotation at the given length.
std::vector< double > distances(const PositionVector &s, bool perpendicular=false) const
distances of all my points to s and all of s points to myself
bool hasElevation() const
return whether two positions differ in z-coordinate
std::pair< PositionVector, PositionVector > splitAt(double where) const
Returns the two lists made when this list vector is splitted at the given point.
A class that stores a 2D geometrical boundary.
#define WRITE_WARNING(msg)
Position getLineCenter() const
get line center
static double legacyDegree(const double angle, const bool positive=false)
double area() const
Returns the area (0 for non-closed)
~PositionVector()
Destructor.
void extrapolate2D(const double val, const bool onlyFirst=false)
extrapolate position vector in two dimensions (Z is ignored)
void push_front_noDoublePos(const Position &p)
insert in front a non double position
void removeDoublePoints(double minDist=POSITION_EPS, bool assertLength=false)
Removes positions if too near.
static double nearest_offset_on_line_to_point2D(const Position &lineStart, const Position &lineEnd, const Position &p, bool perpendicular=true)
std::string toString(const T &t, std::streamsize accuracy=gPrecision)
void scaleAbsolute(double offset)
enlarges/shrinks the polygon by an absolute offset based at the centroid
bool operator==(const PositionVector &v2) const
comparing operation
double beginEndAngle() const
returns the angle in radians of the line connecting the first and the last position ...
A point in 2D or 3D with translation and scaling methods.
Position getPolygonCenter() const
Returns the arithmetic of all corner points.
int operator()(const Position &p1, const Position &p2) const
comparing operation for sort
virtual bool around(const Position &p, double offset=0) const =0
static double angle2D(const Position &p1, const Position &p2)
Returns the angle between two vectors on a plane The angle is from vector 1 to vector 2...
std::vector< double > intersectsAtLengths2D(const PositionVector &other) const
For all intersections between this vector and other, return the 2D-length of the subvector from this ...
const Position & operator[](int index) const
returns the constat position at the given index !!! exceptions?
int insertAtClosest(const Position &p)
inserts p between the two closest positions and returns the insertion index
PositionVector getSubpart(double beginOffset, double endOffset) const
get subpart of a position vector
bool overlapsWith(const AbstractPoly &poly, double offset=0) const
Returns the information whether the given polygon overlaps with this.
as_poly_cw_sorter()
constructor
PositionVector smoothedZFront(double dist=std::numeric_limits< double >::max()) const
returned vector that is smoothed at the front (within dist)
static const double INVALID_OFFSET
a value to signify offsets outside the range of [0, Line.length()]
PositionVector getSubpartByIndex(int beginIndex, int count) const
get subpart of a position vector using index and a cout
void sortByIncreasingXY()
shory by increasing X-Y Psitions
void move2side(double amount)
move position vector to side using certain ammount
PositionVector simplified() const
return the same shape with intermediate colinear points removed
double slopeDegreeAtOffset(double pos) const
Returns the slope at the given length.
PositionVector()
Constructor. Creates an empty position vector.
double isLeft(const Position &P0, const Position &P1, const Position &P2) const
get left
PositionVector getSubpart2D(double beginOffset, double endOffset) const
get subpart of a position vector in two dimensions (Z is ignored)
void rotate2D(double angle)
void extrapolate(const double val, const bool onlyFirst=false, const bool onlyLast=false)
extrapolate position vector
PositionVector simpleHull_2D(const PositionVector &V)
double length() const
Returns the length.
bool isClosed() const
check if PositionVector is closed
static Position sideOffset(const Position &beg, const Position &end, const double amount)
get a side position of position vector using a offset
void scaleRelative(double factor)
enlarges/shrinks the polygon by a factor based at the centroid
double angleAt2D(int pos) const
get angle in certain position of position vector
PositionVector convexHull() const
double offsetAtIndex2D(int index) const
return the offset at the given index
double distanceTo(const Position &p2) const
returns the euclidean distance in 3 dimension
Boundary getBoxBoundary() const
Returns a boundary enclosing this list of lines.
void push_back_noDoublePos(const Position &p)
insert in back a non double position
double getMaxGrade() const
return the maximum grade of all segments as a fraction of zRange/length2D
bool crosses(const Position &p1, const Position &p2) const
double getOverlapWith(const PositionVector &poly, double zThreshold) const
Returns the maximum overlaps between this and the given polygon (when not separated by at least zThre...
void add(double x, double y, double z=0)
Makes the boundary include the given coordinate.
void add(double xoff, double yoff, double zoff)
double nearest_offset_to_point2D(const Position &p, bool perpendicular=true) const
return the nearest offest to point 2D
void closePolygon()
ensures that the last position equals the first
Position positionAtOffset(double pos, double lateralOffset=0) const
Returns the position at the given length.
increasing_x_y_sorter()
constructor
int removeClosest(const Position &p)
removes the point closest to p and return the removal index
Position transformToVectorCoordinates(const Position &p, bool extend=false) const
return position p within the length-wise coordinate system defined by this position vector...
bool intersects(const Position &p1, const Position &p2) const
Returns the information whether this list of points interesects the given line.
static const Position INVALID
used to indicate that a position is valid
void sub(double dx, double dy)
Substracts the given position from this one.