Example #1
0
        public void KDTree()
        {
            var tree = new List <Sorta>();

            for (int j = 0; j != 10; ++j)
            {
                for (int i = 0; i != 10; ++i)
                {
                    tree.Add(new Sorta {
                        pos = new v2(i, j)
                    });
                }
            }

            KDTree_.Build(tree, 2);

            var result = KDTree_.Search(tree, 2, new[] { 5.0, 5.0 }, 1.1).Select(x => x.pos).ToList();

            result.Sort((l, r) =>
            {
                if (l.x != r.x)
                {
                    return(l.x < r.x ? -1 : 1);
                }
                return(l.y < r.y ? -1 : 1);
            });

            Assert.Equal(result.Count, 5);
            Assert.Equal(result[0], new v2(4f, 5f));
            Assert.Equal(result[1], new v2(5f, 4f));
            Assert.Equal(result[2], new v2(5f, 5f));
            Assert.Equal(result[3], new v2(5f, 6f));
            Assert.Equal(result[4], new v2(6f, 5f));
        }
Example #2
0
 /// <summary>Rebuild the map</summary>
 public void BuildSystemMap(IEnumerable <StarSystem> stars)
 {
     Log.Write(ELogLevel.Info, $"Building systems map");
     using (StatusStack.NewStatusMessage($"Updating star map..."))
     {
         m_tree.Clear();
         m_tree.AddRange(stars.Select(x => new StarSystemRef(x)));
         KDTree_.Build(m_tree, 3);
     }
 }
Example #3
0
        /// <summary>Search for trades</summary>
        private async Task FindTradeRoutes(Settings settings, int issue)         // worker thread context
        {
            if (!CanFindTradeRoutes(settings))
            {
                // Settings not valid, ignore until they are.
                RunOnMainThread(() =>
                {
                    if (issue != m_trade_routes_issue)
                    {
                        return;
                    }
                    m_trade_routes_issue_current = issue;
                });
                return;
            }
            else
            {
                // Settings are valid, reset the trade routes before starting
                RunOnMainThread(() =>
                {
                    if (issue != m_trade_routes_issue || TradeRoutes.Count == 0)
                    {
                        return;
                    }

                    TradeRoutes.Clear();
                    TradeRoutesChanged?.Invoke(this, EventArgs.Empty);
                });
            }

            // Get the start point
            var origin_system = await Src.GetStarSystem(settings.Origin.StarSystemID.Value);

            var origin_station = await Src.GetStation(settings.Origin.StationID.Value);

            var origin = new Location(origin_system, origin_station);

            // If a specific destination is given, find trades between the origin and that destination
            if (!settings.AnyDestination)
            {
                var destination_system = await Src.GetStarSystem(settings.Destination.StarSystemID.Value);

                var destination_station = settings.Destination.StationID != null ? await Src.GetStation(settings.Destination.StationID.Value) : null;

                Log.Write(ELogLevel.Info, $"Find trade routes {origin_system.Name}/{origin_station.Name} → {destination_system.Name}/{destination_station?.Name ?? "Any"}");

                var stations = destination_station != null
                                        ? new[] { destination_station }
                                        : Src.EnumStations(
                    system_id: destination_system.ID,
                    max_station_distance: settings.MaxStationDistance,
                    required_pad_size: settings.RequiredPadSize,
                    facilities_incl: EFacilities.Market | EFacilities.Docking,
                    ignore_planetary: settings.IgnorePlanetBases);

                // Look for trade routes between the given stations
                foreach (var station in stations)
                {
                    // Abort if the issue number changes
                    if (m_trade_routes_issue != issue)
                    {
                        return;
                    }

                    var routes = await FindTradeRoutes(settings, origin, new Location(destination_system, station), issue);

                    if (routes.Count == 0)
                    {
                        continue;
                    }

                    RunOnMainThread(() =>
                    {
                        if (issue != m_trade_routes_issue)
                        {
                            return;
                        }
                        MergeTradeRoutes(origin, routes);
                    });
                }
            }
            else
            {
                Log.Write(ELogLevel.Info, $"Find trade routes {origin_system.Name}/{origin_station.Name} within {settings.MaxTradeRouteDistance} LY");

                int considered_systems = 0, last_considered_systems = 0;
                var considered = new HashSet <StarSystemRef>();

                // A queue of systems to consider
                var queue = new Queue <StarSystem>();
                using (var msg = StatusStack.NewStatusMessage("Finding Trade Routes..."))
                {
                    var candidates = Src.Search(origin_system.Position, settings.MaxTradeRouteDistance.Value).ToList();
                    KDTree_.Build(candidates, 3);

                    // Find all systems within the maximum trade route distance.
                    for (queue.Enqueue(origin_system); queue.Count != 0 && !Shutdown.IsCancellationRequested;)
                    {
                        // Abort if the issue number changes
                        if (m_trade_routes_issue != issue)
                        {
                            return;
                        }

                        // Get the next system to consider
                        var hop = queue.Dequeue();

                        // Find the systems within the maximum jump range that have not been considered already
                        var system_refs = KDTree_.Search(candidates, 3, (double[])hop.Position, settings.MaxJumpRange).Where(x => !considered.Contains(x)).ToList();
                        if (system_refs.Count == 0)
                        {
                            continue;
                        }

                        // When the considered number gets large enough, remove them from the map and regenerate it
                        const int RebuildTreeThreshold = 256;
                        considered.AddRange(system_refs);
                        if (considered.Count > RebuildTreeThreshold)
                        {
                            candidates.RemoveSet(considered);
                            KDTree_.Build(candidates, 3);
                            considered.Clear();
                        }

                        // Check the stations in each system
                        foreach (var system_ref in system_refs)
                        {
                            // Abort if the issue number changes
                            if (m_trade_routes_issue != issue)
                            {
                                return;
                            }

                            // Get the system
                            var destination_system = await Src.GetStarSystem(system_ref.ID);

                            // Update status
                            if (++considered_systems - last_considered_systems > 100)
                            {
                                var distance = (destination_system.Position - origin_system.Position).Length;
                                msg.Message             = $"Finding Trade Routes... (checked:{considered_systems} queued:{queue.Count} distance:{distance})";
                                last_considered_systems = considered_systems;
                            }

                            // Needs a permit?
                            if (destination_system.NeedPermit && settings.IgnorePermitSystems)
                            {
                                continue;
                            }

                            // Check the suitable stations
                            var stations = Src.EnumStations(
                                system_id: destination_system.ID,
                                max_station_distance: settings.MaxStationDistance,
                                required_pad_size: settings.RequiredPadSize,
                                facilities_incl: EFacilities.Market | EFacilities.Docking,
                                ignore_planetary: settings.IgnorePlanetBases);
                            foreach (var station in stations)
                            {
                                // Abort if the issue number changes
                                if (m_trade_routes_issue != issue)
                                {
                                    return;
                                }

                                var routes = await FindTradeRoutes(settings, origin, new Location(destination_system, station), issue);

                                if (routes.Count == 0)
                                {
                                    continue;
                                }

                                RunOnMainThread(() =>
                                {
                                    if (issue != m_trade_routes_issue)
                                    {
                                        return;
                                    }
                                    MergeTradeRoutes(origin, routes);
                                });
                            }

                            // Add this system to be considered for the next hop
                            queue.Enqueue(destination_system);
                        }
                    }
                }
            }
            m_trade_routes_issue_current = issue;
        }
Example #4
0
 /// <summary>Search the map for nearby systems</summary>
 public IEnumerable <StarSystemRef> Search(v4 position, double radius)
 {
     return(KDTree_.Search(m_tree, 3, (double[])position, radius));
 }