General Question How to know if you have line of sight?

nbcfrosty

Well-known member
Joined
Jun 16, 2023
Messages
182
Reaction score
215
Points
58
Location
US
Code:
auto v1 = oapiGetFocusInterface();
    auto v2 = oapiGetVesselInterface(oapiGetVesselByName("ISS"));

    VESSELSTATUS v1s, v2s;

    v1->GetStatus(v1s);
    v2->GetStatus(v2s);

    double m = length(_V((v1s.rpos.x + v2s.rpos.x) / 2., (v1s.rpos.y + v2s.rpos.y) / 2., (v1s.rpos.z + v2s.rpos.z) / 2.));
    VECTOR3 p1, p2;
    v1->GetGlobalPos(p1);
    v2->GetGlobalPos(p2);
    double d = dist(p1, p2);
    double dhalf = d / 2.;
    double radius = oapiGetSize(v1s.rbody);
    if (dhalf < sqrt(m * m - radius * radius)) {
        sprintf(oapiDebugString(), "LOS");
    }
    else {
        sprintf(oapiDebugString(), "NO LOS");
    }

I am doing this currently which works reasonably well but not always close to horizon. I want to know simply when 2 vessels can see one another without the reference body occluding.
 

asbjos

tuanibrO
Addon Developer
Joined
Jun 22, 2011
Messages
697
Reaction score
264
Points
78
Location
This place called "home".
What you are interested in is essentially to know the angle of the planet horizon in the Surface HUD, and the angle of the target vessel in the same HUD. This involves some trigonometry.

For the first angle (I call it [imath]\theta[/imath]), you construct a triangle between the planet centre, your main vessel, and the point of the horizon on the planet surface, while recognising that the angle at the surface is a right (90 degrees) angle.
1716705594205.png
Then, the angle of the horizon as seen from your vessel is given as
[math]\theta=-\arccos \left(\frac{R_\mathrm{E}}{|\vec{u}|} \right) ,[/math]where the minus sign is due to the horizon having a negative angle, but as you only want to compare the angles, the most important thing is that you keep it consistent.

Now, for your target vessel, the angle (I call it [imath]\varphi[/imath]) is given by the angle between the vector from the planet to you ([imath]\vec{u}[/imath]) and the the vector constructed between you and the target vessel ([imath]\vec{w}[/imath]). The second vector is equal to the vector from the planet to the target ([imath]\vec{v}[/imath]), minus the vector from the planet to you ([imath]\vec{u}[/imath]).
1716705874394.png
Find the angle with the equation
[math]\varphi=-\arcsin \left(\frac{\vec{u}\cdot\vec{w}}{|\vec{u}| \cdot |\vec{w}|} \right) .[/math]
Then you find out if the target is above the horizon (i.e. not occluding) by comparing [imath]\varphi > \theta[/imath].

I've attached a zipped GeoGebra file where you can drag around the points of the ship and the target, and see the text at the centre of the planet change from "over" to "under" when the target gets occluded. Unzip, go to https://www.geogebra.org/calculator , press the hamburger menu at the top left and open->local file.

To do this in Orbiter and C++, try something like this:
C++:
double planetR = oapiGetSize(planet);
oapiGetRelativePos(planet, vessel, &u);
oapiGetRelativePos(planet, target, &v);
VECTOR3 w = v - u;

double theta = -acos(planetR / length(u));
double phi = asin(dotp(u, w) / (length(u) * length(w)));

if (phi > theta) sprintf(oapiDebugString(), "Over horizon");
else sprintf(oapiDebugString(), "Under horizon");
 

Attachments

  • geogebra-export.zip
    20.3 KB · Views: 0
Top