Janilabo

TPA Polygon Development [Simba]

Jul 21st, 2013
58
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Pascal 11.38 KB | None | 0 0
  1. // Original algorithms by slacky, optimized by Janilabo
  2.  
  3. const
  4.   POLYGON_EXAMPLE = 1; // 0-9.
  5.   DISPLAY_MAINPOINTS = True; // True or False.
  6.   OFFSET = 5; // Used for debug image..
  7.  
  8. {==============================================================================]
  9.   Explanation: Returns polygon by given outlines (shape)
  10.   NOTE: Original algorithm by slacky (warpie)
  11. [==============================================================================}
  12. function TPAPolygon(shape: TPointArray): TPointArray;
  13. var
  14.   b: TBox;
  15.   x, y, h, i, l, r, z: Integer;
  16.   o: TPointArray;
  17.   f: Boolean;
  18.   t: array of TBoolArray;
  19.   e: Extended;
  20.   q, p, d: TPoint;
  21. begin
  22.   h := High(shape);
  23.   if (h > -1) then
  24.   begin
  25.     b := IntToBox(shape[0].X, shape[0].Y, shape[0].X, shape[0].Y);
  26.     for i := 0 to h do
  27.     begin
  28.       q := shape[i];
  29.       if (i < h) then
  30.         p := shape[(i + 1)]
  31.       else
  32.         p := shape[0];
  33.       r := Length(o);
  34.       if ((q.X <> p.X) or (q.Y <> p.Y)) then
  35.       begin
  36.         l := Max(Round(Abs(q.X - p.X)), Round(Abs(q.Y - p.Y)));
  37.         SetLength(o, ((r + l) + 1));
  38.         for z := 0 to l do
  39.           o[(r + z)] := Point((q.X + Round((p.X - q.X) * (z / Extended(l)))), (q.Y + Round((p.Y - q.Y) * (z / Extended(l)))));
  40.       end else
  41.       begin
  42.         SetLength(o, (r + 1));
  43.         o[r] := q;
  44.       end;
  45.       if (shape[i].X < b.X1) then
  46.         b.X1 := shape[i].X
  47.       else
  48.         if (shape[i].X > b.X2) then
  49.           b.X2 := shape[i].X;
  50.       if (shape[i].Y < b.Y1) then
  51.         b.Y1 := shape[i].Y
  52.       else
  53.         if (shape[i].Y > b.Y2) then
  54.           b.Y2 := shape[i].Y;
  55.     end;
  56.     SetLength(t, ((b.X2 - b.X1) + 1));
  57.     for i := 0 to (b.X2 - b.X1) do
  58.       SetLength(t[i], ((b.Y2 - b.Y1) + 1));
  59.     l := Length(o);
  60.     for i := 0 to (l - 1) do
  61.       if not t[(o[i].X - b.X1)][(o[i].Y - b.Y1)] then
  62.         t[(o[i].X - b.X1)][(o[i].Y - b.Y1)] := True;
  63.     SetLength(o, 0);
  64.     for y := 0 to (b.Y2 - b.Y1) do
  65.       for x := 0 to (b.X2 - b.X1) do
  66.       begin
  67.         f := t[x][y];
  68.         if not f then
  69.         begin
  70.           d := Point((x + b.X1), (y + b.Y1));
  71.           q := shape[0];
  72.           for i := 0 to (h + 1) do
  73.           begin
  74.             p := shape[(i mod (h + 1))];
  75.             if (d.Y > Min(q.Y, p.Y)) then
  76.               if (d.Y <= Max(q.Y, p.Y)) then
  77.                 if (d.X <= Max(q.X, p.X)) then
  78.                 begin
  79.                   if (q.y <> p.y) then
  80.                     e := ((d.Y - q.Y) * (p.X - q.X) / Extended((p.Y - q.Y)) + q.X);
  81.                   if ((q.X = p.X) or (d.X < e)) then
  82.                     f := not f;
  83.                 end;
  84.             q := p;
  85.           end;
  86.         end;
  87.         if f then
  88.         begin
  89.           l := Length(Result);
  90.           SetLength(Result, (l + 1));
  91.           Result[l] := Point((x + b.X1), (y + b.Y1));
  92.         end;
  93.       end;
  94.     SetLength(t, 0);
  95.   end else
  96.     SetLength(Result, 0);
  97. end;
  98.  
  99. {==============================================================================]
  100.   Explanation: Given a TPA - this function will connect each point, from first to last.
  101.   NOTE: Original algorithm by slacky (warpie)
  102. [==============================================================================}
  103. function TPAConnect(pts: TPointArray): TPointArray;
  104. var
  105.   i, j, h, l, r, a: Integer;
  106.   q, p: TPoint;
  107. begin
  108.   if (High(pts) > -1) then
  109.   begin
  110.     h := High(pts);
  111.     for i := 0 to h do
  112.     begin
  113.       j := (i + 1);
  114.       if (i = h) then
  115.         j := 0;
  116.       q := pts[i];
  117.       p := pts[j];
  118.       r := Length(Result);
  119.       if ((q.X <> p.X) or (q.Y <> p.Y)) then
  120.       begin
  121.         l := Max(Round(Abs(q.X - p.X)), Round(Abs(q.Y - p.Y)));
  122.         SetLength(Result, ((r + l) + 1));
  123.         for a := 0 to l do
  124.           Result[(r + a)] := Point((q.X + Round((p.X - q.X) * (a / Extended(l)))), (q.Y + Round((p.Y - q.Y) * (a / Extended(l)))));
  125.       end else
  126.       begin
  127.         SetLength(Result, (r + 1));
  128.         Result[r] := q;
  129.       end;
  130.     end;
  131.   end else
  132.     SetLength(Result, 0);
  133. end;
  134.  
  135. {==============================================================================]
  136.   Explanation: Check if a point is within a polygon/shape by the given outline points (shape)
  137.                The points MUST be in order, as if you would draw a line trough each point.
  138.   NOTE: Original algorithm by slacky (warpie)
  139. [==============================================================================}
  140. function InPolygon(pt: TPoint; shape: TPointArray): Boolean;
  141. var
  142.   b: TBox;
  143.   x, y, h, i, v, l, r, z: Integer;
  144.   o: TPointArray;
  145.   f: Boolean;
  146.   t: array of TBoolArray;
  147.   e: Extended;
  148.   q, p, d: TPoint;
  149. begin
  150.   h := High(shape);
  151.   Result := False;
  152.   if (h > -1) then
  153.   begin
  154.     b := IntToBox(shape[0].X, shape[0].Y, shape[0].X, shape[0].Y);
  155.     for i := 0 to h do
  156.     begin
  157.       if (shape[i].X < b.X1) then
  158.         b.X1 := shape[i].X
  159.       else
  160.         if (shape[i].X > b.X2) then
  161.           b.X2 := shape[i].X;
  162.       if (shape[i].Y < b.Y1) then
  163.         b.Y1 := shape[i].Y
  164.       else
  165.         if (shape[i].Y > b.Y2) then
  166.           b.Y2 := shape[i].Y;
  167.     end;
  168.     if ((pt.X >= b.X1) and (pt.Y >= b.Y1) and (pt.X <= b.X2) and (pt.Y <= b.Y2)) then
  169.     begin
  170.       SetLength(t, ((b.X2 - b.X1) + 1));
  171.       for i := 0 to (b.X2 - b.X1) do
  172.         SetLength(t[i], ((b.Y2 - b.Y1) + 1));
  173.       for i := 0 to h do
  174.       begin
  175.         v := (i + 1);
  176.         if (i = h) then
  177.           v := 0;
  178.         q := shape[i];
  179.         p := shape[v];
  180.         r := Length(o);
  181.         if ((q.X <> p.X) or (q.Y <> p.Y)) then
  182.         begin
  183.           l := Max(Round(Abs(q.X - p.X)), Round(Abs(q.Y - p.Y)));
  184.           SetLength(o, ((r + l) + 1));
  185.           for z := 0 to l do
  186.             o[(r + z)] := Point((q.X + Round((p.X - q.X) * (z / Extended(l)))), (q.Y + Round((p.Y - q.Y) * (z / Extended(l)))));
  187.         end else
  188.         begin
  189.           SetLength(o, (r + 1));
  190.           o[r] := q;
  191.         end;
  192.       end;
  193.       l := Length(o);
  194.       for i := 0 to (l - 1) do
  195.         if not t[(o[i].X - b.X1)][(o[i].Y - b.Y1)] then
  196.            t[(o[i].X - b.X1)][(o[i].Y - b.Y1)] := True;
  197.       for y := 0 to (b.Y2 - b.Y1) do
  198.       begin
  199.         for x := 0 to (b.X2 - b.X1) do
  200.         begin
  201.           f := t[x][y];
  202.           if not f then
  203.           begin
  204.             d := Point((x + b.X1), (y + b.Y1));
  205.             q := shape[0];
  206.             for i := 0 to (h + 1) do
  207.             begin
  208.               p := shape[(i mod (h + 1))];
  209.               if (d.Y > Min(q.Y, p.Y)) then
  210.                 if (d.Y <= Max(q.Y, p.Y)) then
  211.                   if (d.X <= Max(q.X, p.X)) then
  212.                   begin
  213.                     if (q.y <> p.y) then
  214.                       e := ((d.Y - q.Y) * (p.X - q.X) / Extended((p.Y - q.Y)) + q.X);
  215.                     if ((q.X = p.X) or (d.X < e)) then
  216.                       f := not f;
  217.                   end;
  218.               q := p;
  219.             end;
  220.           end;
  221.           if f then
  222.           begin
  223.             t[x][y] := True;
  224.             Result := t[(pt.X - b.X1)][(pt.Y - b.Y1)];
  225.           end;
  226.         end;
  227.         if Result then
  228.           Break;
  229.       end;
  230.       SetLength(t, 0);
  231.     end;
  232.   end;
  233. end;
  234.  
  235. {==============================================================================]
  236.   Explanation: Creates all the points needed to define a simple polygon
  237.   NOTE: Original algorithm by slacky (warpie)
  238. [==============================================================================}
  239. function TPAXagon(sides: Integer; C, S: TPoint): TPointArray;
  240. var
  241.   x, y, a, b, v: Integer;
  242.   n, m: Extended;
  243. begin
  244.   SetLength(Result, sides);
  245.   x := S.x;
  246.   y := S.y;
  247.   n := Sin(Radians(360.0 / sides));
  248.   m := Cos(Radians(360.0 / sides));
  249.   for v := 0 to (sides - 1) do
  250.   begin
  251.     a := (x - C.x);
  252.     b := (y - C.y);
  253.     x := Round(((b * n) + (a * m) + C.x));
  254.     y := Round(((b * m) - (a * n) + C.y));
  255.     Result[v] := Point(x, y);
  256.   end;
  257. end;
  258.  
  259. //******* DIRTY EXAMPLE BELLOW: *******//
  260. procedure SetPixels(bmp: Integer; TPA: TPointArray; color: Integer);
  261. var
  262.   a, z, w, h: Integer;
  263. begin
  264.   z := High(TPA);
  265.   if (z > -1) then
  266.   begin
  267.     GetBitmapSize(bmp, w, h);
  268.     for a := 0 to z do
  269.       if ((TPA[a].X >= 0) and (TPA[a].Y >= 0) and (TPA[a].X < w) and (TPA[a].Y < h)) then
  270.         FastSetPixel(bmp, TPA[a].X, TPA[a].Y, color);
  271.   end;
  272. end;
  273.  
  274. procedure SetPixelsMP(bmp: Integer; TPA: TPointArray; color: Integer);
  275. var
  276.   a, z, w, h: Integer;
  277. begin
  278.   z := High(TPA);
  279.   if (z > -1) then
  280.   begin
  281.     GetBitmapSize(bmp, w, h);
  282.     for a := 0 to z do
  283.       if ((TPA[a].X > 0) and (TPA[a].Y > 0) and (TPA[a].X < (w - 1)) and (TPA[a].Y < (h - 1))) then
  284.       begin
  285.         FastSetPixel(bmp, (TPA[a].X - 1), TPA[a].Y, color);
  286.         FastSetPixel(bmp, (TPA[a].X + 1), TPA[a].Y, color);
  287.         FastSetPixel(bmp, TPA[a].X, (TPA[a].Y + 1), color);
  288.         FastSetPixel(bmp, TPA[a].X, (TPA[a].Y - 1), color);
  289.       end;
  290.   end;
  291. end;
  292.  
  293. procedure Setup;
  294. var
  295.   shape, TPA: TPointArray;
  296.   bmp, t, o: Integer;
  297.   v: Boolean;
  298.   a: TBox;
  299. begin
  300.   //Dynamic shapes from Example 6 and down:
  301.   v := True;
  302.   case POLYGON_EXAMPLE of
  303.     // Microshape ------//
  304.     //           TOP           LEFT           BOTTOM          RIGHT
  305.     0: shape := [Point(20,20), Point(20,120), Point(120,120), Point(120,20)];
  306.     // Arrow like shape //
  307.     1: shape := [Point(70,90),Point(185,90),Point(185,116), Point(70,116), //Square +
  308.                  Point(70,140),Point(35,105),Point(70,70)];                //Triangle
  309.     // Triangle --------//
  310.     2: shape := [Point(50,50),Point(0,100),Point(100,150)];
  311.     // Raped pentagon --//
  312.     3: shape := [Point(10,25),Point(35,5),Point(82,22),Point(50,90),Point(4,60)];
  313.     // Octagon ---------//
  314.     4: shape := [Point(100,30), Point(155,50),  //Top-Right
  315.                  Point(180,110),Point(155,160), //Right-Bottom
  316.                  Point(100,180),Point(45,160),  //Bottom-Left
  317.                  Point(20,100), Point(45,50)];  //Left-Top
  318.     // S-shape ---------//
  319.     5: shape := [Point(135,50),Point(123,70),Point(103,58),Point(85,70),Point(85,85),
  320.                  Point(122,105),Point(132,125),Point(120,155),Point(78,164),Point(55,147),
  321.                  Point(64,128),Point(80,140),Point(100,140),Point(96,116),Point(62,98),
  322.                  Point(60,55),Point(111,35)];
  323.     // Xagon: 15 corners //
  324.     6: shape := TPAXagon(15, Point(100,100), Point(60,100));
  325.     // Xagon: 9 corners //
  326.     7: shape := TPAXagon(9, Point(100,100), Point(60,50));
  327.     // Xagon: 5 corners AKA Pentagon //
  328.     8: shape := TPAXagon(5, Point(100,100), Point(74,50));
  329.     // Xagon: 3 corners AKA Triangle //
  330.     9: shape := TPAXagon(3, Point(100,100), Point(48,48));
  331.   else
  332.     v := False;
  333.   end;
  334.   if v then
  335.   begin
  336.     if ((a.X1 > -1) and (a.Y1 > -1)) then
  337.     begin
  338.       if (OFFSET > 0) then
  339.         o := OFFSET;
  340.       t := GetSystemTime;
  341.       if (o > 0) then
  342.         OffsetTPA(shape, Point(o, o));
  343.       TPA := TPAPolygon(shape);
  344.       a := GetTPABounds(TPA);
  345.       bmp := CreateBitmap((a.X2 + o), (a.Y2 + o));
  346.       WriteLn(IntToStr(GetSystemTime - t) + ' ms.');
  347.       SetPixels(bmp, TPA, 357435);
  348.       if DISPLAY_MAINPOINTS then
  349.         SetPixelsMP(bmp, shape, 16777215);
  350.       DisplayDebugImgWindow((a.X2 + a.X1), (a.Y2 + a.Y1));
  351.       DrawBitmapDebugImg(bmp);
  352.       FreeBitmap(bmp);
  353.       SetLength(TPA, 0);
  354.     end else
  355.       WriteLn('Invalid TPA! Negative points found...');
  356.   end else
  357.     WriteLn('Invalid polygon ID!');
  358. end;
  359.  
  360. begin
  361.   ClearDebug;
  362.   Setup;
  363. end.
Advertisement
Add Comment
Please, Sign In to add comment