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).distanceTo2D(*(i + 1));
285 if (seenLength + nextLength > pos) {
288 seenLength += nextLength;
289 }
while (++i != end() - 1);
296 if ((size() == 0) || (size() == 1)) {
302 const_iterator i = begin();
303 double seenLength = 0;
308 if (seenLength + nextLength > pos) {
311 seenLength += nextLength;
312 }
while (++i != end() - 1);
330 const_iterator i = begin();
331 double seenLength = 0;
336 if (seenLength + nextLength > pos) {
339 seenLength += nextLength;
340 }
while (++i != end() - 1);
350 if (pos < 0. || dist < pos) {
353 if (lateralOffset != 0) {
361 return p1 + (p2 - p1) * (pos / dist) + offset;
366 return p1 + (p2 - p1) * (pos / dist);
373 if (pos < 0 || dist < pos) {
376 if (lateralOffset != 0) {
381 return p1 + (p2 - p1) * (pos / dist) + offset;
386 return p1 + (p2 - p1) * (pos / dist);
413 return Position(x / (
double) size(), y / (
double) size(), z / (
double)size());
421 }
else if (size() == 1) {
423 }
else if (size() == 2) {
424 return ((*
this)[0] + (*
this)[1]) * 0.5;
428 tmp.push_back(tmp[0]);
434 const int endIndex = (int)tmp.size() - 1;
438 if (tmp.
area() != 0) {
440 for (
int i = 0; i < endIndex; i++) {
441 const double z = tmp[i].x() * tmp[i + 1].y() - tmp[i + 1].x() * tmp[i].y();
443 x += (tmp[i].x() + tmp[i + 1].x()) * z;
444 y += (tmp[i].y() + tmp[i + 1].y()) * z;
447 result =
Position(x / div, y / div);
451 double lengthSum = 0;
452 for (
int i = 0; i < endIndex; i++) {
453 double length = tmp[i].distanceTo(tmp[i + 1]);
454 x += (tmp[i].x() + tmp[i + 1].x()) *
length / 2;
455 y += (tmp[i].y() + tmp[i + 1].y()) *
length / 2;
458 if (lengthSum == 0) {
462 result =
Position(x / lengthSum, y / lengthSum) + offset;
464 return result + offset;
471 for (
int i = 0; i < static_cast<int>(size()); i++) {
472 (*this)[i] = centroid + (((*this)[i] - centroid) * factor);
480 for (
int i = 0; i < static_cast<int>(size()); i++) {
481 (*this)[i] = centroid + (((*this)[i] - centroid) + offset);
502 for (const_iterator i = begin(); i != end() - 1; i++) {
503 len += (*i).distanceTo(*(i + 1));
515 for (const_iterator i = begin(); i != end() - 1; i++) {
516 len += (*i).distanceTo2D(*(i + 1));
530 tmp.push_back(tmp[0]);
532 const int endIndex = (int)tmp.size() - 1;
534 for (
int i = 0; i < endIndex; i++) {
535 area += tmp[i].x() * tmp[i + 1].y() - tmp[i + 1].x() * tmp[i].y();
549 for (const_iterator i = begin(); i != end(); i++) {
550 if (poly.
around(*i, offset)) {
564std::pair<PositionVector, PositionVector>
570 if (where < 0 || where > len) {
573 if (where <= POSITION_EPS || where >= len - POSITION_EPS) {
577 first.push_back((*
this)[0]);
579 const_iterator it = begin() + 1;
580 double next = use2D ? first.back().distanceTo2D(*it) : first.back().distanceTo(*it);
582 while (where >= seen + next + POSITION_EPS) {
584 first.push_back(*it);
586 next = use2D ? first.back().distanceTo2D(*it) : first.back().distanceTo(*it);
588 if (fabs(where - (seen + next)) > POSITION_EPS || it == end() - 1) {
597 first.push_back(*it);
600 for (; it != end(); it++) {
601 second.push_back(*it);
603 assert(first.size() >= 2);
604 assert(second.size() >= 2);
605 assert(first.back() == second.front());
607 return std::pair<PositionVector, PositionVector>(first, second);
613 for (PositionVector::const_iterator i = geom.begin(); i != geom.end(); i++) {
614 if (i != geom.begin()) {
631 for (
int i = 0; i < (int)size(); i++) {
632 (*this)[i].add(xoff, yoff, zoff);
639 add(-offset.
x(), -offset.
y(), -offset.
z());
645 add(offset.
x(), offset.
y(), offset.
z());
652 for (
auto i1 = begin(); i1 != end(); ++i1) {
653 pv.push_back(*i1 + offset);
661 for (
int i = 0; i < (int)size(); i++) {
662 (*this)[i].mul(1, -1);
672 return atan2(p1.
x(), p1.
y()) < atan2(p2.
x(), p2.
y());
687 if (p1.
x() != p2.
x()) {
688 return p1.
x() < p2.
x();
690 return p1.
y() < p2.
y();
696 return (P1.
x() - P0.
x()) * (P2.
y() - P0.
y()) - (P2.
x() - P0.
x()) * (P1.
y() - P0.
y());
702 if ((size() > 0) && (v.size() > 0) && (back().distanceTo(v[0]) < sameThreshold)) {
703 copy(v.begin() + 1, v.end(), back_inserter(*
this));
705 copy(v.begin(), v.end(), back_inserter(*
this));
712 if ((size() > 0) && (v.size() > 0) && (front().distanceTo(v.back()) < sameThreshold)) {
713 insert(begin(), v.begin(), v.end() - 1);
715 insert(begin(), v.begin(), v.end());
724 if (beginOffset > POSITION_EPS) {
728 if (endOffset <
length() - POSITION_EPS) {
731 ret.push_back(begPos);
734 const_iterator i = begin();
736 while ((i + 1) != end()
738 seen + (*i).distanceTo(*(i + 1)) < beginOffset) {
739 seen += (*i).distanceTo(*(i + 1));
743 while ((i + 1) != end()
745 seen + (*i).distanceTo(*(i + 1)) < endOffset) {
748 seen += (*i).distanceTo(*(i + 1));
753 if (ret.size() == 1) {
754 ret.push_back(endPos);
767 if (beginOffset > POSITION_EPS) {
771 if (endOffset <
length2D() - POSITION_EPS) {
774 ret.push_back(begPos);
777 const_iterator i = begin();
779 while ((i + 1) != end()
781 seen + (*i).distanceTo2D(*(i + 1)) < beginOffset) {
782 seen += (*i).distanceTo2D(*(i + 1));
786 while ((i + 1) != end()
788 seen + (*i).distanceTo2D(*(i + 1)) < endOffset) {
791 seen += (*i).distanceTo2D(*(i + 1));
796 if (ret.size() == 1) {
797 ret.push_back(endPos);
808 if (beginIndex < 0) {
809 beginIndex += (int)size();
812 assert(beginIndex < (
int)size());
813 assert(beginIndex + count <= (
int)size());
815 for (
int i = beginIndex; i < beginIndex + count; ++i) {
816 result.push_back((*
this)[i]);
827 return front().angleTo2D(back());
836 double minDist = std::numeric_limits<double>::max();
839 for (const_iterator i = begin(); i != end() - 1; i++) {
843 if (dist < minDist) {
844 nearestPos = pos + seen;
850 if (cornerDist < minDist) {
855 if (pos1 == (*(i - 1)).distanceTo2D(*i) && pos2 == 0.) {
857 minDist = cornerDist;
861 seen += (*i).distanceTo2D(*(i + 1));
872 double minDist = std::numeric_limits<double>::max();
875 for (const_iterator i = begin(); i != end() - 1; i++) {
879 if (dist < minDist) {
880 const double pos25D = pos * (*i).distanceTo(*(i + 1)) / (*i).distanceTo2D(*(i + 1));
881 nearestPos = pos25D + seen;
887 if (cornerDist < minDist) {
892 if (pos1 == (*(i - 1)).distanceTo2D(*i) && pos2 == 0.) {
894 minDist = cornerDist;
898 seen += (*i).distanceTo(*(i + 1));
916 double minDist = std::numeric_limits<double>::max();
917 double nearestPos = -1;
920 for (const_iterator i = begin(); i != end() - 1; i++) {
924 if (dist < minDist) {
925 nearestPos = pos + seen;
927 sign =
isLeft(*i, *(i + 1), p) >= 0 ? -1 : 1;
932 if (cornerDist < minDist) {
937 if (pos1 == (*(i - 1)).distanceTo2D(*i) && pos2 == 0.) {
939 minDist = cornerDist;
940 sign =
isLeft(*(i - 1), *i, p) >= 0 ? -1 : 1;
944 seen += (*i).distanceTo2D(*(i + 1));
946 if (nearestPos != -1) {
947 return Position(nearestPos, sign * minDist);
959 double minDist = std::numeric_limits<double>::max();
962 for (
int i = 0; i < (int)size(); i++) {
965 if (dist < minDist) {
979 double minDist = std::numeric_limits<double>::max();
980 int insertionIndex = 1;
981 for (
int i = 0; i < (int)size() - 1; i++) {
985 if (dist < minDist) {
986 insertionIndex = i + 1;
993 const double previousZ = (begin() + (insertionIndex - 1))->z();
994 const double nextZ = (begin() + insertionIndex)->z();
996 insert(begin() + insertionIndex,
Position(p.
x(), p.
y(), ((previousZ + nextZ) / 2.0)));
998 insert(begin() + insertionIndex, p);
1000 return insertionIndex;
1009 double minDist = std::numeric_limits<double>::max();
1010 int removalIndex = 0;
1011 for (
int i = 0; i < (int)size(); i++) {
1013 if (dist < minDist) {
1018 erase(begin() + removalIndex);
1019 return removalIndex;
1025 std::vector<double> ret;
1026 if (other.size() == 0) {
1029 for (const_iterator i = other.begin(); i != other.end() - 1; i++) {
1031 copy(atSegment.begin(), atSegment.end(), back_inserter(ret));
1039 std::vector<double> ret;
1044 for (const_iterator i = begin(); i != end() - 1; i++) {
1048 if (
intersects(p1, p2, lp1, lp2, 0., &x, &y, &m)) {
1104 for (const_reverse_iterator i = rbegin(); i != rend(); i++) {
1114 return Position((beg.
y() - end.
y()) * scale, (end.
x() - beg.
x()) * scale);
1124 if (
length2D() == 0 || amount == 0) {
1128 std::vector<int> recheck;
1129 for (
int i = 0; i < static_cast<int>(size()); i++) {
1132 const Position& to = (*this)[i + 1];
1134 shape.push_back(from -
sideOffset(from, to, amount));
1135#ifdef DEBUG_MOVE2SIDE
1137 std::cout <<
" " << i <<
"a=" << shape.back() <<
"\n";
1141 }
else if (i ==
static_cast<int>(size()) - 1) {
1142 const Position& from = (*this)[i - 1];
1145 shape.push_back(to -
sideOffset(from, to, amount));
1146#ifdef DEBUG_MOVE2SIDE
1148 std::cout <<
" " << i <<
"b=" << shape.back() <<
"\n";
1153 const Position& from = (*this)[i - 1];
1155 const Position& to = (*this)[i + 1];
1158 const double extrapolateDev = fromMe[1].distanceTo2D(to);
1159 if (fabs(extrapolateDev) < POSITION_EPS) {
1161 shape.push_back(me -
sideOffset(from, to, amount));
1162#ifdef DEBUG_MOVE2SIDE
1164 std::cout <<
" " << i <<
"c=" << shape.back() <<
"\n";
1167 }
else if (fabs(extrapolateDev - 2 * me.
distanceTo2D(to)) < POSITION_EPS) {
1171 shape.push_back(fromMe2[1]);
1172#ifdef DEBUG_MOVE2SIDE
1174 std::cout <<
" " << i <<
"d=" << shape.back() <<
" " << i <<
"_from=" << from <<
" " << i <<
"_me=" << me <<
" " << i <<
"_to=" << to <<
"\n";
1184 recheck.push_back(i);
1188 shape.push_back(meNew);
1189#ifdef DEBUG_MOVE2SIDE
1191 std::cout <<
" " << i <<
"e=" << shape.back() <<
"\n";
1196 shape.back().set(shape.back().x(), shape.back().y(), me.
z());
1197 const double angle =
localAngle(from, me, to);
1198 if (fabs(angle) > NUMERICAL_EPS) {
1200 const double radius =
length / angle;
1201#ifdef DEBUG_MOVE2SIDE
1203 std::cout <<
" i=" << i <<
" a=" <<
RAD2DEG(angle) <<
" l=" <<
length <<
" r=" << radius <<
" t=" << amount * 1.8 <<
"\n";
1206 if ((radius < 0 && -radius < amount * 1.8) || fabs(
RAD2DEG(angle)) > 170) {
1207 recheck.push_back(i);
1212 if (!recheck.empty()) {
1215 for (
int i = (
int)recheck.size() - 1; i >= 0; i--) {
1216 shape.erase(shape.begin() + recheck[i]);
1232 if (size() != amount.size()) {
1234 +
") does not match number of points (" +
toString(size()) +
")");
1237 for (
int i = 0; i < static_cast<int>(size()); i++) {
1240 const Position& to = (*this)[i + 1];
1242 shape.push_back(from -
sideOffset(from, to, amount[i]));
1244 }
else if (i ==
static_cast<int>(size()) - 1) {
1245 const Position& from = (*this)[i - 1];
1248 shape.push_back(to -
sideOffset(from, to, amount[i]));
1251 const Position& from = (*this)[i - 1];
1253 const Position& to = (*this)[i + 1];
1256 const double extrapolateDev = fromMe[1].distanceTo2D(to);
1257 if (fabs(extrapolateDev) < POSITION_EPS) {
1259 shape.push_back(me -
sideOffset(from, to, amount[i]));
1260 }
else if (fabs(extrapolateDev - 2 * me.
distanceTo2D(to)) < POSITION_EPS) {
1264 shape.push_back(fromMe2[1]);
1275 shape.push_back(meNew);
1278 shape.back().set(shape.back().x(), shape.back().y(), me.
z());
1291 if ((pos + 1) < (
int)size()) {
1292 return (*
this)[pos].angleTo2D((*
this)[pos + 1]);
1301 if ((size() != 0) && ((*
this)[0] != back())) {
1302 push_back((*
this)[0]);
1309 std::vector<double> ret;
1311 for (i = begin(); i != end(); i++) {
1312 const double dist = s.
distance2D(*i, perpendicular);
1314 ret.push_back(dist);
1317 for (i = s.begin(); i != s.end(); i++) {
1318 const double dist =
distance2D(*i, perpendicular);
1320 ret.push_back(dist);
1330 return std::numeric_limits<double>::max();
1331 }
else if (size() == 1) {
1332 return front().distanceTo(p);
1373 if ((size() == 0) || !p.
almostSame(front())) {
1381 if (at == begin()) {
1383 }
else if (at == end()) {
1395 return (size() >= 2) && ((*this)[0] == back());
1402 for (
auto i = begin(); i != end(); i++) {
1414 int curSize = (int)size() - beginOffset - endOffset;
1416 iterator last = begin() + beginOffset;
1417 for (iterator i = last + 1; i != (end() - endOffset) && (!assertLength || curSize > 2);) {
1418 if (last->almostSame(*i, minDist)) {
1419 if (i + 1 == end() - endOffset) {
1421 if (
resample && last > begin() && (last - 1)->distanceTo(*i) >= 2 * minDist) {
1423 const double shiftBack = minDist - last->distanceTo(*i);
1425 (*last) =
positionAtOffset(*(last - 1), *last, (last - 1)->distanceTo(*last) - shiftBack);
1431 i = end() - endOffset;
1434 if (
resample && i + 1 != end() && last->distanceTo(*(i + 1)) >= 2 * minDist) {
1436 const double shiftForward = minDist - last->distanceTo(*i);
1458 return static_cast<vp>(*this) ==
static_cast<vp>(v2);
1464 return static_cast<vp>(*this) !=
static_cast<vp>(v2);
1470 WRITE_ERROR(
TL(
"Trying to substract PositionVectors of different lengths."));
1474 auto i2 = v2.begin();
1475 while (i1 != end()) {
1484 WRITE_ERROR(
TL(
"Trying to substract PositionVectors of different lengths."));
1488 auto i2 = v2.begin();
1489 while (i1 != end()) {
1500 for (const_iterator i = begin(); i != end() - 1; i++) {
1501 if ((*i).z() != (*(i + 1)).z()) {
1511 const double eps = std::numeric_limits<double>::epsilon();
1512 const double denominator = (p22.
y() - p21.
y()) * (p12.
x() - p11.
x()) - (p22.
x() - p21.
x()) * (p12.
y() - p11.
y());
1513 const double numera = (p22.
x() - p21.
x()) * (p11.
y() - p21.
y()) - (p22.
y() - p21.
y()) * (p11.
x() - p21.
x());
1514 const double numerb = (p12.
x() - p11.
x()) * (p11.
y() - p21.
y()) - (p12.
y() - p11.
y()) * (p11.
x() - p21.
x());
1516 if (fabs(numera) < eps && fabs(numerb) < eps && fabs(denominator) < eps) {
1522 if (p11.
x() != p12.
x()) {
1523 a1 = p11.
x() < p12.
x() ? p11.
x() : p12.
x();
1524 a2 = p11.
x() < p12.
x() ? p12.
x() : p11.
x();
1525 a3 = p21.
x() < p22.
x() ? p21.
x() : p22.
x();
1526 a4 = p21.
x() < p22.
x() ? p22.
x() : p21.
x();
1528 a1 = p11.
y() < p12.
y() ? p11.
y() : p12.
y();
1529 a2 = p11.
y() < p12.
y() ? p12.
y() : p11.
y();
1530 a3 = p21.
y() < p22.
y() ? p21.
y() : p22.
y();
1531 a4 = p21.
y() < p22.
y() ? p22.
y() : p21.
y();
1533 if (a1 <= a3 && a3 <= a2) {
1540 if (a3 <= a1 && a1 <= a4) {
1549 if (p11.
x() != p12.
x()) {
1550 *mu = (a - p11.
x()) / (p12.
x() - p11.
x());
1552 *y = p11.
y() + (*mu) * (p12.
y() - p11.
y());
1556 if (p12.
y() == p11.
y()) {
1559 *mu = (a - p11.
y()) / (p12.
y() - p11.
y());
1568 if (fabs(denominator) < eps) {
1572 double mua = numera / denominator;
1574 if (fabs(p12.
x() - p22.
x()) < eps && fabs(p12.
y() - p22.
y()) < eps) {
1577 const double offseta = withinDist / p11.
distanceTo2D(p12);
1578 const double offsetb = withinDist / p21.
distanceTo2D(p22);
1579 const double mub = numerb / denominator;
1580 if (mua < -offseta || mua > 1 + offseta || mub < -offsetb || mub > 1 + offsetb) {
1585 *x = p11.
x() + mua * (p12.
x() - p11.
x());
1586 *y = p11.
y() + mua * (p12.
y() - p11.
y());
1595 const double s = sin(angle);
1596 const double c = cos(angle);
1597 for (
int i = 0; i < (int)size(); i++) {
1598 const double x = (*this)[i].x();
1599 const double y = (*this)[i].y();
1600 const double z = (*this)[i].z();
1601 const double xnew = x * c - y * s;
1602 const double ynew = x * s + y * c;
1603 (*this)[i].set(xnew, ynew, z);
1611 bool changed =
true;
1612 while (changed && result.size() > 3) {
1614 for (
int i = 0; i < (int)result.size(); i++) {
1616 const Position& p2 = result[(i + 2) % result.size()];
1617 const int middleIndex = (i + 1) % result.size();
1618 const Position& p0 = result[middleIndex];
1620 const double triangleArea2 = fabs((p2.
y() - p1.
y()) * p0.
x() - (p2.
x() - p1.
x()) * p0.
y() + p2.
x() * p1.
y() - p2.
y() * p1.
x());
1622 if (distIK > NUMERICAL_EPS && triangleArea2 / distIK < NUMERICAL_EPS) {
1624 result.erase(result.begin() + middleIndex);
1646 result.push_back(base);
1647 if (fabs(baseOffset - closestOffset) > NUMERICAL_EPS) {
1648 result.push_back(tmp[closestIndex]);
1649 if ((closestOffset < baseOffset) != before) {
1652 }
else if (before) {
1654 if (closestIndex > 0) {
1655 result.push_back(tmp[closestIndex - 1]);
1657 result.push_back(tmp[1]);
1662 if (closestIndex < (
int)size() - 1) {
1663 result.push_back(tmp[closestIndex + 1]);
1665 result.push_back(tmp[-1]);
1671 result.
add(base * -1);
1684 const double z0 = (*this)[0].z();
1686 const double dz = (*this)[1].z() - z0;
1688 if (size() > 2 && dz != 0) {
1694 if (pDist.
distanceTo2D((*
this)[iLast]) > POSITION_EPS * 20) {
1698 const double dz2 = result[iLast].z() - z0;
1700 for (
int i = 1; i < iLast; ++i) {
1701 seen += result[i].distanceTo2D(result[i - 1]);
1702 result[i].set(result[i].x(), result[i].y(), z0 + dz2 * seen / dist2);
1716 result[0].setz(zStart);
1717 result[-1].setz(zEnd);
1718 const double dz = zEnd - zStart;
1721 for (
int i = 1; i < (int)size() - 1; ++i) {
1722 seen += result[i].distanceTo2D(result[i - 1]);
1723 result[i].setz(zStart + dz * seen /
length);
1732 if (maxLength == 0) {
1736 if (
length < POSITION_EPS) {
1740 for (
double pos = 0; pos <=
length; pos += maxLength) {
1744 if (adjustEnd && !result.empty() && (result.back() != back())) {
1746 result.push_back(back());
1754 if (index < 0 || index >= (
int)size()) {
1758 for (
int i = 1; i <= index; ++i) {
1759 seen += (*this)[i].distanceTo2D((*
this)[i - 1]);
1768 for (
int i = 1; i < (int)size(); ++i) {
1769 const Position& p1 = (*this)[i - 1];
1771 const double distZ = fabs(p1.
z() - p2.
z());
1774 maxJump =
MAX2(maxJump, distZ);
1776 result =
MAX2(result, distZ / dist2D);
1786 assert(size() < 33);
1787 static const double fac[33] = {
1788 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,
1789 6227020800.0, 87178291200.0, 1307674368000.0, 20922789888000.0, 355687428096000.0, 6402373705728000.0,
1790 121645100408832000.0, 2432902008176640000.0, 51090942171709440000.0, 1124000727777607680000.0,
1791 25852016738884976640000.0, 620448401733239439360000.0, 15511210043330985984000000.0,
1792 403291461126605635584000000.0, 10888869450418352160768000000.0, 304888344611713860501504000000.0,
1793 8841761993739701954543616000000.0, 265252859812191058636308480000000.0,
1794 8222838654177922817725562880000000.0, 263130836933693530167218012160000000.0
1797 const int npts = (int)size();
1799 const double step = (double) 1.0 / (numPoints - 1);
1802 for (
int i1 = 0; i1 < numPoints; i1++) {
1803 if ((1.0 - t) < 5e-6) {
1806 double x = 0., y = 0., z = 0.;
1807 for (
int i = 0; i < npts; i++) {
1808 const double ti = (i == 0) ? 1.0 : pow(t, i);
1809 const double tni = (npts == i + 1) ? 1.0 : pow(1 - t, npts - i - 1);
1810 const double basis = fac[npts - 1] / (fac[i] * fac[npts - 1 - i]) * ti * tni;
1811 x += basis * at(i).
x();
1812 y += basis * at(i).y();
1813 z += basis * at(i).z();
1818 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
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)
Substracts 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
substracts 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 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)
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....