Janilabo

Untitled

Sep 17th, 2013
70
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Pascal 6.10 KB | None | 0 0
  1. // WHITE = TPA NON-Convex Hull points
  2. // RED = TPA Convex Hull points
  3. // GREEN = Shape created by Convex Hull points (red)
  4.  
  5. const
  6.   GENERATE = 100; // Amount of random points.
  7.  
  8. procedure ConvexHull(var TPA: TPointArray);
  9. var
  10.   p, Lower: TPointArray;
  11.   LH, H, I, UH, c, j, idx, x, y: Integer;
  12.   area: TBox;
  13.   m: array of TBoolArray;
  14.   b: Boolean;
  15. begin
  16.   h := High(TPA);
  17.   if (h > 0) then
  18.   begin
  19.     area := GetTPABounds(TPA);
  20.     SetLength(m, ((area.X2 - area.X1) + 1));
  21.     for i := 0 to (area.X2 - area.X1) do
  22.       SetLength(m[i], ((area.Y2 - area.Y1) + 1));
  23.     C := 0;
  24.     for i := 0 to h do
  25.     begin
  26.       x := (TPA[i].X - area.X1);
  27.       y := (TPA[i].Y - area.Y1);
  28.       if m[x][y] then
  29.         Continue;
  30.       m[x][y] := True;
  31.       Inc(C);
  32.     end;
  33.     SetLength(p, C);
  34.     idx := 0;
  35.     b := False;
  36.     for y := area.Y1 to area.Y2 do
  37.     begin
  38.       for x := area.X1 to area.X2 do
  39.         if m[(x - area.X1)][(y - area.Y1)] then
  40.         begin
  41.           p[idx] := Point(x, y);
  42.           Inc(idx);
  43.           b := (idx >= C);
  44.           if b then
  45.             Break;
  46.         end;
  47.       if b then
  48.         Break;
  49.     end;
  50.     h := High(p);
  51.     if (h > 0) then
  52.     begin
  53.       UH := 2;
  54.       SetLength(TPA, (h + 1));
  55.       TPA[0] := p[0];
  56.       TPA[1] := p[1];
  57.       for i := 2 to h do
  58.       begin
  59.         TPA[UH] := p[i];
  60.         Inc(UH);
  61.         while ((UH > 2) and not (((TPA[(UH - 2)].x * TPA[(UH - 1)].y + TPA[(UH - 3)].x * TPA[(UH - 2)].y + TPA[(UH - 1)].x * TPA[(UH - 3)].y) - (TPA[(UH - 2)].x * TPA[(UH - 3)].y + TPA[(UH - 1)].x * TPA[(UH - 2)].y + TPA[(UH - 3)].x * TPA[(UH - 1)].y)) < 0)) do
  62.         begin
  63.           Dec(UH);
  64.           TPA[(UH - 1)] := TPA[UH];
  65.         end;
  66.       end;
  67.       LH := 2;
  68.       SetLength(Lower, (h + 1));
  69.       Lower[0] := p[h];
  70.       Lower[1] := p[(h - 1)];
  71.       for i := 2 to h do
  72.       begin
  73.         Lower[LH] := p[(h - i)];
  74.         Inc(LH);
  75.         while ((LH > 2) and not (((Lower[(LH - 2)].x * Lower[(LH - 1)].y + Lower[(LH - 3)].x * Lower[(LH - 2)].y + Lower[(LH - 1)].x * Lower[(LH - 3)].y) - (Lower[(LH - 2)].x * Lower[(LH - 3)].y + Lower[(LH - 1)].x * Lower[(LH - 2)].y + Lower[(LH - 3)].x * Lower[(LH - 1)].y)) < 0)) do
  76.         begin
  77.           Dec(LH);
  78.           Lower[(LH - 1)] := Lower[LH];
  79.         end;
  80.       end;
  81.       Dec(LH);
  82.       SetLength(TPA, (UH + LH));
  83.       for i := UH to ((UH + LH) - 1) do
  84.         TPA[i] := Lower[(i - UH)];
  85.     end;
  86.   end;
  87. end;
  88.  
  89. {==============================================================================]
  90.   @action: Outputs polygon by given outlines (shape)
  91.   @note: None
  92.   @contributors: slacky, Janilabo
  93. [==============================================================================}
  94. function TPAFromPolygon(shape: TPointArray): TPointArray;
  95. var
  96.   b: TBox;
  97.   x, y, h, i, l, r, z: Integer;
  98.   o: TPointArray;
  99.   f: Boolean;
  100.   t: array of TBoolArray;
  101.   e: Extended;
  102.   q, p, d: TPoint;
  103. begin
  104.   h := High(shape);
  105.   if (h > -1) then
  106.   begin
  107.     SetLength(o, 0);
  108.     b := IntToBox(shape[0].X, shape[0].Y, shape[0].X, shape[0].Y);
  109.     for i := 0 to h do
  110.     begin
  111.       q := shape[i];
  112.       if (i < h) then
  113.         p := shape[(i + 1)]
  114.       else
  115.         p := shape[0];
  116.       r := Length(o);
  117.       if ((q.X <> p.X) or (q.Y <> p.Y)) then
  118.       begin
  119.         l := Max(Round(Abs(q.X - p.X)), Round(Abs(q.Y - p.Y)));
  120.         SetLength(o, ((r + l) + 1));
  121.         for z := 0 to l do
  122.           o[(r + z)] := Point((q.X + Round((p.X - q.X) * (z / Extended(l)))), (q.Y + Round((p.Y - q.Y) * (z / Extended(l)))));
  123.       end else
  124.       begin
  125.         SetLength(o, (r + 1));
  126.         o[r] := q;
  127.       end;
  128.       if (shape[i].X < b.X1) then
  129.         b.X1 := shape[i].X
  130.       else
  131.         if (shape[i].X > b.X2) then
  132.           b.X2 := shape[i].X;
  133.       if (shape[i].Y < b.Y1) then
  134.         b.Y1 := shape[i].Y
  135.       else
  136.         if (shape[i].Y > b.Y2) then
  137.           b.Y2 := shape[i].Y;
  138.     end;
  139.     SetLength(t, ((b.X2 - b.X1) + 1));
  140.     for i := 0 to (b.X2 - b.X1) do
  141.       SetLength(t[i], ((b.Y2 - b.Y1) + 1));
  142.     l := Length(o);
  143.     for i := 0 to (l - 1) do
  144.       if not t[(o[i].X - b.X1)][(o[i].Y - b.Y1)] then
  145.         t[(o[i].X - b.X1)][(o[i].Y - b.Y1)] := True;
  146.     for y := 0 to (b.Y2 - b.Y1) do
  147.       for x := 0 to (b.X2 - b.X1) do
  148.       begin
  149.         f := t[x][y];
  150.         if not f then
  151.         begin
  152.           d := Point((x + b.X1), (y + b.Y1));
  153.           q := shape[0];
  154.           for i := 0 to (h + 1) do
  155.           begin
  156.             p := shape[(i mod (h + 1))];
  157.             if (d.Y > Min(q.Y, p.Y)) then
  158.               if (d.Y <= Max(q.Y, p.Y)) then
  159.                 if (d.X <= Max(q.X, p.X)) then
  160.                 begin
  161.                   if (q.y <> p.y) then
  162.                     e := ((d.Y - q.Y) * (p.X - q.X) / Extended((p.Y - q.Y)) + q.X);
  163.                   if ((q.X = p.X) or (d.X < e)) then
  164.                     f := not f;
  165.                 end;
  166.             q := p;
  167.           end;
  168.         end;
  169.         if f then
  170.         begin
  171.           l := Length(Result);
  172.           SetLength(Result, (l + 1));
  173.           Result[l] := Point((x + b.X1), (y + b.Y1));
  174.         end;
  175.       end;
  176.   end else
  177.     SetLength(Result, 0);
  178. end;
  179.  
  180. function RandomTPA(Amount:Integer; MinX,MinY,MaxX,MaxY:Integer): TPointArray;
  181. var
  182.   i: Integer;
  183. begin
  184.   SetLength(Result, (Amount + 1));
  185.   for i:=0 to Amount do
  186.     Result[i] := Point(RandomRange(MinX, MaxX), RandomRange(MinY, MaxY));
  187. end;
  188.  
  189. //******* Plot a few shapes using this algorithm *******//
  190. var
  191.   TPA,CTPA,OTPA: TPointArray;
  192.   bmp, t: Integer;
  193. begin
  194.   bmp := CreateBitmap(700, 700);
  195.  
  196.   TPA := RandomTPA(GENERATE, 100,100,595,595);
  197.   CTPA := CopyTPA(TPA);
  198.   OTPA := CopyTPA(TPA);
  199.   SetLength(TPA, 0);
  200.   t := GetSystemTime;
  201.   ConvexHull(CTPA);
  202.   WriteLn('ConvexHull took ' + IntToStr(GetSystemTime - t) + ' ms.');
  203.   t := GetSystemTime;
  204.   TPA := TPAFromPolygon(CTPA);
  205.   WriteLn('TPAFromPolygon took ' + IntToStr(GetSystemTime - t) + ' ms.');
  206.   DrawTPABitmap(bmp, TPA, 357435);
  207.   DrawTPABitmap(bmp, OTPA, 16777215);
  208.   DrawTPABitmap(bmp, CTPA, 255);
  209.  
  210.   DisplayDebugImgWindow(700,700);
  211.   DrawBitmapDebugImg(bmp);
  212.   FreeBitmap(bmp);
  213. end.
Advertisement
Add Comment
Please, Sign In to add comment