56 std::copy(v.begin(), v.end(), std::back_inserter(*
this));
61 std::copy(beg, end, std::back_inserter(*
this));
86 for (const_iterator i = begin(); i != (end() - 1); i++) {
92 (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());
104 return (!(fabs(angle) <
M_PI));
118 for (const_iterator i = begin(); i != end() - 1; i++) {
119 if (poly.
crosses(*i, *(i + 1))) {
123 if (size() > 2 && poly.
crosses(back(), front())) {
134 if ((size() == 0) || (poly.size() == 0)) {
138 for (const_iterator i = begin(); i != end() - 1; i++) {
141 if (fabs(closest.
z() - (*i).z()) < zThreshold) {
147 for (const_iterator i = poly.begin(); i != poly.end() - 1; i++) {
150 if (fabs(closest.
z() - (*i).z()) < zThreshold) {
164 for (const_iterator i = begin(); i != end() - 1; i++) {
178 for (const_iterator i = begin(); i != end() - 1; i++) {
189 for (const_iterator i = begin(); i != end() - 1; i++) {
191 if (
intersects(*i, *(i + 1), p1, p2, withinDist, &x, &y, &m)) {
201 for (const_iterator i = begin(); i != end() - 1; i++) {
219 if (index >= 0 && index < (
int)size()) {
221 }
else if (index < 0 && -index <= (
int)size()) {
222 return at((
int)size() + index);
238 if (index >= 0 && index < (
int)size()) {
240 }
else if (index < 0 && -index <= (
int)size()) {
241 return at((
int)size() + index);
256 const_iterator i = begin();
257 double seenLength = 0;
259 const double nextLength = (*i).distanceTo(*(i + 1));
260 if (seenLength + nextLength > pos) {
263 seenLength += nextLength;
264 }
while (++i != end() - 1);
265 if (lateralOffset == 0 || size() < 2) {
268 return positionAtOffset(*(end() - 2), *(end() - 1), (*(end() - 2)).distanceTo(*(end() - 1)), lateralOffset);
281 const_iterator i = begin();
282 double seenLength = 0;
284 const double nextLength = (*i).distanceTo(*(i + 1));
285 if (seenLength + nextLength > pos) {
288 seenLength += nextLength;
289 }
while (++i != end() - 1);
290 return sidePositionAtAngle(*(end() - 2), *(end() - 1), (*(end() - 2)).distanceTo(*(end() - 1)), lateralOffset, angle);
302 const_iterator i = begin();
303 double seenLength = 0;
305 const double nextLength = (*i).distanceTo2D(*(i + 1));
306 if (seenLength + nextLength > pos) {
309 seenLength += nextLength;
310 }
while (++i != end() - 1);
317 if ((size() == 0) || (size() == 1)) {
323 const_iterator i = begin();
324 double seenLength = 0;
329 if (seenLength + nextLength > pos) {
332 seenLength += nextLength;
333 }
while (++i != end() - 1);
351 const_iterator i = begin();
352 double seenLength = 0;
357 if (seenLength + nextLength > pos) {
360 seenLength += nextLength;
361 }
while (++i != end() - 1);
371 if (pos < 0. || dist < pos) {
374 if (lateralOffset != 0) {
382 return p1 + (p2 - p1) * (pos / dist) + offset;
387 return p1 + (p2 - p1) * (pos / dist);
394 if (pos < 0. || dist < pos || dist == 0) {
398 const Position offset(cos(angle) * lateralOffset, sin(angle) * lateralOffset);
399 return p1 + (p2 - p1) * (pos / dist) + offset;
406 if (pos < 0 || dist < pos) {
409 if (lateralOffset != 0) {
414 return p1 + (p2 - p1) * (pos / dist) + offset;
419 return p1 + (p2 - p1) * (pos / dist);
446 return Position(x / (
double) size(), y / (
double) size(), z / (
double)size());
454 }
else if (size() == 1) {
456 }
else if (size() == 2) {
457 return ((*
this)[0] + (*
this)[1]) * 0.5;
461 tmp.push_back(tmp[0]);
467 const int endIndex = (int)tmp.size() - 1;
471 if (tmp.
area() != 0) {
473 for (
int i = 0; i < endIndex; i++) {
474 const double z = tmp[i].x() * tmp[i + 1].y() - tmp[i + 1].x() * tmp[i].y();
476 x += (tmp[i].x() + tmp[i + 1].x()) * z;
477 y += (tmp[i].y() + tmp[i + 1].y()) * z;
480 result =
Position(x / div, y / div);
484 double lengthSum = 0;
485 for (
int i = 0; i < endIndex; i++) {
486 double length = tmp[i].distanceTo(tmp[i + 1]);
487 x += (tmp[i].x() + tmp[i + 1].x()) *
length / 2;
488 y += (tmp[i].y() + tmp[i + 1].y()) *
length / 2;
491 if (lengthSum == 0) {
495 result =
Position(x / lengthSum, y / lengthSum) + offset;
497 return result + offset;
504 for (
int i = 0; i < static_cast<int>(size()); i++) {
505 (*this)[i] = centroid + (((*this)[i] - centroid) * factor);
513 for (
int i = 0; i < static_cast<int>(size()); i++) {
514 (*this)[i] = centroid + (((*this)[i] - centroid) + offset);
535 for (const_iterator i = begin(); i != end() - 1; i++) {
536 len += (*i).distanceTo(*(i + 1));
548 for (const_iterator i = begin(); i != end() - 1; i++) {
549 len += (*i).distanceTo2D(*(i + 1));
563 tmp.push_back(tmp[0]);
565 const int endIndex = (int)tmp.size() - 1;
567 for (
int i = 0; i < endIndex; i++) {
568 area += tmp[i].x() * tmp[i + 1].y() - tmp[i + 1].x() * tmp[i].y();
582 for (const_iterator i = begin(); i != end(); i++) {
583 if (poly.
around(*i, offset)) {
597std::pair<PositionVector, PositionVector>
603 if (where < 0 || where > len) {
606 if (where <= POSITION_EPS || where >= len - POSITION_EPS) {
610 first.push_back((*
this)[0]);
612 const_iterator it = begin() + 1;
613 double next = use2D ? first.back().distanceTo2D(*it) : first.back().distanceTo(*it);
615 while (where >= seen + next + POSITION_EPS) {
617 first.push_back(*it);
619 next = use2D ? first.back().distanceTo2D(*it) : first.back().distanceTo(*it);
621 if (fabs(where - (seen + next)) > POSITION_EPS || it == end() - 1) {
630 first.push_back(*it);
633 for (; it != end(); it++) {
634 second.push_back(*it);
636 assert(first.size() >= 2);
637 assert(second.size() >= 2);
638 assert(first.back() == second.front());
640 return std::pair<PositionVector, PositionVector>(first, second);
646 for (PositionVector::const_iterator i = geom.begin(); i != geom.end(); i++) {
647 if (i != geom.begin()) {
664 for (
int i = 0; i < (int)size(); i++) {
665 (*this)[i].add(xoff, yoff, zoff);
672 add(-offset.
x(), -offset.
y(), -offset.
z());
678 add(offset.
x(), offset.
y(), offset.
z());
685 for (
auto i1 = begin(); i1 != end(); ++i1) {
686 pv.push_back(*i1 + offset);
694 for (
int i = 0; i < (int)size(); i++) {
695 (*this)[i].mul(1, -1);
705 return atan2(p1.
x(), p1.
y()) < atan2(p2.
x(), p2.
y());
720 if (p1.
x() != p2.
x()) {
721 return p1.
x() < p2.
x();
723 return p1.
y() < p2.
y();
729 return (P1.
x() - P0.
x()) * (P2.
y() - P0.
y()) - (P2.
x() - P0.
x()) * (P1.
y() - P0.
y());
735 if ((size() > 0) && (v.size() > 0) && (back().distanceTo(v[0]) < sameThreshold)) {
736 copy(v.begin() + 1, v.end(), back_inserter(*
this));
738 copy(v.begin(), v.end(), back_inserter(*
this));
745 if ((size() > 0) && (v.size() > 0) && (front().distanceTo(v.back()) < sameThreshold)) {
746 insert(begin(), v.begin(), v.end() - 1);
748 insert(begin(), v.begin(), v.end());
757 if (beginOffset > POSITION_EPS) {
761 if (endOffset <
length() - POSITION_EPS) {
764 ret.push_back(begPos);
767 const_iterator i = begin();
769 while ((i + 1) != end()
771 seen + (*i).distanceTo(*(i + 1)) < beginOffset) {
772 seen += (*i).distanceTo(*(i + 1));
776 while ((i + 1) != end()
778 seen + (*i).distanceTo(*(i + 1)) < endOffset) {
781 seen += (*i).distanceTo(*(i + 1));
786 if (ret.size() == 1) {
787 ret.push_back(endPos);
800 if (beginOffset > POSITION_EPS) {
804 if (endOffset <
length2D() - POSITION_EPS) {
807 ret.push_back(begPos);
810 const_iterator i = begin();
812 while ((i + 1) != end()
814 seen + (*i).distanceTo2D(*(i + 1)) < beginOffset) {
815 seen += (*i).distanceTo2D(*(i + 1));
819 while ((i + 1) != end()
821 seen + (*i).distanceTo2D(*(i + 1)) < endOffset) {
824 seen += (*i).distanceTo2D(*(i + 1));
829 if (ret.size() == 1) {
830 ret.push_back(endPos);
841 if (beginIndex < 0) {
842 beginIndex += (int)size();
845 assert(beginIndex < (
int)size());
846 assert(beginIndex + count <= (
int)size());
848 for (
int i = beginIndex; i < beginIndex + count; ++i) {
849 result.push_back((*
this)[i]);
860 return front().angleTo2D(back());
869 double minDist = std::numeric_limits<double>::max();
872 for (const_iterator i = begin(); i != end() - 1; i++) {
876 if (dist < minDist) {
877 nearestPos = pos + seen;
883 if (cornerDist < minDist) {
888 if (pos1 == (*(i - 1)).distanceTo2D(*i) && pos2 == 0.) {
890 minDist = cornerDist;
894 seen += (*i).distanceTo2D(*(i + 1));
905 double minDist = std::numeric_limits<double>::max();
908 for (const_iterator i = begin(); i != end() - 1; i++) {
912 if (dist < minDist) {
913 const double pos25D = pos * (*i).distanceTo(*(i + 1)) / (*i).distanceTo2D(*(i + 1));
914 nearestPos = pos25D + seen;
920 if (cornerDist < minDist) {
925 if (pos1 == (*(i - 1)).distanceTo2D(*i) && pos2 == 0.) {
927 minDist = cornerDist;
931 seen += (*i).distanceTo(*(i + 1));
949 double minDist = std::numeric_limits<double>::max();
950 double nearestPos = -1;
953 for (const_iterator i = begin(); i != end() - 1; i++) {
957 if (dist < minDist) {
958 nearestPos = pos + seen;
960 sign =
isLeft(*i, *(i + 1), p) >= 0 ? -1 : 1;
965 if (cornerDist < minDist) {
970 if (pos1 == (*(i - 1)).distanceTo2D(*i) && pos2 == 0.) {
972 minDist = cornerDist;
973 sign =
isLeft(*(i - 1), *i, p) >= 0 ? -1 : 1;
977 seen += (*i).distanceTo2D(*(i + 1));
979 if (nearestPos != -1) {
980 return Position(nearestPos, sign * minDist);
992 double minDist = std::numeric_limits<double>::max();
995 for (
int i = 0; i < (int)size(); i++) {
998 if (dist < minDist) {
1012 double minDist = std::numeric_limits<double>::max();
1013 int insertionIndex = 1;
1014 for (
int i = 0; i < (int)size() - 1; i++) {
1018 if (dist < minDist) {
1019 insertionIndex = i + 1;
1026 const double previousZ = (begin() + (insertionIndex - 1))->z();
1027 const double nextZ = (begin() + insertionIndex)->z();
1029 insert(begin() + insertionIndex,
Position(p.
x(), p.
y(), ((previousZ + nextZ) / 2.0)));
1031 insert(begin() + insertionIndex, p);
1033 return insertionIndex;
1042 double minDist = std::numeric_limits<double>::max();
1043 int removalIndex = 0;
1044 for (
int i = 0; i < (int)size(); i++) {
1046 if (dist < minDist) {
1051 erase(begin() + removalIndex);
1052 return removalIndex;
1058 std::vector<double> ret;
1059 if (other.size() == 0) {
1062 for (const_iterator i = other.begin(); i != other.end() - 1; i++) {
1064 copy(atSegment.begin(), atSegment.end(), back_inserter(ret));
1072 std::vector<double> ret;
1077 for (const_iterator i = begin(); i != end() - 1; i++) {
1081 if (
intersects(p1, p2, lp1, lp2, 0., &x, &y, &m)) {
1137 for (const_reverse_iterator i = rbegin(); i != rend(); i++) {
1147 return Position((beg.
y() - end.
y()) * scale, (end.
x() - beg.
x()) * scale);
1157 if (
length2D() == 0 || amount == 0) {
1161 std::vector<int> recheck;
1162 for (
int i = 0; i < static_cast<int>(size()); i++) {
1165 const Position& to = (*this)[i + 1];
1167 shape.push_back(from -
sideOffset(from, to, amount));
1168#ifdef DEBUG_MOVE2SIDE
1170 std::cout <<
" " << i <<
"a=" << shape.back() <<
"\n";
1174 }
else if (i ==
static_cast<int>(size()) - 1) {
1175 const Position& from = (*this)[i - 1];
1178 shape.push_back(to -
sideOffset(from, to, amount));
1179#ifdef DEBUG_MOVE2SIDE
1181 std::cout <<
" " << i <<
"b=" << shape.back() <<
"\n";
1186 const Position& from = (*this)[i - 1];
1188 const Position& to = (*this)[i + 1];
1191 const double extrapolateDev = fromMe[1].distanceTo2D(to);
1192 if (fabs(extrapolateDev) < POSITION_EPS) {
1194 shape.push_back(me -
sideOffset(from, to, amount));
1195#ifdef DEBUG_MOVE2SIDE
1197 std::cout <<
" " << i <<
"c=" << shape.back() <<
"\n";
1200 }
else if (fabs(extrapolateDev - 2 * me.
distanceTo2D(to)) < POSITION_EPS) {
1204 shape.push_back(fromMe2[1]);
1205#ifdef DEBUG_MOVE2SIDE
1207 std::cout <<
" " << i <<
"d=" << shape.back() <<
" " << i <<
"_from=" << from <<
" " << i <<
"_me=" << me <<
" " << i <<
"_to=" << to <<
"\n";
1217 recheck.push_back(i);
1221 shape.push_back(meNew);
1222#ifdef DEBUG_MOVE2SIDE
1224 std::cout <<
" " << i <<
"e=" << shape.back() <<
"\n";
1229 shape.back().set(shape.back().x(), shape.back().y(), me.
z());
1230 const double angle =
localAngle(from, me, to);
1231 if (fabs(angle) > NUMERICAL_EPS) {
1233 const double radius =
length / angle;
1234#ifdef DEBUG_MOVE2SIDE
1236 std::cout <<
" i=" << i <<
" a=" <<
RAD2DEG(angle) <<
" l=" <<
length <<
" r=" << radius <<
" t=" << amount * 1.8 <<
"\n";
1239 if ((radius < 0 && -radius < amount * 1.8) || fabs(
RAD2DEG(angle)) > 170) {
1240 recheck.push_back(i);
1245 if (!recheck.empty()) {
1248 for (
int i = (
int)recheck.size() - 1; i >= 0; i--) {
1249 shape.erase(shape.begin() + recheck[i]);
1265 if (size() != amount.size()) {
1267 +
") does not match number of points (" +
toString(size()) +
")");
1270 for (
int i = 0; i < static_cast<int>(size()); i++) {
1273 const Position& to = (*this)[i + 1];
1275 shape.push_back(from -
sideOffset(from, to, amount[i]));
1277 }
else if (i ==
static_cast<int>(size()) - 1) {
1278 const Position& from = (*this)[i - 1];
1281 shape.push_back(to -
sideOffset(from, to, amount[i]));
1284 const Position& from = (*this)[i - 1];
1286 const Position& to = (*this)[i + 1];
1289 const double extrapolateDev = fromMe[1].distanceTo2D(to);
1290 if (fabs(extrapolateDev) < POSITION_EPS) {
1292 shape.push_back(me -
sideOffset(from, to, amount[i]));
1293 }
else if (fabs(extrapolateDev - 2 * me.
distanceTo2D(to)) < POSITION_EPS) {
1297 shape.push_back(fromMe2[1]);
1308 shape.push_back(meNew);
1311 shape.back().set(shape.back().x(), shape.back().y(), me.
z());
1324 if ((pos + 1) < (
int)size()) {
1325 return (*
this)[pos].angleTo2D((*
this)[pos + 1]);
1334 if ((size() != 0) && ((*
this)[0] != back())) {
1335 push_back((*
this)[0]);
1342 std::vector<double> ret;
1344 for (i = begin(); i != end(); i++) {
1345 const double dist = s.
distance2D(*i, perpendicular);
1347 ret.push_back(dist);
1350 for (i = s.begin(); i != s.end(); i++) {
1351 const double dist =
distance2D(*i, perpendicular);
1353 ret.push_back(dist);
1363 return std::numeric_limits<double>::max();
1364 }
else if (size() == 1) {
1365 return front().distanceTo(p);
1406 if ((size() == 0) || !p.
almostSame(front())) {
1414 if (at == begin()) {
1416 }
else if (at == end()) {
1428 return (size() >= 2) && ((*this)[0] == back());
1435 for (
auto i = begin(); i != end(); i++) {
1447 int curSize = (int)size() - beginOffset - endOffset;
1449 iterator last = begin() + beginOffset;
1450 for (iterator i = last + 1; i != (end() - endOffset) && (!assertLength || curSize > 2);) {
1451 if (last->almostSame(*i, minDist)) {
1452 if (i + 1 == end() - endOffset) {
1454 if (
resample && last > begin() && (last - 1)->distanceTo(*i) >= 2 * minDist) {
1456 const double shiftBack = minDist - last->distanceTo(*i);
1458 (*last) =
positionAtOffset(*(last - 1), *last, (last - 1)->distanceTo(*last) - shiftBack);
1464 i = end() - endOffset;
1467 if (
resample && i + 1 != end() && last->distanceTo(*(i + 1)) >= 2 * minDist) {
1469 const double shiftForward = minDist - last->distanceTo(*i);
1491 return static_cast<vp>(*this) ==
static_cast<vp>(v2);
1497 return static_cast<vp>(*this) !=
static_cast<vp>(v2);
1503 WRITE_ERROR(
TL(
"Trying to subtract PositionVectors of different lengths."));
1507 auto i2 = v2.begin();
1508 while (i1 != end()) {
1517 WRITE_ERROR(
TL(
"Trying to subtract PositionVectors of different lengths."));
1521 auto i2 = v2.begin();
1522 while (i1 != end()) {
1530 if (size() != v2.size()) {
1533 auto i2 = v2.begin();
1534 for (
auto i1 = begin(); i1 != end(); i1++) {
1535 if (!i1->almostSame(*i2, maxDiv)) {
1548 for (const_iterator i = begin(); i != end(); i++) {
1549 if ((*i).z() != 0) {
1559 const double eps = std::numeric_limits<double>::epsilon();
1560 const double denominator = (p22.
y() - p21.
y()) * (p12.
x() - p11.
x()) - (p22.
x() - p21.
x()) * (p12.
y() - p11.
y());
1561 const double numera = (p22.
x() - p21.
x()) * (p11.
y() - p21.
y()) - (p22.
y() - p21.
y()) * (p11.
x() - p21.
x());
1562 const double numerb = (p12.
x() - p11.
x()) * (p11.
y() - p21.
y()) - (p12.
y() - p11.
y()) * (p11.
x() - p21.
x());
1564 if (fabs(numera) < eps && fabs(numerb) < eps && fabs(denominator) < eps) {
1570 if (p11.
x() != p12.
x()) {
1571 a1 = p11.
x() < p12.
x() ? p11.
x() : p12.
x();
1572 a2 = p11.
x() < p12.
x() ? p12.
x() : p11.
x();
1573 a3 = p21.
x() < p22.
x() ? p21.
x() : p22.
x();
1574 a4 = p21.
x() < p22.
x() ? p22.
x() : p21.
x();
1576 a1 = p11.
y() < p12.
y() ? p11.
y() : p12.
y();
1577 a2 = p11.
y() < p12.
y() ? p12.
y() : p11.
y();
1578 a3 = p21.
y() < p22.
y() ? p21.
y() : p22.
y();
1579 a4 = p21.
y() < p22.
y() ? p22.
y() : p21.
y();
1581 if (a1 <= a3 && a3 <= a2) {
1588 if (a3 <= a1 && a1 <= a4) {
1597 if (p11.
x() != p12.
x()) {
1598 *mu = (a - p11.
x()) / (p12.
x() - p11.
x());
1600 *y = p11.
y() + (*mu) * (p12.
y() - p11.
y());
1604 if (p12.
y() == p11.
y()) {
1607 *mu = (a - p11.
y()) / (p12.
y() - p11.
y());
1616 if (fabs(denominator) < eps) {
1620 double mua = numera / denominator;
1622 if (fabs(p12.
x() - p22.
x()) < eps && fabs(p12.
y() - p22.
y()) < eps) {
1625 const double offseta = withinDist / p11.
distanceTo2D(p12);
1626 const double offsetb = withinDist / p21.
distanceTo2D(p22);
1627 const double mub = numerb / denominator;
1628 if (mua < -offseta || mua > 1 + offseta || mub < -offsetb || mub > 1 + offsetb) {
1633 *x = p11.
x() + mua * (p12.
x() - p11.
x());
1634 *y = p11.
y() + mua * (p12.
y() - p11.
y());
1643 const double s = sin(angle);
1644 const double c = cos(angle);
1645 for (
int i = 0; i < (int)size(); i++) {
1646 const double x = (*this)[i].x();
1647 const double y = (*this)[i].y();
1648 const double z = (*this)[i].z();
1649 const double xnew = x * c - y * s;
1650 const double ynew = x * s + y * c;
1651 (*this)[i].set(xnew, ynew, z);
1659 bool changed =
true;
1660 while (changed && result.size() > 3) {
1662 for (
int i = 0; i < (int)result.size(); i++) {
1664 const Position& p2 = result[(i + 2) % result.size()];
1665 const int middleIndex = (i + 1) % result.size();
1666 const Position& p0 = result[middleIndex];
1668 const double triangleArea2 = fabs((p2.
y() - p1.
y()) * p0.
x() - (p2.
x() - p1.
x()) * p0.
y() + p2.
x() * p1.
y() - p2.
y() * p1.
x());
1670 if (distIK > NUMERICAL_EPS && triangleArea2 / distIK < NUMERICAL_EPS) {
1672 result.erase(result.begin() + middleIndex);
1694 result.push_back(base);
1695 if (fabs(baseOffset - closestOffset) > NUMERICAL_EPS) {
1696 result.push_back(tmp[closestIndex]);
1697 if ((closestOffset < baseOffset) != before) {
1700 }
else if (before) {
1702 if (closestIndex > 0) {
1703 result.push_back(tmp[closestIndex - 1]);
1705 result.push_back(tmp[1]);
1710 if (closestIndex < (
int)size() - 1) {
1711 result.push_back(tmp[closestIndex + 1]);
1713 result.push_back(tmp[-1]);
1719 result.
add(base * -1);
1732 const double z0 = (*this)[0].z();
1734 const double dz = (*this)[1].z() - z0;
1736 if (size() > 2 && dz != 0) {
1742 if (pDist.
distanceTo2D((*
this)[iLast]) > POSITION_EPS * 20) {
1746 const double dz2 = result[iLast].z() - z0;
1748 for (
int i = 1; i < iLast; ++i) {
1749 seen += result[i].distanceTo2D(result[i - 1]);
1750 result[i].set(result[i].x(), result[i].y(), z0 + dz2 * seen / dist2);
1764 result[0].setz(zStart);
1765 result[-1].setz(zEnd);
1766 const double dz = zEnd - zStart;
1769 for (
int i = 1; i < (int)size() - 1; ++i) {
1770 seen += result[i].distanceTo2D(result[i - 1]);
1771 result[i].setz(zStart + dz * seen /
length);
1780 if (maxLength == 0) {
1784 if (
length < POSITION_EPS) {
1788 for (
double pos = 0; pos <=
length; pos += maxLength) {
1792 if (adjustEnd && !result.empty() && (result.back() != back())) {
1794 result.push_back(back());
1802 if (index < 0 || index >= (
int)size()) {
1806 for (
int i = 1; i <= index; ++i) {
1807 seen += (*this)[i].distanceTo2D((*
this)[i - 1]);
1816 for (
int i = 1; i < (int)size(); ++i) {
1817 const Position& p1 = (*this)[i - 1];
1819 const double distZ = fabs(p1.
z() - p2.
z());
1822 maxJump =
MAX2(maxJump, distZ);
1824 result =
MAX2(result, distZ / dist2D);
1834 assert(size() < 33);
1835 static const double fac[33] = {
1836 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,
1837 6227020800.0, 87178291200.0, 1307674368000.0, 20922789888000.0, 355687428096000.0, 6402373705728000.0,
1838 121645100408832000.0, 2432902008176640000.0, 51090942171709440000.0, 1124000727777607680000.0,
1839 25852016738884976640000.0, 620448401733239439360000.0, 15511210043330985984000000.0,
1840 403291461126605635584000000.0, 10888869450418352160768000000.0, 304888344611713860501504000000.0,
1841 8841761993739701954543616000000.0, 265252859812191058636308480000000.0,
1842 8222838654177922817725562880000000.0, 263130836933693530167218012160000000.0
1845 const int npts = (int)size();
1847 const double step = (double) 1.0 / (numPoints - 1);
1850 for (
int i1 = 0; i1 < numPoints; i1++) {
1851 if ((1.0 - t) < 5e-6) {
1854 double x = 0., y = 0., z = 0.;
1855 for (
int i = 0; i < npts; i++) {
1856 const double ti = (i == 0) ? 1.0 : pow(t, i);
1857 const double tni = (npts == i + 1) ? 1.0 : pow(1 - t, npts - i - 1);
1858 const double basis = fac[npts - 1] / (fac[i] * fac[npts - 1 - i]) * ti * tni;
1859 x += basis * at(i).x();
1860 y += basis * at(i).y();
1861 z += basis * at(i).z();
1865 if (prev != current && !std::isnan(x) && !std::isnan(y) && !std::isnan(z)) {
1866 ret.push_back(current);
#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 slopeTo2D(const Position &other) const
returns the slope of the vector pointing from here to the other position
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 dimension
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
bool almostSame(const Position &p2, double maxDiv=POSITION_EPS) const
check if two position is almost the sme as other
double y() const
Returns the y-position.
int operator()(const Position &p1, const Position &p2) const
comparing operation for sort
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
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 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 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 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)
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 ammount
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
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)
int insertAtClosest(const Position &p, bool interpolateZ)
inserts p between the two closest positions
void push_front(const Position &p)
insert in front a Position
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
Position positionAtOffset2D(double pos, double lateralOffset=0) const
Returns the position at the given length.
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....