예제 #1
0
    private bool GetGridDataValue(GraphPatch graphPatch, Coordinate coords, out string cellValue)
    {
        var gridData = graphPatch.grid;

        if (gridData.values != null && gridData.IsInside(coords.Longitude, coords.Latitude))
        {
            int classification = (int)gridData.GetValue(coords.Longitude, coords.Latitude);
            if (classification == 0)
            {
                cellValue = "None";
            }
            else
            {
                cellValue = "";
                var classificationNames = Enum.GetNames(typeof(ClassificationIndex));
                for (int i = 1, k = 1; i < (int)ClassificationIndex.Count; i++, k *= 2)
                {
                    if ((classification & k) != 0)
                    {
                        cellValue += classificationNames[i] + ", ";
                    }
                }
                cellValue = cellValue.Remove(cellValue.Length - 2);
            }
            return(true);
        }
        cellValue = "N/A";
        return(false);
    }
예제 #2
0
    //
    // Public Method
    //

    public void Init(GraphPatch networkPatch, GridPatch reachabilityPatch, float[] minutesPerMeter, float travelTime)
    {
        this.networkPatch      = networkPatch;
        this.reachabilityPatch = reachabilityPatch;
        this.map = ComponentManager.Instance.Get <MapController>();

        SetMinutesPerMeter(minutesPerMeter);
        SetTravelTime(travelTime);
    }
예제 #3
0
    private void CreateReachabilityPatch(GraphPatch graphPatch)
    {
        GridData grid = new GridData(graphPatch.grid, false);

        grid.InitGridValues();
        grid.minValue  = 0;
        grid.maxValue  = traveTimeSlider.value * travelTimeScale;
        grid.minFilter = grid.maxFilter = 0;
        grid.metadata  = null;

        reachabilityPatch = reachabilityLayer.CreateGridPatch(graphPatch.GetSiteName(), graphPatch.Level, DateTime.Now.Year, grid);
        dataLayers.UpdateLayer(reachabilityLayer);
    }
예제 #4
0
    private void ResetTool(bool turnOff)
    {
        editSpeedToggle.isOn = false;

        // Disable layers visibility event
        dataLayers.OnLayerVisibilityChange -= OnLayerVisibilityChange;

        // Clear layers dropdown
        if (!turnOff)
        {
            layerDropdown.ClearOptions();
        }

        ClearAllUserChanges();

        // Deactivate layers
        if (networkLayer != null)
        {
            // Disable patches visibility events
            networkLayer.OnPatchVisibilityChange -= OnPatchVisibilityChange;
            if (turnOff && dataLayers.IsLayerActive(networkLayer))
            {
                dataLayers.ActivateLayer(networkLayer, false);
            }
        }
        if (reachabilityLayer != null)
        {
            reachabilityLayer.OnPatchVisibilityChange -= OnPatchVisibilityChange;
            if (turnOff && dataLayers.IsLayerActive(reachabilityLayer))
            {
                dataLayers.ActivateLayer(reachabilityLayer, false);
            }
        }

        newRoadPanel.SetActive(false);
        mainPanel.SetActive(true);

        // Reset path references
        networkPatch      = null;
        reachabilityPatch = null;

        ResetErrorMessage();
        movedAwayError        = false;
        deactivatedLayerError = false;

        // Re-enable layers visibility event
        dataLayers.OnLayerVisibilityChange += OnLayerVisibilityChange;
    }
예제 #5
0
    //
    // Public Method
    //

    public void Init(GraphPatch patch, int classification, List <Coordinate> points)
    {
        graph = new GraphData();
        this.classification = classification;

        GraphData g = patch.graph;

        graph.cellSizeX = g.cellSizeX;
        graph.cellSizeY = g.cellSizeY;
        graph.west      = g.west;
        graph.east      = g.east;
        graph.north     = g.north;
        graph.south     = g.south;

        grid = new GridData(patch.grid, false);

        SetPoints(points);
    }
예제 #6
0
    private void SetNetworkPatch(GraphPatch patch)
    {
        networkPatch = patch;

        if (placeStart != null)
        {
            placeStart.NetworkPatch = networkPatch;
        }

        if (patch == null)
        {
            ClearAllUserChanges();
            return;
        }

        var bounds = map.MapCoordBounds;

        if (!reachabilityLayer.HasPatches(siteBrowser.ActiveSite, map.CurrentLevel, bounds.west, bounds.east, bounds.north, bounds.south))
        {
            CreateReachabilityPatch(patch);
        }

        if (!dataLayers.IsLayerActive(reachabilityLayer))
        {
            dataLayers.ActivateLayer(reachabilityLayer, true);
        }

        if (placeStart != null)
        {
            placeStart.ReachabilityPatch = reachabilityPatch;
        }

        // Hide Loading Message
        if (!HasErrorMessage)
        {
            HideMessage();
        }
    }
예제 #7
0
    private IEnumerator Traverse(int countPerFrame)
    {
        GraphPatch graphPatch = networkPatch;
        GraphData  graph      = graphPatch.graph;
        GridData   grid       = reachabilityPatch.grid;

        // Initialize the grid values and the node costs to infinite
        PrepareGrid();

        yield return(null);

        // Prepare the starting cells/nodes
        var nodes    = new Queue <int>();
        var nodesSet = new HashSet <int>();

        foreach (var coord in startPoints)
        {
            // For each point find its grid index
            var startIndex = networkPatch.GetIndex(coord.Longitude, coord.Latitude);

            // Check if highway node is available and we're allowed to be on it
            if (graph.indexToNode.TryGetValue(-startIndex, out GraphNode highwayNode) &&
                classificationToMinutesPerMeter[highwayNode.classifications] > 0)
            {
                startIndex = -startIndex;
            }

            // Snap to the nearest network node?
            if (SnapToNetwork)
            {
                if (startIndex > 0 && !graph.indexToNode.ContainsKey(startIndex))
                {
                    FindClosestNode(coord.Longitude, coord.Latitude, ref startIndex);
                    yield return(null);
                }
            }

            // Initialize the cell value and node cost
            int gridIndex = Math.Abs(startIndex);
            grid.values[gridIndex]     = 0f;
            grid.valuesMask[gridIndex] = 1;
            if (graph.indexToNode.TryGetValue(startIndex, out GraphNode first))
            {
                first.cost = 0;
            }

            nodes.Enqueue(startIndex);
            nodesSet.Add(startIndex);
        }

        // Prepare data for off-grid computation
        GeoCalculator.GetDistanceInMeters(grid.west, grid.south, grid.east, grid.north, out double cellSizeX, out double cellSizeY);
        cellSizeX /= grid.countX;
        cellSizeY /= grid.countY;
        float distanceXY = (float)Math.Sqrt(cellSizeX * cellSizeX + cellSizeY * cellSizeY);
        float distanceX  = (float)cellSizeX;
        float distanceY  = (float)cellSizeY;
        int   lastIndexX = grid.countX - 1;
        int   lastIndexY = grid.countY - 1;

        var visitedNeighbours = new bool[8];
        var indexToOffsetMap  = new int[8]
        {
            -grid.countX - 1,
            -grid.countX,
            -grid.countX + 1,
            -1,
            +1,
            grid.countX - 1,
            grid.countX,
            grid.countX + 1,
        };
        var offsetToIndexMap = new Dictionary <int, int>()
        {
            { -grid.countX - 1, 0 },
            { -grid.countX, 1 },
            { -grid.countX + 1, 2 },
            { -1, 3 },
            { +1, 4 },
            { grid.countX - 1, 5 },
            { grid.countX, 6 },
            { grid.countX + 1, 7 }
        };
        var linkDistances = new float[8]
        {
            distanceXY,
            distanceY,
            distanceXY,
            distanceX,
            distanceX,
            distanceXY,
            distanceY,
            distanceXY,
        };
        float invWalkingSpeed = classificationToMinutesPerMeter[0];


        int count = 0;
        int nodeIndex, neighbourIndex;
        var overlapedLink = new HashSet <int>();

        // Start going thru the nodes
        while (nodes.Count > 0)
        {
            nodeIndex = nodes.Dequeue();
            nodesSet.Remove(nodeIndex);

            // Check if it's a node. It could be an empty cell when going off-track
            if (graph.indexToNode.TryGetValue(nodeIndex, out GraphNode node))
            {
                nodeIndex = Math.Abs(node.index);

                overlapedLink.Clear();

                for (int k = 0; k < newRoads.Count; k++)
                {
                    var newGraph = newRoads[k].graph;

                    // if the node is overlapped by new road
                    if (newRoads[k].graph.indexToNode.ContainsKey(nodeIndex))
                    {
                        var newNode = newGraph.indexToNode[nodeIndex];

                        for (int i = newNode.links.Count - 1; i >= 0; i--)
                        {
                            neighbourIndex = Math.Abs(newNode.links[i].index);
                            overlapedLink.Add(neighbourIndex);

                            if (!graph.indexToNode.ContainsKey(neighbourIndex))
                            {
                                neighbourIndex = -neighbourIndex;
                            }

                            var neighbour = graph.indexToNode[neighbourIndex];

                            // Calculate time: cost (minutes) = distance (meters) / speed (meters/minute)
                            float invSpeed = classificationToMinutesPerMeter[newNode.linkClassifications[i]];
                            float cost     = newNode.linkDistances[i] * invSpeed + node.cost;

                            if (cost < neighbour.cost && cost <= grid.maxFilter)
                            {
                                neighbour.cost = cost;
                                grid.values[neighbourIndex]     = Math.Min(cost, grid.values[neighbourIndex]);
                                grid.valuesMask[neighbourIndex] = 1;

                                if (!nodesSet.Contains(neighbour.index))
                                {
                                    nodes.Enqueue(neighbour.index);
                                    nodesSet.Add(neighbour.index);
                                }

                                count++;
                            }
                        }
                    }
                }

                for (int i = node.links.Count - 1; i >= 0; i--)
                {
                    var neighbour = node.links[i];
                    neighbourIndex = Math.Abs(neighbour.index);

                    var indexOffset = neighbourIndex - nodeIndex;
                    var idx         = offsetToIndexMap[indexOffset];
                    visitedNeighbours[idx] = true;

                    if (overlapedLink.Contains(neighbourIndex))
                    {
                        continue;
                    }

                    // Calculate time: cost (minutes) = distance (meters) / speed (meters/minute)
                    float invSpeed = classificationToMinutesPerMeter[node.linkClassifications[i]];
                    float cost     = node.linkDistances[i] * invSpeed + node.cost;
                    if (cost < neighbour.cost && cost <= travelTime)
                    {
                        neighbour.cost = cost;
                        // Note: a cell may have 2 nodes (e.g. primary + highway). Therefore we need to check the min value
                        grid.values[neighbourIndex]     = cost < grid.values[neighbourIndex]? cost : grid.values[neighbourIndex];
                        grid.valuesMask[neighbourIndex] = 1;

                        if (!nodesSet.Contains(neighbour.index))
                        {
                            nodes.Enqueue(neighbour.index);
                            nodesSet.Add(neighbour.index);
                        }

                        count++;
                    }
                }
            }

            // Calculate off-track
            if (node == null || node.classifications < ClassificationValue.HighwayLink)
            {
                int   nodeY    = nodeIndex / grid.countX;
                int   nodeX    = nodeIndex - nodeY * grid.countX;
                float nodeCost = node == null? grid.values[nodeIndex] : node.cost;

                // Check non-visited neighbours
                for (int i = 0; i < 8; ++i)
                {
                    if (!visitedNeighbours[i])
                    {
                        int x = nodeX + indexToOffsetXMap[i];
                        int y = nodeY + indexToOffsetYMap[i];
                        if (x < 0 || y < 0 || x > lastIndexX || y > lastIndexY)
                        {
                            continue;
                        }

                        neighbourIndex = nodeIndex + indexToOffsetMap[i];

                        // Calculate time: cost (minutes) = distance (meters) / speed (meters/minute)
                        float cost = linkDistances[i] * invWalkingSpeed + nodeCost;
                        if (cost < grid.values[neighbourIndex] && cost <= travelTime)
                        {
                            bool valid = false;
                            if (graph.indexToNode.TryGetValue(neighbourIndex, out GraphNode neighbour))
                            {
                                if (neighbour.classifications < ClassificationValue.HighwayLink)
                                {
                                    neighbour.cost = cost;
                                    valid          = true;
                                }
                            }
                            else
                            {
                                valid = true;
                            }

                            if (valid)
                            {
                                grid.values[neighbourIndex]     = cost;
                                grid.valuesMask[neighbourIndex] = 1;
                                if (!nodesSet.Contains(neighbourIndex))
                                {
                                    nodes.Enqueue(neighbourIndex);
                                    nodesSet.Add(neighbourIndex);
                                }
                            }

                            count++;
                        }
                    }
                    else
                    {
                        visitedNeighbours[i] = false;
                    }
                }
            }

            if (count > countPerFrame)
            {
                count = 0;
                grid.ValuesChanged();
                yield return(null);
            }
        }

        yield return(null);

        CommitPatchChanges();

        gridGeneration = null;
    }