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);
224 throw ProcessError(
"Index out of range in bracket operator of PositionVector");
238 if (index >= 0 && index < (
int)size()) {
240 }
else if (index < 0 && -index <= (
int)size()) {
241 return at((
int)size() + index);
243 throw ProcessError(
"Index out of range in bracket operator of PositionVector");
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);
410 return Position(x / (
double) size(), y / (
double) size(), z / (
double)size());
418 }
else if (size() == 1) {
420 }
else if (size() == 2) {
421 return ((*
this)[0] + (*
this)[1]) * 0.5;
425 tmp.push_back(tmp[0]);
431 const int endIndex = (int)tmp.size() - 1;
435 if (tmp.
area() != 0) {
437 for (
int i = 0; i < endIndex; i++) {
438 const double z = tmp[i].x() * tmp[i + 1].y() - tmp[i + 1].x() * tmp[i].y();
440 x += (tmp[i].x() + tmp[i + 1].x()) * z;
441 y += (tmp[i].y() + tmp[i + 1].y()) * z;
444 result =
Position(x / div, y / div);
448 double lengthSum = 0;
449 for (
int i = 0; i < endIndex; i++) {
450 double length = tmp[i].distanceTo(tmp[i + 1]);
451 x += (tmp[i].x() + tmp[i + 1].x()) *
length / 2;
452 y += (tmp[i].y() + tmp[i + 1].y()) *
length / 2;
455 if (lengthSum == 0) {
459 result =
Position(x / lengthSum, y / lengthSum) + offset;
461 return result + offset;
468 for (
int i = 0; i < static_cast<int>(size()); i++) {
469 (*this)[i] = centroid + (((*this)[i] - centroid) * factor);
477 for (
int i = 0; i < static_cast<int>(size()); i++) {
478 (*this)[i] = centroid + (((*this)[i] - centroid) + offset);
499 for (const_iterator i = begin(); i != end() - 1; i++) {
500 len += (*i).distanceTo(*(i + 1));
512 for (const_iterator i = begin(); i != end() - 1; i++) {
513 len += (*i).distanceTo2D(*(i + 1));
527 tmp.push_back(tmp[0]);
529 const int endIndex = (int)tmp.size() - 1;
531 for (
int i = 0; i < endIndex; i++) {
532 area += tmp[i].x() * tmp[i + 1].y() - tmp[i + 1].x() * tmp[i].y();
546 for (const_iterator i = begin(); i != end(); i++) {
547 if (poly.
around(*i, offset)) {
561 std::pair<PositionVector, PositionVector>
567 if (where < 0 || where > len) {
570 if (where <= POSITION_EPS || where >= len - POSITION_EPS) {
574 first.push_back((*
this)[0]);
576 const_iterator it = begin() + 1;
577 double next = use2D ? first.back().distanceTo2D(*it) : first.back().distanceTo(*it);
579 while (where >= seen + next + POSITION_EPS) {
581 first.push_back(*it);
583 next = use2D ? first.back().distanceTo2D(*it) : first.back().distanceTo(*it);
585 if (fabs(where - (seen + next)) > POSITION_EPS || it == end() - 1) {
594 first.push_back(*it);
597 for (; it != end(); it++) {
598 second.push_back(*it);
600 assert(first.size() >= 2);
601 assert(second.size() >= 2);
602 assert(first.back() == second.front());
604 return std::pair<PositionVector, PositionVector>(first, second);
610 for (PositionVector::const_iterator i = geom.begin(); i != geom.end(); i++) {
611 if (i != geom.begin()) {
628 for (
int i = 0; i < (int)size(); i++) {
629 (*this)[i].add(xoff, yoff, zoff);
636 add(-offset.
x(), -offset.
y(), -offset.
z());
642 add(offset.
x(), offset.
y(), offset.
z());
649 for (
auto i1 = begin(); i1 != end(); ++i1) {
650 pv.push_back(*i1 + offset);
658 for (
int i = 0; i < (int)size(); i++) {
659 (*this)[i].mul(1, -1);
669 return atan2(p1.
x(), p1.
y()) < atan2(p2.
x(), p2.
y());
684 if (p1.
x() != p2.
x()) {
685 return p1.
x() < p2.
x();
687 return p1.
y() < p2.
y();
693 return (P1.
x() - P0.
x()) * (P2.
y() - P0.
y()) - (P2.
x() - P0.
x()) * (P1.
y() - P0.
y());
699 if ((size() > 0) && (v.size() > 0) && (back().distanceTo(v[0]) < sameThreshold)) {
700 copy(v.begin() + 1, v.end(), back_inserter(*
this));
702 copy(v.begin(), v.end(), back_inserter(*
this));
709 if ((size() > 0) && (v.size() > 0) && (front().distanceTo(v.back()) < sameThreshold)) {
710 insert(begin(), v.begin(), v.end() - 1);
712 insert(begin(), v.begin(), v.end());
721 if (beginOffset > POSITION_EPS) {
725 if (endOffset <
length() - POSITION_EPS) {
728 ret.push_back(begPos);
731 const_iterator i = begin();
733 while ((i + 1) != end()
735 seen + (*i).distanceTo(*(i + 1)) < beginOffset) {
736 seen += (*i).distanceTo(*(i + 1));
740 while ((i + 1) != end()
742 seen + (*i).distanceTo(*(i + 1)) < endOffset) {
745 seen += (*i).distanceTo(*(i + 1));
750 if (ret.size() == 1) {
751 ret.push_back(endPos);
764 if (beginOffset > POSITION_EPS) {
768 if (endOffset <
length2D() - POSITION_EPS) {
771 ret.push_back(begPos);
774 const_iterator i = begin();
776 while ((i + 1) != end()
778 seen + (*i).distanceTo2D(*(i + 1)) < beginOffset) {
779 seen += (*i).distanceTo2D(*(i + 1));
783 while ((i + 1) != end()
785 seen + (*i).distanceTo2D(*(i + 1)) < endOffset) {
788 seen += (*i).distanceTo2D(*(i + 1));
793 if (ret.size() == 1) {
794 ret.push_back(endPos);
805 if (beginIndex < 0) {
806 beginIndex += (int)size();
809 assert(beginIndex < (
int)size());
810 assert(beginIndex + count <= (
int)size());
812 for (
int i = beginIndex; i < beginIndex + count; ++i) {
813 result.push_back((*
this)[i]);
824 return front().angleTo2D(back());
833 double minDist = std::numeric_limits<double>::max();
836 for (const_iterator i = begin(); i != end() - 1; i++) {
840 if (dist < minDist) {
841 nearestPos = pos + seen;
847 if (cornerDist < minDist) {
852 if (pos1 == (*(i - 1)).distanceTo2D(*i) && pos2 == 0.) {
854 minDist = cornerDist;
858 seen += (*i).distanceTo2D(*(i + 1));
869 double minDist = std::numeric_limits<double>::max();
872 for (const_iterator i = begin(); i != end() - 1; i++) {
876 if (dist < minDist) {
877 const double pos25D = pos * (*i).distanceTo(*(i + 1)) / (*i).distanceTo2D(*(i + 1));
878 nearestPos = pos25D + seen;
884 if (cornerDist < minDist) {
889 if (pos1 == (*(i - 1)).distanceTo2D(*i) && pos2 == 0.) {
891 minDist = cornerDist;
895 seen += (*i).distanceTo(*(i + 1));
913 double minDist = std::numeric_limits<double>::max();
914 double nearestPos = -1;
917 for (const_iterator i = begin(); i != end() - 1; i++) {
921 if (dist < minDist) {
922 nearestPos = pos + seen;
924 sign =
isLeft(*i, *(i + 1), p) >= 0 ? -1 : 1;
929 if (cornerDist < minDist) {
934 if (pos1 == (*(i - 1)).distanceTo2D(*i) && pos2 == 0.) {
936 minDist = cornerDist;
937 sign =
isLeft(*(i - 1), *i, p) >= 0 ? -1 : 1;
941 seen += (*i).distanceTo2D(*(i + 1));
943 if (nearestPos != -1) {
944 return Position(nearestPos, sign * minDist);
956 double minDist = std::numeric_limits<double>::max();
959 for (
int i = 0; i < (int)size(); i++) {
962 if (dist < minDist) {
976 double minDist = std::numeric_limits<double>::max();
977 int insertionIndex = 1;
978 for (
int i = 0; i < (int)size() - 1; i++) {
982 if (dist < minDist) {
983 insertionIndex = i + 1;
990 const double previousZ = (begin() + (insertionIndex - 1))->z();
991 const double nextZ = (begin() + insertionIndex)->z();
993 insert(begin() + insertionIndex,
Position(p.
x(), p.
y(), ((previousZ + nextZ) / 2.0)));
995 insert(begin() + insertionIndex, p);
997 return insertionIndex;
1006 double minDist = std::numeric_limits<double>::max();
1007 int removalIndex = 0;
1008 for (
int i = 0; i < (int)size(); i++) {
1010 if (dist < minDist) {
1015 erase(begin() + removalIndex);
1016 return removalIndex;
1022 std::vector<double> ret;
1023 if (other.size() == 0) {
1026 for (const_iterator i = other.begin(); i != other.end() - 1; i++) {
1028 copy(atSegment.begin(), atSegment.end(), back_inserter(ret));
1036 std::vector<double> ret;
1041 for (const_iterator i = begin(); i != end() - 1; i++) {
1045 if (
intersects(p1, p2, lp1, lp2, 0., &x, &y, &m)) {
1101 for (const_reverse_iterator i = rbegin(); i != rend(); i++) {
1111 return Position((beg.
y() - end.
y()) * scale, (end.
x() - beg.
x()) * scale);
1121 if (
length2D() == 0 || amount == 0) {
1125 std::vector<int> recheck;
1126 for (
int i = 0; i < static_cast<int>(size()); i++) {
1129 const Position& to = (*this)[i + 1];
1131 shape.push_back(from -
sideOffset(from, to, amount));
1132 #ifdef DEBUG_MOVE2SIDE
1133 if (
gDebugFlag1) std::cout <<
" " << i <<
"a=" << shape.back() <<
"\n";
1136 }
else if (i ==
static_cast<int>(size()) - 1) {
1137 const Position& from = (*this)[i - 1];
1140 shape.push_back(to -
sideOffset(from, to, amount));
1141 #ifdef DEBUG_MOVE2SIDE
1142 if (
gDebugFlag1) std::cout <<
" " << i <<
"b=" << shape.back() <<
"\n";
1146 const Position& from = (*this)[i - 1];
1148 const Position& to = (*this)[i + 1];
1151 const double extrapolateDev = fromMe[1].distanceTo2D(to);
1152 if (fabs(extrapolateDev) < POSITION_EPS) {
1154 shape.push_back(me -
sideOffset(from, to, amount));
1155 #ifdef DEBUG_MOVE2SIDE
1156 if (
gDebugFlag1) std::cout <<
" " << i <<
"c=" << shape.back() <<
"\n";
1158 }
else if (fabs(extrapolateDev - 2 * me.
distanceTo2D(to)) < POSITION_EPS) {
1162 shape.push_back(fromMe2[1]);
1163 #ifdef DEBUG_MOVE2SIDE
1164 if (
gDebugFlag1) std::cout <<
" " << i <<
"d=" << shape.back() <<
" " << i <<
"_from=" << from <<
" " << i <<
"_me=" << me <<
" " << i <<
"_to=" << to <<
"\n";
1173 recheck.push_back(i);
1177 shape.push_back(meNew);
1178 #ifdef DEBUG_MOVE2SIDE
1179 if (
gDebugFlag1) std::cout <<
" " << i <<
"e=" << shape.back() <<
"\n";
1183 shape.back().set(shape.back().x(), shape.back().y(), me.
z());
1184 const double angle =
localAngle(from, me, to);
1185 if (fabs(angle) > NUMERICAL_EPS) {
1186 const double length = (i == 1 || i + 2 == (int)size()
1189 const double radius =
length / angle;
1190 #ifdef DEBUG_MOVE2SIDE
1191 if (
gDebugFlag1) std::cout <<
" i=" << i <<
" a=" <<
RAD2DEG(angle) <<
" l=" <<
length <<
" r=" << radius <<
" t=" << amount * 1.8 <<
"\n";
1193 if ((radius < 0 && -radius < amount * 1.8) || fabs(
RAD2DEG(angle)) > 170) {
1194 recheck.push_back(i);
1199 if (!recheck.empty()) {
1202 for (
int i = (
int)recheck.size() - 1; i >= 0; i--) {
1203 shape.erase(shape.begin() + recheck[i]);
1219 if (size() != amount.size()) {
1221 +
") does not match number of points (" +
toString(size()) +
")");
1224 for (
int i = 0; i < static_cast<int>(size()); i++) {
1227 const Position& to = (*this)[i + 1];
1229 shape.push_back(from -
sideOffset(from, to, amount[i]));
1231 }
else if (i ==
static_cast<int>(size()) - 1) {
1232 const Position& from = (*this)[i - 1];
1235 shape.push_back(to -
sideOffset(from, to, amount[i]));
1238 const Position& from = (*this)[i - 1];
1240 const Position& to = (*this)[i + 1];
1243 const double extrapolateDev = fromMe[1].distanceTo2D(to);
1244 if (fabs(extrapolateDev) < POSITION_EPS) {
1246 shape.push_back(me -
sideOffset(from, to, amount[i]));
1247 }
else if (fabs(extrapolateDev - 2 * me.
distanceTo2D(to)) < POSITION_EPS) {
1251 shape.push_back(fromMe2[1]);
1262 shape.push_back(meNew);
1265 shape.back().set(shape.back().x(), shape.back().y(), me.
z());
1278 if ((pos + 1) < (
int)size()) {
1279 return (*
this)[pos].angleTo2D((*
this)[pos + 1]);
1288 if ((size() != 0) && ((*
this)[0] != back())) {
1289 push_back((*
this)[0]);
1296 std::vector<double> ret;
1298 for (i = begin(); i != end(); i++) {
1299 const double dist = s.
distance2D(*i, perpendicular);
1301 ret.push_back(dist);
1304 for (i = s.begin(); i != s.end(); i++) {
1305 const double dist =
distance2D(*i, perpendicular);
1307 ret.push_back(dist);
1317 return std::numeric_limits<double>::max();
1318 }
else if (size() == 1) {
1319 return front().distanceTo(p);
1360 if ((size() == 0) || !p.
almostSame(front())) {
1368 if (at == begin()) {
1370 }
else if (at == end()) {
1382 return (size() >= 2) && ((*this)[0] == back());
1389 for (
auto i = begin(); i != end(); i++) {
1401 int curSize = (int)size() - beginOffset - endOffset;
1403 iterator last = begin() + beginOffset;
1404 for (iterator i = last + 1; i != (end() - endOffset) && (!assertLength || curSize > 2);) {
1405 if (last->almostSame(*i, minDist)) {
1406 if (i + 1 == end() - endOffset) {
1408 if (
resample && last > begin() && (last - 1)->distanceTo(*i) >= 2 * minDist) {
1410 const double shiftBack = minDist - last->distanceTo(*i);
1412 (*last) =
positionAtOffset(*(last - 1), *last, (last - 1)->distanceTo(*last) - shiftBack);
1418 i = end() - endOffset;
1421 if (
resample && i + 1 != end() && last->distanceTo(*(i + 1)) >= 2 * minDist) {
1423 const double shiftForward = minDist - last->distanceTo(*i);
1445 return static_cast<vp>(*this) ==
static_cast<vp>(v2);
1451 return static_cast<vp>(*this) !=
static_cast<vp>(v2);
1457 WRITE_ERROR(
"Trying to substract PositionVectors of different lengths.");
1461 auto i2 = v2.begin();
1462 while (i1 != end()) {
1471 WRITE_ERROR(
"Trying to substract PositionVectors of different lengths.");
1475 auto i2 = v2.begin();
1476 while (i1 != end()) {
1487 for (const_iterator i = begin(); i != end() - 1; i++) {
1488 if ((*i).z() != (*(i + 1)).z()) {
1498 const double eps = std::numeric_limits<double>::epsilon();
1499 const double denominator = (p22.
y() - p21.
y()) * (p12.
x() - p11.
x()) - (p22.
x() - p21.
x()) * (p12.
y() - p11.
y());
1500 const double numera = (p22.
x() - p21.
x()) * (p11.
y() - p21.
y()) - (p22.
y() - p21.
y()) * (p11.
x() - p21.
x());
1501 const double numerb = (p12.
x() - p11.
x()) * (p11.
y() - p21.
y()) - (p12.
y() - p11.
y()) * (p11.
x() - p21.
x());
1503 if (fabs(numera) < eps && fabs(numerb) < eps && fabs(denominator) < eps) {
1509 if (p11.
x() != p12.
x()) {
1510 a1 = p11.
x() < p12.
x() ? p11.
x() : p12.
x();
1511 a2 = p11.
x() < p12.
x() ? p12.
x() : p11.
x();
1512 a3 = p21.
x() < p22.
x() ? p21.
x() : p22.
x();
1513 a4 = p21.
x() < p22.
x() ? p22.
x() : p21.
x();
1515 a1 = p11.
y() < p12.
y() ? p11.
y() : p12.
y();
1516 a2 = p11.
y() < p12.
y() ? p12.
y() : p11.
y();
1517 a3 = p21.
y() < p22.
y() ? p21.
y() : p22.
y();
1518 a4 = p21.
y() < p22.
y() ? p22.
y() : p21.
y();
1520 if (a1 <= a3 && a3 <= a2) {
1527 if (a3 <= a1 && a1 <= a4) {
1536 if (p11.
x() != p12.
x()) {
1537 *mu = (a - p11.
x()) / (p12.
x() - p11.
x());
1539 *y = p11.
y() + (*mu) * (p12.
y() - p11.
y());
1543 if (p12.
y() == p11.
y()) {
1546 *mu = (a - p11.
y()) / (p12.
y() - p11.
y());
1555 if (fabs(denominator) < eps) {
1559 double mua = numera / denominator;
1561 if (fabs(p12.
x() - p22.
x()) < eps && fabs(p12.
y() - p22.
y()) < eps) {
1564 const double offseta = withinDist / p11.
distanceTo2D(p12);
1565 const double offsetb = withinDist / p21.
distanceTo2D(p22);
1566 const double mub = numerb / denominator;
1567 if (mua < -offseta || mua > 1 + offseta || mub < -offsetb || mub > 1 + offsetb) {
1572 *x = p11.
x() + mua * (p12.
x() - p11.
x());
1573 *y = p11.
y() + mua * (p12.
y() - p11.
y());
1582 const double s = sin(angle);
1583 const double c = cos(angle);
1584 for (
int i = 0; i < (int)size(); i++) {
1585 const double x = (*this)[i].x();
1586 const double y = (*this)[i].y();
1587 const double z = (*this)[i].z();
1588 const double xnew = x * c - y * s;
1589 const double ynew = x * s + y * c;
1590 (*this)[i].set(xnew, ynew, z);
1598 bool changed =
true;
1599 while (changed && result.size() > 3) {
1601 for (
int i = 0; i < (int)result.size(); i++) {
1603 const Position& p2 = result[(i + 2) % result.size()];
1604 const int middleIndex = (i + 1) % result.size();
1605 const Position& p0 = result[middleIndex];
1607 const double triangleArea2 = fabs((p2.
y() - p1.
y()) * p0.
x() - (p2.
x() - p1.
x()) * p0.
y() + p2.
x() * p1.
y() - p2.
y() * p1.
x());
1609 if (distIK > NUMERICAL_EPS && triangleArea2 / distIK < NUMERICAL_EPS) {
1611 result.erase(result.begin() + middleIndex);
1633 result.push_back(base);
1634 if (fabs(baseOffset - closestOffset) > NUMERICAL_EPS) {
1635 result.push_back(tmp[closestIndex]);
1636 if ((closestOffset < baseOffset) != before) {
1639 }
else if (before) {
1641 if (closestIndex > 0) {
1642 result.push_back(tmp[closestIndex - 1]);
1644 result.push_back(tmp[1]);
1649 if (closestIndex < (
int)size() - 1) {
1650 result.push_back(tmp[closestIndex + 1]);
1652 result.push_back(tmp[-1]);
1658 result.
add(base * -1);
1671 const double z0 = (*this)[0].z();
1673 const double dz = (*this)[1].z() - z0;
1675 if (size() > 2 && dz != 0) {
1681 if (pDist.
distanceTo2D((*
this)[iLast]) > POSITION_EPS * 20) {
1685 const double dz2 = result[iLast].z() - z0;
1687 for (
int i = 1; i < iLast; ++i) {
1688 seen += result[i].distanceTo2D(result[i - 1]);
1689 result[i].set(result[i].x(), result[i].y(), z0 + dz2 * seen / dist2);
1703 result[0].setz(zStart);
1704 result[-1].setz(zEnd);
1705 const double dz = zEnd - zStart;
1708 for (
int i = 1; i < (int)size() - 1; ++i) {
1709 seen += result[i].distanceTo2D(result[i - 1]);
1710 result[i].setz(zStart + dz * seen /
length);
1719 if (maxLength == 0) {
1723 if (
length < POSITION_EPS) {
1727 for (
double pos = 0; pos <=
length; pos += maxLength) {
1731 if (adjustEnd && !result.empty() && (result.back() != back())) {
1733 result.push_back(back());
1741 if (index < 0 || index >= (
int)size()) {
1745 for (
int i = 1; i <= index; ++i) {
1746 seen += (*this)[i].distanceTo2D((*
this)[i - 1]);
1755 for (
int i = 1; i < (int)size(); ++i) {
1756 const Position& p1 = (*this)[i - 1];
1758 const double distZ = fabs(p1.
z() - p2.
z());
1761 maxJump =
MAX2(maxJump, distZ);
1763 result =
MAX2(result, distZ / dist2D);
1773 assert(size() < 33);
1774 static const double fac[33] = {
1775 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,
1776 6227020800.0, 87178291200.0, 1307674368000.0, 20922789888000.0, 355687428096000.0, 6402373705728000.0,
1777 121645100408832000.0, 2432902008176640000.0, 51090942171709440000.0, 1124000727777607680000.0,
1778 25852016738884976640000.0, 620448401733239439360000.0, 15511210043330985984000000.0,
1779 403291461126605635584000000.0, 10888869450418352160768000000.0, 304888344611713860501504000000.0,
1780 8841761993739701954543616000000.0, 265252859812191058636308480000000.0,
1781 8222838654177922817725562880000000.0, 263130836933693530167218012160000000.0
1784 const int npts = (int)size();
1786 const double step = (double) 1.0 / (numPoints - 1);
1789 for (
int i1 = 0; i1 < numPoints; i1++) {
1790 if ((1.0 - t) < 5e-6) {
1793 double x = 0., y = 0., z = 0.;
1794 for (
int i = 0; i < npts; i++) {
1795 const double ti = (i == 0) ? 1.0 : pow(t, i);
1796 const double tni = (npts == i + 1) ? 1.0 : pow(1 - t, npts - i - 1);
1797 const double basis = fac[npts - 1] / (fac[i] * fac[npts - 1 - i]) * ti * tni;
1798 x += basis * at(i).
x();
1799 y += basis * at(i).y();
1800 z += basis * at(i).z();
1805 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.
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 constat position at the given index @ToDo !!! exceptions?
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....