Ejemplo n.º 1
0
        /// <summary>
        /// creates the concave hull based on the convex hull and an angle threshold
        /// </summary>
        /// <param name="pConvexEdges">edges of convex hull</param>
        /// <param name="pPoints">the point cloud data set</param>
        /// <param name="pMaxAngle">angle threshold</param>
        /// <returns>list of concave hull edges</returns>
        static List <tEdge> CreateConvaveHullFromConvexEdges(List <DefaultConvexFace <Vertex> > pConvexEdges, HashSet <Vertex> pPoints, double pMaxAngle)
        {
            //initialize arrays
            List <tEdge> convexHull = new List <tEdge>();

            foreach (var v in pConvexEdges)
            {
                convexHull.Add(new tEdge(v.Vertices[0], v.Vertices[1]));
            }
            List <tEdge> concaveHull = new List <tEdge>();

            //iterate through convex hull until concave hull is found
            while (convexHull.Count > 0)
            {
                //find longest edge in convex hull list
                tEdge longestEdge = convexHull.MaxBy(t => t.length);

                //remove longest edge from convex hull
                convexHull.Remove(longestEdge);

                //find nearest point
                List <tEdge> edges     = convexHull.Concat(concaveHull).ToList();
                tVector      nextPoint = FindPointWithSmallestAngle(pPoints, longestEdge, edges, pMaxAngle);
                if (nextPoint == null) //if no next point found
                {
                    concaveHull.Add(longestEdge);
                    continue;
                }

                //create edges based on nearest point
                tEdge e2 = new tEdge(longestEdge.v1, nextPoint.vector);
                tEdge e3 = new tEdge(longestEdge.v2, nextPoint.vector);

                //check if e2 and e3 intersect
                bool intersect = false;
                foreach (tEdge e1 in edges)
                {
                    if (Intersects(e2, e1) || Intersects(e3, e1))
                    {
                        intersect = true;
                        break;
                    }
                }

                //add e2 and e3 to List A again, if no intersection
                if (intersect == false)
                {
                    convexHull.Add(e2); convexHull.Add(e3); continue;
                }

                //if no concaviction found, add longest edge to concaveHull list
                concaveHull.Add(longestEdge);
            }

            return(concaveHull);
        }
Ejemplo n.º 2
0
        /// <summary>
        /// finds the point with the smallest angle from a given dataset towards an edge
        /// </summary>
        /// <param name="pPoints">the dataset</param>
        /// <param name="pLine">the edge to calculate the angle towards</param>
        /// <param name="pBoundaries">boundaries</param>
        /// <param name="pMaxAngle">angle threshold</param>
        /// <returns></returns>
        static tVector FindPointWithSmallestAngle(HashSet <Vertex> pPoints, tEdge pLine, List <tEdge> pBoundaries, double pMaxAngle)
        {
            tVector bestFit    = null;
            Object  lockObject = new object();

            Parallel.ForEach(pPoints, v =>
            {
                //check if point is on concave hull
                if (!IsPointOnConcaveHull(v, pBoundaries))
                {
                    //calculate new potential edges
                    tEdge t1 = new tEdge(pLine.v1, v);
                    tEdge t2 = new tEdge(pLine.v2, v);

                    //check if local maximum < edge length
                    if (t1.length < pLine.length && t2.length < pLine.length)
                    {
                        //calculate the highest angle between lines and the new point
                        double maxAngle;
                        double angleA = Math.Abs(CalculateAngleBetweenTwoLines(pLine, t1));
                        double angleB = Math.Abs(CalculateAngleBetweenTwoLines(pLine, t2));
                        if (angleA > angleB)
                        {
                            maxAngle = angleA;
                        }
                        else
                        {
                            maxAngle = angleB;
                        }

                        //check if highest angle is smaller than threshold
                        if (maxAngle < pMaxAngle)
                        {
                            //check if bestFit has been initialized
                            tVector currentFit = new tVector(v, maxAngle);
                            lock (lockObject)
                                if (bestFit == null)
                                {
                                    bestFit = currentFit;
                                }

                            //check if current point has a better fit
                            lock (lockObject)
                                if (currentFit.maxAngle < bestFit.maxAngle)
                                {
                                    bestFit = currentFit;
                                }
                        }
                    }
                }
            });

            return(bestFit);
        }