我一整天都试图绕过这个......
基本上,我有两个点的坐标总是在一个矩形内。 我也知道矩形角的位置。这两个入口点是在运行时给出的。
我需要一个算法来找到2个点,其中由给定点之间的线段产生的平分线与该矩形相交。
image http://f.cl.ly/items/0o3g1G0F0V120R3S2Q3H/coop.jpg
一些细节:
在上图中,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:
x = (y - center.y + CD_slope*center.x)/CD_slope;
if x > 0 && x < 512: #=> solution found!
由此,我也可以得到另一个片段(假设我找到了C并且我知道了中心),但几何失败了我找到这个片段的延伸直到它与矩形的另一边相交
已更新,其中包含编码代码
(见主要功能评论)
typedef struct { double x; double y; } Point;
Point calculate_center(Point p1, Point p2) {
Point point;
point.x = (p1.x+p2.x)/2;
point.y = (p1.y+p2.y)/2;
return point;
}
double calculate_pslope(Point p1, Point p2) {
double dy = p1.y - p2.y;
double dx = p1.x - p2.x;
double slope = dy/dx; // this is p1 <-> p2 slope
return -1/slope;
}
int calculate_y_knowing_x(double pslope, Point center, double x, Point *point) {
double min= 0.00;
double max= 512.00;
double y = (pslope * (x - center.x)) + center.y;
if(y >= min && y <= max) {
point->x = corner;
point->y = y;
printf("++> found Y for X, point is P(%f, %f)\n", point->x, point->y);
return 1;
}
return 0;
}
int calculate_x_knowing_y(double pslope, Point center, double y, Point *point) {
double min= 0.00;
double max= 512.00;
double x = (y - center.y + pslope*center.x)/pslope;
if(x >= min && x <= max) {
point->x = x;
point->y = y;
printf("++> found X for Y, point is: P(%f, %f)\n", point->x, point->y);
return 1;
}
return 0;
}
int main(int argc, char **argv) {
Point A, B;
// parse argv and define A and B
// this code is omitted here, let's assume:
// A.x = 175.00;
// A.y = 420.00;
// B.x = 316.00;
// B.y = 62.00;
Point C;
Point D;
Point center;
double pslope;
center = calculate_center(A, B);
pslope = calculate_pslope(A, B);
// Here's where the fun happens:
// I'll need to find the right succession of calls to calculate_*_knowing_*
// for 4 cases: x=0, X=512 #=> call calculate_y_knowing_x
// y=0, y=512 #=> call calculate_x_knowing_y
// and do this 2 times for both C and D points.
// Also, if point C is found, point D should not be on the same side (thus C != D)
// for the given A and B points the succession is:
calculate_y_knowing_x(pslope, center, 0.00, C);
calculate_y_knowing_x(pslope, center, 512.00, D);
// will yield: C(0.00, 144.308659), D(512.00, 345.962291)
// But if A(350.00, 314.00) and B(106.00, 109.00)
// the succesion should be:
// calculate_y_knowing_x(pslope, center, 0.00, C);
// calculate_x_knowing_y(pslope, center, 512.00, D);
// to yield C(0.00, 482.875610) and D(405.694672, 0.00)
return 0;
}
这是C代码。
注意:
答案 0 :(得分:3)
你有 CD 的等式(格式为(y - y0)= m(x - x0)),您可以将其转换为形式y = mx + c 。您也可以将其转换为 x =(1 / m)y - (c / m)的形式。
然后您只需找到 x = 0 , x = 512 , y = 0 , y =的解决方案512
答案 1 :(得分:2)
我们从中心点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
或
CD = C.x*D.x + C.y*D.y
P.x * D.x + P.y * D.y - CD = 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个点的Px和Py都在0到512之间。你还需要检查特殊情况Dx = 0或Dy = 0。
答案 2 :(得分:2)
以下代码可以解决这个问题:
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;
}