Janilabo

Untitled

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