/// <summary> /// Calculating the value of the hexahedron /// </summary> /// <returns></returns> public override double GetVolume(Mesh mesh) { //returning value double ret = 0; try { LocationTimeValue[] vert = GetVertices(mesh); //Splitting up the hexahedron into six tetrahedons LocationTimeValue centerPoint = new LocationTimeValue( vert.Average(x => x.X), vert.Average(x => x.Y), vert.Average(x => x.Z) ); CreateFaces(mesh); for (int i = 0; i < 6; i++) { double height = Faces[i].PointDistanceToPlane(centerPoint.ToVector3D()); ret += (1.0 / 3.0) * height * Faces[i].GetArea(); } } catch { ret = 0; } return(ret); }
/// <summary> /// Identifies the vertice objects of the mesh /// </summary> /// <param name="mesh"></param> /// <returns></returns> public override LocationTimeValue[] GetVertices(Mesh mesh) { LocationTimeValue[] ret = new LocationTimeValue[8]; for (int i = 0; i < Vertices.Count(); i++) { ret[i] = mesh.Vertices[Vertices[i]]; } return(ret); }
/// <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> /// Specific constructor /// </summary> public LocationTimeValue(LocationTimeValue loc) { X = loc.X; Y = loc.Y; Z = loc.Z; loc.MeshIndex.CopyTo(MeshIndex, 0); Name = loc.name; Date = loc.Date; Geographic = loc.Geographic; IsActive = loc.IsActive; IsExterior = loc.IsExterior; Value = new List <double>(loc.Value); }
private static int Orientation(LocationTimeValue p1, LocationTimeValue p2, LocationTimeValue p) { // Determinant double Orin = (p2.X - p1.X) * (p.Y - p1.Y) - (p.X - p1.X) * (p2.Y - p1.Y); if (Orin > 0) { return(-1); // (* Orientation is to the left-hand side *) } if (Orin < 0) { return(1); // (* Orientation is to the right-hand side *) } return(0); // (* Orientation is neutral aka collinear *) }
/// <summary> /// Checks if the triangle shares an edge with another triangle /// </summary> /// <param name="triangle1"></param> /// <returns></returns> public bool SharesEdge(LocationTimeValue loc1, LocationTimeValue loc2) { try { if (this.Vertices.Contains(loc1) && this.Vertices.Contains(loc2)) { return(true); } } catch { } return(false); }
/// <summary> /// Calculates the volume of the tetrahedon /// </summary> /// <returns></returns> public override double GetVolume(Mesh mesh) { double ret = 0; try { LocationTimeValue[] vert = GetVertices(mesh); LocationTimeValue loc = vert.OrderByDescending(x => Faces[0].PointDistanceToPlane(x.ToVector3D())).First(); double a = Faces[0].PointDistanceToPlane(loc.ToVector3D()); ret = Faces[0].GetArea() * Faces[0].PointDistanceToPlane(loc.ToVector3D()) * (1.0 / 3.0); } catch { ret = double.NaN; } return(ret); }
/// <summary> /// Subdividing an hexahedron based on the octree-logic /// </summary> /// <returns></returns> public override async Task <ICell[]> Subdivide() { Hexahedron[] ret = new Hexahedron[8]; try { await Task.Delay(0); LocationTimeValue loc12 = new LocationTimeValue(); Hexahedron hex1 = new Hexahedron(); hex1.CellType = CellType.Hexahedron; } catch { } return(ret); }
/// <summary> /// A static class to calculate data normalization range of positive double values /// </summary> /// <param name="list"></param> /// <returns></returns> public static List <LocationTimeValue> Normalization(List <LocationTimeValue> list) { //return object List <LocationTimeValue> ret = new List <LocationTimeValue>(list); try { //Maximum values double maxItem1 = list.Max(x => x.X); double maxItem2 = list.Max(x => x.Y); double maxItem3 = list.Max(x => x.Z); //Minimum values double minItem1 = list.Min(x => x.X); double minItem2 = list.Min(x => x.Y); double minItem3 = list.Min(x => x.Z); int i = 0; foreach (LocationTimeValue val in list) { //calculating values double x = (val.X - minItem1) / (maxItem1 - minItem1); double y = (val.Y - minItem2) / (maxItem2 - minItem2); double z = (val.Z - minItem3) / (maxItem3 - minItem3); //adding to list ret[i] = new LocationTimeValue() { X = x, Y = y, Z = z }; i += 1; } } catch { } return(ret); }
/// <summary> /// Computing the 2D convex hull of a set of points /// </summary> /// <param name="P"></param> /// <returns></returns> public static IEnumerable <LocationTimeValue> ComputeConvexHull2D(List <LocationTimeValue> points) { if (points.Count() < 3) { throw new ArgumentException("At least 3 points required", "points"); } points = points.GroupBy(x => x.X).Select(x => x.First()).Distinct().ToList(); points = points.GroupBy(x => x.Y).Select(x => x.First()).Distinct().ToList(); List <LocationTimeValue> hull = new List <LocationTimeValue>(); // get leftmost point LocationTimeValue vPointOnHull = points.Where(p => p.X == points.Min(min => min.X)).First(); LocationTimeValue vEndpoint; do { hull.Add(vPointOnHull); vEndpoint = points[0]; for (int i = 1; i < points.Count; i++) { if ((vPointOnHull == vEndpoint) || (Orientation(vPointOnHull, vEndpoint, points[i]) == -1)) { vEndpoint = points[i]; } } if (hull.Count() > points.Count()) { return(new List <LocationTimeValue>()); } vPointOnHull = vEndpoint; }while (vEndpoint != hull[0]); return(hull); }
/// <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> /// Joining the meshes according to their shared position /// </summary> /// <param name="meshes"></param> /// <returns></returns> public static DataTable JoinMeshesToDataTable(List <Mesh> meshes, JoinMethod joinMethod = JoinMethod.Exact, double threshold = 0.01) { DataTable dat = new DataTable(); dat.TableName = "MultivariateDataTable"; if (meshes == null || meshes.Count() == 0) { throw new ArgumentNullException("Meshes"); } try { for (int i = 0; i < meshes.Count(); i++) { dat.Columns.Add(new DataColumn(meshes[i].Name, typeof(double))); } //Iterate through all points in mesh 0 for (int i = 0; i < meshes[0].Vertices.Count(); i++) { DataRow dr = dat.NewRow(); dr[0] = meshes[0].Vertices[i].Value[0]; if (meshes.Count() > 1) { for (int j = 1; j < meshes.Count(); j++) { double value = 0; //Searches the point, which either exactly fits to the point of mesh 0 or is the closest if (joinMethod == JoinMethod.Exact) { value = meshes[j].Vertices.FirstOrDefault(x => meshes[0].Vertices[i].X == x.X && meshes[0].Vertices[i].Y == x.Y && meshes[0].Vertices[i].Z == meshes[0].Vertices[i].Z).Value[0]; } else { LocationTimeValue loc = meshes[j].Vertices.OrderBy(x => meshes[0].Vertices[i].GetEuclideanDistance(x)).FirstOrDefault(); if (loc.GetEuclideanDistance(meshes[0].Vertices[i]) <= threshold) { value = loc.Value[0]; } else { throw new Exception("All points exceed the threshold value."); } } dr[j] = value; } } //Adding the row to the data table dat.Rows.Add(dr); } } catch { throw new Exception("Cannot join the tables"); } return(dat); }
/// <summary> /// Calculating the range of an x,y,z vector or the distance of two geographic points /// </summary> /// <param name=""></param> /// <param name=""></param> /// <param name=""></param> /// <returns></returns> public static double EuclideanDistance(LocationTimeValue point1, LocationTimeValue point2) { return(Math.Sqrt((point2.X - point1.X) * (point2.X - point1.X) + (point2.Y - point1.Y) * (point2.Y - point1.Y) + (point2.Z - point1.Z) * (point2.Z - point1.Z))); }
/// <summary> /// Builds a search ellipsoid, rotates the point set and determines, which points are contained in the search ellipsoid and which are not /// </summary> /// <param name="pointSet"></param> /// <param name="location"></param> /// <param name="distanceX"></param> /// <param name="distanceY"></param> /// <param name="distanceZ"></param> /// <param name="azimuth"></param> /// <param name="dip"></param> /// <param name="plunge"></param> /// <param name="maximumNumber"></param> /// <returns></returns> public static async Task <int[]> SearchByDistance(IEnumerable <LocationTimeValue> pointSet, LocationTimeValue location, double distanceX = 9999, double distanceY = 9999, double distanceZ = 9999, double azimuth = 0, double dip = 0, double plunge = 0, int maximumNumber = 9999, InterpolationFeature interpolationFeature = InterpolationFeature.Value) { if (pointSet.Count() == 0) { return(new int[0]); } int[] ret = new int[0]; Dictionary <int, double> distances = new Dictionary <int, double>(); List <LocationTimeValue> locs = new List <LocationTimeValue>(); lock (pointSet) { locs = new List <LocationTimeValue>(pointSet.ToList()); ret = new int[pointSet.Count()]; } //Initializing the transformation matrices double[,] transZ = GetTransformationMatrixZ(azimuth); double[,] transY = GetTransformationMatrixY(plunge); double[,] transX = GetTransformationMatrixX(dip); for (int i = 0; i < ret.Length; i++) { try { await Task.Delay(0); //Calculating the relative position of the point with regard to its rotation center double[] vec = new double[3] { Math.Abs(location.X - locs[i].X), Math.Abs(location.Y - locs[i].Y), Math.Abs(location.Z - locs[i].Z) }; //Dependent on the feature which should be interpolated, the respective distance is set to 0 switch (interpolationFeature) { case InterpolationFeature.Elevation: vec[2] = 0; break; case InterpolationFeature.Latitude: vec[1] = 0; break; case InterpolationFeature.Longitude: vec[0] = 0; break; } //Calculating the new position of the point after rotation vec = vec.Dot(transZ); vec = vec.Dot(transX); vec = vec.Dot(transY); //Searching if the point is located in the defined search ellipsoid whose center is the target point if (!IsInsideEllipse(vec, distanceX, distanceY, distanceZ) || (vec[0] == 0 && vec[1] == 0 && vec[2] == 0)) { ret[i] = -1; } else { if (maximumNumber > distances.Count() || distances.Where(x => x.Value > vec.Euclidean()) .Select(e => (KeyValuePair <int, double>?)e) .FirstOrDefault() != null) { ret[i] = i; distances.Add(i, vec.Euclidean()); if (distances.Count() > maximumNumber) { //Getting the key of the maximum value int a = distances.Aggregate((x, y) => x.Value > y.Value ? x : y).Key; ret[a] = -1; distances.Remove(a); } } else { ret[i] = -1; } } } catch { } } //returning the points return(ret.Where(x => x != -1).ToArray()); }
/// <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> /// Explicit constructor /// </summary> /// <param name="a"></param> /// <param name="b"></param> /// <param name="c"></param> public Quadrilateral(LocationTimeValue a, LocationTimeValue b, LocationTimeValue c, LocationTimeValue d) { Vertices = new LocationTimeValue[] { a, b, c, d }; FaceType = FaceType.Quadrilateral; }
/// <summary> /// Explicit constructor /// </summary> /// <param name="a"></param> /// <param name="b"></param> /// <param name="c"></param> public Triangle(LocationTimeValue a, LocationTimeValue b, LocationTimeValue c) { Vertices = new LocationTimeValue[] { a, b, c }; }
/// <summary> /// Joining the meshes according to their shared position /// </summary> /// <param name="meshes"></param> /// <returns></returns> public static Mesh JoinMeshes(List <Mesh> meshes, JoinMethod joinMethod = JoinMethod.Exact, double threshold = 0.01) { if (meshes == null || meshes.Count() == 0) { throw new ArgumentNullException("Meshes"); } Mesh ret = new Mesh(meshes[0]); try { //Iterate through all points in mesh 0 for (int i = 0; i < ret.Vertices.Count(); i++) { if (meshes.Count() > 1) { for (int j = 1; j < meshes.Count(); j++) { double value = 0; //Searches the point, which either exactly fits to the point of mesh 0 or is the closest if (joinMethod == JoinMethod.Exact) { value = meshes[j].Vertices.FirstOrDefault(x => ret.Vertices[i].X == x.X && ret.Vertices[i].Y == x.Y && ret.Vertices[i].Z == x.Z).Value[0]; } else if (joinMethod == JoinMethod.Threshold) { LocationTimeValue loc = meshes[j].Vertices.OrderBy(x => meshes[0].Vertices[i].GetEuclideanDistance(x)).FirstOrDefault(); if (loc.GetEuclideanDistance(meshes[0].Vertices[i]) <= threshold) { value = loc.Value[0]; } else { throw new Exception("All points exceed the threshold value."); } } else if (joinMethod == JoinMethod.Name) { value = meshes[j].Vertices.FirstOrDefault(x => ret.Vertices[i].Name == x.Name).Value[0]; } if (value == 0) { ret.Vertices.RemoveAt(i); i -= 1; break; } ret.Vertices[i].Value.Add(value); } } } for (int i = 0; i < meshes.Count(); i++) { ret.Properties.Add(new KeyValuePair <int, string>(i, meshes[i].Name)); } } catch { throw new Exception("Cannot join the meshes"); } return(ret); }
/// <summary> /// Checks if a polygon contains a points /// </summary> /// <param name="polygon2D"></param> /// <param name="point"></param> /// <returns></returns> public static bool ContainsXY(this IEnumerable <LocationTimeValue> polygon2D, LocationTimeValue point) { Point p1, p2; Point p = new Point(point.X, point.Y); Point[] poly = polygon2D.Select(x => new Point(x.X, x.Y)).ToArray(); bool inside = false; if (poly.Length < 3) { return(inside); } Point oldPoint = new Point(poly[poly.Length - 1].X, poly[poly.Length - 1].Y); for (int i = 0; i < poly.Length; i++) { Point newPoint = new Point(poly[i].X, poly[i].Y); if (newPoint.X > oldPoint.X) { p1 = oldPoint; p2 = newPoint; } else { p1 = newPoint; p2 = oldPoint; } if ((newPoint.X < p.X) == (p.X <= oldPoint.X) && ((long)p.Y - (long)p1.Y) * (long)(p2.X - p1.X) <= ((long)p2.Y - (long)p1.Y) * (long)(p.X - p1.X)) { inside = !inside; } oldPoint = newPoint; } return(inside); }