Janilabo

Untitled

Sep 13th, 2013
45
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Pascal 4.41 KB | None | 0 0
  1. function TPABounds(TPA: TPointArray): TBox;
  2. var
  3.   h, i: Integer;
  4. begin
  5.   h := High(TPA);
  6.   if (h > -1) then
  7.   begin
  8.     Result.X1 := TPA[0].X; Result.X2 := TPA[0].X;
  9.     Result.Y2 := TPA[0].Y; Result.Y2 := TPA[0].Y;
  10.     if (h > 0) then
  11.     for i := 1 to h do
  12.     begin
  13.       if (TPA[i].X < Result.X1) then
  14.         Result.X1 := TPA[i].X
  15.       else if (TPA[i].X > Result.X2) then
  16.         Result.X2 := TPA[i].X;
  17.       if (TPA[i].Y < Result.Y1) then
  18.         Result.Y1 := TPA[i].Y
  19.       else if (TPA[i].Y > Result.Y2) then
  20.         Result.Y2 := TPA[i].Y;
  21.     end;
  22.   end;
  23. end;
  24.  
  25. function CrossTurn(p, q, r: TPoint): Boolean;
  26. var
  27.   sum1,sum2:Single; //Int?
  28. begin
  29.   //Do the vectors pq:qr form a right turn, or not?
  30.   Result := False;
  31.   sum1 := q.x*r.y + p.x*q.y + r.x*p.y;
  32.   sum2 := q.x*p.y + r.x*q.y + p.x*r.y;
  33.   if (sum1 - sum2) < 0 then
  34.     Result := True;
  35. end;
  36.  
  37. function CleanAndSortTPA(TPA:TPointArray): TPointArray;
  38. var
  39.   Matrix: Array of TBoolArray;
  40.   i,c,H,j,idx,x,y: Integer;
  41.   Bounds:TBox;
  42. begin
  43.   Bounds := TPABounds(TPA);
  44.   H := High(TPA);
  45.   SetLength(Matrix, (Bounds.Y2-Bounds.Y1)+1);
  46.   for i:=0 to Bounds.y2 do
  47.     SetLength(Matrix[i], (Bounds.X2-Bounds.X1)+1);
  48.   C := 0;
  49.   for i:=0 to H do
  50.   begin
  51.     x := TPA[i].x - Bounds.X1;
  52.     y := TPA[i].y - Bounds.Y1;
  53.     if Matrix[y][x] = True then
  54.       Continue;
  55.     Matrix[y][x] := True;
  56.     Inc(C);
  57.   end;
  58.   SetLength(Result, C);
  59.  
  60.   idx := 0;
  61.   for x:=Bounds.x1 to Bounds.x2 do
  62.     for y:=Bounds.y1 to Bounds.y2 do
  63.       if Matrix[y-Bounds.y1][x-Bounds.x1] = True then
  64.       begin
  65.         Result[idx] := Point(x,y);
  66.         Inc(idx);
  67.         if (idx >= C) then Exit;
  68.       end;
  69.   SetLength(Matrix, 0);
  70. end;
  71.  
  72. function ConvexHull(TPA:TPointArray): TPointArray;
  73. var
  74.   Points, Lower: TPointArray;
  75.   LH,H,I,UH:Integer;
  76. begin
  77.   // Get a local list copy of the points, and remove dupes.
  78.   points := CleanAndSortTPA(TPA);
  79.   H := High(points);
  80.   if H <= 0 then Exit;
  81.  
  82.   // Upper half..
  83.   UH := 2;
  84.   SetLength(Result, H+1);
  85.   Result[0] := Points[0];
  86.   Result[1] := Points[1];
  87.   for i:=2 to H do
  88.   begin
  89.     Result[UH] := points[i];
  90.     Inc(UH);
  91.     while (UH > 2) and not(CrossTurn(Result[UH-3], Result[UH-2], Result[UH-1])) do
  92.     begin
  93.       Dec(UH);
  94.       Result[UH-1] := Result[UH];
  95.     end;
  96.   end;
  97.  
  98.   // Lower half..
  99.   LH := 2;
  100.   SetLength(Lower, H+1);
  101.   Lower[0] := points[H];
  102.   Lower[1] := points[H-1];
  103.   for i:=2 to H do
  104.   begin
  105.     Lower[LH] := points[H-i];
  106.     Inc(LH);
  107.     while (LH > 2) and not(CrossTurn(Lower[LH-3], Lower[LH-2], Lower[LH-1])) do
  108.     begin
  109.       Dec(LH);
  110.       Lower[LH-1] := Lower[LH];
  111.     end;
  112.   end;
  113.  
  114.   Dec(LH);
  115.   SetLength(Result, UH+LH);
  116.   for i:=UH to (UH+LH)-1 do
  117.     Result[i] := Lower[i-UH];
  118.  
  119.   SetLength(Lower, 0);
  120.   SetLength(Points, 0);
  121. end;
  122.  
  123. function SamePoints(P1, P2:TPoint):Boolean;
  124. begin
  125.   Result := False;
  126.   if ((P1.x = P2.x) and (P1.y = P2.y)) then
  127.     Result := True;
  128. end;
  129.  
  130. { Given a TPA - This function will connect each point, from first to last }
  131. function ConnectPts(Pts:TPointArray):TPointArray;
  132. var
  133.   i,j,h,l,rl,a: Integer;
  134.   f,t:TPoint;
  135.   AdivL: Extended;
  136. begin
  137.   h := high(pts);
  138.   for i:=0 to h do
  139.   begin
  140.     j := i+1;
  141.     if i=h then
  142.       j:=0;
  143.     f := pts[i];
  144.     t := pts[j];
  145.     rl := length(Result);
  146.     if not(SamePoints(f, t)) then
  147.     begin
  148.       l := Max(Round(Abs(f.X - t.X)), Round(Abs(f.Y - t.Y)));
  149.       SetLength(Result, rl+l+1);
  150.       for a := 0 to l do begin
  151.         AdivL := a / Extended(l);
  152.         Result[rl+a] := Point(f.X + Round((t.X - f.X) * AdivL), f.Y + Round((t.Y - f.Y) * AdivL));
  153.       end;
  154.     end
  155.     else
  156.     begin
  157.       SetLength(Result,rl + 1);
  158.       Result[rl] := f
  159.     end;
  160.   end;
  161. end;
  162.  
  163. function RandomTPA(Amount:Integer; MinX,MinY,MaxX,MaxY:Integer): TPointArray;
  164. var i:Integer;
  165. begin
  166.   SetLength(Result, Amount+1);
  167.   for i:=0 to Amount do
  168.   begin
  169.     Result[i] := Point(RandomRange(MinX, MaxX), RandomRange(MinY, MaxY));
  170.   end;
  171. end;
  172.  
  173. //******* Plot a few shapes using this algorithm *******//
  174. var
  175.   TPA,CTPA: TPointArray;
  176.   bmp: Integer;
  177. begin
  178.   bmp := CreateBitmap(700, 700);
  179.  
  180.   TPA := RandomTPA(10000, 100,100,595,595);
  181.   CTPA := CopyTPA(TPA);
  182.   CTPA := ConvexHull(CTPA);
  183.   //pp_TPAConvexHull(CTPA);
  184.   CTPA := ConnectPts(CTPA);
  185.  
  186.   DrawTPABitmap(bmp, TPA, 357435);
  187.   DrawTPABitmap(bmp, CTPA, 255);
  188.  
  189.   DisplayDebugImgWindow(700,700);
  190.   DrawBitmapDebugImg(bmp);
  191.   FreeBitmap(bmp);
  192. end.
Advertisement
Add Comment
Please, Sign In to add comment