Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- const
- DIST = 8;
- var
- bmp, width, height: Integer;
- colors: TIntegerArray;
- procedure DrawBoxOutline(var bmp: Integer; bx: TBox; color: Integer);
- var
- x, y: Integer;
- begin
- for x := bx.X1 to bx.X2 do
- if ((x > -1) and (bx.Y1 > -1) and (x < width) and (bx.Y1 < height)) then
- FastSetPixel(bmp, x, bx.Y1, color);
- for y := bx.Y1 to bx.Y2 do
- if ((bx.X2 > -1) and (y > -1) and (bx.X2 < width) and (y < height)) then
- FastSetPixel(bmp, bx.X2, y, color);
- for x := bx.X2 downto bx.X1 do
- if ((x > -1) and (bx.Y2 > -1) and (x < width) and (bx.Y2 < height)) then
- FastSetPixel(bmp, x, bx.Y2, color);
- for y := bx.Y2 downto bx.Y1 do
- if ((bx.X1 > -1) and (y > -1) and (bx.X1 < width) and (y < height)) then
- FastSetPixel(bmp, bx.X1, y, color);
- end;
- {==============================================================================]
- Explanation: Returns the line of points fromPt => toPt.
- [==============================================================================}
- function GetTPALine(fromPt, toPt: TPoint): TPointArray;
- var
- i, h: integer;
- begin
- if ((fromPt.X <> toPt.X) or (fromPt.Y <> toPt.Y)) then
- begin
- h := Max(Round(Abs(fromPt.X - toPt.X)), Round(Abs(fromPt.Y - toPt.Y)));
- SetLength(Result, (h + 1));
- for i := 0 to h do
- Result[i] := Point((fromPt.X + Round((toPt.X - fromPt.X) * (Extended(i) / h))), (fromPt.Y + Round((toPt.Y - fromPt.Y) * (Extended(i) / h))));
- end else
- Result := [fromPt];
- end;
- {==============================================================================]
- Splits TPA with minDist, maxDist.
- [==============================================================================}
- function TPADistributeEx(TPA: TPointArray; minDist, maxDist: Extended): T2DPointArray;
- var
- h, i, l, c, s, x, y, o, r, d, m: Integer;
- p: T2DIntegerArray;
- q: TPointArray;
- a, b, db: TBox;
- e: Extended;
- z: TPoint;
- tmp: Integer;
- begin
- SetLength(Result, 0);
- h := High(TPA);
- if ((minDist <= maxDist) and (h > -1)) then
- if (h > 0) then // We make sure array is bigger than 1 item...
- begin
- b := GetTPABounds(TPA);
- 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.
- for i := 0 to (b.X2 - b.X1) do // Creating 2D side with loop.
- begin
- SetLength(p[i], ((b.Y2 - b.Y1) + 1));
- for c := 0 to (b.Y2 - b.Y1) do
- p[i][c] := 0; // Setting 0 as default value for all array items.
- end;
- if (maxDist < 0.0) then // Making sure maxDist isn't lower than 0
- maxDist := 0.0; // ..when it isn't, we set it to 0.
- d := Ceil(maxDist); // Storing distance by maxDist to d variable, which will be used for scanning the point groups to result.
- m := Max(((b.X2 - b.X1) + 1), ((b.Y2 - b.Y1) + 1)); // We get the maximum radius that we should be using.
- 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.
- d := m;
- 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.
- Inc(p[(TPA[i].X - b.X1)][(TPA[i].Y - b.Y1)]);
- for i := 0 to h do
- if (p[(TPA[i].X - b.X1)][(TPA[i].Y - b.Y1)] > 0) then // Time to start capturing the groups
- begin
- c := Length(Result);
- SetLength(Result, (c + 1)); // Creating first/next group of points for result.
- 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.
- 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.
- Result[c][o] := TPA[i];
- FastSetPixel(bmp, TPA[i].X, TPA[i].Y, colors[c]);
- db := IntToBox((z.X - d), (z.Y - d), (z.X + d), (z.Y + d));
- DrawBitmapDebugImg(bmp);
- tmp := CopyBitmap(bmp);
- DrawBoxOutline(tmp, db, 255);
- FreeBitmap(tmp);
- DisplayDebugImgWindow(width, height);
- SetLength(q, 1); // Creating new queue
- q[0] := TPA[i]; // ..we set the current TPA item as the object for it...
- 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
- 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.
- Exit;
- 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!
- s := 1; // Simply needed for the while..do loop to work.
- while (s > 0) do // While there's still queue items to check through...
- begin
- s := High(q); // Highest queue
- z := q[s]; // Storing the point to Z variable for checking.
- a.X1 := (z.X - d); // Creating the area from point Z (by QUEUE) with radius, for scanning the points.
- a.Y1 := (z.Y - d);
- a.X2 := (z.X + d);
- a.Y2 := (z.Y + d);
- SetLength(q, s); // We decrease queue by 1, pretty much.
- 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.
- a.X1 := b.X1
- else
- if (a.X1 > b.X2) then
- a.X1 := b.X2;
- if (a.Y1 < b.Y1) then
- a.Y1 := b.Y1
- else
- if (a.Y1 > b.Y2) then
- a.Y1 := b.Y2;
- if (a.X2 < b.X1) then
- a.X2 := b.X1
- else
- if (a.X2 > b.X2) then
- a.X2 := b.X2;
- if (a.Y2 < b.Y1) then
- a.Y2 := b.Y1
- else
- if (a.Y2 > b.Y2) then
- a.Y2 := b.Y2; // END: DONE! This way, there's no looping outside the bounds, speeds up things.
- tmp := CopyBitmap(bmp);
- DrawBoxOutline(tmp, a, 255);
- DrawBitmapDebugImg(tmp);
- DisplayDebugImgWindow(width, height);
- FreeBitmap(tmp);
- for x := a.X1 to a.X2 do // Lets loop through area for new points to group.
- for y := a.Y1 to a.Y2 do
- 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)!
- begin
- e := Sqrt(Sqr(z.X - x) + Sqr(z.Y - y)); // Calculating the distance between Z (center point) and this new point from table.
- 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.
- begin
- l := Length(Result[c]);
- 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.
- for o := 0 to (p[(x - b.X1)][(y - b.Y1)] - 1) do
- begin
- Result[c][(l + o)].X := x;
- Result[c][(l + o)].Y := y;
- end;
- FastSetPixel(bmp, x, y, colors[c]);
- DrawBitmapDebugImg(bmp);
- DisplayDebugImgWindow(width, height);
- r := (r + p[(x - b.X1)][(y - b.Y1)]);
- if (r > h) then
- Exit;
- p[(x - b.X1)][(y - b.Y1)] := 0;
- SetLength(q, (s + 1));
- q[s] := Result[c][l]; // Added the point to checking/scanning queu.
- Inc(s);
- end;
- end;
- end;
- end;
- end else
- 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...
- SetLength(Result, 1);
- SetLength(Result[0], 1);
- Result[0][0] := TPA[0];
- end;
- end;
- function TPADistribute(TPA: TPointArray; dist: Extended): T2DPointArray;
- begin
- Result := TPADistributeEx(TPA, 0, dist);
- end;
- {==============================================================================]
- Explanation: Returns all the color points from bitmap as TPointArray.
- Result is based on Row-by-Row.
- [==============================================================================}
- function GetBitmapColorTPA(bmp: Integer; color: Integer): TPointArray;
- var
- x, y, r: Integer;
- begin
- SetLength(Result, (width * height));
- for y := 0 to (height - 1) do
- for x := 0 to (width - 1) do
- if (FastGetPixel(bmp, x, y) = color) then
- begin
- Result[r] := Point(x, y);
- Inc(r);
- end;
- SetLength(Result, r);
- end;
- procedure Setup;
- begin
- bmp := BitmapFromString(220, 84, 'meJztklGOHTAMAnv/S29VrVTt177ExkAS5gDxAPn6CiGEEEIIIYRgxB8cd6Rwi+YArYeb5hvKog1lAqeK+xa8L5EPnCqmF+SPeFkcHzhtTM8nGfGyOD5w2pieT7LjuVkkda3DaWN6PknJh2YRNrYCrZDJ6WQNH5pF2NgKtEImp5M1fGIWeWm/w+wEPRfDWR6KKQy/VYPZCW4onrM8FFMYfqsGsxPcUDxneSiyLfbchCHWszfOBihhh1B8VeBFf8nqLNughB1C8VWBF+ckUZ6lTSpAbE1CSTwlR6fRGqIqdahdJSk5Oo1Qst+nT/MqSfNayqg8m31alS80dK6ljMqzU6Zb+VpD52YKCCU7Tbo1r9UzL2cLrWGzSava5W7+Fa2gdet3uIVzHLkAraWOv4MDFts4Dg7krsraJhooRuOUE5lo8OsqC5toQBjK0gxloiEpzUQM1ZU2BSqajwnZE254KPBimz1byTBt4W7nAmwVUrWVDNMW7mZCISCw1X7V0zK7PkxhrJgD5ZjAVptVT5sUlMjCKDE5zaTwYss9T5sUlMjCKDEhN+WF70tow1ZMwn2RgbNyqvC0knBlcEgocgmeVmRujQ/PRWhg9wrH6qMh5OVf3kcB9DRMN5S99r6JVfPK7qEaHb0+hIDw4OXH56yYDdRuEcSAEDICU/dfxrrxe2heHLL6KIx90wpUk5B3JB8AchSrtK6KetkKbIed11R/AHgX4rPrCXncCnjG2oPIH7CZAn66I1M2bJ5wYyLX1pv4T7ATZ+h6waSp17kSfjL3ExZnGhVY14C4lQ+Fn0z8ga2NRgXWNYBWhXPhP6jROwM5OMCVSmuEf/TL76/j4DDhU93kdVD9d6ZxcJgz6e3zHBMTFHaRC0xrILZ6hbkVtkaRCxAcQIvdz/QQi4u8IPDRIXzD2eLjHFoBwvUVjfCNyRZaAcL1FY3wjckWWgHC9RWN8I3PFhdfX9cIX05/csjHqofqSs9huAX/KOQiVullbLc45dyo1ZtMb9Gcw/NQgY7bg/hvQbgyWgKqh3c4ZQvJ+24lvMNBW8w9PlTCUA8vkCHgDZxbhQ9ZAdjA6VX48PgKkPjXtOHDyxNAPuFNhfjwcv/A33hNJz682Xw+5BE81Xn+ZHAjfzIYkg8Z3MifDIbkQ4YQQgghhBBCCGGXv/ixuwM=');
- GetBitmapSize(bmp, width, height);
- colors := [2588671, 969215, 1959605, 15245824, 10766755, 12829635, 5733049, 15391129];
- DrawBitmapDebugImg(bmp);
- DisplayDebugImgWindow(width, height);
- end;
- var
- TPA: TPointArray;
- ATPA: T2DPointArray;
- begin
- Setup;
- TPA := GetBitmapColorTPA(bmp, 0);
- ATPA := TPADistribute(TPA, DIST);
- WriteLn(Length(ATPA));
- SetLength(TPA, 0);
- SetLength(ATPA, 0);
- FreeBitmap(bmp);
- end.
Advertisement
Add Comment
Please, Sign In to add comment