SRL Archive - Suggestions

TPA.pas: FilterPointsPie


masterBB

2012-02-20 11:30:04

Can this be changed?

cWise := StartD > EndD;
while StartD > 360.0 do
StartD := StartD - 360.0;
while EndD > 360.0 do
EndD := EndD - 360.0;
while StartD < 0.0 do
StartD := StartD + 360.0;
while EndD < 0.0 do
EndD := EndD + 360.0;
if StartD > EndD then
SwapE(StartD, EndD);

to


while StartD > 360.0 do
StartD := StartD - 360.0;
while EndD > 360.0 do
EndD := EndD - 360.0;
while StartD < 0.0 do
StartD := StartD + 360.0;
while EndD < 0.0 do
EndD := EndD + 360.0;
cWise := StartD > EndD;
if cWise then
SwapE(StartD, EndD);

Will make FilterPointsPie(-20,20) possible. And will also fix a bug that makes radial walk to the north impossible.

Here's the thread which brought it to my attention: http://villavu.com/forum/showthread.php?p=936472#post936472

Richard

2012-02-20 12:50:42

Not only that, but you could use mod for 2 of those. Would make it more efficient and save a couple of lines of code :)

StartD := StartD mod 360;
EndD := EndD mod 360

masterBB

2012-02-20 13:12:22

Just realise there is more to optimize, but that isn't really part of this suggestion.

procedure FilterPointsDist(var Points: TPointArray; const MinDist,
MaxDist: Extended; Mx, My: Integer);
var
c,i,l : integer;
d : extended;
mind,maxd : extended;
begin
l := high(points);
c := 0;
mind := sqr(mindist);
maxd := sqr(maxdist);
for i := 0 to l do
begin
d := sqr(Points[i].x - mx) + sqr(points[i].y - my);
if (d >= mind) and (d <= maxd) then
begin
points[c] := points[i];
inc(c);
end;
end;
setlength(points,c);
end;

to

procedure FilterPointsDist(var Points: TPointArray; const MinDist,
MaxDist: Extended; Mx, My: Integer);
var
c,i,l : integer;
dist2 : extended;
min2,max2 : extended;
begin
l := high(points);
c := 0;
min2 := mindist * mindist;
max2 := maxdist * maxdist;
for i := 0 to l do
begin
dist2 := (Points[i].x - mx) * (Points[i].x - mx) + (points[i].y - my) * (points[i].y - my);
if (dist2 >= min2) and (dist2 <= max2) then
begin
points[c] := points[i];
inc(c);
end;
end;
setlength(points,c);
end;

Wizzup?

2012-02-20 13:18:31

As long as it doesn't break any backwards compatibility, I have no problems with it.

Richard

2012-02-20 13:36:25

From: masterBB
Just realise there is more to optimize, but that isn't really part of this suggestion.

procedure FilterPointsDist(var Points: TPointArray; const MinDist,
MaxDist: Extended; Mx, My: Integer);
var
c,i,l : integer;
d : extended;
mind,maxd : extended;
begin
l := high(points);
c := 0;
mind := sqr(mindist);
maxd := sqr(maxdist);
for i := 0 to l do
begin
d := sqr(Points[i].x - mx) + sqr(points[i].y - my);
if (d >= mind) and (d <= maxd) then
begin
points[c] := points[i];
inc(c);
end;
end;
setlength(points,c);
end;

to

procedure FilterPointsDist(var Points: TPointArray; const MinDist,
MaxDist: Extended; Mx, My: Integer);
var
c,i,l : integer;
dist2 : extended;
min2,max2 : extended;
begin
l := high(points);
c := 0;
min2 := mindist * mindist;
max2 := maxdist * maxdist;
for i := 0 to l do
begin
dist2 := (Points[i].x - mx) * (Points[i].x - mx) + (points[i].y - my) * (points[i].y - my);
if (dist2 >= min2) and (dist2 <= max2) then
begin
points[c] := points[i];
inc(c);
end;
end;
setlength(points,c);
end;


N3s33s would be proud of us becoming optimisation freaks.

Slightly improved version now I'm at a computer:
StartD := StartD mod 360;
StartD := StartD + (Ord(StartD < 0) * 360);
EndD := EndD mod 360;
EndD := EndD + (Ord(EndD < 0) * 360);
if cWise then
SwapE(StartD, EndD);

masterBB

2012-02-20 13:43:23

From: Richard
N3s33s would be proud of us becoming optimisation freaks.

Slightly improved version now I'm at a computer:
StartD := StartD mod 360;
StartD := StartD + (Ord(StartD < 0) * 360);
EndD := EndD mod 360;
EndD := EndD + (Ord(EndD < 0) * 360);
if cWise then
SwapE(StartD, EndD);


Seems faster, but you just removed the fix and the main point of this thread :D

StartD := StartD mod 360;
StartD := StartD + (Ord(StartD < 0) * 360);
EndD := EndD mod 360;
EndD := EndD + (Ord(EndD < 0) * 360);
cWise := StartD > EndD;
if cWise then
SwapE(StartD, EndD);

nielsie95

2012-02-20 13:53:37

From: Richard
Not only that, but you could use mod for 2 of those. Would make it more efficient and save a couple of lines of code :)

StartD := StartD mod 360;
EndD := EndD mod 360

You cannot use mod on floats.

From: Wizzup?
As long as it doesn't break any backwards compatibility, I have no problems with it.

Depending on what cWise does later on, it will break compatibility.

The way it works that way in that thread you linked, is because of backwards compatibility. (10, 20) searches clockwise, while (20, 10) searches counterclockwise. The problem actually lies in variantToDirection, as in the old version of RadialWalkEx it didn't do FixD before the if (SD > ED) check. Now, -20 is already converted to 340 in variantToDirection.

masterBB

2012-02-20 14:01:04

From: nielsie95
Depending on what cWise does later on, it will break compatibility.

The way it works that way in that thread you linked, is because of backwards compatibility. (10, 20) searches clockwise, while (20, 10) searches counterclockwise. The problem actually lies in variantToDirection, as in the old version of RadialWalkEx it didn't do FixD before the if (SD > ED) check. Now, -20 is already converted to 340 in variantToDirection.


It will break older scripts, but it does make more sense. And why does SRL do that anyway, it's already handled by the MMLCore.

nielsie95

2012-02-20 14:18:34

I guess it does make more sense.

RadialWalk actually works differently for (10, 20) and (20, 10). The first one searches clockwise, the second counterclockwise. But they both search the same area!

Richard

2012-02-20 14:22:57

From: nielsie95
You cannot use mod on floats.


Depending on what cWise does later on, it will break compatibility.

The way it works that way in that thread you linked, is because of backwards compatibility. (10, 20) searches clockwise, while (20, 10) searches counterclockwise. The problem actually lies in variantToDirection, as in the old version of RadialWalkEx it didn't do FixD before the if (SD > ED) check. Now, -20 is already converted to 340 in variantToDirection.


Ah, I didn't really read the code properly to realise it was a float… In terms of efficiency, would it be more effective to use this method (just extracting numbers to the left of the DP, performing the mod, then adding the numbers to the right of the DP), or entering a while loop. Assuming that we don't use extreme data. The Ord would still work though, rather than having to enter a loop, just looks neater.

EDIT:

Attempt 3!
StartD := (Floor(StartD) mod 360.0)  + (StartD - Floor(StartD));
StartD := StartD + (Ord(StartD < 0.0) * 360);
EndD := (Floor(EndD) mod 360.0) + (EndD - Floor(EndD));
EndD := EndD + (Ord(EndD < 0.0) * 360);
cWise := StartD > EndD;
if cWise then
SwapE(StartD, EndD);

Looks a bit ugly, but it works using the same system, probably less efficient with all those arithmetic operations though.

nielsie95

2012-02-20 14:31:46

Yes, it would be a nice solution. In terms of efficiency it wouldn't matter anything, though. The time consuming work is done in the other loop, where all the points are compared.

masterBB

2012-02-20 14:44:38

D := sqrt(Sqr(Points[I].X - Mx) + Sqr(Points[I].Y - My));
if( D <= MinR) or (D >= MaxR) then

to

D := Sqr(Points[I].X - Mx) + Sqr(Points[I].Y - My);
if( D <= MinR * MinR) or (D >= MaxR * MaxR) then

I think that would be noticeable, cpu hates those square roots. I'm not sure if replacing square with a * a is faster. I though on java it was.

nielsie95

2012-02-20 14:50:12

Yes, especially when you precalculate the MinR*MinR and MaxR*MaxR.
Calculating the angle of a point is probably the most time consuming in the loop, so this optimization would only be noticeable on a specific array of points (arrays with a lot of points not between MinR and MaxR).

Wizzup?

2012-03-09 08:20:04

File a pull request if you want this merged. :)

masterBB

2012-03-11 07:33:50

I just had an idea, might be worth looking into. I remember when I made a game a while back, I didn't used a ArcTan2 for every point. I calculated the two lines and then checked if they were above or beneath those lines. Like this:


I would be able to make this. It would save tons of time. I finally can contribute something to simba(delta e1994 didn't work out). What do you think?