/// <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);
        }
예제 #3
0
        /// <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);
        }
예제 #4
0
 /// <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);
 }
예제 #5
0
        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  *)
        }
예제 #6
0
        /// <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);
        }
예제 #10
0
        /// <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);
        }
예제 #11
0
        /// <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);
        }
예제 #12
0
        /// <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);
        }
예제 #13
0
 /// <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());
        }
예제 #15
0
        /// <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);
        }
예제 #16
0
 /// <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;
 }
예제 #17
0
 /// <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 };
 }
예제 #18
0
        /// <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);
        }
예제 #19
0
        /// <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);
        }