returns 两个 TShape 的交集函数,包括 TPaths?
Function that returns intersection of two TShapes, including TPaths?
有人知道 returns 两个 TShape 的交点 TPath 的函数吗?特别是 returns 两个 TPath 的交集 TPath。
例如:
pthIntersection := PathIntersection(Path1,Path2);
没有内置函数。
但我认为你正在尝试做的是:
给定一个由线连接的不同点组成的多边形(又名 TPath)。
Return ShapeA 中位于 ShapeB 内部的所有点。
交点
这可以使用 PointInObjectLocal
.
来完成
运行 循环访问 PathA
中的所有点并查看是否有任何点位于 PathB
中。
直线相交
如果你想知道所有重叠的顶点,你首先必须 Flatten
(副本)两个 TPaths 然后 运行 两个形状中所有线的线相交算法。
这会将所有曲线转换为直线。
这是执行此操作的例程:
来自:http://www.partow.net/projects/fastgeo/index.html
function Intersect(const x1, y1, x2, y2, x3, y3, x4, y4: TFloat; out ix, iy: TFloat): boolean;
var
UpperX, UpperY, LowerX, LowerY: TFloat;
Ax, Bx, Cx, Ay, By, Cy: TFloat;
D, F, E, Ratio: TFloat;
begin
Result:= false;
Ax:= x2 - x1;
Bx:= x3 - x4;
if Ax < Zero then begin
LowerX:= x2;
UpperX:= x1;
end else begin
UpperX:= x2;
LowerX:= x1;
end;
if Bx > Zero then begin
if (UpperX < x4) or (x3 < LowerX) then Exit;
end else if (UpperX < x3) or (x4 < LowerX) then Exit;
Ay:= y2 - y1;
By:= y3 - y4;
if Ay < Zero then begin
LowerY:= y2;
UpperY:= y1;
end else begin
UpperY:= y2;
LowerY:= y1;
end;
if By > Zero then begin
if (UpperY < y4) or (y3 < LowerY) then Exit;
end else if (UpperY < y3) or (y4 < LowerY) then Exit;
Cx:= x1 - x3;
Cy:= y1 - y3;
D:= (By * Cx) - (Bx * Cy);
F:= (Ay * Bx) - (Ax * By);
if F > Zero then begin
if (D < Zero) or (D > F) then Exit;
end else if (D > Zero) or (D < F) then Exit;
E:= (Ax * Cy) - (Ay * Cx);
if F > Zero then begin
if (E < Zero) or (E > F) then Exit;
end else if (E > Zero) or (E < F) then Exit;
Result:= true;
Ratio:= (Ax * -By) - (Ay * -Bx);
if NotEqual(Ratio, Zero) then begin
Ratio:= ((Cy * -Bx) - (Cx * -By)) / Ratio;
ix:= x1 + (Ratio * Ax);
iy:= y1 + (Ratio * Ay);
end else begin
//if Collinear(x1,y1,x2,y2,x3,y3) then
if IsEqual((Ax * -Cy), ( -Cx * Ay)) then begin
ix:= x3;
iy:= y3;
end else begin
ix:= x4;
iy:= y4;
end;
end;
end;
function Intersect(const Segment1,Segment2:TSegment2D; out ix, iy : TFloat):Boolean;
begin
Result := Intersect(Segment1[1].x,Segment1[1].y,Segment1[2].x,Segment1[2].y,Segment2[1].x,Segment2[1].y,Segment2[2].x,Segment2[2].y,ix,iy);
end;
只需将 TFloat
x,y 对转换为 TPointF
即可。
该例程的妙处在于它还会告诉您线条重叠的确切点。
如果您沿着这些线,直到两条线重叠,然后从那里开始跟踪重叠线和 PointInShape,您就可以构建两个形状重叠的精确图像。
让它更快
如果扁平化和线段数量的相应增加使您的代码太慢,您可以保留曲线并查看 line/curve 是否与另一条曲线相交。
为此,您可以将曲线转换为 bezier curves and use De_Casteljau's algorithm
更多信息
另请参阅第一个或第二个答案中的 this question and the link to Delphi source code。
有人知道 returns 两个 TShape 的交点 TPath 的函数吗?特别是 returns 两个 TPath 的交集 TPath。
例如:
pthIntersection := PathIntersection(Path1,Path2);
没有内置函数。
但我认为你正在尝试做的是:
给定一个由线连接的不同点组成的多边形(又名 TPath)。
Return ShapeA 中位于 ShapeB 内部的所有点。
交点
这可以使用 PointInObjectLocal
.
来完成
运行 循环访问 PathA
中的所有点并查看是否有任何点位于 PathB
中。
直线相交
如果你想知道所有重叠的顶点,你首先必须 Flatten
(副本)两个 TPaths 然后 运行 两个形状中所有线的线相交算法。
这会将所有曲线转换为直线。
这是执行此操作的例程:
来自:http://www.partow.net/projects/fastgeo/index.html
function Intersect(const x1, y1, x2, y2, x3, y3, x4, y4: TFloat; out ix, iy: TFloat): boolean;
var
UpperX, UpperY, LowerX, LowerY: TFloat;
Ax, Bx, Cx, Ay, By, Cy: TFloat;
D, F, E, Ratio: TFloat;
begin
Result:= false;
Ax:= x2 - x1;
Bx:= x3 - x4;
if Ax < Zero then begin
LowerX:= x2;
UpperX:= x1;
end else begin
UpperX:= x2;
LowerX:= x1;
end;
if Bx > Zero then begin
if (UpperX < x4) or (x3 < LowerX) then Exit;
end else if (UpperX < x3) or (x4 < LowerX) then Exit;
Ay:= y2 - y1;
By:= y3 - y4;
if Ay < Zero then begin
LowerY:= y2;
UpperY:= y1;
end else begin
UpperY:= y2;
LowerY:= y1;
end;
if By > Zero then begin
if (UpperY < y4) or (y3 < LowerY) then Exit;
end else if (UpperY < y3) or (y4 < LowerY) then Exit;
Cx:= x1 - x3;
Cy:= y1 - y3;
D:= (By * Cx) - (Bx * Cy);
F:= (Ay * Bx) - (Ax * By);
if F > Zero then begin
if (D < Zero) or (D > F) then Exit;
end else if (D > Zero) or (D < F) then Exit;
E:= (Ax * Cy) - (Ay * Cx);
if F > Zero then begin
if (E < Zero) or (E > F) then Exit;
end else if (E > Zero) or (E < F) then Exit;
Result:= true;
Ratio:= (Ax * -By) - (Ay * -Bx);
if NotEqual(Ratio, Zero) then begin
Ratio:= ((Cy * -Bx) - (Cx * -By)) / Ratio;
ix:= x1 + (Ratio * Ax);
iy:= y1 + (Ratio * Ay);
end else begin
//if Collinear(x1,y1,x2,y2,x3,y3) then
if IsEqual((Ax * -Cy), ( -Cx * Ay)) then begin
ix:= x3;
iy:= y3;
end else begin
ix:= x4;
iy:= y4;
end;
end;
end;
function Intersect(const Segment1,Segment2:TSegment2D; out ix, iy : TFloat):Boolean;
begin
Result := Intersect(Segment1[1].x,Segment1[1].y,Segment1[2].x,Segment1[2].y,Segment2[1].x,Segment2[1].y,Segment2[2].x,Segment2[2].y,ix,iy);
end;
只需将 TFloat
x,y 对转换为 TPointF
即可。
该例程的妙处在于它还会告诉您线条重叠的确切点。
如果您沿着这些线,直到两条线重叠,然后从那里开始跟踪重叠线和 PointInShape,您就可以构建两个形状重叠的精确图像。
让它更快
如果扁平化和线段数量的相应增加使您的代码太慢,您可以保留曲线并查看 line/curve 是否与另一条曲线相交。
为此,您可以将曲线转换为 bezier curves and use De_Casteljau's algorithm
更多信息
另请参阅第一个或第二个答案中的 this question and the link to Delphi source code。