Skip to content

Commit 932b91a

Browse files
committed
performance(TRSMap): filters tweaks
- Made some tweaks to how position filters work internally and TRSMap should be 10% faster now by using some pre-computed math and also separating the types of filters to be used more efficiently. - Added a lot of extra postion debugging to TRSMap when the compiler directive `{$DEFINE WL_DEBUG_MAP} ` is added - added TModel docs
1 parent 41a3665 commit 932b91a

6 files changed

Lines changed: 412 additions & 52 deletions

File tree

osrs.simba

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ less confusing way.
1717
{$DEFINE WL_DEBUG_UPTEXT}
1818
{$DEFINE WL_DEBUG_INTERFACES}
1919
{$DEFINE WL_GENERATE_GRAPH_ALWAYS}
20+
{$DEFINE WL_DEBUG_MAP}
2021
{$DEFINE WL_TRANSPORTER_DEBUG}
2122
```
2223
These are the main compiler directives available in the library.

osrs/position/map/entities.simba

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
(*
2-
# Entities
2+
# RSEntities
33
This file is responsible for interacting with `RSEntities`.
44

55
`RSEntities` is anything in the game that has a {ref}`ERSMinimapDot` assign to

osrs/position/map/map.simba

Lines changed: 94 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,14 @@ For a online interactive map you can visit
1111

1212
For something simpler and much closer to the original
1313
[slacky](https://slacky.one/) walker check out {ref}`Image Map`.
14+
15+
For debugging purposes you can use `{$DEFINE WL_DEBUG_MAP}` before including
16+
{ref}`WaspLib`.
1417
*)
1518

1619
{$DEFINE WL_MAP_INCLUDED}
1720
{$INCLUDE_ONCE WaspLib/osrs.simba}
21+
{.$DEFINE WL_DEBUG_MAP}
1822

1923
type
2024
(*
@@ -68,6 +72,48 @@ function TRSMap.Position(): TPoint; forward;
6872
function TRSMap.Height(pt: TPoint = [0,0]; global: Boolean = True): Single; forward;
6973

7074

75+
(*
76+
## Map.AddLocalFilter
77+
```pascal
78+
procedure TRSMap.AddLocalFilter(filter: TBox; inside: Boolean);
79+
```
80+
Adds a position filter to the `TRSMap`.
81+
82+
This is a way to making it impossible for you to get positions inside of the
83+
`filter` boxes your `TRSMap` has.
84+
85+
It's useful to understand the different between local and global coordinates to
86+
know if you should use this or {ref}`Map.AddGlobalFilter` instead.
87+
*)
88+
procedure TRSMap.AddLocalFilter(filter: TBox; inside: Boolean);
89+
begin
90+
with Self.Loader do
91+
Self.Filters += [[
92+
filter.X1 div Downscale, filter.Y1 div Downscale,
93+
filter.X2 div Downscale, filter.Y2 div Downscale
94+
], inside];
95+
end;
96+
97+
(*
98+
## Map.AddGlobalFilter
99+
```pascal
100+
procedure TRSMap.AddGlobalFilter(regionIdx: Integer; filter: TBox; inside: Boolean);
101+
```
102+
Adds a position filter to the `TRSMap`.
103+
104+
This is a way to making it impossible for you to get positions inside of the
105+
`filter` boxes your `TRSMap` has.
106+
107+
It's useful to understand the different between local and global coordinates to
108+
know if you should use this or {ref}`Map.AddLocalFilter` instead.
109+
*)
110+
procedure TRSMap.AddGlobalFilter(regionIdx: Integer; filter: TBox; inside: Boolean);
111+
begin
112+
filter := Self.Loader.GetLocal(regionIdx, filter);
113+
filter := filter.Clip(Self.Loader.Regions[regionIdx].Region);
114+
Self.AddLocalFilter(filter, inside);
115+
end;
116+
71117
(*
72118
## Map.InternalSetup
73119
```pascal
@@ -107,8 +153,8 @@ begin
107153
Self.Filters := [];
108154
for i := 0 to High(Self.Loader.Regions) do
109155
begin
110-
b := Self.Loader.Regions[i].Region.Expand(-(Self.Loader.Padding));
111-
Self.Filters += [b, True];
156+
b := Self.Loader.Regions[i].Region.Expand(-Self.Loader.Padding);
157+
Self.AddLocalFilter(b, True);
112158
end;
113159

114160
if not Self.IsSetup then
@@ -229,10 +275,15 @@ function TRSMap.ScaledSearch(img: TImage): TPointArray;
229275
var
230276
sample: TImage;
231277
matrix: TSingleMatrix;
232-
w, h, i, loops: Integer;
278+
w, h, i, loops, width, height, padding: Integer;
233279
pt, loaderOffset: TPoint;
234-
width, height: Integer;
280+
filters: TBoxArray;
281+
{$IFDEF WL_DEBUG_MAP}
282+
debugImg, matrixImg: TImage;
283+
{$ENDIF}
235284
begin
285+
padding := Self.Loader.Padding div Self.Loader.Downscale;
286+
236287
sample := Minimap.ScaleMinimap(img, Self.Loader.Downscale, Self.Sample.Radius);
237288
matrix := MatchTemplateMask(Self.Cache.MatchTemplate, sample.ToMatrix(), ETMFormula.TM_CCOEFF_NORMED);
238289

@@ -244,35 +295,48 @@ begin
244295
width -= 1;
245296
height -= 1;
246297

247-
while Length(Result) < Self.Sample.Amount do
298+
for i := 0 to High(Self.Filters) do
248299
begin
249-
with matrix.ArgMax() do
250-
begin
251-
pt := Offset(w, h);
252-
pt := pt * Self.Loader.Downscale;
253-
254-
for i := 0 to High(Self.Filters) do
255-
begin
256-
if Self.Filters[i].Valid(pt) then
257-
begin
258-
Result += pt + loaderOffset;
259-
matrix.Fill([Max(0, X-5), Max(0, Y-5), Min(width, X+5), Min(height, Y+5)], 0);
260-
Continue(2);
261-
end;
262-
end;
300+
if Self.Filters[i].Inside then
301+
filters += Self.Filters[i].Box.Offset([-padding, -padding])
302+
else
303+
matrix.Fill(Self.Filters[i].Box.Offset([-padding, -padding]), 0);
304+
end;
263305

264-
matrix.Fill([Max(0, X-5), Max(0, Y-5), Min(width, X+5), Min(height, Y+5)], 0);
265-
end;
306+
{$IFDEF WL_DEBUG_MAP}
307+
debugImg := Self.Loader.DownscaledMap.Copy();
308+
matrixImg := new TImage();
309+
matrixImg.FromMatrix(matrix);
310+
debugImg.DrawAlpha := $A7;
311+
debugImg.DrawImage(matrixImg, [padding, padding]);
312+
for i := 0 to High(Self.Filters) do
313+
begin
314+
if Self.Filters[i].Inside then
315+
debugImg.DrawColor := $00FF00
316+
else
317+
debugImg.DrawColor := $0000FF;
318+
debugImg.DrawBox(Self.Filters[i].Box);
319+
end;
320+
debugImg.Show();
321+
Sleep(2000);
322+
{$ENDIF}
266323

267-
if Inc(loops) > 70 then Break;
324+
while Length(Result) < Self.Sample.Amount do
325+
begin
326+
pt := matrix.ArgMax();
327+
if filters.ContainsPoint(pt) > -1 then
328+
Result += (pt.Offset(w, h) * Self.Loader.Downscale) + loaderOffset;
329+
matrix.Fill([Max(0, pt.X-5), Max(0, pt.Y-5), Min(width, pt.X+5), Min(height, pt.Y+5)], 0);
330+
if Inc(loops) > 70 then
331+
Break;
268332
end;
269333
end;
270334

271335
(*
272336
## Map.Position
273337
```pascal
274338
function TRSMap.Position(): TPoint;
275-
property TRSMap.FullPosition(): TRSPosition;
339+
function TRSMap.FullPosition(): TRSPosition;
276340
```
277341
Returns the players current position on the loaded map.
278342
`TRSMap.FullPosition()` also returns the current Z level.
@@ -337,7 +401,7 @@ begin
337401
Self.Cache.Position := Result;
338402
end;
339403

340-
property TRSMap.FullPosition: TRSPosition;
404+
function TRSMap.FullPosition(): TRSPosition;
341405
begin
342406
with Self.Position() do
343407
begin
@@ -460,7 +524,7 @@ function TRSMap.DebugPosition(print: Boolean = True): TPoint;
460524
end;
461525
var
462526
x1, y1, x2, y2, x, y, i: Int32;
463-
p, local: TPoint;
527+
pt, local: TPoint;
464528
img, map, cleanMinimap: TImage;
465529
time: Double;
466530
lines: TStringArray;
@@ -471,7 +535,6 @@ begin
471535

472536
time := PerformanceTime();
473537
Result := Self.Position();
474-
475538
time := PerformanceTime() - time;
476539

477540
case Self.RegionIndex of
@@ -520,21 +583,21 @@ begin
520583
map.DrawBox([x - 2, y - 2, x + 2, y + 2]);
521584

522585
cleanMinimap := Minimap.GetCleanImage();
523-
img := new TImage(700 + cleanMinimap.Width, 440);
586+
img := new TImage(700 + cleanMinimap.Width, 450);
524587
img.DrawImage(map, [10, 20]);
525588

526589
with cleanMinimap.Center do
527590
begin
528591
if RSClient.Mode = ERSMode.FIXED then
529-
p := Point(X, Y).Offset(0, 8).Rotate(-Minimap.CompassRadians, [X,Y])
592+
pt := Point(X, Y).Offset(0, 8).Rotate(-rads, [X,Y])
530593
else
531-
p := Point(X, Y).Offset(2, 1).Rotate(-Minimap.CompassRadians, [X,Y]);
594+
pt := Point(X, Y).Offset(2, 1).Rotate(-rads, [X,Y]);
532595
end;
533596

534597
cleanMinimap.DrawColor := $FFFFFF;
535-
cleanMinimap.DrawBox(TBox.Create(p, 1, 1));
598+
cleanMinimap.DrawBox(TBox.Create(pt, 1, 1));
536599
cleanMinimap.DrawColor := $FF;
537-
cleanMinimap.DrawCross(p, 4);
600+
cleanMinimap.DrawCross(pt, 4);
538601

539602
{$IFDEF WINDOWS}
540603
img.FontName := 'Consolas';

osrs/position/map/maploader.simba

Lines changed: 32 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -149,57 +149,67 @@ end;
149149
(*
150150
### TRSMapLoader.GetGlobal
151151
```pascal
152-
function TRSMapLoader.GetGlobal(regionIndex: Integer; pt: TPoint; offset: TPoint = [0,0]): TPoint;
152+
function TRSMapLoader.GetGlobal(regionIdx: Integer; pt: TPoint; offset: TPoint = [0,0]): TPoint;
153153
function TRSMapLoader.GetGlobal(pt: TPoint; offset: TPoint = [0,0]): TPoint; overload;
154154
```
155155
Converts a {ref}`Local point` to a {ref}`Global point`.
156156

157-
You can optionally specify the `regionIndex` you want your `pt` to be converted to or let Simba figure it out.
157+
You can optionally specify the `regionIdx` you want your `pt` to be converted to or let Simba figure it out.
158158
For points in bulk from the same region specifying it is better as you save Simba from doing more math.
159159

160160
The specified `pt` is returned unmodified if not region index matching the point is found.
161161
*)
162-
function TRSMapLoader.GetGlobal(regionIndex: Integer; pt: TPoint; offset: TPoint = [0,0]): TPoint;
162+
function TRSMapLoader.GetGlobal(regionIdx: Integer; pt: TPoint; offset: TPoint = [0,0]): TPoint;
163163
begin
164-
Result := pt + Self.Regions[regionIndex].Offset - [Self.Regions[regionIndex].Region.X1, Self.Regions[regionIndex].Region.Y1] + offset;
164+
Result := pt + Self.Regions[regionIdx].Offset - [Self.Regions[regionIdx].Region.X1, Self.Regions[regionIdx].Region.Y1] + offset;
165165
end;
166166

167167
function TRSMapLoader.GetGlobal(pt: TPoint; offset: TPoint = [0,0]): TPoint; overload;
168168
var
169-
regionIndex: Integer;
169+
regionIdx: Integer;
170170
begin
171-
regionIndex := Self.LocalIndex(pt);
172-
if regionIndex = -1 then Exit(pt);
173-
Result := Self.GetGlobal(regionIndex, pt, offset);
171+
regionIdx := Self.LocalIndex(pt);
172+
if regionIdx = -1 then Exit(pt);
173+
Result := Self.GetGlobal(regionIdx, pt, offset);
174174
end;
175175

176176

177177
(*
178178
### TRSMapLoader.GetLocal
179179
```pascal
180-
function TRSMapLoader.GetLocal(regionIndex: Integer; pt: TPoint; offset: TPoint = [0,0]): TPoint;
180+
function TRSMapLoader.GetLocal(regionIdx: Integer; pt: TPoint; offset: TPoint = [0,0]): TPoint;
181+
function TRSMapLoader.GetLocal(regionIdx: Integer; b: TBox; offset: TPoint = [0,0]): TBox; overload;
181182
function TRSMapLoader.GetLocal(pt: TPoint; offset: TPoint = [0,0]): TPoint; overload;
182183
function TRSMapLoader.GetLocal(tpa: TPointArray; offset: TPoint = [0,0]): TPointArray; overload;
183184
```
184185
Converts a {ref}`Global point` to a {ref}`Local point`.
185186

186-
You can optionally specify the `regionIndex` you want your `pt` to be converted to or let Simba figure it out.
187+
You can optionally specify the `regionIdx` you want your `pt` to be converted to or let Simba figure it out.
187188
You can also optionally specify points in bulk as a `tpa`.
188189

189190
The specified `pt` is returned unmodified if not region index matching the point is found.
190191
*)
191-
function TRSMapLoader.GetLocal(regionIndex: Integer; pt: TPoint; offset: TPoint = [0,0]): TPoint;
192+
function TRSMapLoader.GetLocal(regionIdx: Integer; pt: TPoint; offset: TPoint = [0,0]): TPoint;
192193
begin
193-
Result := pt - Self.Regions[regionIndex].Offset + Self.Regions[regionIndex].Region.TopLeft + offset;
194+
Result := pt - Self.Regions[regionIdx].Offset + Self.Regions[regionIdx].Region.TopLeft + offset;
195+
end;
196+
197+
function TRSMapLoader.GetLocal(regionIdx: Integer; b: TBox; offset: TPoint = [0,0]): TBox; overload;
198+
var
199+
topLeft, btmRight: TPoint;
200+
begin
201+
topLeft := Self.GetLocal(regionIdx, b.TopLeft, offset);
202+
btmRight := Self.GetLocal(regionIdx, b.BottomRight, offset);
203+
Result := [topLeft.X, topLeft.Y, btmRight.X, btmRight.Y];
194204
end;
195205

196206
function TRSMapLoader.GetLocal(pt: TPoint; offset: TPoint = [0,0]): TPoint; overload;
197207
var
198-
regionIndex: Integer;
208+
regionIdx: Integer;
199209
begin
200-
regionIndex := Self.GlobalIndex(pt);
201-
if regionIndex = -1 then Exit(pt);
202-
Result := Self.GetLocal(regionIndex, pt, offset);
210+
regionIdx := Self.GlobalIndex(pt);
211+
if regionIdx = -1 then Exit(pt);
212+
Result := Self.GetLocal(regionIdx, pt, offset);
203213
end;
204214

205215
function TRSMapLoader.GetLocal(tpa: TPointArray; offset: TPoint = [0,0]): TPointArray; overload;
@@ -211,6 +221,7 @@ begin
211221
end;
212222

213223

224+
214225
procedure TRSMapLoader.Free();
215226
begin
216227
Self.Map := nil;
@@ -467,7 +478,8 @@ begin
467478
raise GetDebugLn('MapLoader', 'Failed to create cache directory: ' + path);
468479

469480
Result := WebGraphGenerator.BuildGraph(name, map);
470-
Self.CacheGraph(Result, path);
481+
if Result <> Default(TWebGraph) then
482+
Self.CacheGraph(Result, path);
471483
Exit;
472484
end;
473485

@@ -685,6 +697,7 @@ This is an internal method. Usually, {ref}`TRSMap` `Load` methods will call this
685697
procedure TRSMapLoader.Load(chunks: TRSMapChunkArray; downscale: Integer = 8; padding: Integer = 40);
686698
begin
687699
Self.Setup(downscale);
688-
Self.Padding := padding;
689-
Self.Add(chunks, downscale, padding);
700+
if Self.Padding = 0 then
701+
Self.Padding := padding;
702+
Self.Add(chunks, downscale, Self.Padding);
690703
end;

0 commit comments

Comments
 (0)