Janilabo

visualize

Aug 24th, 2013
64
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Pascal 10.04 KB | None | 0 0
  1. const
  2.   DIST = 10;
  3.  
  4. var
  5.   bmp: TSCARBitmap;
  6.   colors: TIntArray;
  7.        
  8. procedure DrawBoxOutline(var bmp: TSCARBitmap; bx: TBox; color: Integer);
  9. var
  10.   x, y: Integer;
  11. begin
  12.   for x := bx.X1 to bx.X2 do
  13.     if ((x > -1) and (bx.Y1 > -1) and (x < bmp.Width) and (bx.Y1 < bmp.Height)) then
  14.       bmp.Pixels[x, bx.Y1] := color;
  15.   for y := bx.Y1 to bx.Y2 do
  16.     if ((bx.X2 > -1) and (y > -1) and (bx.X2 < bmp.Width) and (y < bmp.Height)) then
  17.       bmp.Pixels[bx.X2, y] := color;
  18.   for x := bx.X2 downto bx.X1 do
  19.     if ((x > -1) and (bx.Y2 > -1) and (x < bmp.Width) and (bx.Y2 < bmp.Height)) then
  20.       bmp.Pixels[x, bx.Y2] := color;
  21.   for y := bx.Y2 downto bx.Y1 do
  22.     if ((bx.X1 > -1) and (y > -1) and (bx.X1 < bmp.Width) and (y < bmp.Height)) then
  23.       bmp.Pixels[bx.X1, y] := color;
  24. end;
  25.  
  26. {==============================================================================]
  27.   Explanation: Returns the line of points fromPt => toPt.
  28. [==============================================================================}
  29. function GetTPALine(fromPt, toPt: TPoint): TPointArray;
  30. var
  31.   i, h: integer;
  32. begin
  33.   if ((fromPt.X <> toPt.X) or (fromPt.Y <> toPt.Y)) then
  34.   begin
  35.     h := Max(Round(Abs(fromPt.X - toPt.X)), Round(Abs(fromPt.Y - toPt.Y)));
  36.     SetLength(Result, (h + 1));
  37.     for i := 0 to h do
  38.       Result[i] := Point((fromPt.X + Round((toPt.X - fromPt.X) * (Extended(i) / h))), (fromPt.Y + Round((toPt.Y - fromPt.Y) * (Extended(i) / h))));
  39.   end else
  40.     Result := [fromPt];
  41. end;
  42.  
  43. {==============================================================================]
  44.  Splits TPA with minDist, maxDist.
  45. [==============================================================================}
  46. function TPADistributeEx(TPA: TPointArray; minDist, maxDist: Extended): T2DPointArray;
  47. var
  48.   h, i, l, c, s, x, y, o, r, d, m: Integer;
  49.   p: T2DIntArray;
  50.   q: TPointArray;
  51.   a, b: TBox;
  52.   e: Extended;
  53.   z: TPoint;
  54.   tmp: TSCARBitmap;
  55. begin
  56.   SetLength(Result, 0);
  57.   h := High(TPA);
  58.   if ((minDist <= maxDist) and (h > -1)) then
  59.     if (h > 0) then // We make sure array is bigger than 1 item...
  60.     begin
  61.       b := TPABounds(TPA);
  62.       SetLength(p, ((b.X2 - b.X1) + 1)); // We create 2D Integer table, for storing point counts (if array contains duplicates). This part is the 1D.
  63.       for i := 0 to (b.X2 - b.X1) do // Creating 2D side with loop.
  64.       begin
  65.         SetLength(p[i], ((b.Y2 - b.Y1) + 1));
  66.         for c := 0 to (b.Y2 - b.Y1) do
  67.           p[i][c] := 0; // Setting 0 as default value for all array items.
  68.       end;
  69.       if (maxDist < 0.0) then // Making sure maxDist isn't lower than 0
  70.         maxDist := 0.0; // ..when it isn't, we set it to 0.
  71.       d := Ceil(maxDist); // Storing distance by maxDist to d variable, which will be used for scanning the point groups to result.
  72.       m := Max(((b.X2 - b.X1) + 1), ((b.Y2 - b.Y1) + 1)); // We get the maximum radius that we should be using.
  73.       if (d > m) then // We make sure d isn't greater than maximum radius could be in the first place.. To reduce checking a bit, when user hits with long distances that aren't even needed.
  74.         d := m;
  75.       for i := 0 to h do // We loop through whole array increasing the Integer table values with points, this we will get the point counts.
  76.         Inc(p[(TPA[i].X - b.X1)][(TPA[i].Y - b.Y1)]);
  77.       for i := 0 to h do
  78.         if (p[(TPA[i].X - b.X1)][(TPA[i].Y - b.Y1)] > 0) then // Time to start capturing the groups
  79.         begin
  80.           c := Length(Result);
  81.           SetLength(Result, (c + 1)); // Creating first/next group of points for result.
  82.           SetLength(Result[c], p[(TPA[i].X - b.X1)][(TPA[i].Y - b.Y1)]); // We set the length for all points at this coordinate, by point count.
  83.           for o := 0 to (p[(TPA[i].X - b.X1)][(TPA[i].Y - b.Y1)] - 1) do // Loop for planting all the points from current TPA index to this new group.
  84.             Result[c][o] := TPA[i];                                  
  85.           bmp.Pixels[TPA[i].X, TPA[i].Y] := colors[c];
  86.           DebugBitmap(bmp);
  87.           SetLength(q, 1); // Creating new queue
  88.           q[0] := TPA[i]; // ..we set the current TPA item as the object for it...
  89.           r := (r + p[(TPA[i].X - b.X1)][(TPA[i].Y - b.Y1)]); // R variable is for keeping track of points that we have "met" so far, this part increases it by the total points
  90.           if (r > h) then // We can simply exit, there's no more to go through, because there was so many duplicates in the array, probably.
  91.             Exit;
  92.           p[(TPA[i].X - b.X1)][(TPA[i].Y - b.Y1)] := 0; // Setting the point count to 0, that way we don't hit the same place twice, which would fuck up things pretty bad!          
  93.           s := 1; // Simply needed for the while..do loop to work.
  94.           while (s > 0) do // While there's still queue items to check through...
  95.           begin
  96.             s := High(q); // Highest queue
  97.             z := q[s]; // Storing the point to Z variable for checking.
  98.             a.X1 := (z.X - d); // Creating the area from point Z (by QUEUE) with radius, for scanning the points.
  99.             a.Y1 := (z.Y - d);
  100.             a.X2 := (z.X + d);
  101.             a.Y2 := (z.Y + d);
  102.             SetLength(q, s); // We decrease queue by 1, pretty much.
  103.             if (a.X1 < b.X1) then // START: Lets constrain TBox a (scan area) to the boundaries of b, which is the variable for our TPA bounds.
  104.               a.X1 := b.X1
  105.             else
  106.               if (a.X1 > b.X2) then
  107.                 a.X1 := b.X2;
  108.             if (a.Y1 < b.Y1) then
  109.               a.Y1 := b.Y1
  110.             else
  111.               if (a.Y1 > b.Y2) then
  112.                 a.Y1 := b.Y2;
  113.             if (a.X2 < b.X1) then
  114.               a.X2 := b.X1
  115.             else
  116.               if (a.X2 > b.X2) then
  117.                 a.X2 := b.X2;
  118.             if (a.Y2 < b.Y1) then
  119.               a.Y2 := b.Y1
  120.             else
  121.               if (a.Y2 > b.Y2) then
  122.                 a.Y2 := b.Y2; // END: DONE! This way, there's no looping outside the bounds, speeds up things.
  123.             tmp := bmp.Clone;
  124.             DrawBoxOutline(tmp, a, clRed);
  125.             DebugBitmap(tmp);      
  126.             tmp.Free;
  127.             for x := a.X1 to a.X2 do // Lets loop through area for new points to group.
  128.               for y := a.Y1 to a.Y2 do
  129.                 if (p[(x - b.X1)][(y - b.Y1)] > 0) then // When we hit Integer table slot which contains more than 0 points, we possibly hitted a match... Time to capture the point(s)!
  130.                 begin
  131.                   e := Sqrt(Sqr(z.X - x) + Sqr(z.Y - y)); // Calculating the distance between Z (center point) and this new point from table.
  132.                   if ((e >= minDist) and (e <= maxDist)) then // ..and if it's within minDist and maxDist, we take it in, else we will leave it, because its not valid.
  133.                   begin
  134.                     l := Length(Result[c]);
  135.                     SetLength(Result[c], (l + p[(x - b.X1)][(y - b.Y1)])); // Once again, capturing the point(s) to group, pretty much the same actions as with the first group item.
  136.                     for o := 0 to (p[(x - b.X1)][(y - b.Y1)] - 1) do
  137.                     begin
  138.                       Result[c][(l + o)].X := x;
  139.                       Result[c][(l + o)].Y := y;
  140.                     end;                          
  141.                     bmp.Pixels[x, y] := colors[c];
  142.                     DebugBitmap(bmp);              
  143.                     r := (r + p[(x - b.X1)][(y - b.Y1)]);
  144.                     if (r > h) then
  145.                       Exit;
  146.                     p[(x - b.X1)][(y - b.Y1)] := 0;
  147.                     SetLength(q, (s + 1));
  148.                     q[s] := Result[c][l]; // Added the point to checking/scanning queu.
  149.                     Inc(s);
  150.                   end;
  151.                 end;
  152.           end;
  153.         end;
  154.     end else
  155.     begin // When we have only 1 point, there's no need to do any looping, so lets just create the array simply this easy way...
  156.       SetLength(Result, 1);
  157.       SetLength(Result[0], 1);
  158.       Result[0][0] := TPA[0];
  159.     end;
  160. end;
  161.  
  162. function TPADistribute(TPA: TPointArray; dist: Extended): T2DPointArray;
  163. begin
  164.   Result := TPADistributeEx(TPA, 0, dist);
  165. end;
  166.  
  167. {==============================================================================]
  168.   Explanation: Returns all the color points from bitmap as TPointArray.
  169.                Result is based on Row-by-Row.
  170. [==============================================================================}
  171. function GetBitmapColorTPA(bmp: TSCARBitmap; color: Integer): TPointArray;
  172. var
  173.   x, y, r: Integer;
  174. begin
  175.   SetLength(Result, (bmp.Width * bmp.Height));
  176.   for y := 0 to (bmp.Height - 1) do
  177.     for x := 0 to (bmp.Width - 1) do
  178.       if (bmp.Pixels[x, y] = color) then
  179.       begin
  180.         Result[r] := Point(x, y);
  181.         Inc(r);
  182.       end;
  183.   SetLength(Result, r);
  184. end;
  185.  
  186. procedure Setup;
  187. begin
  188.   bmp := TSCARBitmap.Create('deNrt2lt2wyAMBUAvssvvXtod5LSJj' +
  189.     'a6kuf9xQAx+AN/X1/UjIiIiIiIiSbnuy4xepHUtCknTcWRy9l3LCDLJZNNBZPJ' +
  190.     'kYTuCZJLJQJOHx7FvX8LZM7nNZPjd+FhBmGSSSSYLH4vPlZTJYSbzv6eYZJJJJ' +
  191.     'gv7kr/0dLgsTNb2pcWKKJNMNjV5VzuZLOxL/p+WVJLJqr6U/O+VFyY3m7xSw2R' +
  192.     'CX0r+mkkmH2qhZzeTac9Q3zhMBt6pZnzs1LYtdj1trclalgltY/L2hjVdrgxpW' +
  193.     'PK+w8kezVi6P9ngMSCZDCxaSMNa7M8e61qXKT/jphSYJc+gfJYoMsnkYWBNTbZ' +
  194.     'b1mDyv8XpZbLdloT3ybcrwySTma+Cy19ru2zuLPwwYfKuUkxao04oBZBMentJA' +
  195.     '3lyL77kLevpER+2w77H5C2/Cvy+aLdkx+SLi6edEGByxvvk51eO2mjYYHL87u0' +
  196.     'BS+HfvK3XkPeYLLmaLeD32rnBZMkFZ++4HXgbnMqy6pq1EsJNOos17JOwu0nHs' +
  197.     'ZjMMelE1uB1s44mHcpiMsqkQ1lM5ph0DGYDyL+MS4jJwTubTHY0OX7DncleJsN' +
  198.     'PRDC5zWSLgzpMMskkk0xKlMnyvSQgmTzWnqg68NZozfyJJgXOTdj6mvywYZl1I' +
  199.     'G2AyTeal1wH0nKG40wL8+cmZsNMvmhnizowljMcjza10dwELGREVIDJqEFRASC' +
  200.     'jBsWsZDJqXExJJqOGxpRkMmd0zEcgQ4bJM4JJYVKwBFKYFHmCpRqKiIiIiIiIb' +
  201.     'MsvNuu8Mw==');
  202.   colors := [2588671, 969215, 1959605, 15245824, 10766755, 12829635, 5733049, 15391129];
  203.   DebugBitmap(bmp);
  204. end;
  205.  
  206. var
  207.   TPA: TPointArray;
  208.   ATPA: T2DPointArray;
  209.  
  210. begin
  211.   Setup;
  212.   TPA := GetBitmapColorTPA(bmp, 0);
  213.   ATPA := TPADistribute(TPA, DIST);
  214.   WriteLn(Length(ATPA));
  215.   SetLength(TPA, 0);
  216.   SetLength(ATPA, 0);
  217.   bmp.Free;
  218. end.
Advertisement
Add Comment
Please, Sign In to add comment