Поскольку вы уже используете GDI (Canvas
), вы также можете использовать регионы, вот пример:
procedure TForm1.PaintBox1Paint(Sender: TObject);
var
Canvas: TCanvas;
T1, T2: array[0..2] of TPoint;
R1, R2: HRGN;
Buffer: PRgnData;
BufferSize: Cardinal;
P: PRect;
I: Integer;
Pt1, Pt2: TPoint; // result intersection points
begin
Canvas := (Sender as TPaintBox).Canvas;
// first triangle region
T1[0] := Point(100, 100);
T1[1] := Point(260, 10);
T1[2] := Point(30, 3);
R1 := CreatePolygonRgn(T1[0], 3, ALTERNATE);
if R1 = 0 then
RaiseLastOSError;
try
// show the first triangle as red (not needed for computation)
Canvas.Brush.Color := clRed;
FillRgn(Canvas.Handle, R1, Canvas.Brush.Handle);
// second triangle region
T2[0] := Point(20, 80);
T2[1] := Point(300, 40);
T2[2] := Point(100, 100);
R2 := CreatePolygonRgn(T2[0], 3, ALTERNATE);
if R2 = 0 then
RaiseLastOSError;
try
// show the second triangle as green (not needed for computation)
Canvas.Brush.Color := clGreen;
FillRgn(Canvas.Handle, R2, Canvas.Brush.Handle);
// determine the intersecting region
if CombineRgn(R1, R1, R2, RGN_AND) = ERROR then
RaiseLastOSError;
// show intersection as yellow (not needed for computation)
Canvas.Brush.Color := clYellow;
FillRgn(Canvas.Handle, R1, Canvas.Brush.Handle);
// determine the needed buffer size
Buffer := nil;
BufferSize := GetRegionData(R1, 0, Buffer);
// allocate buffer and get region data (array of rectangles)
Buffer := AllocMem(BufferSize);
try
if GetRegionData(R1, BufferSize, Buffer) = 0 then
RaiseLastOSError;
// enumerate all rectangles and find points with leftmost and rightmost X
P := @Buffer^.Buffer[0];
Pt1 := P^.TopLeft;
Pt2 := Point(P^.Right, P^.Top);
for I := 0 to Buffer^.rdh.nCount - 1 do
begin
if P^.Left < Pt1.X then
Pt1 := P^.TopLeft;
if P^.Right > Pt2.X then
Pt2 := Point(P^.Right, P^.Top);
Inc(P);
end;
// connect the points with a blue line (not needed for computation)
Canvas.Pen.Color := clNavy;
Canvas.MoveTo(Pt1.X, Pt1.Y);
Canvas.LineTo(Pt2.X, Pt2.Y);
// output result points (not needed for computation)
Canvas.Brush.Color := Self.Color;
Canvas.Font.Color := clWindowText;
Canvas.TextOut(8, 108, Format('Pt1: %d, %d, Pt2: %d, %d', [Pt1.X, Pt1.Y, Pt2.X, Pt2.Y]));
finally
FreeMem(Buffer);
end;
finally
DeleteObject(R2);
end;
finally
DeleteObject(R1);
end;
end;
Это даст следующий результат: