Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

The intersection of the straight line and the triangle sides

enter image description here

Required points are red. I draw this using delphi.

   with Image1.Canvas do
begin
Image1.Canvas.Pen.Color :=RGB(255,0,0);
    MoveTo(30,3); // 1
    LineTo(260,10);// 1-2
    LineTo(100,100);//2-3
    LineTo(30,3);//3-1
Image1.Canvas.Pen.Color :=RGB(0,0,255);
    MoveTo(20,80);//4
    LineTo(300,40);//4-5

end;
like image 705
Wolfgang Avatar asked Nov 30 '11 06:11

Wolfgang


1 Answers

Since you're already using GDI (Canvas), you can also use regions, here is an example:

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;

This will produce the following result:

Screenshot

like image 140
Ondrej Kelle Avatar answered Sep 21 '22 06:09

Ondrej Kelle