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;
499 result = lengthSum == 0. ? tmp[0] :
Position(x / lengthSum, y / lengthSum);
501 return result + offset;
508 for (
int i = 0; i < static_cast<int>(size()); i++) {
509 (*this)[i] = centroid + (((*this)[i] - centroid) * factor);
517 for (
int i = 0; i < static_cast<int>(size()); i++) {
518 (*this)[i] = centroid + (((*this)[i] - centroid) + offset);
539 for (const_iterator i = begin(); i != end() - 1; i++) {
540 len += (*i).distanceTo(*(i + 1));
552 for (const_iterator i = begin(); i != end() - 1; i++) {
553 len += (*i).distanceTo2D(*(i + 1));
567 tmp.push_back(tmp[0]);
569 const int endIndex = (int)tmp.size() - 1;
571 for (
int i = 0; i < endIndex; i++) {
572 area += tmp[i].x() * tmp[i + 1].y() - tmp[i + 1].x() * tmp[i].y();
586 for (const_iterator i = begin(); i != end(); i++) {
587 if (poly.
around(*i, offset)) {
601std::pair<PositionVector, PositionVector>
607 if (where < 0 || where > len) {
610 if (where <= POSITION_EPS || where >= len - POSITION_EPS) {
614 first.push_back((*
this)[0]);
616 const_iterator it = begin() + 1;
617 double next = use2D ? first.back().distanceTo2D(*it) : first.back().distanceTo(*it);
619 while (where >= seen + next + POSITION_EPS) {
621 first.push_back(*it);
623 next = use2D ? first.back().distanceTo2D(*it) : first.back().distanceTo(*it);
625 if (fabs(where - (seen + next)) > POSITION_EPS || it == end() - 1) {
634 first.push_back(*it);
637 for (; it != end(); it++) {
638 second.push_back(*it);
640 assert(first.size() >= 2);
641 assert(second.size() >= 2);
642 assert(first.back() == second.front());
644 return std::pair<PositionVector, PositionVector>(first, second);
650 for (PositionVector::const_iterator i = geom.begin(); i != geom.end(); i++) {
651 if (i != geom.begin()) {
666 const Position centroid = std::accumulate(begin(), end(),
Position(0, 0)) / (double)size();
675 for (
int i = 0; i < (int)size(); i++) {
676 (*this)[i].add(xoff, yoff, zoff);
683 add(-offset.
x(), -offset.
y(), -offset.
z());
689 add(offset.
x(), offset.
y(), offset.
z());
696 for (
auto i1 = begin(); i1 != end(); ++i1) {
697 pv.push_back(*i1 + offset);
705 for (
int i = 0; i < (int)size(); i++) {
706 (*this)[i].mul(1, -1);
716 double angle1 = atAngle2D(p1);
717 double angle2 = atAngle2D(p2);
718 if (angle1 > angle2) {
721 if (angle1 == angle2) {
724 if (squaredDistance1 < squaredDistance2) {
734 double angle = atan2(p.
y(), p.
x());
735 return angle < 0.0 ? angle : angle + 2.0 *
M_PI;
749 if (p1.
x() != p2.
x()) {
750 return p1.
x() < p2.
x();
752 return p1.
y() < p2.
y();
758 return (P1.
x() - P0.
x()) * (P2.
y() - P0.
y()) - (P2.
x() - P0.
x()) * (P1.
y() - P0.
y());
764 if ((size() > 0) && (v.size() > 0) && (back().distanceTo(v[0]) < sameThreshold)) {
765 copy(v.begin() + 1, v.end(), back_inserter(*
this));
767 copy(v.begin(), v.end(), back_inserter(*
this));
774 if ((size() > 0) && (v.size() > 0) && (front().distanceTo(v.back()) < sameThreshold)) {
775 insert(begin(), v.begin(), v.end() - 1);
777 insert(begin(), v.begin(), v.end());
786 if (beginOffset > POSITION_EPS) {
790 if (endOffset <
length() - POSITION_EPS) {
793 ret.push_back(begPos);
796 const_iterator i = begin();
798 while ((i + 1) != end()
800 seen + (*i).distanceTo(*(i + 1)) < beginOffset) {
801 seen += (*i).distanceTo(*(i + 1));
805 while ((i + 1) != end()
807 seen + (*i).distanceTo(*(i + 1)) < endOffset) {
810 seen += (*i).distanceTo(*(i + 1));
815 if (ret.size() == 1) {
816 ret.push_back(endPos);
829 if (beginOffset > POSITION_EPS) {
833 if (endOffset <
length2D() - POSITION_EPS) {
836 ret.push_back(begPos);
839 const_iterator i = begin();
841 while ((i + 1) != end()
843 seen + (*i).distanceTo2D(*(i + 1)) < beginOffset) {
844 seen += (*i).distanceTo2D(*(i + 1));
848 while ((i + 1) != end()
850 seen + (*i).distanceTo2D(*(i + 1)) < endOffset) {
853 seen += (*i).distanceTo2D(*(i + 1));
858 if (ret.size() == 1) {
859 ret.push_back(endPos);
870 if (beginIndex < 0) {
871 beginIndex += (int)size();
874 assert(beginIndex < (
int)size());
875 assert(beginIndex + count <= (
int)size());
877 for (
int i = beginIndex; i < beginIndex + count; ++i) {
878 result.push_back((*
this)[i]);
889 return front().angleTo2D(back());
898 double minDist = std::numeric_limits<double>::max();
901 for (const_iterator i = begin(); i != end() - 1; i++) {
905 if (dist2 < minDist) {
906 nearestPos = pos + seen;
912 if (cornerDist2 < minDist) {
917 if (pos1 == (*(i - 1)).distanceTo2D(*i) && pos2 == 0.) {
919 minDist = cornerDist2;
923 seen += (*i).distanceTo2D(*(i + 1));
934 double minDist = std::numeric_limits<double>::max();
937 for (const_iterator i = begin(); i != end() - 1; i++) {
941 if (dist < minDist) {
942 const double pos25D = pos * (*i).distanceTo(*(i + 1)) / (*i).distanceTo2D(*(i + 1));
943 nearestPos = pos25D + seen;
949 if (cornerDist < minDist) {
954 if (pos1 == (*(i - 1)).distanceTo2D(*i) && pos2 == 0.) {
956 minDist = cornerDist;
960 seen += (*i).distanceTo(*(i + 1));
978 double minDist = std::numeric_limits<double>::max();
979 double nearestPos = -1;
982 for (const_iterator i = begin(); i != end() - 1; i++) {
986 if (dist < minDist) {
987 nearestPos = pos + seen;
989 sign =
isLeft(*i, *(i + 1), p) >= 0 ? -1 : 1;
994 if (cornerDist < minDist) {
999 if (pos1 == (*(i - 1)).distanceTo2D(*i) && pos2 == 0.) {
1001 minDist = cornerDist;
1002 sign =
isLeft(*(i - 1), *i, p) >= 0 ? -1 : 1;
1006 seen += (*i).distanceTo2D(*(i + 1));
1008 if (nearestPos != -1) {
1009 return Position(nearestPos, sign * minDist);
1021 double minDist = std::numeric_limits<double>::max();
1024 for (
int i = 0; i < (int)size(); i++) {
1027 if (dist < minDist) {
1041 double minDist = std::numeric_limits<double>::max();
1042 int insertionIndex = 1;
1043 for (
int i = 0; i < (int)size() - 1; i++) {
1047 if (dist < minDist) {
1048 insertionIndex = i + 1;
1055 const double previousZ = (begin() + (insertionIndex - 1))->z();
1056 const double nextZ = (begin() + insertionIndex)->z();
1058 insert(begin() + insertionIndex,
Position(p.
x(), p.
y(), ((previousZ + nextZ) / 2.0)));
1060 insert(begin() + insertionIndex, p);
1062 return insertionIndex;
1071 double minDist = std::numeric_limits<double>::max();
1072 int removalIndex = 0;
1073 for (
int i = 0; i < (int)size(); i++) {
1075 if (dist < minDist) {
1080 erase(begin() + removalIndex);
1081 return removalIndex;
1087 std::vector<double> ret;
1088 if (other.size() == 0) {
1091 for (const_iterator i = other.begin(); i != other.end() - 1; i++) {
1093 copy(atSegment.begin(), atSegment.end(), back_inserter(ret));
1101 std::vector<double> ret;
1106 for (const_iterator i = begin(); i != end() - 1; i++) {
1110 if (
intersects(p1, p2, lp1, lp2, 0., &x, &y, &m)) {
1166 for (const_reverse_iterator i = rbegin(); i != rend(); i++) {
1176 return Position((beg.
y() - end.
y()) * scale, (end.
x() - beg.
x()) * scale);
1186 if (
length2D() == 0 || amount == 0) {
1190 std::vector<int> recheck;
1191 for (
int i = 0; i < static_cast<int>(size()); i++) {
1194 const Position& to = (*this)[i + 1];
1196 shape.push_back(from -
sideOffset(from, to, amount));
1197#ifdef DEBUG_MOVE2SIDE
1199 std::cout <<
" " << i <<
"a=" << shape.back() <<
"\n";
1203 }
else if (i ==
static_cast<int>(size()) - 1) {
1204 const Position& from = (*this)[i - 1];
1207 shape.push_back(to -
sideOffset(from, to, amount));
1208#ifdef DEBUG_MOVE2SIDE
1210 std::cout <<
" " << i <<
"b=" << shape.back() <<
"\n";
1215 const Position& from = (*this)[i - 1];
1217 const Position& to = (*this)[i + 1];
1220 const double extrapolateDev = fromMe[1].distanceTo2D(to);
1221 if (fabs(extrapolateDev) < POSITION_EPS) {
1223 shape.push_back(me -
sideOffset(from, to, amount));
1224#ifdef DEBUG_MOVE2SIDE
1226 std::cout <<
" " << i <<
"c=" << shape.back() <<
"\n";
1229 }
else if (fabs(extrapolateDev - 2 * me.
distanceTo2D(to)) < POSITION_EPS) {
1233 shape.push_back(fromMe2[1]);
1234#ifdef DEBUG_MOVE2SIDE
1236 std::cout <<
" " << i <<
"d=" << shape.back() <<
" " << i <<
"_from=" << from <<
" " << i <<
"_me=" << me <<
" " << i <<
"_to=" << to <<
"\n";
1246 recheck.push_back(i);
1250 shape.push_back(meNew);
1251#ifdef DEBUG_MOVE2SIDE
1253 std::cout <<
" " << i <<
"e=" << shape.back() <<
"\n";
1258 shape.back().set(shape.back().x(), shape.back().y(), me.
z());
1259 const double angle =
localAngle(from, me, to);
1260 if (fabs(angle) > NUMERICAL_EPS) {
1262 const double radius =
length / angle;
1263#ifdef DEBUG_MOVE2SIDE
1265 std::cout <<
" i=" << i <<
" a=" <<
RAD2DEG(angle) <<
" l=" <<
length <<
" r=" << radius <<
" t=" << amount * 1.8 <<
"\n";
1268 if ((radius < 0 && -radius < amount * 1.8) || fabs(
RAD2DEG(angle)) > 170) {
1269 recheck.push_back(i);
1274 if (!recheck.empty()) {
1277 for (
int i = (
int)recheck.size() - 1; i >= 0; i--) {
1278 shape.erase(shape.begin() + recheck[i]);
1294 if (size() != amount.size()) {
1296 +
") does not match number of points (" +
toString(size()) +
")");
1299 for (
int i = 0; i < static_cast<int>(size()); i++) {
1302 const Position& to = (*this)[i + 1];
1304 shape.push_back(from -
sideOffset(from, to, amount[i]));
1306 }
else if (i ==
static_cast<int>(size()) - 1) {
1307 const Position& from = (*this)[i - 1];
1310 shape.push_back(to -
sideOffset(from, to, amount[i]));
1313 const Position& from = (*this)[i - 1];
1315 const Position& to = (*this)[i + 1];
1318 const double extrapolateDev = fromMe[1].distanceTo2D(to);
1319 if (fabs(extrapolateDev) < POSITION_EPS) {
1321 shape.push_back(me -
sideOffset(from, to, amount[i]));
1322 }
else if (fabs(extrapolateDev - 2 * me.
distanceTo2D(to)) < POSITION_EPS) {
1326 shape.push_back(fromMe2[1]);
1337 shape.push_back(meNew);
1340 shape.back().set(shape.back().x(), shape.back().y(), me.
z());
1353 if ((pos + 1) < (
int)size()) {
1354 return (*
this)[pos].angleTo2D((*
this)[pos + 1]);
1362 if ((size() > 1) && (front() == back())) {
1370 if ((size() != 0) && ((*
this)[0] != back())) {
1371 push_back((*
this)[0]);
1378 std::vector<double> ret;
1380 for (i = begin(); i != end(); i++) {
1381 const double dist = s.
distance2D(*i, perpendicular);
1383 ret.push_back(dist);
1386 for (i = s.begin(); i != s.end(); i++) {
1387 const double dist =
distance2D(*i, perpendicular);
1389 ret.push_back(dist);
1399 return std::numeric_limits<double>::max();
1400 }
else if (size() == 1) {
1401 return front().distanceTo2D(p);
1442 if ((size() == 0) || !p.
almostSame(front())) {
1450 if (at == begin()) {
1452 }
else if (at == end()) {
1464 return (size() >= 2) && ((*this)[0] == back());
1471 for (
auto i = begin(); i != end(); i++) {
1482 const double limit = 2 * pow(10, -precision);
1490 if (avoidDegeneration && size() > 1) {
1493 for (
int i = 0; i < (int)size(); i++) {
1494 (*this)[i].round(precision);
1501 int curSize = (int)size() - beginOffset - endOffset;
1503 iterator last = begin() + beginOffset;
1504 for (iterator i = last + 1; i != (end() - endOffset) && (!assertLength || curSize > 2);) {
1505 if (last->almostSame(*i, minDist)) {
1506 if (i + 1 == end() - endOffset) {
1508 if (
resample && last > begin() && (last - 1)->distanceTo(*i) >= 2 * minDist) {
1510 const double shiftBack = minDist - last->distanceTo(*i);
1512 (*last) =
positionAtOffset(*(last - 1), *last, (last - 1)->distanceTo(*last) - shiftBack);
1518 i = end() - endOffset;
1521 if (
resample && i + 1 != end() && last->distanceTo(*(i + 1)) >= 2 * minDist) {
1523 const double shiftForward = minDist - last->distanceTo(*i);
1545 return static_cast<vp>(*this) ==
static_cast<vp>(v2);
1551 return static_cast<vp>(*this) !=
static_cast<vp>(v2);
1557 WRITE_ERROR(
TL(
"Trying to subtract PositionVectors of different lengths."));
1561 auto i2 = v2.begin();
1562 while (i1 != end()) {
1571 WRITE_ERROR(
TL(
"Trying to add PositionVectors of different lengths."));
1575 auto i2 = v2.begin();
1576 while (i1 != end()) {
1584 if (size() != v2.size()) {
1587 auto i2 = v2.begin();
1588 for (
auto i1 = begin(); i1 != end(); i1++) {
1589 if (!i1->almostSame(*i2, maxDiv)) {
1602 for (const_iterator i = begin(); i != end(); i++) {
1603 if ((*i).z() != 0) {
1613 const double eps = std::numeric_limits<double>::epsilon();
1614 const double denominator = (p22.
y() - p21.
y()) * (p12.
x() - p11.
x()) - (p22.
x() - p21.
x()) * (p12.
y() - p11.
y());
1615 const double numera = (p22.
x() - p21.
x()) * (p11.
y() - p21.
y()) - (p22.
y() - p21.
y()) * (p11.
x() - p21.
x());
1616 const double numerb = (p12.
x() - p11.
x()) * (p11.
y() - p21.
y()) - (p12.
y() - p11.
y()) * (p11.
x() - p21.
x());
1618 if (fabs(numera) < eps && fabs(numerb) < eps && fabs(denominator) < eps) {
1624 if (p11.
x() != p12.
x()) {
1625 a1 = p11.
x() < p12.
x() ? p11.
x() : p12.
x();
1626 a2 = p11.
x() < p12.
x() ? p12.
x() : p11.
x();
1627 a3 = p21.
x() < p22.
x() ? p21.
x() : p22.
x();
1628 a4 = p21.
x() < p22.
x() ? p22.
x() : p21.
x();
1630 a1 = p11.
y() < p12.
y() ? p11.
y() : p12.
y();
1631 a2 = p11.
y() < p12.
y() ? p12.
y() : p11.
y();
1632 a3 = p21.
y() < p22.
y() ? p21.
y() : p22.
y();
1633 a4 = p21.
y() < p22.
y() ? p22.
y() : p21.
y();
1635 if (a1 <= a3 && a3 <= a2) {
1642 if (a3 <= a1 && a1 <= a4) {
1651 if (p11.
x() != p12.
x()) {
1652 *mu = (a - p11.
x()) / (p12.
x() - p11.
x());
1654 *y = p11.
y() + (*mu) * (p12.
y() - p11.
y());
1658 if (p12.
y() == p11.
y()) {
1661 *mu = (a - p11.
y()) / (p12.
y() - p11.
y());
1670 if (fabs(denominator) < eps) {
1674 double mua = numera / denominator;
1676 if (fabs(p12.
x() - p22.
x()) < eps && fabs(p12.
y() - p22.
y()) < eps) {
1679 const double offseta = withinDist / p11.
distanceTo2D(p12);
1680 const double offsetb = withinDist / p21.
distanceTo2D(p22);
1681 const double mub = numerb / denominator;
1682 if (mua < -offseta || mua > 1 + offseta || mub < -offsetb || mub > 1 + offsetb) {
1687 *x = p11.
x() + mua * (p12.
x() - p11.
x());
1688 *y = p11.
y() + mua * (p12.
y() - p11.
y());
1697 const double s = sin(angle);
1698 const double c = cos(angle);
1699 for (
int i = 0; i < (int)size(); i++) {
1700 const double x = (*this)[i].x();
1701 const double y = (*this)[i].y();
1702 const double z = (*this)[i].z();
1703 const double xnew = x * c - y * s;
1704 const double ynew = x * s + y * c;
1705 (*this)[i].set(xnew, ynew, z);
1735 bool changed =
true;
1736 while (changed && result.size() > 3) {
1738 for (
int i = 0; i < (int)result.size(); i++) {
1740 const Position& p2 = result[(i + 2) % result.size()];
1741 const int middleIndex = (i + 1) % result.size();
1742 const Position& p0 = result[middleIndex];
1744 const double triangleArea2 = fabs((p2.
y() - p1.
y()) * p0.
x() - (p2.
x() - p1.
x()) * p0.
y() + p2.
x() * p1.
y() - p2.
y() * p1.
x());
1746 if (distIK > NUMERICAL_EPS && triangleArea2 / distIK < NUMERICAL_EPS) {
1748 result.erase(result.begin() + middleIndex);
1768 if (!closed && (index == 0 || index == (
int)pv.size() - 1)) {
1772 const Position& a = pv[(index + (int)pv.size() - 1) % pv.size()];
1773 const Position& b = pv[(index + 1) % pv.size()];
1775 if (distAB <
MIN2(eps, NUMERICAL_EPS)) {
1781 const Position dir = (b - a) / distAB;
1782 const double projectedLength = (a - p).dotProduct(dir);
1783 if (projectedLength <= -distAB) {
1786 if (projectedLength >= 0.) {
1789 const Position distVector = (a - p) - dir * projectedLength;
1790 return distVector.
length();
1792 std::vector<double> scores;
1793 double minScore = eps + 1.;
1795 for (
int i = 0; i < (int)size(); i++) {
1796 scores.push_back(calcScore(*
this, i));
1797 if (scores.back() < minScore) {
1798 minScore = scores.back();
1802 if (minScore >= eps) {
1806 while (minScore < eps) {
1807 result.erase(result.begin() + minIndex);
1808 if (result.size() < 3) {
1811 scores.erase(scores.begin() + minIndex);
1812 const int prevIndex = (minIndex + (int)result.size() - 1) % result.size();
1813 scores[prevIndex] = calcScore(result, prevIndex);
1814 scores[minIndex % result.size()] = calcScore(result, minIndex % result.size());
1815 minScore = eps + 1.;
1816 for (
int i = 0; i < (int)result.size(); i++) {
1817 if (scores[i] < minScore) {
1818 minScore = scores[i];
1840 result.push_back(base);
1841 if (fabs(baseOffset - closestOffset) > NUMERICAL_EPS) {
1842 result.push_back(tmp[closestIndex]);
1843 if ((closestOffset < baseOffset) != before) {
1846 }
else if (before) {
1848 if (closestIndex > 0) {
1849 result.push_back(tmp[closestIndex - 1]);
1851 result.push_back(tmp[1]);
1856 if (closestIndex < (
int)size() - 1) {
1857 result.push_back(tmp[closestIndex + 1]);
1859 result.push_back(tmp[-1]);
1865 result.
add(base * -1);
1878 const double z0 = (*this)[0].z();
1880 const double dz = (*this)[1].z() - z0;
1882 if (size() > 2 && dz != 0) {
1888 if (pDist.
distanceTo2D((*
this)[iLast]) > POSITION_EPS * 20) {
1892 const double dz2 = result[iLast].z() - z0;
1894 for (
int i = 1; i < iLast; ++i) {
1895 seen += result[i].distanceTo2D(result[i - 1]);
1896 result[i].set(result[i].x(), result[i].y(), z0 + dz2 * seen / dist2);
1910 result[0].setz(zStart);
1911 result[-1].setz(zEnd);
1912 const double dz = zEnd - zStart;
1915 for (
int i = 1; i < (int)size() - 1; ++i) {
1916 seen += result[i].distanceTo2D(result[i - 1]);
1917 result[i].setz(zStart + dz * seen /
length);
1926 if (maxLength == 0) {
1930 if (
length < POSITION_EPS) {
1934 for (
double pos = 0; pos <=
length; pos += maxLength) {
1938 if (adjustEnd && !result.empty() && (result.back() != back())) {
1940 result.push_back(back());
1948 if (index < 0 || index >= (
int)size()) {
1952 for (
int i = 1; i <= index; ++i) {
1953 seen += (*this)[i].distanceTo2D((*
this)[i - 1]);
1962 for (
int i = 1; i < (int)size(); ++i) {
1963 const Position& p1 = (*this)[i - 1];
1965 const double distZ = fabs(p1.
z() - p2.
z());
1968 maxJump =
MAX2(maxJump, distZ);
1970 result =
MAX2(result, distZ / dist2D);
1979 double minZ = std::numeric_limits<double>::max();
1981 minZ =
MIN2(minZ, i.z());
1990 assert(size() < 33);
1991 static const double fac[33] = {
1992 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,
1993 6227020800.0, 87178291200.0, 1307674368000.0, 20922789888000.0, 355687428096000.0, 6402373705728000.0,
1994 121645100408832000.0, 2432902008176640000.0, 51090942171709440000.0, 1124000727777607680000.0,
1995 25852016738884976640000.0, 620448401733239439360000.0, 15511210043330985984000000.0,
1996 403291461126605635584000000.0, 10888869450418352160768000000.0, 304888344611713860501504000000.0,
1997 8841761993739701954543616000000.0, 265252859812191058636308480000000.0,
1998 8222838654177922817725562880000000.0, 263130836933693530167218012160000000.0
2001 const int npts = (int)size();
2003 const double step = (double) 1.0 / (numPoints - 1);
2006 for (
int i1 = 0; i1 < numPoints; i1++) {
2007 if ((1.0 - t) < 5e-6) {
2010 double x = 0., y = 0., z = 0.;
2011 for (
int i = 0; i < npts; i++) {
2012 const double ti = (i == 0) ? 1.0 : pow(t, i);
2013 const double tni = (npts == i + 1) ? 1.0 : pow(1 - t, npts - i - 1);
2014 const double basis = fac[npts - 1] / (fac[i] * fac[npts - 1 - i]) * ti * tni;
2015 x += basis * at(i).x();
2016 y += basis * at(i).y();
2017 z += basis * at(i).z();
2021 if (prev != current && !std::isnan(x) && !std::isnan(y) && !std::isnan(z)) {
2022 ret.push_back(current);
2037 const double y_min = std::min_element(begin(), end(), [](
Position p1,
Position p2) {
2038 return p1.
y() < p2.
y();
2040 const double gap = y_min > 0.0 ? 0.0 : y_min;
2042 const int last = (int)size() - 1;
2043 for (
int i = 0; i < last; i++) {
2044 const Position& firstPoint = at(i);
2045 const Position& secondPoint = at(i + 1);
2046 area += (secondPoint.
x() - firstPoint.
x()) / (secondPoint.
y() + firstPoint.
y()) / 2.0;
2048 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....