找到向量构造的交叉点

时间:2016-05-31 08:47:42

标签: c++ algorithm math vector

所以在我的软件中我有两个向量。第一个向量matrix存储给定3D模型的形状信息。所以我得到了一个数组向量来存储点的x,y,z坐标。

std::vector<std::array<double, 3>> matrix;

此向量已经排序,因此我得到了模型的轮廓。 在第二个向量boundingbox中,我存储了边界框的信息。

std::vector<std::array<double, 3>> boundingbox;

在此向量中,前四个元素描述轮廓周围的边界框。为了填充轮廓,我在其上放置了一个网格。在这种情况下,网格由软件基于变量定义。变量infill由用户在运行时设置。所以目前我的程序创建了以下图像。

Contour with BoundingBox and Infill

现在,下一步是找到网格和轮廓之间的交点。我的方法是典型的数学方法。 我会使用两个for - 循环。第一个循环将用于迭代网格,以便网格的每一行被调用一次。

第二个循环将使用向量进行矩阵。我开发了一个伪代码,我在其中描述了我的程序。

int fillingStart; //first element of boundingbox to contain information about the grid
int n; //number of lines in the Grid. 
for(size_t i=fillingStart; i<(n-1); i+2)
{
  double A_x=boundingbox[j][0];
  double A_y=boundingbox[j][1];
  double B_x=boundingbox[j+1][0];
  double B_y=boundingbox[j+1][0];

  double AB_x=B_x-A_x;
  double AB_y=B_y-A_y;

  double intersectionpoint_y = DBL_MAX;
  double intersectionpoint_x = DBL_MAX;
  double intersectionpoint2_y = DBL_MAX;
  double intersectionpoint2_x = DBL_MAX;

  for(size_t j=0; j<(matrix.size()-1); j++)
  {
     double C_x = matrix[j][0];
     double C_y = matrix[j][1];
     double D_x = matrix[j+1][0];
     double D_y = matrix[j+1][1];

     double CD_x = D_x-C_x;
     double CD_y = D_y-C_y;

     double s = (((C_x-A_x)*(-CD_y))-((-CD_x)*(C_y-A_y)))/((AB_x*(-CD_y))-((-CD_x)*AB_y));//Cramer's rule
     double t = ((AB_x*(C_y-A_y))-((C_x-A_x)*AB_y)) / ((AB_x * (-CD_y))-((-CD_x)*AB_y));//Cramer's rule

     double point_x = A_x+s*AB_x;
     double point_y = A_y*s*AB_y;

    if(point_x < intersectionpoint_x && point_y < intersectionpoint_y)
    {
        intersectionpoint_x = point_x;
        intersectionpoint_y = point_y;
    }
    else if(point_x < intersectionpoint2_x && point_y < intersectionpoint2_y)
    {
        intersectionpoint2_x = point_x;
        intersectionpoint2_y = point_y;
    }
  }

  intersects.push_back(std::array<double, 3>());
  double q = boundingbox.size()-1;
  intersects[q][0] = intersectionpoint_x;
  intersects[q][1] = intersectionpoint_y;

  intersects.push_back(std::array<double, 3>());
  double q = boundingbox.size()-1;
  intersects[q][0] = intersectionpoint2_x;
  intersects[q][1] = intersectionpoint2_y;
}

通过这两个循环,我会找到网格的每一行和轮廓的每个向量(两点之间)的交点。然后我必须找到最接近网格线的两个交叉点并存储这些点。特殊情况是,如果在contoure中有什么东西,就像一个洞。在这种情况下,我会找到四点。

编辑:为什么我要使用交叉点,如下图所示 enter image description here 这里我们有一个矩形的轮廓。正如您所看到的,只有几点可以描述这个数字。 下图显示了模型的填充 enter image description here 由于轮廓的几个点,我必须计算轮廓和网格的交点。

EDIT2 :我现在让代码正常工作并在此更新代码,但问题是它在intersectionpoint中始终保存相同的点。那是因为if语句,但我无法弄清楚它是如何工作的。

1 个答案:

答案 0 :(得分:0)

您可以迭代轮廓,并且对于每两个连续点,检查两者之间是否存在线,如果存在,则计算交点。

std::vector<std::array<double, 3>> intersects;

auto it = matrix.begin();

while (it != matrix.end() - 1) {
    auto &p1 = *it;
    auto &p2 = *(++it);
    double x;
    // Check if there is a vertical line between p1 and p2
    if (has_vertical_line(p1, p2, &x)) {
        // The equation of the line joining p1 and p2 is:
        //     (p2[1] - p1[1]) / (p2[0] - p1[0]) * x + p1[0]
        double y = (p2[1] - p1[1]) / (p2[0] - p1[0]) * x + p1[0];
        intersects.push_back({x, y, 0.0});
    }
}

has_vertical_line类似于:

bool has_vertical_line (std::array<double, 3> const& p1, 
                        std::array<double, 3> const& p2,
                        double *px) {
    double x1 = p1[0], x2 = p2[0];
    if (x2 <= x1) {
        std::swap(x1, x2);
    }
    size_t lx2 = closest_from_below(x2),
           lx1 = closest_from_above(x1);
    if (lx1 == lx2) {
        *px = lines[lx1]; // Assuming abscissa
        return true;
    }
    return false;
}

其中closest_from_belowclosest_from_above是简单函数,可以找到当前横坐标下方/上方的线条(由于线条是垂直的,因此很简单)。