57 std::copy(v.begin(), v.end(), std::back_inserter(*
this));
62 std::copy(beg, end, std::back_inserter(*
this));
87 for (const_iterator i = begin(); i != (end() - 1); i++) {
93 (i + 1)->y() - p.
y());
98 (end() - 1)->x() - p.
x(),
99 (end() - 1)->y() - p.
y());
101 begin()->x() - p.
x(),
102 begin()->y() - p.
y());
105 return (!(fabs(angle) <
M_PI));
119 for (const_iterator i = begin(); i != end() - 1; i++) {
120 if (poly.
crosses(*i, *(i + 1))) {
124 if (size() > 2 && poly.
crosses(back(), front())) {
135 if ((size() == 0) || (poly.size() == 0)) {
139 for (const_iterator i = begin(); i != end() - 1; i++) {
142 if (fabs(closest.
z() - (*i).z()) < zThreshold) {
148 for (const_iterator i = poly.begin(); i != poly.end() - 1; i++) {
151 if (fabs(closest.
z() - (*i).z()) < zThreshold) {
165 for (const_iterator i = begin(); i != end() - 1; i++) {
179 for (const_iterator i = begin(); i != end() - 1; i++) {
190 for (const_iterator i = begin(); i != end() - 1; i++) {
192 if (
intersects(*i, *(i + 1), p1, p2, withinDist, &x, &y, &m)) {
202 for (const_iterator i = begin(); i != end() - 1; i++) {
220 if (index >= 0 && index < (
int)size()) {
222 }
else if (index < 0 && -index <= (
int)size()) {
223 return at((
int)size() + index);
239 if (index >= 0 && index < (
int)size()) {
241 }
else if (index < 0 && -index <= (
int)size()) {
242 return at((
int)size() + index);
257 const_iterator i = begin();
258 double seenLength = 0;
260 const double nextLength = (*i).distanceTo(*(i + 1));
261 if (seenLength + nextLength > pos) {
264 seenLength += nextLength;
265 }
while (++i != end() - 1);
266 if (lateralOffset == 0 || size() < 2) {
269 return positionAtOffset(*(end() - 2), *(end() - 1), (*(end() - 2)).distanceTo(*(end() - 1)), lateralOffset);
282 const_iterator i = begin();
283 double seenLength = 0;
285 const double nextLength = (*i).distanceTo(*(i + 1));
286 if (seenLength + nextLength > pos) {
289 seenLength += nextLength;
290 }
while (++i != end() - 1);
291 return sidePositionAtAngle(*(end() - 2), *(end() - 1), (*(end() - 2)).distanceTo(*(end() - 1)), lateralOffset, angle);
303 const_iterator i = begin();
304 double seenLength = 0;
306 const double nextLength = (*i).distanceTo2D(*(i + 1));
307 if (seenLength + nextLength > pos) {
308 return positionAtOffset2D(*i, *(i + 1), pos - seenLength, lateralOffset, extrapolateBeyond);
310 seenLength += nextLength;
311 }
while (++i != end() - 1);
312 if (extrapolateBeyond) {
313 return positionAtOffset2D(*(i - 1), *i, pos - seenLength + (*i).distanceTo2D(*(i - 1)), lateralOffset, extrapolateBeyond);
321 if ((size() == 0) || (size() == 1)) {
327 const_iterator i = begin();
328 double seenLength = 0;
333 if (seenLength + nextLength > pos) {
336 seenLength += nextLength;
337 }
while (++i != end() - 1);
355 const_iterator i = begin();
356 double seenLength = 0;
361 if (seenLength + nextLength > pos) {
364 seenLength += nextLength;
365 }
while (++i != end() - 1);
375 if (pos < 0. || dist < pos) {
378 if (lateralOffset != 0) {
386 return p1 + (p2 - p1) * (pos / dist) + offset;
391 return p1 + (p2 - p1) * (pos / dist);
398 if (pos < 0. || dist < pos || dist == 0) {
402 const Position offset(cos(angle) * lateralOffset, sin(angle) * lateralOffset);
403 return p1 + (p2 - p1) * (pos / dist) + offset;
410 if ((pos < 0 || dist < pos) && !extrapolateBeyond) {
416 if (lateralOffset != 0) {
421 return p1 + (p2 - p1) * (pos / dist) + offset;
426 return p1 + (p2 - p1) * (pos / dist);
453 return Position(x / (
double) size(), y / (
double) size(), z / (
double)size());
461 }
else if (size() == 1) {
463 }
else if (size() == 2) {
464 return ((*
this)[0] + (*
this)[1]) * 0.5;
468 tmp.push_back(tmp[0]);
474 const int endIndex = (int)tmp.size() - 1;
478 if (tmp.
area() != 0) {
480 for (
int i = 0; i < endIndex; i++) {
481 const double z = tmp[i].x() * tmp[i + 1].y() - tmp[i + 1].x() * tmp[i].y();
483 x += (tmp[i].x() + tmp[i + 1].x()) * z;
484 y += (tmp[i].y() + tmp[i + 1].y()) * z;
487 result =
Position(x / div, y / div);
491 double lengthSum = 0;
492 for (
int i = 0; i < endIndex; i++) {
493 double length = tmp[i].distanceTo(tmp[i + 1]);
494 x += (tmp[i].x() + tmp[i + 1].x()) *
length / 2;
495 y += (tmp[i].y() + tmp[i + 1].y()) *
length / 2;
498 if (lengthSum == 0) {
502 result =
Position(x / lengthSum, y / lengthSum) + offset;
504 return result + offset;
511 for (
int i = 0; i < static_cast<int>(size()); i++) {
512 (*this)[i] = centroid + (((*this)[i] - centroid) * factor);
520 for (
int i = 0; i < static_cast<int>(size()); i++) {
521 (*this)[i] = centroid + (((*this)[i] - centroid) + offset);
542 for (const_iterator i = begin(); i != end() - 1; i++) {
543 len += (*i).distanceTo(*(i + 1));
555 for (const_iterator i = begin(); i != end() - 1; i++) {
556 len += (*i).distanceTo2D(*(i + 1));
570 tmp.push_back(tmp[0]);
572 const int endIndex = (int)tmp.size() - 1;
574 for (
int i = 0; i < endIndex; i++) {
575 area += tmp[i].x() * tmp[i + 1].y() - tmp[i + 1].x() * tmp[i].y();
589 for (const_iterator i = begin(); i != end(); i++) {
590 if (poly.
around(*i, offset)) {
604std::pair<PositionVector, PositionVector>
610 if (where < 0 || where > len) {
613 if (where <= POSITION_EPS || where >= len - POSITION_EPS) {
617 first.push_back((*
this)[0]);
619 const_iterator it = begin() + 1;
620 double next = use2D ? first.back().distanceTo2D(*it) : first.back().distanceTo(*it);
622 while (where >= seen + next + POSITION_EPS) {
624 first.push_back(*it);
626 next = use2D ? first.back().distanceTo2D(*it) : first.back().distanceTo(*it);
628 if (fabs(where - (seen + next)) > POSITION_EPS || it == end() - 1) {
637 first.push_back(*it);
640 for (; it != end(); it++) {
641 second.push_back(*it);
643 assert(first.size() >= 2);
644 assert(second.size() >= 2);
645 assert(first.back() == second.front());
647 return std::pair<PositionVector, PositionVector>(first, second);
653 for (PositionVector::const_iterator i = geom.begin(); i != geom.end(); i++) {
654 if (i != geom.begin()) {
669 const Position centroid = std::accumulate(begin(), end(),
Position(0, 0)) / (double)size();
678 for (
int i = 0; i < (int)size(); i++) {
679 (*this)[i].add(xoff, yoff, zoff);
686 add(-offset.
x(), -offset.
y(), -offset.
z());
692 add(offset.
x(), offset.
y(), offset.
z());
699 for (
auto i1 = begin(); i1 != end(); ++i1) {
700 pv.push_back(*i1 + offset);
708 for (
int i = 0; i < (int)size(); i++) {
709 (*this)[i].mul(1, -1);
719 double angle1 = atAngle2D(p1);
720 double angle2 = atAngle2D(p2);
721 if (angle1 > angle2) {
724 if (angle1 == angle2) {
727 if (squaredDistance1 < squaredDistance2) {
737 double angle = atan2(p.
y(), p.
x());
738 return angle < 0.0 ? angle : angle + 2.0 *
M_PI;
752 if (p1.
x() != p2.
x()) {
753 return p1.
x() < p2.
x();
755 return p1.
y() < p2.
y();
761 return (P1.
x() - P0.
x()) * (P2.
y() - P0.
y()) - (P2.
x() - P0.
x()) * (P1.
y() - P0.
y());
767 if ((size() > 0) && (v.size() > 0) && (back().distanceTo(v[0]) < sameThreshold)) {
768 copy(v.begin() + 1, v.end(), back_inserter(*
this));
770 copy(v.begin(), v.end(), back_inserter(*
this));
777 if ((size() > 0) && (v.size() > 0) && (front().distanceTo(v.back()) < sameThreshold)) {
778 insert(begin(), v.begin(), v.end() - 1);
780 insert(begin(), v.begin(), v.end());
789 if (beginOffset > POSITION_EPS) {
793 if (endOffset <
length() - POSITION_EPS) {
796 ret.push_back(begPos);
799 const_iterator i = begin();
801 while ((i + 1) != end()
803 seen + (*i).distanceTo(*(i + 1)) < beginOffset) {
804 seen += (*i).distanceTo(*(i + 1));
808 while ((i + 1) != end()
810 seen + (*i).distanceTo(*(i + 1)) < endOffset) {
813 seen += (*i).distanceTo(*(i + 1));
818 if (ret.size() == 1) {
819 ret.push_back(endPos);
832 if (beginOffset > POSITION_EPS) {
836 if (endOffset <
length2D() - POSITION_EPS) {
839 ret.push_back(begPos);
842 const_iterator i = begin();
844 while ((i + 1) != end()
846 seen + (*i).distanceTo2D(*(i + 1)) < beginOffset) {
847 seen += (*i).distanceTo2D(*(i + 1));
851 while ((i + 1) != end()
853 seen + (*i).distanceTo2D(*(i + 1)) < endOffset) {
856 seen += (*i).distanceTo2D(*(i + 1));
861 if (ret.size() == 1) {
862 ret.push_back(endPos);
873 if (beginIndex < 0) {
874 beginIndex += (int)size();
877 assert(beginIndex < (
int)size());
878 assert(beginIndex + count <= (
int)size());
880 for (
int i = beginIndex; i < beginIndex + count; ++i) {
881 result.push_back((*
this)[i]);
892 return front().angleTo2D(back());
901 double minDist = std::numeric_limits<double>::max();
904 for (const_iterator i = begin(); i != end() - 1; i++) {
908 if (dist2 < minDist) {
909 nearestPos = pos + seen;
915 if (cornerDist2 < minDist) {
920 if (pos1 == (*(i - 1)).distanceTo2D(*i) && pos2 == 0.) {
922 minDist = cornerDist2;
926 seen += (*i).distanceTo2D(*(i + 1));
937 double minDist = std::numeric_limits<double>::max();
940 for (const_iterator i = begin(); i != end() - 1; i++) {
944 if (dist < minDist) {
945 const double pos25D = pos * (*i).distanceTo(*(i + 1)) / (*i).distanceTo2D(*(i + 1));
946 nearestPos = pos25D + seen;
952 if (cornerDist < minDist) {
957 if (pos1 == (*(i - 1)).distanceTo2D(*i) && pos2 == 0.) {
959 minDist = cornerDist;
963 seen += (*i).distanceTo(*(i + 1));
981 double minDist = std::numeric_limits<double>::max();
982 double nearestPos = -1;
985 for (const_iterator i = begin(); i != end() - 1; i++) {
989 if (dist < minDist) {
990 nearestPos = pos + seen;
992 sign =
isLeft(*i, *(i + 1), p) >= 0 ? -1 : 1;
997 if (cornerDist < minDist) {
1002 if (pos1 == (*(i - 1)).distanceTo2D(*i) && pos2 == 0.) {
1004 minDist = cornerDist;
1005 sign =
isLeft(*(i - 1), *i, p) >= 0 ? -1 : 1;
1009 seen += (*i).distanceTo2D(*(i + 1));
1011 if (nearestPos != -1) {
1012 return Position(nearestPos, sign * minDist);
1024 double minDist = std::numeric_limits<double>::max();
1027 for (
int i = 0; i < (int)size(); i++) {
1030 if (dist < minDist) {
1044 double minDist = std::numeric_limits<double>::max();
1045 int insertionIndex = 1;
1046 for (
int i = 0; i < (int)size() - 1; i++) {
1050 if (dist < minDist) {
1051 insertionIndex = i + 1;
1058 const double previousZ = (begin() + (insertionIndex - 1))->z();
1059 const double nextZ = (begin() + insertionIndex)->z();
1061 insert(begin() + insertionIndex,
Position(p.
x(), p.
y(), ((previousZ + nextZ) / 2.0)));
1063 insert(begin() + insertionIndex, p);
1065 return insertionIndex;
1074 double minDist = std::numeric_limits<double>::max();
1075 int removalIndex = 0;
1076 for (
int i = 0; i < (int)size(); i++) {
1078 if (dist < minDist) {
1083 erase(begin() + removalIndex);
1084 return removalIndex;
1090 std::vector<double> ret;
1091 if (other.size() == 0) {
1094 for (const_iterator i = other.begin(); i != other.end() - 1; i++) {
1096 copy(atSegment.begin(), atSegment.end(), back_inserter(ret));
1104 std::vector<double> ret;
1109 for (const_iterator i = begin(); i != end() - 1; i++) {
1113 if (
intersects(p1, p2, lp1, lp2, 0., &x, &y, &m)) {
1169 for (const_reverse_iterator i = rbegin(); i != rend(); i++) {
1179 return Position((beg.
y() - end.
y()) * scale, (end.
x() - beg.
x()) * scale);
1189 if (
length2D() == 0 || amount == 0) {
1193 std::vector<int> recheck;
1194 for (
int i = 0; i < static_cast<int>(size()); i++) {
1197 const Position& to = (*this)[i + 1];
1199 shape.push_back(from -
sideOffset(from, to, amount));
1200#ifdef DEBUG_MOVE2SIDE
1202 std::cout <<
" " << i <<
"a=" << shape.back() <<
"\n";
1206 }
else if (i ==
static_cast<int>(size()) - 1) {
1207 const Position& from = (*this)[i - 1];
1210 shape.push_back(to -
sideOffset(from, to, amount));
1211#ifdef DEBUG_MOVE2SIDE
1213 std::cout <<
" " << i <<
"b=" << shape.back() <<
"\n";
1218 const Position& from = (*this)[i - 1];
1220 const Position& to = (*this)[i + 1];
1223 const double extrapolateDev = fromMe[1].distanceTo2D(to);
1224 if (fabs(extrapolateDev) < POSITION_EPS) {
1226 shape.push_back(me -
sideOffset(from, to, amount));
1227#ifdef DEBUG_MOVE2SIDE
1229 std::cout <<
" " << i <<
"c=" << shape.back() <<
"\n";
1232 }
else if (fabs(extrapolateDev - 2 * me.
distanceTo2D(to)) < POSITION_EPS) {
1236 shape.push_back(fromMe2[1]);
1237#ifdef DEBUG_MOVE2SIDE
1239 std::cout <<
" " << i <<
"d=" << shape.back() <<
" " << i <<
"_from=" << from <<
" " << i <<
"_me=" << me <<
" " << i <<
"_to=" << to <<
"\n";
1249 recheck.push_back(i);
1253 shape.push_back(meNew);
1254#ifdef DEBUG_MOVE2SIDE
1256 std::cout <<
" " << i <<
"e=" << shape.back() <<
"\n";
1261 shape.back().set(shape.back().x(), shape.back().y(), me.
z());
1262 const double angle =
localAngle(from, me, to);
1263 if (fabs(angle) > NUMERICAL_EPS) {
1265 const double radius =
length / angle;
1266#ifdef DEBUG_MOVE2SIDE
1268 std::cout <<
" i=" << i <<
" a=" <<
RAD2DEG(angle) <<
" l=" <<
length <<
" r=" << radius <<
" t=" << amount * 1.8 <<
"\n";
1271 if ((radius < 0 && -radius < amount * 1.8) || fabs(
RAD2DEG(angle)) > 170) {
1272 recheck.push_back(i);
1277 if (!recheck.empty()) {
1280 for (
int i = (
int)recheck.size() - 1; i >= 0; i--) {
1281 shape.erase(shape.begin() + recheck[i]);
1297 if (size() != amount.size()) {
1299 +
") does not match number of points (" +
toString(size()) +
")");
1302 for (
int i = 0; i < static_cast<int>(size()); i++) {
1305 const Position& to = (*this)[i + 1];
1307 shape.push_back(from -
sideOffset(from, to, amount[i]));
1309 }
else if (i ==
static_cast<int>(size()) - 1) {
1310 const Position& from = (*this)[i - 1];
1313 shape.push_back(to -
sideOffset(from, to, amount[i]));
1316 const Position& from = (*this)[i - 1];
1318 const Position& to = (*this)[i + 1];
1321 const double extrapolateDev = fromMe[1].distanceTo2D(to);
1322 if (fabs(extrapolateDev) < POSITION_EPS) {
1324 shape.push_back(me -
sideOffset(from, to, amount[i]));
1325 }
else if (fabs(extrapolateDev - 2 * me.
distanceTo2D(to)) < POSITION_EPS) {
1329 shape.push_back(fromMe2[1]);
1340 shape.push_back(meNew);
1343 shape.back().set(shape.back().x(), shape.back().y(), me.
z());
1356 if ((pos + 1) < (
int)size()) {
1357 return (*
this)[pos].angleTo2D((*
this)[pos + 1]);
1365 if ((size() > 1) && (front() == back())) {
1373 if ((size() != 0) && ((*
this)[0] != back())) {
1374 push_back((*
this)[0]);
1381 std::vector<double> ret;
1383 for (i = begin(); i != end(); i++) {
1384 const double dist = s.
distance2D(*i, perpendicular);
1386 ret.push_back(dist);
1389 for (i = s.begin(); i != s.end(); i++) {
1390 const double dist =
distance2D(*i, perpendicular);
1392 ret.push_back(dist);
1402 return std::numeric_limits<double>::max();
1403 }
else if (size() == 1) {
1404 return front().distanceTo2D(p);
1445 if ((size() == 0) || !p.
almostSame(front())) {
1453 if (at == begin()) {
1455 }
else if (at == end()) {
1467 return (size() >= 2) && ((*this)[0] == back());
1474 for (
auto i = begin(); i != end(); i++) {
1485 const double limit = 2 * pow(10, -precision);
1493 if (avoidDegeneration && size() > 1) {
1496 for (
int i = 0; i < (int)size(); i++) {
1497 (*this)[i].round(precision);
1504 int curSize = (int)size() - beginOffset - endOffset;
1506 iterator last = begin() + beginOffset;
1507 for (iterator i = last + 1; i != (end() - endOffset) && (!assertLength || curSize > 2);) {
1508 if (last->almostSame(*i, minDist)) {
1509 if (i + 1 == end() - endOffset) {
1511 if (
resample && last > begin() && (last - 1)->distanceTo(*i) >= 2 * minDist) {
1513 const double shiftBack = minDist - last->distanceTo(*i);
1515 (*last) =
positionAtOffset(*(last - 1), *last, (last - 1)->distanceTo(*last) - shiftBack);
1521 i = end() - endOffset;
1524 if (
resample && i + 1 != end() && last->distanceTo(*(i + 1)) >= 2 * minDist) {
1526 const double shiftForward = minDist - last->distanceTo(*i);
1548 return static_cast<vp>(*this) ==
static_cast<vp>(v2);
1554 return static_cast<vp>(*this) !=
static_cast<vp>(v2);
1560 WRITE_ERROR(
TL(
"Trying to subtract PositionVectors of different lengths."));
1564 auto i2 = v2.begin();
1565 while (i1 != end()) {
1574 WRITE_ERROR(
TL(
"Trying to add PositionVectors of different lengths."));
1578 auto i2 = v2.begin();
1579 while (i1 != end()) {
1587 if (size() != v2.size()) {
1590 auto i2 = v2.begin();
1591 for (
auto i1 = begin(); i1 != end(); i1++) {
1592 if (!i1->almostSame(*i2, maxDiv)) {
1605 for (const_iterator i = begin(); i != end(); i++) {
1606 if ((*i).z() != 0) {
1616 const double eps = std::numeric_limits<double>::epsilon();
1617 const double denominator = (p22.
y() - p21.
y()) * (p12.
x() - p11.
x()) - (p22.
x() - p21.
x()) * (p12.
y() - p11.
y());
1618 const double numera = (p22.
x() - p21.
x()) * (p11.
y() - p21.
y()) - (p22.
y() - p21.
y()) * (p11.
x() - p21.
x());
1619 const double numerb = (p12.
x() - p11.
x()) * (p11.
y() - p21.
y()) - (p12.
y() - p11.
y()) * (p11.
x() - p21.
x());
1621 if (fabs(numera) < eps && fabs(numerb) < eps && fabs(denominator) < eps) {
1627 if (p11.
x() != p12.
x()) {
1628 a1 = p11.
x() < p12.
x() ? p11.
x() : p12.
x();
1629 a2 = p11.
x() < p12.
x() ? p12.
x() : p11.
x();
1630 a3 = p21.
x() < p22.
x() ? p21.
x() : p22.
x();
1631 a4 = p21.
x() < p22.
x() ? p22.
x() : p21.
x();
1633 a1 = p11.
y() < p12.
y() ? p11.
y() : p12.
y();
1634 a2 = p11.
y() < p12.
y() ? p12.
y() : p11.
y();
1635 a3 = p21.
y() < p22.
y() ? p21.
y() : p22.
y();
1636 a4 = p21.
y() < p22.
y() ? p22.
y() : p21.
y();
1638 if (a1 <= a3 && a3 <= a2) {
1645 if (a3 <= a1 && a1 <= a4) {
1654 if (p11.
x() != p12.
x()) {
1655 *mu = (a - p11.
x()) / (p12.
x() - p11.
x());
1657 *y = p11.
y() + (*mu) * (p12.
y() - p11.
y());
1661 if (p12.
y() == p11.
y()) {
1664 *mu = (a - p11.
y()) / (p12.
y() - p11.
y());
1673 if (fabs(denominator) < eps) {
1677 double mua = numera / denominator;
1679 if (fabs(p12.
x() - p22.
x()) < eps && fabs(p12.
y() - p22.
y()) < eps) {
1682 const double offseta = withinDist / p11.
distanceTo2D(p12);
1683 const double offsetb = withinDist / p21.
distanceTo2D(p22);
1684 const double mub = numerb / denominator;
1685 if (mua < -offseta || mua > 1 + offseta || mub < -offsetb || mub > 1 + offsetb) {
1690 *x = p11.
x() + mua * (p12.
x() - p11.
x());
1691 *y = p11.
y() + mua * (p12.
y() - p11.
y());
1700 const double s = sin(angle);
1701 const double c = cos(angle);
1702 for (
int i = 0; i < (int)size(); i++) {
1703 const double x = (*this)[i].x();
1704 const double y = (*this)[i].y();
1705 const double z = (*this)[i].z();
1706 const double xnew = x * c - y * s;
1707 const double ynew = x * s + y * c;
1708 (*this)[i].set(xnew, ynew, z);
1738 bool changed =
true;
1739 while (changed && result.size() > 3) {
1741 for (
int i = 0; i < (int)result.size(); i++) {
1743 const Position& p2 = result[(i + 2) % result.size()];
1744 const int middleIndex = (i + 1) % result.size();
1745 const Position& p0 = result[middleIndex];
1747 const double triangleArea2 = fabs((p2.
y() - p1.
y()) * p0.
x() - (p2.
x() - p1.
x()) * p0.
y() + p2.
x() * p1.
y() - p2.
y() * p1.
x());
1749 if (distIK > NUMERICAL_EPS && triangleArea2 / distIK < NUMERICAL_EPS) {
1751 result.erase(result.begin() + middleIndex);
1771 if (!closed && (index == 0 || index == (
int)pv.size() - 1)) {
1775 const Position& a = pv[(index + (int)pv.size() - 1) % pv.size()];
1776 const Position& b = pv[(index + 1) % pv.size()];
1778 if (distAB <
MIN2(eps, NUMERICAL_EPS)) {
1784 const Position dir = (b - a) / distAB;
1785 const double projectedLength = (a - p).dotProduct(dir);
1786 if (projectedLength <= -distAB) {
1789 if (projectedLength >= 0.) {
1792 const Position distVector = (a - p) - dir * projectedLength;
1793 return distVector.
length();
1795 std::vector<double> scores;
1796 double minScore = eps + 1.;
1798 for (
int i = 0; i < (int)size(); i++) {
1799 scores.push_back(calcScore(*
this, i));
1800 if (scores.back() < minScore) {
1801 minScore = scores.back();
1805 if (minScore >= eps) {
1809 while (minScore < eps) {
1810 result.erase(result.begin() + minIndex);
1811 if (result.size() < 3) {
1814 scores.erase(scores.begin() + minIndex);
1815 const int prevIndex = (minIndex + (int)result.size() - 1) % result.size();
1816 scores[prevIndex] = calcScore(result, prevIndex);
1817 scores[minIndex % result.size()] = calcScore(result, minIndex % result.size());
1818 minScore = eps + 1.;
1819 for (
int i = 0; i < (int)result.size(); i++) {
1820 if (scores[i] < minScore) {
1821 minScore = scores[i];
1843 result.push_back(base);
1844 if (fabs(baseOffset - closestOffset) > NUMERICAL_EPS) {
1845 result.push_back(tmp[closestIndex]);
1846 if ((closestOffset < baseOffset) != before) {
1849 }
else if (before) {
1851 if (closestIndex > 0) {
1852 result.push_back(tmp[closestIndex - 1]);
1854 result.push_back(tmp[1]);
1859 if (closestIndex < (
int)size() - 1) {
1860 result.push_back(tmp[closestIndex + 1]);
1862 result.push_back(tmp[-1]);
1868 result.
add(base * -1);
1881 const double z0 = (*this)[0].z();
1883 const double dz = (*this)[1].z() - z0;
1885 if (size() > 2 && dz != 0) {
1891 if (pDist.
distanceTo2D((*
this)[iLast]) > POSITION_EPS * 20) {
1895 const double dz2 = result[iLast].z() - z0;
1897 for (
int i = 1; i < iLast; ++i) {
1898 seen += result[i].distanceTo2D(result[i - 1]);
1899 result[i].set(result[i].x(), result[i].y(), z0 + dz2 * seen / dist2);
1913 result[0].setz(zStart);
1914 result[-1].setz(zEnd);
1915 const double dz = zEnd - zStart;
1918 for (
int i = 1; i < (int)size() - 1; ++i) {
1919 seen += result[i].distanceTo2D(result[i - 1]);
1920 result[i].setz(zStart + dz * seen /
length);
1929 if (maxLength == 0) {
1933 if (
length < POSITION_EPS) {
1937 for (
double pos = 0; pos <=
length; pos += maxLength) {
1941 if (adjustEnd && !result.empty() && (result.back() != back())) {
1943 result.push_back(back());
1951 if (index < 0 || index >= (
int)size()) {
1955 for (
int i = 1; i <= index; ++i) {
1956 seen += (*this)[i].distanceTo2D((*
this)[i - 1]);
1965 for (
int i = 1; i < (int)size(); ++i) {
1966 const Position& p1 = (*this)[i - 1];
1968 const double distZ = fabs(p1.
z() - p2.
z());
1971 maxJump =
MAX2(maxJump, distZ);
1973 result =
MAX2(result, distZ / dist2D);
1982 double minZ = std::numeric_limits<double>::max();
1984 minZ =
MIN2(minZ, i.z());
1993 assert(size() < 33);
1994 static const double fac[33] = {
1995 1.0, 1.0, 2.0, 6.0, 24.0, 120.0, 720.0, 5040.0, 40320.0, 362880.0, 3628800.0, 39916800.0, 479001600.0,
1996 6227020800.0, 87178291200.0, 1307674368000.0, 20922789888000.0, 355687428096000.0, 6402373705728000.0,
1997 121645100408832000.0, 2432902008176640000.0, 51090942171709440000.0, 1124000727777607680000.0,
1998 25852016738884976640000.0, 620448401733239439360000.0, 15511210043330985984000000.0,
1999 403291461126605635584000000.0, 10888869450418352160768000000.0, 304888344611713860501504000000.0,
2000 8841761993739701954543616000000.0, 265252859812191058636308480000000.0,
2001 8222838654177922817725562880000000.0, 263130836933693530167218012160000000.0
2004 const int npts = (int)size();
2006 const double step = (double) 1.0 / (numPoints - 1);
2009 for (
int i1 = 0; i1 < numPoints; i1++) {
2010 if ((1.0 - t) < 5e-6) {
2013 double x = 0., y = 0., z = 0.;
2014 for (
int i = 0; i < npts; i++) {
2015 const double ti = (i == 0) ? 1.0 : pow(t, i);
2016 const double tni = (npts == i + 1) ? 1.0 : pow(1 - t, npts - i - 1);
2017 const double basis = fac[npts - 1] / (fac[i] * fac[npts - 1 - i]) * ti * tni;
2018 x += basis * at(i).x();
2019 y += basis * at(i).y();
2020 z += basis * at(i).z();
2024 if (prev != current && !std::isnan(x) && !std::isnan(y) && !std::isnan(z)) {
2025 ret.push_back(current);
2040 const double y_min = std::min_element(begin(), end(), [](
Position p1,
Position p2) {
2041 return p1.
y() < p2.
y();
2043 const double gap = y_min > 0.0 ? 0.0 : y_min;
2045 const int last = (int)size() - 1;
2046 for (
int i = 0; i < last; i++) {
2047 const Position& firstPoint = at(i);
2048 const Position& secondPoint = at(i + 1);
2049 area += (secondPoint.
x() - firstPoint.
x()) / (secondPoint.
y() + firstPoint.
y()) / 2.0;
2051 area += (at(0).x() - at(last).x()) / (at(0).y() + at(last).y()) / 2.0;
#define WRITE_WARNINGF(...)
std::ostream & operator<<(std::ostream &os, const PositionVector &geom)
bool gDebugFlag1
global utility flags for debugging
const double INVALID_DOUBLE
invalid double
std::string toString(const T &t, std::streamsize accuracy=gPrecision)
virtual bool partialWithin(const AbstractPoly &poly, double offset=0) const =0
Returns whether the AbstractPoly is partially within the given polygon.
virtual bool crosses(const Position &p1, const Position &p2) const =0
Returns whether the AbstractPoly crosses the given line.
virtual bool around(const Position &p, double offset=0) const =0
Returns whether the AbstractPoly the given coordinate.
A class that stores a 2D geometrical boundary.
void add(double x, double y, double z=0)
Makes the boundary include the given coordinate.
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,...
static const double INVALID_OFFSET
a value to signify offsets outside the range of [0, Line.length()]
static double nearest_offset_on_line_to_point2D(const Position &lineStart, const Position &lineEnd, const Position &p, bool perpendicular=true)
static double legacyDegree(const double angle, const bool positive=false)
static double angleDiff(const double angle1, const double angle2)
Returns the difference of the second angle to the first angle in radiants.
A point in 2D or 3D with translation and scaling methods.
double length() const
Computes the length of the given vector.
double distanceSquaredTo2D(const Position &p2) const
returns the square of the distance to another position (Only using x and y positions)
double slopeTo2D(const Position &other) const
returns the slope of the vector pointing from here to the other position (in radians between -M_PI an...
double dotProduct(const Position &pos) const
returns the dot product (scalar product) between this point and the second one
static const Position INVALID
used to indicate that a position is valid
double distanceTo2D(const Position &p2) const
returns the euclidean distance in the x-y-plane
double distanceTo(const Position &p2) const
returns the euclidean distance in 3 dimensions
void sub(double dx, double dy)
Subtracts the given position from this one.
double x() const
Returns the x-position.
void add(const Position &pos)
Adds the given position to this one.
double z() const
Returns the z-position.
double angleTo2D(const Position &other) const
returns the angle in the plane of the vector pointing from here to the other position (in radians bet...
bool almostSame(const Position &p2, double maxDiv=POSITION_EPS) const
check whether the other position has a euclidean distance of less than maxDiv
double y() const
Returns the y-position.
int operator()(const Position &p1, const Position &p2) const
comparing operation for sort
double atAngle2D(const Position &p) const
computes the angle of the given vector, in the range $[0,2*\pi[$
as_poly_cw_sorter()
constructor
clase for increasing Sorter
increasing_x_y_sorter()
constructor
int operator()(const Position &p1, const Position &p2) const
comparing operation
bool isClockwiseOriented(void)
PositionVector operator-(const PositionVector &v2) const
subtracts two vectors (requires vectors of the same length)
void scaleAbsolute(double offset)
enlarges/shrinks the polygon by an absolute offset based at the centroid
double length2D() const
Returns the length.
void append(const PositionVector &v, double sameThreshold=2.0)
bool overlapsWith(const AbstractPoly &poly, double offset=0) const
Returns the information whether the given polygon overlaps with this.
PositionVector added(const Position &offset) const
double isLeft(const Position &P0, const Position &P1, const Position &P2) const
get left
double beginEndAngle() const
returns the angle in radians of the line connecting the first and the last position
double getMinZ() const
return minimum z-coordinate
double length() const
Returns the length.
void move2sideCustom(std::vector< double > amount, double maxExtension=100)
move position vector to side using a custom offset for each geometry point
void round(int precision, bool avoidDegeneration=true)
round all coordinates to the given precision
void sortAsPolyCWByAngle()
sort as polygon CW by angle
PositionVector simplified() const
return the same shape with intermediate colinear points removed
void rotate2D(double angle)
PositionVector()
Constructor. Creates an empty position vector.
Position getPolygonCenter() const
Returns the arithmetic of all corner points.
Position intersectionPosition2D(const Position &p1, const Position &p2, const double withinDist=0.) const
Returns the position of the intersection.
const Position & operator[](int index) const
returns the constant position at the given index, negative indices are interpreted python style
double rotationAtOffset(double pos) const
Returns the rotation at the given length.
std::vector< Position > vp
vector of position
void ensureMinLength(int precision)
ensure minimum length so that the geometry will not degenerate to 0-length on writing with the given ...
void push_front_noDoublePos(const Position &p)
insert in front a non double position
bool operator!=(const PositionVector &v2) const
comparing operation
PositionVector resample(double maxLength, const bool adjustEnd) const
resample shape (i.e. transform to segments, equal spacing)
void sortByIncreasingXY()
sort by increasing X-Y Positions
double rotationDegreeAtOffset(double pos) const
Returns the rotation at the given length.
bool isNAN() const
check if PositionVector is NAN
Position positionAtOffset(double pos, double lateralOffset=0) const
Returns the position at the given length.
void add(double xoff, double yoff, double zoff)
void closePolygon()
ensures that the last position equals the first
static Position sideOffset(const Position &beg, const Position &end, const double amount)
get a side position of position vector using a offset
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 ...
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 prepend(const PositionVector &v, double sameThreshold=2.0)
double nearest_offset_to_point2D(const Position &p, bool perpendicular=true) const
return the nearest offest to point 2D
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
PositionVector getOrthogonal(const Position &p, double extend, bool before, double length=1.0, double deg=90) const
return orthogonal through p (extending this vector if necessary)
void openPolygon()
open polygon
int indexOfClosest(const Position &p, bool twoD=false) const
std::pair< PositionVector, PositionVector > splitAt(double where, bool use2D=false) const
Returns the two lists made when this list vector is splitted at the given point.
void move2side(double amount, double maxExtension=100)
move position vector to side using certain amount
bool almostSame(const PositionVector &v2, double maxDiv=POSITION_EPS) const
check if the two vectors have the same length and pairwise similar positions
bool crosses(const Position &p1, const Position &p2) const
Returns whether the AbstractPoly crosses the given line.
PositionVector getSubpart2D(double beginOffset, double endOffset) const
get subpart of a position vector in two dimensions (Z is ignored)
PositionVector interpolateZ(double zStart, double zEnd) const
returned vector that varies z smoothly over its length
Boundary getBoxBoundary() const
Returns a boundary enclosing this list of lines.
double offsetAtIndex2D(int index) const
return the offset at the given index
PositionVector smoothedZFront(double dist=std::numeric_limits< double >::max()) const
returned vector that is smoothed at the front (within dist)
double angleAt2D(int pos) const
get angle in certain position of position vector (in radians between -M_PI and M_PI)
void insert_noDoublePos(const std::vector< Position >::iterator &at, const Position &p)
insert in front a non double position
double slopeDegreeAtOffset(double pos) const
Returns the slope at the given length.
bool hasElevation() const
return whether two positions differ in z-coordinate
static const PositionVector EMPTY
empty Vector
void extrapolate(const double val, const bool onlyFirst=false, const bool onlyLast=false)
extrapolate position vector
PositionVector bezier(int numPoints)
return a bezier interpolation
Position getLineCenter() const
get line center
Position getCentroid() const
Returns the centroid (closes the polygon if unclosed)
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...
PositionVector operator+(const PositionVector &v2) const
adds two vectors (requires vectors of the same length)
void extrapolate2D(const double val, const bool onlyFirst=false)
extrapolate position vector in two dimensions (Z is ignored)
void rotateAroundFirstElement2D(double angle)
int insertAtClosest(const Position &p, bool interpolateZ)
inserts p between the two closest positions
const PositionVector simplified2(const bool closed, const double eps=NUMERICAL_EPS) const
void push_front(const Position &p)
insert in front a Position
Position positionAtOffset2D(double pos, double lateralOffset=0, bool extrapolateBeyond=false) const
Returns the position at the given length.
void scaleRelative(double factor)
enlarges/shrinks the polygon by a factor based at the centroid
void push_back_noDoublePos(const Position &p)
insert in back a non double position
void removeDoublePoints(double minDist=POSITION_EPS, bool assertLength=false, int beginOffset=0, int endOffset=0, bool resample=false)
Removes positions if too near.
bool partialWithin(const AbstractPoly &poly, double offset=0) const
Returns the information whether this polygon lies partially within the given polygon.
double getMaxGrade(double &maxJump) const
double area() const
Returns the area (0 for non-closed)
bool isClosed() const
check if PositionVector is closed
void pop_front()
pop first Position
double nearest_offset_to_point25D(const Position &p, bool perpendicular=true) const
return the nearest offest to point 2D projected onto the 3D geometry
int removeClosest(const Position &p)
removes the point closest to p and return the removal index
static double localAngle(const Position &from, const Position &pos, const Position &to)
Position sidePositionAtAngle(double pos, double lateralOffset, double angle) const
bool intersects(const Position &p1, const Position &p2) const
Returns the information whether this list of points interesects the given line.
PositionVector reverse() const
reverse position vector
PositionVector getSubpartByIndex(int beginIndex, int count) const
get subpart of a position vector using index and a cout
bool operator==(const PositionVector &v2) const
comparing operation
void sub(const Position &offset)
PositionVector getSubpart(double beginOffset, double endOffset) const
get subpart of a position vector
~PositionVector()
Destructor.
bool around(const Position &p, double offset=0) const
Returns the information whether the position vector describes a polygon lying around the given point.
Position transformToVectorCoordinates(const Position &p, bool extend=false) const
return position p within the length-wise coordinate system defined by this position vector....