c++ - 点集的最大四边形

标签 c++ algorithm geometry computational-geometry

我正在寻找一种方法来找到面积最大的四边形。我已经计算了凸包的点并按顺时针方向对它们进行了排序。我尝试了蛮力,但当然它太慢了。所以我在这里找到了最大三角形的算法:

How to find largest triangle in convex hull aside from brute force search

它看起来非常好,所以我尝试重新制作它。我有一个函数可以通过将四边形分成两个三角形来计算任何四边形的面积(在这个函数中我对输入点进行排序以确保我正在计算直角三角形)。在这里:

int n = convexHull.size();
int A = 0; int B = 1; int C = 2; int D = 3;
int bestA = A; int bestB = B; int bestC = C; int bestD = D;
while(true) { // loop A
      while(true) { // loop B
        while(true) { // loop C
          while(quadrangleArea(A, B, C, D) <=  quadrangleArea(A, B, C, (D+1)%n) ) { // loop D
              D = (D+1)%n;
          }
          if(quadrangleArea(A, B, C, D) <=  quadrangleArea(A, B, (C+1)%n, D) ) {
              C = (C+1)%n;
              continue;
          }
          else break;
        }
        if(quadrangleArea(A, B, C, D) <=  quadrangleArea(A, (B+1)%n, C, D) ) {
          B = (B+1)%n;
          continue;
        }
        else break;
      }
      if(quadrangleArea(A, B, C, D) >  quadrangleArea(bestA, bestB, bestC, bestD) ) {
        bestA = A; bestB = B; bestC = C; bestD = D;
      }
      A = (A+1)%n;
      if (A==B) B = (B+1)%n;
      if (B==C) C = (C+1)%n;
      if (C==D) D = (D+1)%n;
      if (A==0) break;
}

它看起来不错,并且为我的简单测试提供了良好的结果,但恐怕有些地方不对。通过这种推理,我可以为每个具有 n 个顶点的多边形制定算法 - 但凭直觉我认为这是不可能的。我说得对吗?

我正在尝试解决 "SHAMAN" spoj 上的问题,我得到了错误的答案。我 99% 确定我的程序的其余部分没问题,所以上面的代码有问题。你能帮我改进一下吗?也许你有一些棘手的测试可以证明这个算法不能正常工作?如果有任何提示,我将不胜感激!

最佳答案

我将凸包 segmentation 为两半,找到每一半中最大的三角形,计算总和 - 然后旋转“分隔线”穿过凸包。像这样:

size_t n = convexHull.size();
size_t A = 0;
size_t B = n/2;
size_t C, D;
size_t maxarea = 0;
size_t area;
size_t maxQuad[4];

// size_t findLargestTriangle(convHullType c, int& tip);
//    make this search the hull "c" with the assumption
//    that the first and last point in it form the longest
//    possible side, and therefore will be base of the
//    triangle with the largest area. The "other" point
//    will be returned, as will be the size.
while (A < n/2 && B < n) {
    // this is partially pseudocode, as you need to treat
    // the container as "circular list", where indices wrap
    // around at container.size() - i.e. would have
    // to be container[n + x] == container[n]. No ordinary
    // C++ std:: container type behaves like this but it's
    // not too hard to code this.
    // This simply says, "two sub-ranges".
    area =
        findLargestTriangle(convexHull[A..B], C) +
        findLargestTriangle(convexHull[B..A], D);
    if (area > maxarea) {
        maxarea = area;
        maxQuad = { A, B, A + C, B + D };
    }
    A++; B++;
}

我不是一个很好的数学家,因此不完全确定(无法证明)你可以旋转 AB 一起像这样。希望有人可以填补这个空白......总是渴望学习自己;-)

关于c++ - 点集的最大四边形,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16788408/

相关文章:

javascript - Three.js:将对象投影到垂直于相机的平面上

java - 如何 : Split while loop with double comparisson into two?

javascript - 执行某种淡入淡出的功能所涉及的机制/算法是什么?

algorithm - 基于数组的不相交集数据结构的时间复杂度

iOS - 带角度渐变的圆

c++ - 既然其他可滥用但有用的特性已经标准化,为什么不#pragma once呢?

c++ - Opengl - GLM::Ortho + GLM_COORDINATE_SYSTEM = 奇怪?

c++ - boost asio 行为 - 从多个线程调用 ios_service::run

c++ - 无法在我的字符串中找到准确数量的以标点符号(如引号)开头的单词

r - 点矩阵之间的距离,简单的 if 和 for