58 std::copy(v.begin(), v.end(), std::back_inserter(*
this));
63 std::copy(beg, end, std::back_inserter(*
this));
87 for (const_iterator i = begin(); i != end() - 1; i++) {
92 (*(i + 1)).x() - p.
x(),
93 (*(i + 1)).y() - p.
y());
97 (*(end() - 1)).x() - p.
x(),
98 (*(end() - 1)).y() - p.
y());
100 (*(begin())).x() - p.
x(),
101 (*(begin())).y() - p.
y());
103 return (!(fabs(angle) <
M_PI));
117 for (const_iterator i = begin(); i != end() - 1; i++) {
118 if (poly.
crosses(*i, *(i + 1))) {
122 if (size() > 2 && poly.
crosses(back(), front())) {
134 for (const_iterator i = begin(); i != end() - 1; i++) {
137 if (fabs(closest.
z() - (*i).z()) < zThreshold) {
143 for (const_iterator i = poly.begin(); i != poly.end() - 1; i++) {
146 if (fabs(closest.
z() - (*i).z()) < zThreshold) {
160 for (const_iterator i = begin(); i != end() - 1; i++) {
174 for (const_iterator i = begin(); i != end() - 1; i++) {
185 for (const_iterator i = begin(); i != end() - 1; i++) {
187 if (
intersects(*i, *(i + 1), p1, p2, withinDist, &x, &y, &m)) {
197 for (const_iterator i = begin(); i != end() - 1; i++) {
211 return at((
int)size() + index);
221 return at((
int)size() + index);
229 const_iterator i = begin();
230 double seenLength = 0;
232 const double nextLength = (*i).distanceTo(*(i + 1));
233 if (seenLength + nextLength > pos) {
236 seenLength += nextLength;
237 }
while (++i != end() - 1);
238 if (lateralOffset == 0 || size() < 2) {
241 return positionAtOffset(*(end() - 2), *(end() - 1), (*(end() - 2)).distanceTo(*(end() - 1)), lateralOffset);
248 const_iterator i = begin();
249 double seenLength = 0;
251 const double nextLength = (*i).distanceTo2D(*(i + 1));
252 if (seenLength + nextLength > pos) {
255 seenLength += nextLength;
256 }
while (++i != end() - 1);
266 const_iterator i = begin();
267 double seenLength = 0;
272 if (seenLength + nextLength > pos) {
275 seenLength += nextLength;
276 }
while (++i != end() - 1);
291 const_iterator i = begin();
292 double seenLength = 0;
297 if (seenLength + nextLength > pos) {
300 seenLength += nextLength;
301 }
while (++i != end() - 1);
311 if (pos < 0. || dist < pos) {
314 if (lateralOffset != 0) {
322 return p1 + (p2 - p1) * (pos / dist) + offset;
327 return p1 + (p2 - p1) * (pos / dist);
334 if (pos < 0 || dist < pos) {
337 if (lateralOffset != 0) {
342 return p1 + (p2 - p1) * (pos / dist) + offset;
347 return p1 + (p2 - p1) * (pos / dist);
354 for (const_iterator i = begin(); i != end(); i++) {
366 for (const_iterator i = begin(); i != end(); i++) {
371 return Position(x / (
double) size(), y / (
double) size(), z / (
double)size());
379 tmp.push_back(tmp[0]);
381 const int endIndex = (int)tmp.size() - 1;
385 if (tmp.
area() != 0) {
387 for (
int i = 0; i < endIndex; i++) {
388 const double z = tmp[i].x() * tmp[i + 1].y() - tmp[i + 1].x() * tmp[i].y();
390 x += (tmp[i].x() + tmp[i + 1].x()) * z;
391 y += (tmp[i].y() + tmp[i + 1].y()) * z;
398 double lengthSum = 0;
399 for (
int i = 0; i < endIndex; i++) {
400 double length = tmp[i].distanceTo(tmp[i + 1]);
401 x += (tmp[i].x() + tmp[i + 1].x()) * length / 2;
402 y += (tmp[i].y() + tmp[i + 1].y()) * length / 2;
405 if (lengthSum == 0) {
409 return Position(x / lengthSum, y / lengthSum);
417 for (
int i = 0; i < static_cast<int>(size()); i++) {
418 (*this)[i] = centroid + (((*this)[i] - centroid) * factor);
426 for (
int i = 0; i < static_cast<int>(size()); i++) {
427 (*this)[i] = centroid + (((*this)[i] - centroid) + offset);
444 for (const_iterator i = begin(); i != end() - 1; i++) {
445 len += (*i).distanceTo(*(i + 1));
454 for (const_iterator i = begin(); i != end() - 1; i++) {
455 len += (*i).distanceTo2D(*(i + 1));
469 tmp.push_back(tmp[0]);
471 const int endIndex = (int)tmp.size() - 1;
473 for (
int i = 0; i < endIndex; i++) {
474 area += tmp[i].x() * tmp[i + 1].y() - tmp[i + 1].x() * tmp[i].y();
488 for (const_iterator i = begin(); i != end() - 1; i++) {
489 if (poly.
around(*i, offset)) {
503 std::pair<PositionVector, PositionVector>
512 first.push_back((*
this)[0]);
514 const_iterator it = begin() + 1;
515 double next = first.back().distanceTo(*it);
519 first.push_back(*it);
521 next = first.back().distanceTo(*it);
523 if (fabs(where - (seen + next)) >
POSITION_EPS || it == end() - 1) {
530 first.push_back(*it);
533 for (; it != end(); it++) {
534 second.push_back(*it);
536 assert(first.size() >= 2);
537 assert(second.size() >= 2);
538 assert(first.back() == second.front());
540 return std::pair<PositionVector, PositionVector>(first, second);
546 for (PositionVector::const_iterator i = geom.begin(); i != geom.end(); i++) {
547 if (i != geom.begin()) {
564 for (
int i = 0; i < static_cast<int>(size()); i++) {
565 (*this)[i].add(xoff, yoff, zoff);
572 add(offset.
x(), offset.
y(), offset.
z());
578 for (
int i = 0; i < static_cast<int>(size()); i++) {
579 (*this)[i].mul(1, -1);
589 return atan2(p1.
x(), p1.
y()) < atan2(p2.
x(), p2.
y());
605 if (p1.
x() != p2.
x()) {
606 return p1.
x() < p2.
x();
608 return p1.
y() < p2.
y();
614 return (P1.
x() - P0.
x()) * (P2.
y() - P0.
y()) - (P2.
x() - P0.
x()) * (P1.
y() - P0.
y());
620 if (size() > 0 && v.size() > 0 && back().distanceTo(v[0]) < sameThreshold) {
621 copy(v.begin() + 1, v.end(), back_inserter(*
this));
623 copy(v.begin(), v.end(), back_inserter(*
this));
639 ret.push_back(begPos);
642 const_iterator i = begin();
644 while ((i + 1) != end()
646 seen + (*i).distanceTo(*(i + 1)) < beginOffset) {
647 seen += (*i).distanceTo(*(i + 1));
651 while ((i + 1) != end()
653 seen + (*i).distanceTo(*(i + 1)) < endOffset) {
656 seen += (*i).distanceTo(*(i + 1));
661 if (ret.size() == 1) {
662 ret.push_back(endPos);
679 ret.push_back(begPos);
682 const_iterator i = begin();
684 while ((i + 1) != end()
686 seen + (*i).distanceTo2D(*(i + 1)) < beginOffset) {
687 seen += (*i).distanceTo2D(*(i + 1));
691 while ((i + 1) != end()
693 seen + (*i).distanceTo2D(*(i + 1)) < endOffset) {
696 seen += (*i).distanceTo2D(*(i + 1));
701 if (ret.size() == 1) {
702 ret.push_back(endPos);
710 if (beginIndex < 0) {
711 beginIndex += (int)size();
714 assert(beginIndex < (
int)size());
715 assert(beginIndex + count <= (
int)size());
717 for (
int i = beginIndex; i < beginIndex + count; ++i) {
718 result.push_back((*
this)[i]);
726 return front().angleTo2D(back());
735 for (const_iterator i = begin(); i != end() - 1; i++) {
739 if (dist < minDist) {
740 nearestPos = pos + seen;
746 if (cornerDist < minDist) {
751 if (pos1 == (*(i - 1)).distanceTo2D(*i) && pos2 == 0.) {
753 minDist = cornerDist;
757 seen += (*i).distanceTo2D(*(i + 1));
773 double nearestPos = -1;
776 for (const_iterator i = begin(); i != end() - 1; i++) {
780 if (dist < minDist) {
781 nearestPos = pos + seen;
783 sign =
isLeft(*i, *(i + 1), p) >= 0 ? -1 : 1;
788 if (cornerDist < minDist) {
793 if (pos1 == (*(i - 1)).distanceTo2D(*i) && pos2 == 0.) {
795 minDist = cornerDist;
796 sign =
isLeft(*(i - 1), *i, p) >= 0 ? -1 : 1;
800 seen += (*i).distanceTo2D(*(i + 1));
802 if (nearestPos != -1) {
803 return Position(nearestPos, sign * minDist);
816 for (
int i = 0; i < (int)size(); i++) {
818 if (dist < minDist) {
830 int insertionIndex = 1;
831 for (
int i = 0; i < (int)size() - 1; i++) {
835 if (dist < minDist) {
836 insertionIndex = i + 1;
840 insert(begin() + insertionIndex, p);
841 return insertionIndex;
851 int removalIndex = 0;
852 for (
int i = 0; i < (int)size(); i++) {
854 if (dist < minDist) {
859 erase(begin() + removalIndex);
866 std::vector<double> ret;
867 for (const_iterator i = other.begin(); i != other.end() - 1; i++) {
869 copy(atSegment.begin(), atSegment.end(), back_inserter(ret));
877 std::vector<double> ret;
879 for (const_iterator i = begin(); i != end() - 1; i++) {
883 if (
intersects(p1, p2, lp1, lp2, 0., &x, &y, &m)) {
884 ret.push_back(
Position(x, y).distanceTo2D(p1) + pos);
935 for (const_reverse_iterator i = rbegin(); i != rend(); i++) {
945 return Position((beg.
y() - end.
y()) * scale, (end.
x() - beg.
x()) * scale);
959 for (
int i = 0; i < static_cast<int>(size()); i++) {
962 const Position& to = (*this)[i + 1];
964 shape.push_back(from -
sideOffset(from, to, amount));
966 }
else if (i == static_cast<int>(size()) - 1) {
967 const Position& from = (*this)[i - 1];
970 shape.push_back(to -
sideOffset(from, to, amount));
973 const Position& from = (*this)[i - 1];
975 const Position& to = (*this)[i + 1];
978 const double extrapolateDev = fromMe[1].distanceTo2D(to);
981 shape.push_back(me -
sideOffset(from, to, amount));
986 shape.push_back(fromMe[1]);
997 shape.push_back(meNew);
1000 shape.back().set(shape.back().x(), shape.back().y(), me.
z());
1009 assert((
int)size() > pos + 1);
1010 return (*
this)[pos].angleTo2D((*
this)[pos + 1]);
1016 if (size() == 0 || (*
this)[0] == back()) {
1019 push_back((*
this)[0]);
1025 std::vector<double> ret;
1027 for (i = begin(); i != end(); i++) {
1028 const double dist = s.
distance2D(*i, perpendicular);
1030 ret.push_back(dist);
1033 for (i = s.begin(); i != s.end(); i++) {
1034 const double dist =
distance2D(*i, perpendicular);
1036 ret.push_back(dist);
1047 }
else if (size() == 1) {
1048 return front().distanceTo(p);
1077 if (at == begin()) {
1079 }
else if (at == end()) {
1091 return size() >= 2 && (*this)[0] == back();
1098 iterator last = begin();
1099 for (iterator i = begin() + 1; i != end() && (!assertLength || size() > 2);) {
1100 if (last->almostSame(*i, minDist)) {
1113 return static_cast<vp>(*this) ==
static_cast<vp>(v2);
1119 return static_cast<vp>(*this) !=
static_cast<vp>(v2);
1125 WRITE_ERROR(
"Trying to substract PositionVectors of different lengths.");
1129 auto i2 = v2.begin();
1130 while (i1 != end()) {
1139 WRITE_ERROR(
"Trying to substract PositionVectors of different lengths.");
1143 auto i2 = v2.begin();
1144 while (i1 != end()) {
1155 for (const_iterator i = begin(); i != end() - 1; i++) {
1156 if ((*i).z() != (*(i + 1)).z()) {
1166 const double eps = std::numeric_limits<double>::epsilon();
1167 const double denominator = (p22.
y() - p21.
y()) * (p12.
x() - p11.
x()) - (p22.
x() - p21.
x()) * (p12.
y() - p11.
y());
1168 const double numera = (p22.
x() - p21.
x()) * (p11.
y() - p21.
y()) - (p22.
y() - p21.
y()) * (p11.
x() - p21.
x());
1169 const double numerb = (p12.
x() - p11.
x()) * (p11.
y() - p21.
y()) - (p12.
y() - p11.
y()) * (p11.
x() - p21.
x());
1171 if (fabs(numera) < eps && fabs(numerb) < eps && fabs(denominator) < eps) {
1177 if (p11.
x() != p12.
x()) {
1178 a1 = p11.
x() < p12.
x() ? p11.
x() : p12.
x();
1179 a2 = p11.
x() < p12.
x() ? p12.
x() : p11.
x();
1180 a3 = p21.
x() < p22.
x() ? p21.
x() : p22.
x();
1181 a4 = p21.
x() < p22.
x() ? p22.
x() : p21.
x();
1183 a1 = p11.
y() < p12.
y() ? p11.
y() : p12.
y();
1184 a2 = p11.
y() < p12.
y() ? p12.
y() : p11.
y();
1185 a3 = p21.
y() < p22.
y() ? p21.
y() : p22.
y();
1186 a4 = p21.
y() < p22.
y() ? p22.
y() : p21.
y();
1188 if (a1 <= a3 && a3 <= a2) {
1195 if (a3 <= a1 && a1 <= a4) {
1204 if (p11.
x() != p12.
x()) {
1205 *mu = (a - p11.
x()) / (p12.
x() - p11.
x());
1207 *y = p11.
y() + (*mu) * (p12.
y() - p11.
y());
1211 if (p12.
y() == p11.
y()) {
1214 *mu = (a - p11.
y()) / (p12.
y() - p11.
y());
1223 if (fabs(denominator) < eps) {
1227 double mua = numera / denominator;
1229 if (fabs(p12.
x() - p22.
x()) < eps && fabs(p12.
y() - p22.
y()) < eps) {
1232 const double offseta = withinDist / p11.
distanceTo2D(p12);
1233 const double offsetb = withinDist / p21.
distanceTo2D(p22);
1234 const double mub = numerb / denominator;
1235 if (mua < -offseta || mua > 1 + offseta || mub < -offsetb || mub > 1 + offsetb) {
1240 *x = p11.
x() + mua * (p12.
x() - p11.
x());
1241 *y = p11.
y() + mua * (p12.
y() - p11.
y());
1250 const double s = sin(angle);
1251 const double c = cos(angle);
1252 for (
int i = 0; i < (int)size(); i++) {
1253 const double x = (*this)[i].x();
1254 const double y = (*this)[i].y();
1255 const double z = (*this)[i].z();
1256 const double xnew = x * c - y * s;
1257 const double ynew = x * s + y * c;
1258 (*this)[i].set(xnew, ynew, z);
1266 bool changed =
true;
1267 while (changed && result.size() > 3) {
1269 for (
int i = 0; i < (int)result.size(); i++) {
1271 const Position& p2 = result[(i + 2) % result.size()];
1272 const int middleIndex = (i + 1) % result.size();
1273 const Position& p0 = result[middleIndex];
1275 const double triangleArea2 = fabs((p2.
y() - p1.
y()) * p0.
x() - (p2.
x() - p1.
x()) * p0.
y() + p2.
x() * p1.
y() - p2.
y() * p1.
x());
1279 result.erase(result.begin() + middleIndex);
1300 result.push_back(base);
1302 result.push_back(tmp[closestIndex]);
1303 }
else if (before) {
1305 if (closestIndex > 0) {
1306 result.push_back(tmp[closestIndex - 1]);
1308 result.push_back(tmp[1]);
1312 if (closestIndex < (
int)size() - 1) {
1313 result.push_back(tmp[closestIndex + 1]);
1315 result.push_back(tmp[-1]);
1320 result.
add(base * -1);
1330 const double z0 = (*this)[0].z();
1332 const double dz = (*this)[1].z() - z0;
1334 if (size() > 2 && dz != 0) {
1344 const double dz2 = result[iLast].z() - z0;
1346 for (
int i = 1; i < iLast; ++i) {
1347 seen += result[i].distanceTo2D(result[i - 1]);
1348 result[i].set(result[i].x(), result[i].y(), z0 + dz2 * seen / dist2);
1358 if (index < 0 || index >= (
int)size()) {
1362 for (
int i = 1; i <= index; ++i) {
1363 seen += (*this)[i].distanceTo2D((*
this)[i - 1]);
1372 for (
int i = 1; i < (int)size(); ++i) {
1373 const Position& p1 = (*this)[i - 1];
clase for increasing Sorter
double z() const
Returns the z-position.
bool hasElevation() const
return whether two positions differ in z-coordinate
double distanceTo2D(const Position &p2) const
returns the euclidean distance in the x-y-plane
void append(const PositionVector &v, double sameThreshold=2.0)
void sortAsPolyCWByAngle()
short as polygon CV by angle
Position intersectionPosition2D(const Position &p1, const Position &p2, const double withinDist=0.) const
Returns the position of the intersection.
void add(const Position &pos)
Adds the given position to this one.
virtual bool around(const Position &p, double offset=0) const =0
bool around(const Position &p, double offset=0) const
Returns the information whether the position vector describes a polygon lying around the given point...
double nearest_offset_to_point2D(const Position &p, bool perpendicular=true) const
return the nearest offest to point 2D
friend std::ostream & operator<<(std::ostream &os, const PositionVector &geom)
bool operator!=(const PositionVector &v2) const
comparing operation
double x() const
Returns the x-position.
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 ...
Position getCentroid() const
Returns the centroid (closes the polygon if unclosed)
bool intersects(const Position &p1, const Position &p2) const
Returns the information whether this list of points interesects the given line.
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) ...
double slopeDegreeAtOffset(double pos) const
Returns the slope at the given length.
PositionVector getSubpartByIndex(int beginIndex, int count) const
get subpart of a position vector using index and a cout
PositionVector getSubpart2D(double beginOffset, double endOffset) const
get subpart of a position vector in two dimensions (Z is ignored)
PositionVector getOrthogonal(const Position &p, double extend, bool before, double length=1.0) const
return orthogonal through p (extending this vector if necessary)
void insert_noDoublePos(const std::vector< Position >::iterator &at, const Position &p)
insert in front a non double position
PositionVector operator-(const PositionVector &v2) const
substracts two vectors (requires vectors of the same length)
bool isClosed() const
check if PositionVector is closed
const Position & operator[](int index) const
returns the constat position at the given index !!! exceptions?
A class that stores a 2D geometrical boundary.
#define WRITE_WARNING(msg)
bool overlapsWith(const AbstractPoly &poly, double offset=0) const
Returns the information whether the given polygon overlaps with this.
static double legacyDegree(const double angle, const bool positive=false)
PositionVector reverse() const
reverse position vector
~PositionVector()
Destructor.
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...
double isLeft(const Position &P0, const Position &P1, const Position &P2) const
get left
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
double area() const
Returns the area (0 for non-closed)
void removeDoublePoints(double minDist=POSITION_EPS, bool assertLength=false)
Removes positions if too near.
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
static double nearest_offset_on_line_to_point2D(const Position &lineStart, const Position &lineEnd, const Position &p, bool perpendicular=true)
PositionVector simplified() const
return the same shape with intermediate colinear points removed
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
A point in 2D or 3D with translation and scaling methods.
std::vector< Position > vp
vector of position
double rotationDegreeAtOffset(double pos) const
Returns the rotation at the given length.
int indexOfClosest(const Position &p) const
index of the closest position to p
int operator()(const Position &p1, const Position &p2) const
comparing operation for sort
double y() const
Returns the y-position.
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...
virtual bool crosses(const Position &p1, const Position &p2) const =0
double length() const
Returns the length.
bool partialWithin(const AbstractPoly &poly, double offset=0) const
Returns the information whether this polygon lies partially within the given polygon.
PositionVector operator+(const PositionVector &v2) const
adds two vectors (requires vectors of the same length)
Position positionAtOffset2D(double pos, double lateralOffset=0) const
Returns the position at the given length.
int insertAtClosest(const Position &p)
inserts p between the two closest positions and returns the insertion index
as_poly_cw_sorter()
constructor
static const double INVALID_OFFSET
a value to signify offsets outside the range of [0, Line.length()]
void sortByIncreasingXY()
shory by increasing X-Y Psitions
void move2side(double amount)
move position vector to side using certain ammount
double distanceTo(const Position &p2) const
returns the euclidean distance in 3 dimension
bool operator==(const PositionVector &v2) const
comparing operation
double getMaxGrade() const
return the maximum grade of all segments as a fraction of zRange/length2D
bool almostSame(const Position &p2, double maxDiv=POSITION_EPS) const
checki if two position is almost the sme as other
PositionVector()
Constructor. Creates an empty position vector.
PositionVector smoothedZFront(double dist=std::numeric_limits< double >::max()) const
returned vector that is smoothed at the front (within dist)
void rotate2D(double angle)
double rotationAtOffset(double pos) const
Returns the rotation at the given length.
void extrapolate(const double val, const bool onlyFirst=false, const bool onlyLast=false)
extrapolate position vector
double length2D() const
Returns the length.
Position positionAtOffset(double pos, double lateralOffset=0) const
Returns the position at the given length.
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
Position getLineCenter() const
get line center
PositionVector getSubpart(double beginOffset, double endOffset) const
get subpart of a position vector
std::pair< PositionVector, PositionVector > splitAt(double where) const
Returns the two lists made when this list vector is splitted at the given point.
void push_back_noDoublePos(const Position &p)
insert in back a non double position
int operator()(const Position &p1, const Position &p2) const
comparing operation
double offsetAtIndex2D(int index) const
return the offset at the given index
virtual bool partialWithin(const AbstractPoly &poly, double offset=0) const =0
Position getPolygonCenter() const
Returns the arithmetic of all corner points.
void add(double x, double y, double z=0)
Makes the boundary include the given coordinate.
void add(double xoff, double yoff, double zoff)
void closePolygon()
ensures that the last position equals the first
Boundary getBoxBoundary() const
Returns a boundary enclosing this list of lines.
increasing_x_y_sorter()
constructor
bool crosses(const Position &p1, const Position &p2) const
int removeClosest(const Position &p)
removes the point closest to p and return the removal index
double angleAt2D(int pos) const
get angle in certain position of position vector
double angleTo2D(const Position &other) const
returns the angle in the plane of the vector pointing from here to the other position ...
double beginEndAngle() const
returns the angle in radians of the line connecting the first and the last position ...
static const Position INVALID
used to indicate that a position is valid
Position transformToVectorCoordinates(const Position &p, bool extend=false) const
return position p within the length-wise coordinate system defined by this position vector...
void sub(double dx, double dy)
Substracts the given position from this one.