//private static ThreadLocal<Region> instances = new ThreadLocal<Region>(() => new Region()); //public static Region Instance //{ // get { return instances.Value; } //} /// <summary> /// This method only add regional nodes to the first region. /// Subsequent node additions to latter regions are done inside of /// <see cref="PredictiveForest.Update(System.Device.Location.GeoCoordinate, double)" />. /// </summary> /// <param name="nodes"></param> public void Update(IEnumerable <Node> nodes) { var newRegion = new ConcurrentDictionary <int, RegionalNode>(); foreach (var node in nodes) { var regionalNode = new RegionalNode(node, null); newRegion.TryAdd(node.NodeID, regionalNode); } Regions.TryAdd(RegionCount, newRegion); }
public void Update(Coordinate center, double radius) { if (CurrentStep == 0) { MRegion.Update(GetRoadNetwork().GetNodesWithinRange(center, radius)); MRegion.Regions.TryGetValue(CurrentStep, out var region); ExpandPredictiveTrees(region); CurrentStep += 1; return; } // retrieve all nodes from previous region MRegion.Regions.TryGetValue(CurrentStep - 1, out var pastNodes); // gathering child nodes from previous region var children = new HashSet <int>(); foreach (var kv in pastNodes) { children.UnionWith(kv.Value.Children); } // gathering new nodes within latest region var currentNodes = new HashSet <int>(); foreach (var n in GetRoadNetwork().GetNodesWithinRange(center, radius)) { currentNodes.Add(n.NodeID); } // only keep the nodes from newest region which intersects the previous region's children currentNodes.IntersectWith(children); // pruning children from the nodes of previous region // for each node in previous region, intersect its set of children with current nodes // if the resulting set is empty, the previous node is obsolete var obsoleteParents = new HashSet <int>(); var validParents = new HashSet <int>(); foreach (var kv in pastNodes) { var pastNode = kv.Value; pastNode.Children.IntersectWith(currentNodes); if (pastNode.Children.Count == 0) { obsoleteParents.Add(pastNode.NodeID); continue; } validParents.Add(pastNode.NodeID); } // adding all valid nodes to the latest region // Note: the first region is initialized in <see cref="Region.Update(IEnumerable{Node})"/> // var newRegion = new ConcurrentDictionary <int, RegionalNode>(); foreach (var nodeID in currentNodes) // note that current node has been cleared of all dead-end nodes { GetRoadNetwork().Nodes.TryGetValue(nodeID, out var node); var currentNode = new RegionalNode(node, validParents); newRegion.TryAdd(nodeID, currentNode); } // add newest region to the Region buffer // make sure the new region is added to buffer before pruning obsolete parents // because the pruning function needs reference to this new region MRegion.Regions.TryAdd(CurrentStep, newRegion); PruneRegions(CurrentStep - 1, obsoleteParents); ExpandPredictiveTrees(newRegion); // Populate and expand predictive trees for new region CurrentStep += 1; // increment how many steps we've received updates from }