Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/55.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 查找一个圆内的所有直线,对于多个圆。优化_C_Optimization_Computational Geometry - Fatal编程技术网

C 查找一个圆内的所有直线,对于多个圆。优化

C 查找一个圆内的所有直线,对于多个圆。优化,c,optimization,computational-geometry,C,Optimization,Computational Geometry,我正在做一个程序,在这个程序中,我需要找到所有的线,这些线位于一个半径为笛卡尔点的圆中 目前,对于每个圆,我迭代所有线,检查线是否在任何点进入/接触圆 代码基本上如下所示 for (int i = 0; i < num_circles; i++) { for (int j = 0; j < num_lines; j++) { if(lineIntersectWithCircle(circle[i], lines[j])) {

我正在做一个程序,在这个程序中,我需要找到所有的线,这些线位于一个半径为笛卡尔点的圆中

目前,对于每个圆,我迭代所有线,检查线是否在任何点进入/接触圆

代码基本上如下所示

for (int i = 0; i < num_circles; i++) 
{
    for (int j = 0; j < num_lines; j++) 
    {
        if(lineIntersectWithCircle(circle[i], lines[j])) 
        {
            //Append line[j] to a list of lines intersecting with circle[i];

            //some code
        }
    }
}
for(int i=0;i
我一直在想很多方法来优化它,但我遇到了麻烦。 我已经按最小笛卡尔距离对圆排序,按最大距离对线排序。通过这种方式,您可以进行一些优化,但这是非常小的,因为一旦达到
line[j].max>circle[i].min的点,您仍然需要迭代所有其余的行

我对我的交叉点检查方法很满意,我只想尽量减少调用它的次数


有什么好办法吗?

最便宜的办法就是在进行更昂贵的相交测试之前检查两种形状(直线和圆)的边界范围/矩形。很有可能,您甚至可以动态计算直线/圆的范围,而不是预计算,并且仍然可以获得不错的性能提升,除非直线/圆交点已经非常便宜

一个真正有效的方法,但需要更多的工作,就是创建一个网格。您可以使用上面计算的边界矩形廉价地查看形状相交的网格单元

struct GridNode
{
    // Points to the index of the next node in the grid cell
    // or -1 if we're at the end of the singly-linked list.
    int next_node;

    // Points to the index of the shape being stored.
    int shape;
};

struct GridCell
{
    // Points to the first node or -1 if the cell is empty.
    int first_node;
};

struct Grid
{
    // Stores the cells in the grid. This is just illustrative
    // code. You should dynamically allocate this with adjustable
    // grid widths and heights based on your needs.
    struct GridCell cells[grid_width * grid_height];

    // Stores the nodes in the grid (one or more nodes per shape
    // inserted depending on how many it intersects). This is 
    // a variable-sized array you can realloc needed (ex: double 
    // the size when you're out of room).
    struct GridNode* nodes;

    // The maximum number of nodes we can store before realloc.
    int node_cap;

    // The number of nodes inserted so far. realloc when this
    // exceeds node_cap.
    int node_num;
};
。。。这样的事情。这样,大多数情况下,您只需执行一些整数(模拟指针)操作并将一些网格节点项添加到此可变大小的
节点
数组,就可以将元素插入网格。堆分配很少发生

我发现,在实践中,如果你有许多动态元素从一个单元格移动到下一个单元格,这比四叉树要好,就像在2D视频游戏中,所有东西都在移动,而我们需要快速碰撞检测,如果在遍历与所测试形状相交的网格单元时,小心节点的内存布局,以最小化缓存未命中,甚至可以与四叉树进行搜索。您甚至可以在构建网格后执行post pass,以便根据交叉点搜索的效率重新排列每个节点的内存,以进行缓存友好列表迭代。如果你想变得有趣,你可以使用Bresenham精确地计算出一条线与哪些网格单元相交,例如,但是考虑到你所做的事情的二次复杂性,你可以指数级地改进,而不必费心去做,只需用一种非常简单的方法来做边界矩形

基本上要找到交点,首先抓取形状的边界矩形。然后查看它在网格中与哪些单元相交。现在检查与原始形状相交的网格单元中包含的形状是否相交。通过这种方式,除了巨大的形状(O(n)的最坏情况)之外,您可以朝着恒定的时间复杂度工作,这可能是一种罕见的情况


我甚至发现在三维空间中,当物体移动很多的时候,这些都是有用的。它们通常比八叉树、BVH树和kd树的变体便宜,后者提供了广泛的搜索加速,但代价是更昂贵的构建和更新,如果您为每个网格单元使用单个链接列表的策略,而不必单独分配节点,你可以将它存储在一个非常合理的内存量中,即使是三维空间。我不会使用三维版本的光线跟踪,但它对于三维碰撞检测非常有用,比如检测每一帧移动的粒子之间的碰撞。

最便宜的方法就是在更昂贵的相交测试之前检查两个形状(直线和圆)的边界范围/矩形。很有可能,您甚至可以动态计算直线/圆的范围,而不是预计算,并且仍然可以获得不错的性能提升,除非直线/圆交点已经非常便宜

一个真正有效的方法,但需要更多的工作,就是创建一个网格。您可以使用上面计算的边界矩形廉价地查看形状相交的网格单元

struct GridNode
{
    // Points to the index of the next node in the grid cell
    // or -1 if we're at the end of the singly-linked list.
    int next_node;

    // Points to the index of the shape being stored.
    int shape;
};

struct GridCell
{
    // Points to the first node or -1 if the cell is empty.
    int first_node;
};

struct Grid
{
    // Stores the cells in the grid. This is just illustrative
    // code. You should dynamically allocate this with adjustable
    // grid widths and heights based on your needs.
    struct GridCell cells[grid_width * grid_height];

    // Stores the nodes in the grid (one or more nodes per shape
    // inserted depending on how many it intersects). This is 
    // a variable-sized array you can realloc needed (ex: double 
    // the size when you're out of room).
    struct GridNode* nodes;

    // The maximum number of nodes we can store before realloc.
    int node_cap;

    // The number of nodes inserted so far. realloc when this
    // exceeds node_cap.
    int node_num;
};
。。。这样的事情。这样,大多数情况下,您只需执行一些整数(模拟指针)操作并将一些网格节点项添加到此可变大小的
节点
数组,就可以将元素插入网格。堆分配很少发生

我发现,在实践中,如果你有许多动态元素从一个单元格移动到下一个单元格,这比四叉树要好,就像在2D视频游戏中,所有东西都在移动,而我们需要快速碰撞检测,如果在遍历与所测试形状相交的网格单元时,小心节点的内存布局,以最小化缓存未命中,甚至可以与四叉树进行搜索。您甚至可以在构建网格后执行post pass,以便根据交叉点搜索的效率重新排列每个节点的内存,以进行缓存友好列表迭代。如果你想变得有趣,你可以使用Bresenham精确地计算出一条线与哪些网格单元相交,例如,但是考虑到你所做的事情的二次复杂性,你可以指数级地改进,而不必费心去做,只需用一种非常简单的方法来做边界矩形

基本上要找到交点,首先抓取形状的边界矩形。然后查看它在网格中与哪些单元相交。现在检查是否与网格单元中包含的形状相交
lineIntersectWithCircle(size_t circle, size_t line){
  struct circle C = circle_cache[circle]; //these may be separate arrays
  struct line L = line_cache[line];       //from your point data

  long tmp = C.x * L.y10 - C.y * L.x10 + L.delta;
  return (tmp*tmp < L.sides * C.R2);
}
bool lineIntersectWithCircle(size_t circle, size_t line){
  struct circle C = circle_cache[circle]; //these may be separate arrays
  struct line L = line_cache[line];       //from your point data

  //if the bounding boxes don't intersect neither does the line
  //this may not be _that_ helpful and you would need to:
  // figure out the bounding boxes for each line/circle
  // and cache additional data
  if (C.leftx > L.rightx || L.leftx > C.rightx) //a box is to the side
    return 0;
  if (C.topy < L.boty || L.topy < C.boty) //a box is below/above
    return 0;

  //the bounding boxes intersected so check exact calculation
  long tmp = C.x * L.y10 - C.y * L.x10 + L.delta;
  return (tmp*tmp < L.sides * C.R2);
}