/// <summary> /// Calculating the Dijkstra distance /// </summary> /// <returns></returns> public double GetAstarDistance(LocationTimeValue a, LocationTimeValue b, Mesh mesh) { double ret = 0; try { TemporalMesh = new Mesh(mesh); End = TemporalMesh.Vertices.OrderBy(x => GeographyHelper.EuclideanDistance(b, x)).First(); for (int i = 0; i < TemporalMesh.Vertices.Count(); i++) { //Preparing the mesh for distance storage if (TemporalMesh.Vertices[i].Value.Count() == 1) { TemporalMesh.Vertices[i].Value.Add(0); } else if (TemporalMesh.Vertices[i].Value.Count() == 0) { TemporalMesh.Vertices[i].Value.AddRange(new List <double>() { 0, 0 }); } //Initializing the distances TemporalMesh.Vertices[i].Value[0] = double.PositiveInfinity; TemporalMesh.Vertices[i].Value[1] = End.GetEuclideanDistance(TemporalMesh.Vertices[i]); TemporalMesh.Vertices[i].Neighbors = new List <LocationTimeValue>(); TemporalMesh.Vertices[i].IsActive = false; } Start = TemporalMesh.Vertices.OrderBy(x => GeographyHelper.EuclideanDistance(a, x)).First(); Start.Value[0] = 0; End = TemporalMesh.Vertices.OrderBy(x => GeographyHelper.EuclideanDistance(b, x)).First(); if (Start.GetEuclideanDistance(End) == 0) { return(0); } //Building the shortest path BuildShortestPathAstar(); ret = ShortestPathCost; } catch { } return(ret); }
/// <summary> /// Building the shortest path /// </summary> /// <param name="list"></param> /// <param name="node"></param> private void BuildShortestPath(List <LocationTimeValue> list, LocationTimeValue node) { if (node.Neighbors.Count() == 0) { return; } LocationTimeValue nearestNeighbor = node.Neighbors.Where(x => x.Neighbors.Count > 0).First(); list.Add(nearestNeighbor); ShortestPathLength += GeographyHelper.EuclideanDistance(nearestNeighbor, node); ShortestPathCost += GeographyHelper.EuclideanDistance(nearestNeighbor, node); nearestNeighbor.Neighbors.Remove(node); if (nearestNeighbor.Equals(Start)) { return; } BuildShortestPath(list, nearestNeighbor); }
/// <summary> /// Converts a hexahedron to a list of tetrahedons /// </summary> /// <returns></returns> public List <Cell> ToTetrahedons(Mesh mesh) { //return object List <Cell> ret = new List <Cell>(); try { LocationTimeValue[] vert = GetVertices(mesh); CreateFaces(mesh); LocationTimeValue loc1 = vert[0]; LocationTimeValue loc2 = vert.OrderByDescending(x => GeographyHelper.EuclideanDistance(x, loc1)).First(); for (int i = 0; i < Faces.Count(); i++) { Faces[i].Vertices.OrderBy(x => GeographyHelper.EuclideanDistance(x, Faces[i].Vertices[0])); Tetrahedron tet = new Tetrahedron(); tet.Vertices = new List <int>() { mesh.Vertices.IndexOf(Faces[i].Vertices[0]), mesh.Vertices.IndexOf(Faces[i].Vertices[1]), mesh.Vertices.IndexOf(Faces[i].Vertices[2]) }; if (Faces[i].Vertices.Contains(loc1)) { tet.Vertices.Add(mesh.Vertices.IndexOf(loc2)); } else { tet.Vertices.Add(mesh.Vertices.IndexOf(loc1)); } tet.CreateFaces(mesh); tet = new Tetrahedron(); tet.Vertices = new List <int>() { mesh.Vertices.IndexOf(Faces[i].Vertices[3]), mesh.Vertices.IndexOf(Faces[i].Vertices[1]), mesh.Vertices.IndexOf(Faces[i].Vertices[2]) }; if (Faces[i].Vertices.Contains(loc1)) { tet.Vertices.Add(mesh.Vertices.IndexOf(loc2)); } else { tet.Vertices.Add(mesh.Vertices.IndexOf(loc1)); } tet.CreateFaces(mesh); ret.Add(tet); } } catch { ret = new List <Cell>(); } return(ret); }
/// <summary> /// Computing the IDW data matrix /// </summary> public void ComputeIDW() { if (OriginalLocationValues.Count < 1) { DiscretizedLocationValues = new List <LocationTimeValue <double> >(); DiscretizedLocationVariance = new List <LocationTimeValue <double> >(); } List <LocationTimeValue <double> > ret = new List <LocationTimeValue <double> >(); double rmseSum = 0; try { //Doing discretization if not done yet if (!OriginalLocationValues.First().IsDiscretized) { DiscretizedLocationValues = new List <LocationTimeValue <double> >(); DiscretizedLocationVariance = new List <LocationTimeValue <double> >(); DiscretizeOriginalLocalLocationValuesIntoRegularGrid(); } for (int i = 0; i < DiscretizedLocationValues.Count(); i++) { double value = 0; double weightSum = 0; //Calculating IDW values for (int j = 0; j < OriginalLocationValues.Count(); j++) { double dist = GeographyHelper.EuclideanDistance(DiscretizedLocationValues[i].X - OriginalLocationValues[j].X, DiscretizedLocationValues[i].Y - OriginalLocationValues[j].Y, DiscretizedLocationValues[i].Z - OriginalLocationValues[j].Z, false); if (dist != 0) { //Summing up the weights weightSum += 1 / Math.Pow(dist, Power); //Increasing the value by the constrain value and it's weight value += Convert.ToDouble(OriginalLocationValues[j].Value) / Math.Pow(dist, Power); } else { value = OriginalLocationValues[j].Value; break; } } DiscretizedLocationValues[i].Value = value / weightSum; } //Calculating the RMSE for (int i = 0; i < OriginalLocationValues.Count(); i++) { double weightSum = 0; double value = 0; for (int j = 0; j < OriginalLocationValues.Count(); j++) { if (i != j) { double dist = GeographyHelper.EuclideanDistance(DiscretizedLocationValues[i].X - OriginalLocationValues[j].X, DiscretizedLocationValues[i].Y - OriginalLocationValues[j].Y, DiscretizedLocationValues[i].Z - OriginalLocationValues[j].Z, false); if (dist != 0) { weightSum += 1 / Math.Pow(dist, Power); value += Convert.ToDouble(OriginalLocationValues[j].Value) / Math.Pow(dist, Power); } else { continue; } } } rmseSum += Math.Abs(Math.Pow(OriginalLocationValues[i].Value - (value / weightSum), 2)); } RMSE = Math.Sqrt(rmseSum / OriginalLocationValues.Count()); } catch { } }
/// <summary> /// Triangulates a surface /// </summary> /// <param name="points"></param> /// <returns></returns> public List <Face> TriangulateSurface(List <LocationTimeValue> inputVertices) { List <Face> mesh = new List <Face>(); try { // Important! Sort the list so that points sweep from left - right inputVertices.Sort(); SqlGeometry MultiPoint = inputVertices.ToSqlGeometry(); // Calculate the "supertriangle" that encompasses the pointset SqlGeometry Envelope = MultiPoint.STEnvelope(); // Width double dx = (double)(Envelope.STPointN(2).STX - Envelope.STPointN(1).STX); // Height double dy = (double)(Envelope.STPointN(4).STY - Envelope.STPointN(1).STY); // Maximum dimension double dmax = (dx > dy) ? dx : dy; // Centre double avgx = (double)Envelope.STCentroid().STX; double avgy = (double)Envelope.STCentroid().STY; // Create the points at corners of the supertriangle LocationTimeValue a = new LocationTimeValue(avgx - 2 * dmax, avgy - dmax); LocationTimeValue b = new LocationTimeValue(avgx + 2 * dmax, avgy - dmax); LocationTimeValue c = new LocationTimeValue(avgx, avgy + 2 * dmax); Triangle superTriangle = new Triangle(a, b, c); List <Triangle> Triangles = new List <Triangle>(); Triangles.Add(superTriangle); // Loop through each point Parallel.For(0, inputVertices.Count(), i => { // Initialise the edge buffer List <LocationTimeValue[]> Edges = new List <LocationTimeValue[]>(); try { // Loop through each triangle for (int j = Triangles.Count - 1; j >= 0; j--) { // If the point lies within the circumcircle of this triangle if (GeographyHelper.EuclideanDistance(Triangles[j].GetCircumCentre(), inputVertices[i]) <= Triangles[j].GetRadius()) { // Add the triangle edges to the edge buffer Edges.Add(new LocationTimeValue[] { Triangles[j].Vertices[0], Triangles[j].Vertices[1] }); Edges.Add(new LocationTimeValue[] { Triangles[j].Vertices[1], Triangles[j].Vertices[2] }); Edges.Add(new LocationTimeValue[] { Triangles[j].Vertices[2], Triangles[j].Vertices[0] }); // Remove this triangle from the list Triangles.RemoveAt(j); } // If this triangle is complete else if (inputVertices[i].X >= Triangles[j].GetCircumCentre().X + Triangles[j].GetRadius()) { mesh.Add(Triangles[j]); Triangles.RemoveAt(j); } } // Remove duplicate edges for (int j = Edges.Count - 1; j > 0; j--) { for (int k = j - 1; k >= 0; k--) { // Compare if this edge match in either direction if (Edges[j][0].Equals(Edges[k][1]) && Edges[j][1].Equals(Edges[k][0])) { // Remove both duplicates Edges.RemoveAt(j); Edges.RemoveAt(k); // We've removed an item from lower down the list than where j is now, so update j j--; break; } } } // Create new triangles for the current point for (int j = 0; j < Edges.Count; j++) { Triangle T = new Triangle(Edges[j][0], Edges[j][1], inputVertices[i]); Triangles.Add(T); } } catch { } }); mesh.AddRange(Triangles); int count = mesh.Count(); //We've finished triangulation. Move any remaining triangles onto the completed list for (int i = 0; i < count; i++) { if (mesh[i].Vertices.Any(x => superTriangle.Vertices.Contains(x))) { mesh.RemoveAt(i); count--; i--; } } } catch { } return(mesh); }
/// <summary> /// Performing a A* search /// </summary> private void AstarSearch() { NodeVisits = 0; //Initializing priority queue var prioQueue = new List <LocationTimeValue>(); //Adding start point to the queue prioQueue.Add(Start); //Filling priority queue and iterating through it until break conditions are met do { NodeVisits++; //Order points by distance to start prioQueue = prioQueue.OrderBy(x => x.Value[0] + x.Value[1]).ToList(); var node = prioQueue.First(); prioQueue.Remove(node); //Getting the neighbors of the node var neighbors = TemporalMesh.GetNeighbors(node).Result.OrderBy(x => GeographyHelper.EuclideanDistance(x, node)).ToList(); //Iterating over the neighbors and detect which one has the lowest distance to the node for (int i = 0; i < neighbors.Count(); i++) { //Check that the point does not equals the node where we came from if (node.Neighbors.Count > 0) { if (neighbors[i].Equals(node.Neighbors.First())) { continue; } } //Determining the euclidean distance to the neighbor double dist = GeographyHelper.EuclideanDistance(neighbors[i], node); neighbors[i].Value[0] = node.Value[0] + dist; if (neighbors[i].Neighbors.Count == 0 || !neighbors.Where(x => !x.Equals(node)).Any(x => x.Value[0] < neighbors[i].Value[0])) { //Setting the node as a neighbor neighbors[i].Neighbors.Clear(); neighbors[i].Neighbors.Add(node); //If the node equals the end, we reached our aim if (node.Equals(End)) { return; } //Adding node to the priority queue if (!prioQueue.Contains(neighbors[i])) { prioQueue.Add(neighbors[i]); } } } //"Deactivating" the node that it will not be used again node.IsActive = true; } while (prioQueue.Any()); }