Ok, this was a fun ride and I wanted to share it with you guys.
It started with a "simple" question in the OrbiterSDK forum, where I asked how to determine if a vessel is on a runway or outside of it.
The solution is trivial for a runway aligned with x and y (East-West or North-South) but what happens in other cases?
Urwumpe's quick answer was:
A few minutes later RisingFury jumped in. He had solved exactly that problem for OBSP so he handed me the C++ code and the explanation.
I understood RisingFury's solution for the problem and I was able to apply it. Basically it's using trigonometry to get the define a triangle whose sides are the distances of the vessel from endpoint1 & endpoint2 of the runway and the 3rd side is the length of the runway. Then you find the angles of the triangle and combined with the runway width, one is able to determine whether a vessel is inside it or not.
My "Trig-Fu" was never very strong, but the equations and the explanation were handed to me, so it was relatively easy to apply it in Lua script.
But I was intrigued by Urwumpe's suggestion. All I knew was what a barycenter is and that's where my knowledge ended. So, I looked up "barycentric coordinates" and the wiki page looked very interesting to me. Perhaps because I always prefered algebra to trigonometry.
If I could do this, I would be able to define a rectangular area with two triangles and then determine if a point with coordinates x and y is inside those triangles or not.
In fact, one can choose any 2D area, find it's barycenter, break it down to triangles and apply the same method.
I had no idea how I would be able to do it; plus my math skills are at highschool level - which I graduated from almost 20 years ago.
But that's no reason to quit. I have a good understanding of basic algebra and as long as things don't get too complicated too fast, I am usually able to follow what I'm reading.
I searched for "point inside a rectangle" and I found a few very interesting methods. The one that looked the "simplest" and more elegant to me was this one from the math forums:
This is exactly what I thought:
Joking aside, I could almost understand this. I had to define the "points" that outline a runway, calculate the areas of the triangles that are defined by my vessel and two of those "points" and then if all the areas are positive (or all negative), the vessel is inside. Otherwise, it's outside.
But I didn't know what a determinant was, so I looked it up.
Basically, for a 3x3 table, it's like trying to figure out how to write "123" in all possible combinations: 123 132 213 231 321 312. Then you start with + - and you alternate them:
+123-132-213+231+321-312.
Each number "place" represents the "row" in the table and the number itself represents the "column". (Don't ask me about the signs, I don't know why you place them in that order -yet).
So now, it was easy to convert the formula for the area of a triangle into something I could understand more easily:
At this point I thought: "Oh crap, now I'll get lost with all those "x1"s and "y2"s and it will get very complicated as I add more points to define the area that I want."
Still, I wanted to follow this through and see were it would take me, (or at which point I would give up).
So I got my self some (electronic) pen and paper and traced a rectangle along "counter-clockwise-ly". I made sure that I wouldn't mix the order of the points.
Then moved the mouse to a random point on the screen. That would be my vessel with x0y0 coordinates. I also colored the areas of the triangles to see it better.
Then I re-wrote the equation for A1 and started to write the equation for A2 below it.
As I looked at it I realised that it wasn't complicated after all. To get the equation of the next area, all I had to do was to copy/paste, leave x0 and y0 the same and "go up one" in the other "x"s and "y"s. (This will make more sense when you see all 4 equations and follow the "x"s and "y"s vertically).
That's all I needed. Now all I had to do was to check if the values of all the areas where positive, or if they were all negative. That would mean that the vessel is inside. Ortherwise, it would be outside.
Coding it in Lua was a breeze:
I tested it and it worked beautifully.
The great thing is that you can add as many points XnYn as you want. You simply copy paste from the previous calculation for the area, leave x0 and y0 as they are and "go up" a value in the rest "x"s and "y"s. You just have to make sure that to get to the next point, you trace the perimeter of the area you want in a counter-clockwise manner.
Now I'm pretty sure that there must be an even easier solution for this problem, but for me it was a quite a fun journey of exploration in "unknown" territory. All it took was some paper, a pen and a couple of hours of my time.
I guess the moral of the story is: simply because something is "unknown", doesn't mean it's "unknowable" and things that might seem complicated at first glance, may turn out to be simple if you take some time to investigate them.
Many thanks to Urwumpe and RisingFury for helping me with my question.
It started with a "simple" question in the OrbiterSDK forum, where I asked how to determine if a vessel is on a runway or outside of it.
The solution is trivial for a runway aligned with x and y (East-West or North-South) but what happens in other cases?
Urwumpe's quick answer was:
What about defining the runway with barycentric coordinates?
A few minutes later RisingFury jumped in. He had solved exactly that problem for OBSP so he handed me the C++ code and the explanation.
I understood RisingFury's solution for the problem and I was able to apply it. Basically it's using trigonometry to get the define a triangle whose sides are the distances of the vessel from endpoint1 & endpoint2 of the runway and the 3rd side is the length of the runway. Then you find the angles of the triangle and combined with the runway width, one is able to determine whether a vessel is inside it or not.
My "Trig-Fu" was never very strong, but the equations and the explanation were handed to me, so it was relatively easy to apply it in Lua script.
But I was intrigued by Urwumpe's suggestion. All I knew was what a barycenter is and that's where my knowledge ended. So, I looked up "barycentric coordinates" and the wiki page looked very interesting to me. Perhaps because I always prefered algebra to trigonometry.
If I could do this, I would be able to define a rectangular area with two triangles and then determine if a point with coordinates x and y is inside those triangles or not.
In fact, one can choose any 2D area, find it's barycenter, break it down to triangles and apply the same method.
I had no idea how I would be able to do it; plus my math skills are at highschool level - which I graduated from almost 20 years ago.
But that's no reason to quit. I have a good understanding of basic algebra and as long as things don't get too complicated too fast, I am usually able to follow what I'm reading.
I searched for "point inside a rectangle" and I found a few very interesting methods. The one that looked the "simplest" and more elegant to me was this one from the math forums:
Given any three points on the plane (x0,y0), (x1,y1), and
(x2,y2), the area of the triangle determined by them is
given by the following formula:
To be inside a rectangle (or any convex body), as you trace
around in a counter-clockwise direction from p1 to p2 to p3 to p4 and
back to p1, the "areas" of triangles p1 p2 p, p2 p3 p, p3 p4 p,
and p4 p1 p must all be positive. If you don't know the
orientation of your rectangle, then they must either all be
positive or all be negative."
This is exactly what I thought:
Joking aside, I could almost understand this. I had to define the "points" that outline a runway, calculate the areas of the triangles that are defined by my vessel and two of those "points" and then if all the areas are positive (or all negative), the vessel is inside. Otherwise, it's outside.
But I didn't know what a determinant was, so I looked it up.
Basically, for a 3x3 table, it's like trying to figure out how to write "123" in all possible combinations: 123 132 213 231 321 312. Then you start with + - and you alternate them:
+123-132-213+231+321-312.
Each number "place" represents the "row" in the table and the number itself represents the "column". (Don't ask me about the signs, I don't know why you place them in that order -yet).
So now, it was easy to convert the formula for the area of a triangle into something I could understand more easily:
At this point I thought: "Oh crap, now I'll get lost with all those "x1"s and "y2"s and it will get very complicated as I add more points to define the area that I want."
Still, I wanted to follow this through and see were it would take me, (or at which point I would give up).
So I got my self some (electronic) pen and paper and traced a rectangle along "counter-clockwise-ly". I made sure that I wouldn't mix the order of the points.
Then moved the mouse to a random point on the screen. That would be my vessel with x0y0 coordinates. I also colored the areas of the triangles to see it better.
Then I re-wrote the equation for A1 and started to write the equation for A2 below it.
As I looked at it I realised that it wasn't complicated after all. To get the equation of the next area, all I had to do was to copy/paste, leave x0 and y0 the same and "go up one" in the other "x"s and "y"s. (This will make more sense when you see all 4 equations and follow the "x"s and "y"s vertically).
That's all I needed. Now all I had to do was to check if the values of all the areas where positive, or if they were all negative. That would mean that the vessel is inside. Ortherwise, it would be outside.
Coding it in Lua was a breeze:
Code:
x1 = -135.473650
x2 = -135.38672
x3 = x2
x4 = x1
y1 = 12.744590
y2 = y1
y3 = 12.746220
y4 = y3 [COLOR="SeaGreen"]-- finished outlining the area. This one is aligned with x and y but it could be any shape really[/COLOR]
hobj = v:get_surfaceref()
equ = oapi.global_to_equ (hobj, v:get_globalpos())
x0 = equ.lng*180/PI
y0 = equ.lat*180/PI [COLOR="Teal"]-- got x and y of my vessel[/COLOR]
a_1 = 0.5*((x1*y2)-(y1*x2)-(x0*y2)+(y0*x2)+(x0*y1)-(y0*x1))
a_2 = 0.5*((x2*y3)-(y2*x3)-(x0*y3)+(y0*x3)+(x0*y2)-(y0*x2))
a_3 = 0.5*((x3*y4)-(y3*x4)-(x0*y4)+(y0*x4)+(x0*y3)-(y0*x3))
a_4 = 0.5*((x4*y1)-(y4*x1)-(x0*y1)+(y0*x1)+(x0*y4)-(y0*x4)) [COLOR="Teal"]--got the areas, now all I need is to check if all are positive[/COLOR]
vessel_inside=0
if a_1 > 0 and a_2 > 0 and a_3 > 0 and a_4 > 0 then
vessel_inside=1
end
if a_1 < 0 and a_2 < 0 and a_3 < 0 and a_4 < 0 then
vessel_inside=1 [COLOR="Teal"]-- Just in case I moved clockwise while going through the points that outline the area[/COLOR]
end
The great thing is that you can add as many points XnYn as you want. You simply copy paste from the previous calculation for the area, leave x0 and y0 as they are and "go up" a value in the rest "x"s and "y"s. You just have to make sure that to get to the next point, you trace the perimeter of the area you want in a counter-clockwise manner.
Now I'm pretty sure that there must be an even easier solution for this problem, but for me it was a quite a fun journey of exploration in "unknown" territory. All it took was some paper, a pen and a couple of hours of my time.
I guess the moral of the story is: simply because something is "unknown", doesn't mean it's "unknowable" and things that might seem complicated at first glance, may turn out to be simple if you take some time to investigate them.
Many thanks to Urwumpe and RisingFury for helping me with my question.