Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/amazon-s3/2.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_Algorithm_Geometry_2d_Computational Geometry - Fatal编程技术网

C 直线平分线与矩形的交点

C 直线平分线与矩形的交点,c,algorithm,geometry,2d,computational-geometry,C,Algorithm,Geometry,2d,Computational Geometry,我一整天都在想这个 基本上,我有两个点的坐标,它们总是在一个矩形内。 我还知道矩形角的位置。这两个入口点在运行时给出 我需要一个算法来找到给定点之间的线段所形成的平分线与矩形相交的2个点 一些细节: 在上图中,A和B由它们的坐标给出:A(x1,y1)和B(x2,y2)。基本上,我需要找到C和D的位置。 红色X是AB段的中心。这一点(我们称之为中心)必须在CD线上 我所做的: 找到中心: center.x = (A.x+B.x)/2; center.y = (A.y+B.y)/2; 找到

我一整天都在想这个

基本上,我有两个点的坐标,它们总是在一个矩形内。 我还知道矩形角的位置。这两个入口点在运行时给出

我需要一个算法来找到给定点之间的线段所形成的平分线与矩形相交的2个点

一些细节:

在上图中,A和B由它们的坐标给出:A(x1,y1)和B(x2,y2)。基本上,我需要找到C和D的位置。 红色X是AB段的中心。这一点(我们称之为中心)必须在CD线上

我所做的:

  • 找到中心:

    center.x = (A.x+B.x)/2;
    center.y = (A.y+B.y)/2;
    
  • 找到的CD坡度:

    AB_slope =  A.y - B.y / A.x - B.x;
    CD_slope = -1/AB_slope;
    
知道中心和CD斜率给了我CD的方程,我试图通过试着在矩形的所有4个边界上的点的位置来找到一个解决方案。 然而,由于某些原因,它不起作用:每次我有一个解决方案,比如说对于C,D在外面绘制,反之亦然。

以下是我使用的方程式:

  • 了解x:

    y = (CD_slope * (x - center.x)) + center.y;
    if y > 0 && y < 512: #=> solution found!
    
    y=(CD_斜率*(x-center.x))+center.y;
    如果y>0&&y<512:#=>找到解决方案!
    
  • 了解y:

    x = (y - center.y + CD_slope*center.x)/CD_slope;
    if x > 0 && x < 512: #=> solution found!
    
    x=(y-center.y+CD_-slope*center.x)/CD_-slope;
    如果x>0&&x<512:#=>找到解决方案!
    
由此,我也可以得到另一段(假设我找到了C,我知道中心),但几何体无法找到这段的延伸,直到它与矩形的另一侧相交

更新为包含编码片段

(参见主功能中的注释)

typedef结构{double x;double y;}点;
点计算中心(点p1,点p2){
点-点;
点x=(p1.x+p2.x)/2;
点y=(p1.y+p2.y)/2;
返回点;
}
双计算坡度(点p1,点p2){
双dy=p1.y-p2.y;
双dx=p1.x-p2.x;
双斜率=dy/dx;//这是p1 p2斜率
返回-1/坡度;
}
int计算(双坡,点中心,双x,点*点){
双最小值=0.00;
双最大值=512.00;
双y=(p坡度*(x-center.x))+center.y;
如果(y>=min&&y x=corner;
点->y=y;
printf(“++>为X找到Y,点为P(%f,%f)\n”,点->X,点->Y);
返回1;
}
返回0;
}
int计算(双坡、点中心、双y、点*点){
双最小值=0.00;
双最大值=512.00;
双x=(y-中心.y+P坡度*中心.x)/P坡度;
如果(x>=min&&x x=x;
点->y=y;
printf(“++>为Y找到X,点为:P(%f,%f)\n”,点->X,点->Y);
返回1;
}
返回0;
}
int main(int argc,字符**argv){
A、B点;
//解析argv并定义A和B
//这里省略了此代码,让我们假设:
//A.x=175.00;
//A.y=420.00;
//B.x=316.00;
//B.y=62.00;
C点;
D点;
点中心;
双坡;
中心=计算中心(A,B);
p斜率=计算p斜率(A,B);
//这里是有趣的地方:
//我需要找到正确的连续调用来计算
//对于4种情况:x=0,x=512#=>调用calculate\u y\u knowing\u x
//y=0,y=512#=>调用calculate_x_y
//对C点和D点都这样做2次。
//此外,如果找到点C,则点D不应位于同一侧(因此C!=D)
//对于给定的A点和B点,顺序为:
计算_y_x(p坡度,中心,0.00,C);
计算出(P斜率,中心,512.00,D);
//收益率:C(0.00144.308659),D(512.00345.962291)
//但如果A(350.00,314.00)和B(106.00,109.00)
//成功应为:
//计算_y_x(p坡度,中心,0.00,C);
//计算x(p斜率,中心,512.00,D);
//产生C(0.00482.875610)和D(405.694672,0.00)
返回0;
}
这是C代码

注:

  • 这幅画是手工画的
  • 坐标系逆时针旋转90°,但不应对解决方案产生影响
  • 我正在寻找一个C语言的算法,但我可以阅读其他编程语言
  • 这是一个二维问题
你有CD的方程(形式为(y-y0)=m(x-x0)),你可以把它转换成形式y=mx+c。你也可以把它转换成形式x=(1/m)y-(c/m)


然后,您只需找到当x=0,x=512,y=0,y=512时的解。

我们从中心点C和AB,D的方向开始:

C.x = (A.x+B.x) / 2
C.y = (A.y+B.y) / 2
D.x = (A.x-B.x) / 2
D.y = (A.y-B.y) / 2
如果p是直线上的一个点,则CP必须垂直于D。直线方程为:

DotProduct(P-C, D) = 0

对于正方形的四条边,我们有一个等式:

P.x=0 -> P.y = CD / D.y
P.y=0 -> P.x = CD / D.x
P.x=512 -> P.y = (CD - 512*D.x) / D.y
P.y=512 -> P.x = (CD - 512*D.y) / D.x

除了2个点重合的退化情况外,这4个点中只有2个点的p.x和p.y都在0和512之间。您还必须检查特殊情况D.x=0或D.y=0。

以下代码应该可以实现这一点:

typedef struct { float x; float y; } Point;
typedef struct { Point point[2]; } Line;
typedef struct { Point origin; float width; float height; } Rect;
typedef struct { Point origin; Point direction; } Vector;

Point SolveVectorForX(Vector vector, float x)
{
    Point solution;
    solution.x = x;
    solution.y = vector.origin.y +
        (x - vector.origin.x)*vector.direction.y/vector.direction.x;
    return solution;
}

Point SolveVectorForY(Vector vector, float y)
{
    Point solution;
    solution.x = vector.origin.x +
        (y - vector.origin.y)*vector.direction.x/vector.direction.y;
    solution.y = y;
    return solution;
}

Line FindLineBisectorIntersectionWithRect(Rect rect, Line AB)
{
    Point A = AB.point[0];
    Point B = AB.point[1];
    int pointCount = 0;
    int testEdge = 0;
    Line result;
    Vector CD;

    // CD.origin = midpoint of line AB
    CD.origin.x = (A.x + B.x)/2.0;
    CD.origin.y = (A.y + B.y)/2.0;

    // CD.direction = negative inverse of AB.direction (perpendicular to AB)
    CD.direction.x = (B.y - A.y);
    CD.direction.y = (A.x - B.x);

    // for each edge of the rectangle, check:
    // 1. that an intersection with CD is possible (avoid division by zero)
    // 2. that the intersection point falls within the endpoints of the edge
    // 3. if both check out, use that point as one of the solution points
    while ((++testEdge <= 4) && (pointCount < 2))
    {
        Point point;

        switch (testEdge)
        {
            case 1: // check minimum x edge of rect
                if (CD.direction.x == 0) { continue; }
                point = SolveVectorForX(CD, rect.origin.x);
                if (point.y < rect.origin.y) { continue; }
                if (point.y > (rect.origin.y + rect.height)) { continue; }
                break;

            case 2: // check maximum x edge of rect
                if (CD.direction.x == 0) { continue; }
                point = SolveVectorForX(CD, rect.origin.x + rect.width);
                if (point.y < rect.origin.y) { continue; }
                if (point.y > (rect.origin.y + rect.height)) { continue; }
                break;

            case 3: // check minimum y edge of rect
                if (CD.direction.y == 0) { continue; }
                point = SolveVectorForY(CD, rect.origin.y);
                if (point.x < rect.origin.x) { continue; }
                if (point.x > (rect.origin.x + rect.width)) { continue; }
                break;

            case 4: // check maximum y edge of rect
                if (CD.direction.y == 0) { continue; }
                point = SolveVectorForY(CD, rect.origin.y + rect.height);
                if (point.x < rect.origin.x) { continue; }
                if (point.x > (rect.origin.x + rect.width)) { continue; }
                break;
        };

        // if we made it here, this point is one of the solution points
        result.point[pointCount++] = point;
    }

    // pointCount should always be 2
    assert(pointCount == 2);

    return result;
}
typedef结构{float x;float y;}点;
typedef结构{Point-Point[2];}行;
typedef结构{点原点;浮动宽度;浮动高度;}Rect;
typedef结构{点原点;点方向;}向量;
点解算矢量FORX(矢量,浮点x)
{
点解;
解x=x;
solution.y=vector.origin.y+
(x-vector.origin.x)*vector.direction.y/vector.direction.x;
回流液;
}
点解算矢量(矢量,浮点y)
{
点解;
解.x=向量.origin.x+
(y-vector.origin.y)*vector.direction.x/vector.direction.y;
解y=y;
回流液;
}
折线平分线与Rect相交(Rect Rect,AB线)
{
A点=AB点[0];
B点=AB点[1];
int pointCount=0;
int testEdge=0;
线路结果;
载体CD;
P.x=0 -> P.y = CD / D.y
P.y=0 -> P.x = CD / D.x
P.x=512 -> P.y = (CD - 512*D.x) / D.y
P.y=512 -> P.x = (CD - 512*D.y) / D.x
typedef struct { float x; float y; } Point;
typedef struct { Point point[2]; } Line;
typedef struct { Point origin; float width; float height; } Rect;
typedef struct { Point origin; Point direction; } Vector;

Point SolveVectorForX(Vector vector, float x)
{
    Point solution;
    solution.x = x;
    solution.y = vector.origin.y +
        (x - vector.origin.x)*vector.direction.y/vector.direction.x;
    return solution;
}

Point SolveVectorForY(Vector vector, float y)
{
    Point solution;
    solution.x = vector.origin.x +
        (y - vector.origin.y)*vector.direction.x/vector.direction.y;
    solution.y = y;
    return solution;
}

Line FindLineBisectorIntersectionWithRect(Rect rect, Line AB)
{
    Point A = AB.point[0];
    Point B = AB.point[1];
    int pointCount = 0;
    int testEdge = 0;
    Line result;
    Vector CD;

    // CD.origin = midpoint of line AB
    CD.origin.x = (A.x + B.x)/2.0;
    CD.origin.y = (A.y + B.y)/2.0;

    // CD.direction = negative inverse of AB.direction (perpendicular to AB)
    CD.direction.x = (B.y - A.y);
    CD.direction.y = (A.x - B.x);

    // for each edge of the rectangle, check:
    // 1. that an intersection with CD is possible (avoid division by zero)
    // 2. that the intersection point falls within the endpoints of the edge
    // 3. if both check out, use that point as one of the solution points
    while ((++testEdge <= 4) && (pointCount < 2))
    {
        Point point;

        switch (testEdge)
        {
            case 1: // check minimum x edge of rect
                if (CD.direction.x == 0) { continue; }
                point = SolveVectorForX(CD, rect.origin.x);
                if (point.y < rect.origin.y) { continue; }
                if (point.y > (rect.origin.y + rect.height)) { continue; }
                break;

            case 2: // check maximum x edge of rect
                if (CD.direction.x == 0) { continue; }
                point = SolveVectorForX(CD, rect.origin.x + rect.width);
                if (point.y < rect.origin.y) { continue; }
                if (point.y > (rect.origin.y + rect.height)) { continue; }
                break;

            case 3: // check minimum y edge of rect
                if (CD.direction.y == 0) { continue; }
                point = SolveVectorForY(CD, rect.origin.y);
                if (point.x < rect.origin.x) { continue; }
                if (point.x > (rect.origin.x + rect.width)) { continue; }
                break;

            case 4: // check maximum y edge of rect
                if (CD.direction.y == 0) { continue; }
                point = SolveVectorForY(CD, rect.origin.y + rect.height);
                if (point.x < rect.origin.x) { continue; }
                if (point.x > (rect.origin.x + rect.width)) { continue; }
                break;
        };

        // if we made it here, this point is one of the solution points
        result.point[pointCount++] = point;
    }

    // pointCount should always be 2
    assert(pointCount == 2);

    return result;
}