public float GetContoursSquareMeters() { if (grid.countX == 0) { return(0); } double x, y; GeoCalculator.GetDistanceInMeters(grid.west, grid.south, grid.east, grid.north, out x, out y); double xSize = x / grid.countX; double ySize = y / grid.countY; return((float)(xSize * ySize)); }
public void ComputeAndUpdateTotalLength(LineInfo[] lineInfos, int index) { currLineInspectionIndex = index; LineInfo lineInfo = lineInfos[index]; // Computations double lon1 = lineInfo.coords[0].Longitude, lat1 = lineInfo.coords[0].Latitude, lon2 = lineInfo.coords[1].Longitude, lat2 = lineInfo.coords[1].Latitude, totalLength = GeoCalculator.GetDistanceInMeters(lon1, lat1, lon2, lat2) / 1000.0; linePS[currLineInspectionIndex].totalLength = totalLength; // Update total length shown if (linePSUIRef.summaryDropdown.value == LinePS.SelectedLine) { linePSUIRef.SelectedTotalLength(linePS[currLineInspectionIndex]); } else if (linePSUIRef.summaryDropdown.value == LinePS.AllLinesCombined) { lineDO.AllCombinedTotalLength(linePS, linePSUIRef); } }
public void ComputeAndUpdateTotalLength(LineInfo[] lineInfos, int index) { currLineInspectionIndex = index; LineInfo lineInfo = lineInfos[index]; // Computations double lon1 = lineInfo.coords[0].Longitude, lat1 = lineInfo.coords[0].Latitude, lon2 = lineInfo.coords[1].Longitude, lat2 = lineInfo.coords[1].Latitude, totalLength = GeoCalculator.GetDistanceInMeters(lon1, lat1, lon2, lat2) / 1000.0; propertiesAndSummaries[currLineInspectionIndex].totalLength = totalLength; // Update total length shown if (summaryDropdown.value == SelectedLine) { SelectedLineTotalLength(); } else if (summaryDropdown.value == AllLinesCombined) { AllLinesCombinedTotalLength(); } }
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; }
// // Private Method // private void CreateRoad(List <Coordinate> points) { // Check if all points are inside of graph if (!PointsInsideGraph(points, graph)) { Debug.LogWarning("New road is not inside the graph"); return; } double kX = 1.0 / graph.cellSizeX; double kY = 1.0 / graph.cellSizeY; for (int i = 0; i < points.Count - 1; i++) { Coordinate coorStart = points[i]; Coordinate coorEnd = points[i + 1]; int startIndex = (int)((coorStart.Longitude - graph.west) * kX) + grid.countX * (int)((graph.north - coorStart.Latitude) * kY); int endIndex = (int)((coorEnd.Longitude - graph.west) * kX) + grid.countX * (int)((graph.north - coorEnd.Latitude) * kY); var startNode = new GraphNode(coorStart.Longitude, coorStart.Latitude, classification, startIndex); var endNode = new GraphNode(coorEnd.Longitude, coorEnd.Latitude, classification, endIndex); int startRow = startIndex / grid.countX; int startColumn = startIndex - startRow * grid.countX; int endRow = endIndex / grid.countX; int endColumn = endIndex - endRow * grid.countX; if (startIndex == endIndex) { if (i == 0) { AddNode(startIndex, startNode); } continue; } int countX = Math.Abs(startColumn - endColumn); int countY = Math.Abs(startRow - endRow); double k; if (countX >= countY) { k = (endNode.latitude - startNode.latitude) / (endNode.longitude - startNode.longitude); } else { k = (endNode.longitude - startNode.longitude) / (endNode.latitude - startNode.latitude); } for (int j = 0; j <= Math.Max(countY, countX); j++) { if (j == 0) // startNode { if (i == 0) { if (startNode.classifications == ClassificationValue.Highway) // 16 { // The first point is highway link startNode.classifications = ClassificationValue.HighwayLink; // 8 } AddNode(startIndex, startNode); continue; } else { continue; } } else if (j == Math.Max(countY, countX)) // endNode { GraphNode lastNode = graph.nodes[graph.nodes.Count - 1]; if ((i == points.Count - 2) && endNode.classifications == ClassificationValue.Highway) // 16 { endNode.classifications = ClassificationValue.HighwayLink; // 8 } AddNode(endIndex, endNode); var distance = (float)GeoCalculator.GetDistanceInMeters(endNode.longitude, endNode.latitude, lastNode.longitude, lastNode.latitude); GraphNode.AddLink(endNode, lastNode, distance, endNode.classifications); } else { GraphNode lastNode = graph.nodes[graph.nodes.Count - 1]; double lon; double lat; if (countX >= countY) { if (endColumn > startColumn) { lon = lastNode.longitude + graph.cellSizeX; lat = lastNode.latitude + k * graph.cellSizeX; } else { lon = lastNode.longitude - graph.cellSizeX; lat = lastNode.latitude - k * graph.cellSizeX; } } else { if (endRow < startRow) { lat = lastNode.latitude + graph.cellSizeY; lon = lastNode.longitude + k * graph.cellSizeY; } else { lat = lastNode.latitude - graph.cellSizeY; lon = lastNode.longitude - k * graph.cellSizeY; } } int index = (int)((lon - graph.west) * kX) + grid.countX * (int)((graph.north - lat) * kY); var newNode = new GraphNode(lon, lat, classification, index); var distance = (float)GeoCalculator.GetDistanceInMeters(endNode.longitude, endNode.latitude, lastNode.longitude, lastNode.latitude); AddNode(index, newNode); if (i == 0 && j == 1) { GraphNode.AddLink(endNode, lastNode, distance, ClassificationValue.HighwayLink); // 8 } else { GraphNode.AddLink(newNode, lastNode, distance, classification); } } } } }
public void CreatePotentialNetwork(GridData grid) { int existingNodeCount = nodes.Count; for (int i = grid.countX * grid.countY - 1; i >= 0; i--) { if (indexToNode.ContainsKey(i) && indexToNode.ContainsKey(-i)) // there are both highway and highway link { if (indexToNode[i].value >= ClassificationValue.HighwayLink) // 8 { CreateHighwayLink(i); } } if (grid.values[i] == ClassificationValue.None) // 0 { // Create new nodes int row = i / grid.countX; int column = i - row * grid.countX; double lonX = column * cellSizeX + west; double latY = north - row * cellSizeY; GraphNode newNode = new GraphNode(lonX, latY, 0); newNode.index = i; nodes.Add(newNode); indexToNode.Add(i, newNode); } } double x, y; GeoCalculator.GetDistanceInMeters(west, south, east, north, out x, out y); x /= grid.countX; y /= grid.countY; float distanceXY = (float)Math.Pow(x * x + y * y, 0.5); float distanceX = (float)x; float distanceY = (float)y; // create links for each new node int nodeCount = nodes.Count; for (int i = existingNodeCount; i < nodeCount; i++) { GraphNode node = nodes[i]; if (node.value == 0) { int thisIndex = node.index; int row = thisIndex / grid.countX; int column = thisIndex - row * grid.countX; if (row > 0) { int upIndex = thisIndex - grid.countX; if (indexToNode.ContainsKey(upIndex)) { GraphNode.AddLink(node, indexToNode[upIndex], distanceY, ClassificationValue.None); } } if (column > 0) // not on the left edge { int leftIndex = thisIndex - 1; if (indexToNode.ContainsKey(leftIndex)) { GraphNode.AddLink(node, indexToNode[leftIndex], distanceX, ClassificationValue.None); } } if (row < grid.countY - 1) // not on the bottom { int downIndex = thisIndex + grid.countX; if (indexToNode.ContainsKey(downIndex)) { GraphNode.AddLink(node, indexToNode[downIndex], distanceY, ClassificationValue.None); } } if (column < grid.countX - 1) { int rightIndex = thisIndex + 1; if (indexToNode.ContainsKey(rightIndex)) { GraphNode.AddLink(node, indexToNode[rightIndex], distanceX, ClassificationValue.None); } } if (row > 0 && column > 0) { int upleftIndex = thisIndex - grid.countX - 1; if (indexToNode.ContainsKey(upleftIndex)) { GraphNode.AddLink(node, indexToNode[upleftIndex], distanceXY, ClassificationValue.None); } } if (row > 0 && column < grid.countX - 1) { int uprightIndex = thisIndex - grid.countX + 1; if (indexToNode.ContainsKey(uprightIndex)) { GraphNode.AddLink(node, indexToNode[uprightIndex], distanceXY, ClassificationValue.None); } } if (row < grid.countY - 1 && column > 0) { int downleftIndex = thisIndex + grid.countX - 1; if (indexToNode.ContainsKey(downleftIndex)) { GraphNode.AddLink(node, indexToNode[downleftIndex], distanceXY, ClassificationValue.None); } } if (row < grid.countY - 1 && column < grid.countX - 1) { int downrightIndex = thisIndex + grid.countX + 1; if (indexToNode.ContainsKey(downrightIndex)) { GraphNode.AddLink(node, indexToNode[downrightIndex], distanceXY, ClassificationValue.None); } } } } }