PDA

View Full Version : REAL compass Angles!



boberman
04-24-2008, 07:11 PM
This is a somewhat limited function, but it gets the job done. it requires a sub function "isWhite".

function isWhite(color : TColor) : boolean;
var
R, G, B : Integer;
begin
ColorToRGB(color, R, G, B);
Result := False;
if ((R > 225) and (G > 225) and (B > 225)) then
Result := True;
end;

function getCorrectedCompassAngle(startPoint : TPoint) : Extended;
var
endPoint : TPoint;
found : boolean;
i, foundX : integer;
begin
Repeat
startPoint.X := startPoint.X - 1;
Until ((startPoint.X <= 0) or (isWhite(GetColor(startPoint.X, startPoint.Y))));

if startPoint.X > 0 then
begin
Repeat // This loop should put the starting point at the bottem left corner of the bank
begin
found := false;

for i := -1 to 1 do
begin
if isWhite(GetColor(startPoint.X + i, startPoint.Y + 1)) then
begin
found := true;
foundX := i;
end;
end;

if found then
begin
startPoint.X := startPoint.X + foundX;
startPoint.Y := startPoint.Y + 1;
end;
end;
Until not found;

endPoint := startPoint;
endPoint.X := startPoint.X;
endPoint.Y := startPoint.Y;
WriteLn(IntToStr(startPoint.X) + ' ' + IntToStr(startPoint.Y) + ' ' + IntToStr(endPoint.X) + ' ' + IntToStr(endPoint.Y));
Repeat // Should shift the end point to the opisite side of the bank.
begin
found := false
for i := -1 to 1 do
begin;
if isWhite(getColor(endPoint.X + 1, endPoint.Y + i)) then
begin
found := true;
foundX := i;
end;
end;

if found then
begin
endPoint.X := endPoint.X + 1;
endPoint.Y := endPoint.Y + foundX;
end;
end;
Until not found;
Result := -(ArcTan2(startPoint.Y - endPoint.Y, endPoint.X - startPoint.X));
if Result < 0 Then Result := Result + (2 * PI);
end else
Result := 0;
end;

So here are the restrictions not included into the code.

First, you must be looking mostly north (within about 45 degrees of north)

Second, you must be in a building, or at least surrounded by a white boarder of some kind.

Third, People should be able to walk near or on the boarder (as this will mess up the results).

So, how does it work? You give the function a starting point, (doesn't have to be white) If the starting point isn't white the function will shot left of the starting point (STRAIGHT left, IE not compass left but the next pixel left) until it finds a point that is white. Once found it will creep down until it finds the corner of whatever building it is you have.

After it hits the corner it keeps that marked as the starting position, then it follows the wall until it finds the next corner (keeping on the white)

Once it decides its at the next corner, it measures the angle between those two corners and reports back. If the wall slopes down you get a negative number, if it slopes up you will get a positive number (in radians)

I haven't yet finished translating that into compass angles we all know and love, but that wont be too hard.

So, good luck with it. Let me know if you get it to work or need help understanding what is going on.

*Edited with Wissups Correct Math Suggestion. Thanks! :D...*

*Edit NM. Sat back and thought about it, the suggestion is actually incorrect with the way the script works, though the second half of WizzUp's Suggestion is correct. I did fix it so that it represents the correct compass angle (Compass angles are backwards :))*

Wizzup?
04-24-2008, 08:06 PM
Result := Degrees(ArcTan2(startPoint.Y - endPoint.Y, endPoint.X - startPoint.X)) + 90;
If Result < 0 Then Result := Result + 360;

That should work. :)

ShowerThoughts
04-24-2008, 08:15 PM
Man, Looks nice bit confusing because i don't use english word while i learn math on school :S but looks okay, does it works?

boberman
04-24-2008, 08:28 PM
Result := Degrees(ArcTan2(startPoint.Y - endPoint.Y, endPoint.X - startPoint.X)) + 90;
If Result < 0 Then Result := Result + 360;

That should work. :)

Ahh, Thanks (though, I prefer to keep my answers in radians... Calculus has spoiled me :))

Wait, Looking over the change that doesn't work. The Problem is that it doesn't crawl up the wall but along the lower wall (I really need pictures)
|..........|
|..........|
|_____|
^ ++++^
s ------e

So, it starts at s and ends at e. I did this because nobody can walk near those points (at least in varrock east bank) where as the wall people can walk in-between and near them.


Man, Looks nice bit confusing because i don't use english word while i learn math on school :S but looks okay, does it works?
So far it seems to work, I am still testing it but from the initial results it seems to be pretty good. It seems to be accurate up to about .5 a degree (doesn't catch a single pixel shift up). So, for short distances that should be plenty, It isn't going to get you across the world though ;)