463 static std::vector<int>
ConvexHull2D(
const std::vector<std::pair<T, T>>& polygonPoints )
465 if ( polygonPoints.size() == 0 ) {
468 else if ( polygonPoints.size() == 1 ) {
471 else if ( polygonPoints.size() == 2 ) {
475 std::vector<IndexedPair<int, T>> sortedPoints;
476 sortedPoints.reserve(polygonPoints.size() + 1);
477 for (
int i = 0; i < static_cast<int>(polygonPoints.size()); i++ ) {
478 sortedPoints.emplace_back(
IndexedPair<int, T>(i, polygonPoints.at(i).first, polygonPoints.at(i).second));
482 sortedPoints.begin(),
484 [] (
const auto& a,
const auto& b ) {
486 return a.second < b.second;
492 Point<T> startEndDiff = top - bottom;
493 T angleThreshold = startEndDiff.fastAngleModded();
495 std::vector<PointAngle<T>> pointsOnLeft;
496 std::vector<PointAngle<T>> pointsOnRight;
501 if ( point == bottom || point == top ) {
506 T angle = temp.fastAngleModded();
508 if ( point.first == top.first && point.first == bottom.second ) {
511 else if ( angle > angleThreshold ) {
512 pointsOnLeft.emplace_back(point.index, angle);
515 pointsOnRight.emplace_back(point.index, angle);
520 std::sort(pointsOnLeft.begin(), pointsOnLeft.end(), std::greater<
PointAngle<T>>());
521 std::sort(pointsOnRight.begin(), pointsOnRight.end());
524 std::unordered_set<int> visitedPoints;
525 visitedPoints.reserve(polygonPoints.size());
528 std::vector<int> convexLeft;
529 std::vector<int> convexRight;
530 convexLeft.reserve(polygonPoints.size());
531 convexRight.reserve(polygonPoints.size());
534 convexLeft.push_back(bottom.index);
535 visitedPoints.insert(bottom.index);
536 if ( pointsOnLeft.size() > 0 ) {
537 convexLeft.push_back(pointsOnLeft.at(0).index);
538 visitedPoints.insert(pointsOnLeft.at(0).index);
539 Point<T> pt = CalculateVector<T>(polygonPoints, pointsOnLeft.at(0).index, bottom.index);
543 if ( nextPoint.index == top.index ) {
548 if ( visitedPoints.contains(nextPoint.index) ) {
553 if ( visitedPoints.find(nextPoint.index) != visitedPoints.end() ) {
561 visitedPoints.insert(nextPoint.index);
562 AddPointToConvex<T>(convexLeft, nextPoint.index, polygonPoints,
true);
565 AddPointToConvex<T>(convexLeft, top.index, polygonPoints,
true);
572 visitedPoints.clear();
573 convexRight.push_back(bottom.index);
574 visitedPoints.insert(bottom.index);
575 if ( pointsOnRight.size() > 0 ) {
576 convexRight.push_back(pointsOnRight.at(0).index);
577 visitedPoints.insert(pointsOnRight.at(0).index);
583 if ( nextPoint.index == top.index ) {
587 if ( visitedPoints.find(nextPoint.index) != visitedPoints.end() ) {
593 visitedPoints.insert(nextPoint.index);
594 AddPointToConvex<T>(convexRight, nextPoint.index, polygonPoints);
597 AddPointToConvex<T>(convexRight, top.index, polygonPoints);
626 for (
auto it = convexLeft.end(); it != convexLeft.begin(); ) {
629 if ( point == top.index || point == bottom.index ) {
continue; }
630 convexRight.push_back(point);