Example #1
0
        public link_data ComputeLink(Vessel v, HashSet <Guid> avoid_inf_recursion)
        {
            // if it has no antenna
            if (antennas[v.id].range <= double.Epsilon)
            {
                return(new link_data(false, link_status.no_antenna, 0.0));
            }

            // if there is a storm and the vessel is inside a magnetosphere
            if (Blackout(v))
            {
                return(new link_data(false, link_status.no_link, 0.0));
            }

            // check for direct link
            // note: we also get distance from the cache and store it in the link
            double direct_visible_dist = direct_visibility_cache[v.id];
            bool   direct_visible      = direct_visible_dist > 0.0;

            if (direct_visible)
            {
                return(new link_data(true, link_status.direct_link, direct_visible_dist));
            }

            // avoid infinite recursion
            avoid_inf_recursion.Add(v.id);

            // get antenna data
            antenna_data v_ad = antennas[v.id];

            // check for indirect link
            foreach (Vessel w in FlightGlobals.Vessels)
            {
                // skip invalid vessels
                if (!Lib.IsVessel(w))
                {
                    continue;
                }

                // avoid infinite recursion
                if (avoid_inf_recursion.Contains(w.id))
                {
                    continue;
                }

                // avoid testing against itself
                if (v == w)
                {
                    continue;
                }

                // get antenna data
                antenna_data w_ad = antennas[w.id];

                // check for indirect link to home body
                // note: we also get distance from the cache
                // note: we check the relay range, that is asymmetric
                double indirect_visible_dist = indirect_visibility_cache[Lib.CombineGuid(v.id, w.id)];
                bool   indirect_visible      = indirect_visible_dist > 0.0 && indirect_visible_dist < Math.Min(v_ad.range, w_ad.relay_range);
                if (indirect_visible)
                {
                    // check link to home body, recursively
                    link_data next_link = ComputeLink(w, avoid_inf_recursion);

                    // if indirectly linked
                    if (next_link.linked)
                    {
                        // flag the relay for ec consumption, but only once
                        if (!active_relays.ContainsKey(w.id))
                        {
                            active_relays.Add(w.id, w_ad.relay_cost);
                        }

                        // update the link data and return it
                        next_link.status   = link_status.indirect_link;
                        next_link.distance = indirect_visible_dist; //< store distance of last link
                        next_link.path.Add(w.vesselName);
                        next_link.path_id.Add(w.id);
                        return(next_link);
                    }
                }
            }

            // no link
            return(new link_data(false, link_status.no_link, 0.0));
        }
Example #2
0
        // build the visibility caches
        void BuildVisibility()
        {
            // get home body
            CelestialBody home = FlightGlobals.GetHomeBody();

            // build direct visibility cache
            direct_visibility_cache.Clear();
            foreach (Vessel v in FlightGlobals.Vessels)
            {
                // skip invalid vessels
                if (!Lib.IsVessel(v))
                {
                    continue;
                }

                // get antenna data
                antenna_data ad = antennas[v.id];

                // raytrace home body
                Vector3d dir;
                double   dist    = 0.0;
                bool     visible = Sim.RaytraceBody(v, home, out dir, out dist);
                dist = Math.Abs(dist); //< avoid problem below water level

                // store in visibility cache
                // note: we store distance & visibility flag at the same time
                direct_visibility_cache.Add(v.id, visible && dist < ad.range ? dist : 0.0);
            }


            // build indirect visibility cache
            indirect_visibility_cache.Clear();
            foreach (Vessel v in FlightGlobals.Vessels)
            {
                // skip invalid vessels
                if (!Lib.IsVessel(v))
                {
                    continue;
                }

                // get antenna data
                antenna_data v_ad = antennas[v.id];

                // for each vessel
                foreach (Vessel w in FlightGlobals.Vessels)
                {
                    // skip invalid vessels
                    if (!Lib.IsVessel(w))
                    {
                        continue;
                    }

                    // do not test with itself
                    if (v == w)
                    {
                        continue;
                    }

                    // do not compute visibility when both vessels have a direct link
                    // rationale: optimization, the indirect visibility it never used in this case
                    if (direct_visibility_cache[v.id] > double.Epsilon && direct_visibility_cache[w.id] > double.Epsilon)
                    {
                        continue;
                    }

                    // generate merged guid
                    Guid id = Lib.CombineGuid(v.id, w.id);

                    // avoid raycasting the same pair twice
                    if (indirect_visibility_cache.ContainsKey(id))
                    {
                        continue;
                    }

                    // get antenna data
                    antenna_data w_ad = antennas[w.id];

                    // raytrace the vessel
                    Vector3d dir;
                    double   dist    = 0.0;
                    bool     visible = Sim.RaytraceVessel(v, w, out dir, out dist);

                    // store visibility in cache
                    // note: we store distance & visibility flag at the same time
                    // note: relay visibility is asymmetric, done at link build time
                    indirect_visibility_cache.Add(id, visible && dist < Math.Min(v_ad.range, w_ad.range) ? dist : 0.0);
                }
            }
        }