SRL Archive - SRL Snippets

function FindTPointCluster(): TPointArray


Runaway

2012-05-17 12:19:09

This is a function similar to function FindTPACluster(): array of TPointArray, but it's actually quite different. That is a slower, but more precise version.

function FindTPointCluster(Colors: TIntegerArray; Tol: Integer; SortFrom: TPoint; Filter, Trim, MaxDist: Integer; Strict: Boolean; x1, y1, x2, y2: Integer): TPointArray;

You can input as many colors as you need and it will only return clusters it finds where ALL colors specified are within the given distance of the "primary" color (which is the color declared first in the Colors array). This is done by using the NearbyPointInArray function, and a point is only added to the result array if it's within the specified distance of every other color found. Very useful for Map walking, and object finding since you can specify which color to click, but still use the color comparison advantage that this function supplies.

I'll be updating this thread with extensive testing as soon as I get to it. I've used this function in my Rimmington Tele-Banker script for item-finding, map walking, and npc-finding if you want to see it in action.

Usage:

Arr := FindTPACluster(Colors, Tol, SortFrom, FilterArr, TrimArr, 0, MaxDist, True, Area[0], Area[1], Area[2], Area[3]);
SplitTPAWrap(Arr, MaxDist, aArr);
SMART_ClearCanvas;
for a := 0 to High(aArr) do
SMART_DrawCircle(False, MiddleTPA(Arr[a]), MaxDist, False, clred);

It's 100% failsafe'd, and it's got a great debug if you have any problems. It currently takes between 100-300 ms to find and parse all of the colors/points. I'd love to see some people test this out in scripts and see how it goes :)

Descripton:

(*
FindTPointCluster
~~~~~~~

.. code-block:: pascal

function FindTPointCluster(Colors: TIntegerArray; Tol: Integer; SortFrom: TPoint; Filter, Trim, MaxDist: Integer; Strict: Boolean; x1, y1, x2, y2: Integer): TPointArray;

Results a TPointArray which holds "clusters" of the the first specified color in
each TPoint. It can search for an unlimited number of colors in x1, y1, x2, y2.
* Colors: The colors to be found and grouped depending on proximity. Enter the
main color first in the array.
* Tol: The tolerance on each color.
* SortFrom: The point to sort each TPoint from.
* Filter: The maximum distance between SortFrom and each TPoint. -1 to not use.
* Trim: The maximum length of each TPointArray. -1 to not use.
* MaxDist: The maximum distance between each color can be in each cluster.
* Strict: True to exit the function if not all of the specified colors are found.

.. note::

by Runaway

Example:

.. code-block:: pascal

Colors := [16514558, 5062187, 4664874];
Arr := FindTPointCluster(Colors, 20, Point(MMCX, MMCY), -1, 200, 30, True, MMX1, MMY1, MMX2, MMY2);
SplitTPAWrap(Arr, 30, aArr);
for i := 0 to High(aArr) do
begin
x := MiddleTPA(aArr[i]).x;
y := MiddleTPA(aArr[i]).y;
if (not rs_OnMinimap(x, y)) then
Continue;
Mouse(x, y, 3, 3, mouse_left);
if DidClick(True, RandomRange(750, 1250)) then
Break;
end;
*)

Function:

function FindTPointCluster(Colors: TIntegerArray; Tol: Integer; SortFrom: TPoint; Filter, Trim, MaxDist: Integer; Strict: Boolean; x1, y1, x2, y2: Integer): TPointArray;
var
TPA: TPointArray;
aPoints: array of TPointArray;
hPoints, hColors: Integer;
Error, Len, Match: Integer;
t, r, i, ii: Integer;
begin
MarkTime(t);
SetLength(aPoints, Length(Colors));
hColors := High(Colors);
Error := 0;
r := 0;
for i := 0 to hColors do
begin
if (FindColorsTolerance(TPA, Colors[i], x1, y1, x2, y2, Tol)) then
begin
SortTPAFrom(TPA, SortFrom);
if (Filter <> -1) then
FilterPointsDist(TPA, 0, Filter, SortFrom.x, SortFrom.y);
if (Trim <> -1) and (Length(TPA) > Trim) then
SetLength(TPA, Trim);
aPoints[i - Error] := TPA;
end else
begin
if Strict then
begin
Writeln('Error: not enough colors found!');
Exit;
end;
Len := Length(aPoints) - 1;
SetLength(aPoints, Len);
Inc(Error);
end;
if (Error >= hColors) then
begin
Writeln('Error: not enough colors found!');
Exit;
end;
end;
hPoints := High(aPoints);
for i := 0 to High(aPoints[0]) do
begin
Match := 0;
for ii := 1 to hPoints do
begin
if NearbyPointInArray(aPoints[0][i], MaxDist, aPoints[ii]) then
begin
Inc(Match);
if (Match >= hPoints) then
begin
SetLength(Result, r + 1);
Result[r] := aPoints[0][i];
Inc(r);
end;
end else
Break;
end;
end;
SortTPAFrom(Result, SortFrom);
Writeln('Took: '+IntToStr(TimeFromMark(t))+' ms, found '+IntToStr(Length(Result))+' point(s)');
end;

Example Debug:

Searching: color 1 of 3...
Found: 584 point(s) of color 8083520
Using: first 500 point(s) of color 8083520
Searching: color 2 of 3...
Found: 1314 point(s) of color 16777215
Using: first 500 point(s) of color 16777215
Searching: color 3 of 3...
Found: 327 point(s) of color 15326682
Using: first 327 point(s) of color 15326682
Searching... done
Sorting...
Sorting... done
Took: 218 ms, found 445 point(s)
Successfully executed.

If you want to test it out for yourself, I've attached a testing script with debug, paint, and all sorts of options all set up and ready to go. All you have to do is select the area, colors, etc. :)

Kyle Undefined

2012-05-17 12:42:27

Oh nice! Mind if I change it around a bit to accept Hue/Sat to be passed in? Will see if this makes my RC script more stable.

Runaway

2012-05-17 12:53:28

From: Kyle Undefined
Oh nice! Mind if I change it around a bit to accept Hue/Sat to be passed in? Will see if this makes my RC script more stable.


Of course! Let me know how it goes :)

Kyle Undefined

2012-05-17 14:37:40

I'll let you know how it goes tonight :)

Kyle Undefined

2012-05-19 03:22:23

Double post, I know, but I need your help :p

This is what I'm using, just trying to play with this.

program new;
{$DEFINE SMART}
{$i srl/srl.simba}
{$i srl/srl/misc/paintsmart.simba}

var
Arr : TPointArray;
aArr : T2DPointArray;
a : Integer;

function FindTPointCluster(Colors: TIntegerArray; Tol: Integer; SortFrom: TPoint; Filter, Trim, MaxDist: Integer; Strict: Boolean; x1, y1, x2, y2: Integer): TPointArray;
var
TPA: TPointArray;
aPoints: array of TPointArray;
hPoints, hColors: Integer;
Error, Len, Match: Integer;
t, r, i, ii: Integer;
begin
MarkTime(t);
SetLength(aPoints, Length(Colors));
hColors := High(Colors);
writeln(hcolors);
writeln(length(apoints));
Error := 0;
r := 0;
for i := 0 to hColors do
begin
if (FindColorsTolerance(TPA, Colors[i], x1, y1, x2, y2, Tol)) then
begin
writeln('in');
writeln(length(tpa));
writeln(filter);
writeln(trim);
SortTPAFrom(TPA, SortFrom);
if (Filter <> -1) then
FilterPointsDist(TPA, 0, Filter, SortFrom.x, SortFrom.y);
if (Trim <> -1) and (Length(TPA) > Trim) then
SetLength(TPA, Trim);
aPoints[i - Error] := TPA;
writeln(i);
writeln(error);
writeln(tpa);
end else
begin
if Strict then
begin
Writeln('Error: not enough colors found!');
Exit;
end;
Len := Length(aPoints) - 1;
SetLength(aPoints, Len);
Inc(Error);
end;
if (Error > hColors) then
begin
Writeln('Error: not enough colors found!');
Exit;
end;
end;
hPoints := High(aPoints);
for i := 0 to High(aPoints[0]) do
begin
Match := 0;
for ii := 1 to hPoints do
begin
if NearbyPointInArray(aPoints[0][i], MaxDist, aPoints[ii]) then
begin
Inc(Match);
if (Match >= hPoints) then
begin
SetLength(Result, r + 1);
Result[r] := aPoints[0][i];
Inc(r);
end;
end else
Break;
end;
end;
SortTPAFrom(Result, SortFrom);
Writeln('Took: '+IntToStr(TimeFromMark(t))+' ms, found '+IntToStr(Length(Result))+' point(s)');
end;

begin
Smart_Server := 10;
Smart_Members := True;
Smart_Signed := True;
setupsrl;
cleardebug;

ColorToleranceSpeed(2);
SetColorSpeed2Modifiers(0.25, 1.01);

Arr := FindTPointCluster([6251056], 24, Point(MSCX, MSCY), -1, -1, 30, False, MSX1, MSY1, MSX2, MSY2);
SplitTPAWrap(Arr, 30, aArr);
SMART_ClearCanvas;
for a := 0 to High(aArr) do
SMART_DrawCircle(False, MiddleTPA(aArr[a]), 30, False, clred);

ColorToleranceSpeed(1);
SetColorSpeed2Modifiers(0.2, 0.2);
end.

The only thing I have changed is this line:
if (Error > hColors) then

Took out the equal sign, since I'm only using one color, it always exits. However, even though it's finding the color, it's saying it found no points. Here is the debug:

0
1
in
736
-1
-1
0
0
[(190, 156), (190, 155), (189, 158), (189, 157), (189, 156), (259, 250), (260, 250), (259, 251), (260, 251), (258, 251), (257, 251), (254, 251), (253, 251), (252, 251), (251, 251), (259, 252), (258, 252), (260, 252), (257, 252), (256, 252), (253, 252), (252, 252), (251, 252), (252, 253), (251, 253), (252, 254), (251, 254), (250, 254), (249, 254), (248, 254), (252, 255), (251, 255), (246, 255), (253, 256), (252, 256), (244, 255), (251, 256), (243, 255), (246, 256), (245, 256), (244, 256), (243, 256), (242, 256), (241, 256), (246, 257), (240, 256), (245, 257), (244, 257), (243, 257), (249, 258), (242, 257), (248, 258), (247, 258), (241, 257), (246, 258), (240, 257), (245, 258), (244, 258), (239, 257), (243, 258), (247, 259), (241, 258), (246, 259), (240, 258), (245, 259), (239, 258), (244, 259), (243, 259), (242, 259), (239, 259), (244, 260), (243, 260), (238, 259), (242, 260), (237, 259), (241, 260), (240, 260), (238, 260), (237, 260), (240, 261), (242, 262), (237, 261), (238, 262), (237, 262), (238, 263), (237, 263), (281, 263), (282, 263), (287, 262), (288, 262), (285, 263), (289, 262), (282, 264), (286, 263), (283, 264), (290, 262), (287, 263), (284, 264), (288, 263), (285, 264), (289, 263), (282, 265), (286, 264), (283, 265), (287, 264), (284, 265), (288, 264), (285, 265), (289, 264), (282, 266), (283, 266), (290, 264), (284, 266), (291, 264), (288, 265), (285, 266), (289, 265), (282, 267), (286, 266), (283, 267), (290, 265), (284, 267), (285, 267), (282, 268), (271, 270), (283, 268), (288, 267), (286, 268), (287, 268), (288, 268), (289, 268), (290, 268), (287, 269), (291, 268), (288, 269), (289, 269), (290, 269), (291, 269), (290, 270), (291, 270), (260, 281), (261, 281), (260, 282), (261, 282), (260, 283), (261, 283), (262, 283), (253, 283), (262, 284), (253, 284), (263, 285), (255, 285), (254, 285), (260, 287), (268, 287), (259, 288), (258, 288), (260, 288), (257, 288), (256, 288), (268, 288), (257, 289), (261, 289), (262, 289), (256, 289), (108, 222), (109, 225), (108, 223), (107, 221), (108, 224), (103, 208), (107, 222), (100, 193), (108, 225), (103, 209), (106, 220), (107, 223), (103, 210), (108, 226), (106, 221), (107, 224), (102, 208), (106, 222), (107, 225), (99, 193), (102, 209), (105, 220), (106, 223), (107, 226), (102, 210), (105, 221), (106, 224), (101, 207), (98, 192), (101, 208), (106, 225), (98, 193), (101, 209), (104, 220), (105, 223), (101, 210), (100, 206), (98, 196), (104, 221), (105, 224), (98, 197), (100, 207), (100, 208), (105, 225), (97, 193), (100, 209), (104, 223), (103, 220), (105, 226), (97, 195), (100, 210), (99, 206), (97, 196), (103, 221), (104, 224), (97, 198), (99, 208), (104, 225), (102, 219), (96, 192), (97, 199), (96, 193), (99, 209), (96, 194), (103, 223), (102, 220), (104, 226), (96, 195), (98, 206), (96, 196), (102, 221), (103, 224), (97, 202), (102, 222), (96, 198), (103, 225), (98, 208), (101, 219), (96, 199), (95, 193), (102, 223), (101, 220), (97, 205), (95, 194), (103, 226), (95, 195), (97, 206), (102, 224), (101, 221), (97, 207), (101, 222), (102, 225), (100, 219), (97, 208), (94, 192), (96, 204), (95, 199), (94, 193), (101, 223), (100, 220), (96, 205), (95, 200), (94, 194), (94, 195), (95, 201), (96, 206), (100, 221), (95, 202), (96, 207), (100, 222), (93, 192), (95, 204), (94, 199), (93, 193), (99, 220), (95, 205), (94, 200), (93, 194), (93, 195), (94, 201), (95, 206), (99, 221), (94, 202), (99, 222), (98, 219), (92, 192), (94, 204), (92, 193), (94, 205), (92, 194), (94, 206), (97, 219), (91, 192), (93, 204), (92, 199), (91, 193), (93, 205), (92, 200), (91, 194), (92, 201), (93, 206), (92, 202), (92, 203), (90, 192), (91, 199), (90, 193), (92, 205), (91, 200), (90, 194), (92, 206), (91, 201), (91, 202), (91, 203), (90, 198), (91, 204), (89, 192), (89, 193), (91, 205), (89, 194), (107, 250), (91, 206), (90, 202), (89, 197), (90, 203), (89, 198), (90, 204), (88, 192), (88, 193), (90, 205), (106, 250), (88, 194), (90, 206), (89, 202), (106, 251), (89, 203), (89, 204), (87, 192), (87, 193), (105, 250), (89, 205), (106, 252), (92, 218), (89, 206), (87, 196), (88, 202), (105, 251), (92, 219), (106, 253), (88, 203), (87, 198), (92, 220), (88, 204), (86, 192), (103, 248), (87, 199), (104, 250), (91, 217), (105, 252), (86, 193), (88, 205), (92, 221), (86, 194), (91, 218), (88, 206), (86, 195), (104, 251), (105, 253), (86, 196), (87, 202), (88, 207), (91, 219), (86, 197), (87, 203), (85, 191), (91, 220), (102, 248), (103, 250), (87, 204), (104, 252), (85, 192), (90, 217), (105, 254), (85, 193), (87, 205), (91, 221), (85, 194), (90, 218), (87, 206), (102, 249), (101, 247), (103, 251), (85, 195), (104, 253), (105, 255), (85, 196), (86, 202), (87, 207), (90, 219), (86, 203), (102, 250), (103, 252), (90, 220), (84, 191), (104, 254), (86, 204), (84, 192), (89, 217), (105, 256), (85, 199), (86, 205), (84, 193), (101, 249), (102, 251), (103, 253), (86, 206), (104, 255), (86, 207), (85, 202), (101, 250), (85, 203), (102, 252), (103, 254), (104, 256), (85, 204), (83, 192), (85, 205), (83, 193), (84, 200), (101, 251), (102, 253), (83, 194), (103, 255), (85, 206), (83, 195), (84, 202), (100, 250), (101, 252), (102, 254), (84, 203), (103, 256), (84, 204), (100, 251), (84, 205), (101, 253), (82, 193), (102, 255), (83, 200), (82, 194), (84, 206), (83, 201), (82, 195), (99, 250), (83, 202), (82, 196), (100, 252), (101, 254), (102, 256), (82, 197), (83, 203), (82, 198), (83, 204), (99, 251), (100, 253), (101, 255), (83, 205), (81, 193), (82, 200), (81, 194), (83, 206), (82, 201), (81, 195), (98, 250), (99, 252), (100, 254), (82, 202), (81, 196), (81, 197), (81, 198), (98, 251), (82, 204), (99, 253), (100, 255), (80, 193), (81, 200), (80, 194), (82, 206), (97, 250), (98, 252), (81, 201), (99, 254), (80, 195), (81, 202), (80, 196), (80, 197), (81, 203), (97, 251), (98, 253), (80, 198), (81, 204), (79, 193), (97, 252), (96, 250), (79, 194), (98, 254), (81, 206), (80, 201), (80, 202), (79, 196), (79, 197), (96, 251), (97, 253), (79, 198), (80, 204), (79, 199), (78, 193), (96, 252), (95, 250), (78, 194), (79, 201), (79, 202), (78, 196), (95, 251), (96, 253), (94, 249), (78, 197), (78, 198), (79, 204), (78, 199), (94, 250), (96, 254), (93, 248), (77, 193), (78, 200), (77, 194), (78, 201), (77, 195), (78, 202), (95, 253), (94, 251), (93, 249), (77, 196), (78, 203), (77, 197), (77, 198), (94, 252), (95, 254), (93, 250), (77, 199), (92, 248), (77, 200), (78, 206), (79, 211), (77, 201), (76, 195), (94, 253), (93, 251), (95, 255), (92, 249), (76, 196), (77, 203), (76, 197), (76, 198), (77, 204), (93, 252), (94, 254), (92, 250), (76, 199), (76, 200), (93, 253), (94, 255), (92, 251), (75, 196), (75, 197), (93, 254), (92, 252), (94, 256), (91, 250), (75, 198), (75, 199), (92, 253), (93, 255), (91, 251), (90, 249), (89, 247), (88, 245), (92, 254), (91, 252), (93, 256), (90, 250), (89, 248), (88, 246), (91, 253), (92, 255), (90, 251), (88, 247), (87, 245), (91, 254), (90, 252), (92, 256), (87, 246), (91, 255), (90, 253), (87, 247), (90, 254), (91, 256), (87, 248), (86, 246), (90, 255), (89, 253), (88, 251), (86, 247), (89, 254), (90, 256), (88, 252), (86, 248), (89, 255), (88, 253), (87, 251), (86, 249), (85, 247), (89, 256), (88, 254), (85, 248), (88, 255), (85, 249), (84, 247), (88, 256), (80, 238), (84, 248), (83, 246), (80, 239), (82, 244), (84, 249), (81, 242), (79, 237), (83, 247), (80, 240), (82, 245), (78, 235), (81, 243), (79, 238), (83, 248), (80, 241), (82, 246), (78, 236), (79, 239), (83, 249), (80, 242), (78, 237), (82, 247), (79, 240), (77, 235), (78, 238), (82, 248), (79, 241), (77, 236), (78, 239), (77, 237), (76, 235), (77, 238), (76, 236), (77, 239), (76, 237), (76, 238), (74, 241), (73, 239), (74, 242), (72, 237), (73, 240), (74, 243), (73, 241), (74, 244), (72, 239), (73, 242), (71, 237), (72, 240), (73, 243), (72, 241), (73, 244), (71, 239), (72, 242), (70, 237), (71, 240), (72, 243), (71, 241), (72, 244), (70, 239), (71, 242), (69, 237), (70, 240), (71, 243), (70, 241), (69, 239), (70, 242), (69, 240), (70, 243), (68, 238), (69, 241), (70, 244), (68, 239), (69, 242), (70, 245), (68, 240), (69, 243), (67, 238), (68, 241), (69, 244), (67, 239), (68, 242), (69, 245), (67, 240), (68, 243), (67, 241), (68, 244), (67, 242), (68, 245), (44, 122), (43, 123), (42, 121), (42, 120), (40, 118), (38, 118), (35, 117), (34, 118), (34, 117), (33, 117), (30, 131), (29, 130), (29, 117), (25, 137), (28, 117)]
Took: 78 ms, found 0 point(s)
Successfully executed.


Any suggestions? It's too late into the night for me to property debug this. Only thing I can think of right now is that it's not working because I'm only searching for one color.

Runaway

2012-05-19 03:55:09

Ahhh yes, it's because of the single color.


for i := 0 to High(aPoints[0]) do
begin
Match := 0;
for ii := 1 to hPoints do // There is nothing above 0, so this part doesn't work
begin
if NearbyPointInArray(aPoints[0][i], MaxDist, aPoints[ii]) then // Which means this isn't comparing anything
begin
Inc(Match);
if (Match >= hPoints) then
begin
SetLength(Result, r + 1);
Result[r] := aPoints[0][i];
Inc(r);
end;
end else
Break;
end;
end;

It's not outputting anything because there are no points to compare the primary TPA to (the first color) :p

Kyle Undefined

2012-05-19 04:24:33

Ahh I see, at least I kinda knew what it was doing. I'll play with it some more later. Thanks!

Kyle Undefined

2012-05-22 15:50:50

I've sorted this out for the one color, it was a simple change from for ii := 1 to hPoints do to for ii := 0 to hPoints do.

Thanks! It's working perfectly :)

Runaway

2012-05-22 16:02:18

From: Kyle Undefined
I've sorted this out for the one color, it was a simple change from for ii := 1 to hPoints do to for ii := 0 to hPoints do.

Thanks! It's working perfectly :)


Ohhhh that's what you were trying to do! Sorry I probably could have helped if I had known you were trying to compare it to… itself :p

Glad to hear it's working though!