Exemplo n.º 1
0
        public void Test_Includeness()
        {
            var hash = new HashSet <(int, int)>();

            for (var numberOfTests = 0; numberOfTests < 10; ++numberOfTests)
            {
                var numberOfPoints = 20 + numberOfTests * 10;
                var arr            = new PointD2DAnnotated[numberOfPoints];

                hash.Clear();
                for (var i = 0; i < numberOfPoints;)
                {
                    var x = _random.Next(-1000, 1000);
                    var y = _random.Next(-1000, 1000);

                    if (!hash.Contains((x, y)))
                    {
                        hash.Add((x, y));
                        arr[i] = new PointD2DAnnotated(x, y, i);
                        ++i;
                    }
                }

                for (double concaveness = 1; concaveness >= -1; concaveness -= 1 / 16.0)
                {
                    var concaveCalc = new ConcaveHull(arr, concaveness, 100, true);

                    IncludenessTest(concaveCalc.ConvexHullPoints, arr);
                    IncludenessTest(concaveCalc.ConcaveHullPoints, arr);
                }
            }
        }
Exemplo n.º 2
0
            public static double GetDistance(PointD2DAnnotated node1, PointD2DAnnotated node2)
            {
                var dx = node1.X - node2.X;
                var dy = node1.Y - node2.Y;

                return(Math.Sqrt(dx * dx + dy * dy));
            }
Exemplo n.º 3
0
        public void Test_Includeness()
        {
            var hash = new HashSet <(int, int)>();

            for (var numberOfTests = 0; numberOfTests < 100; ++numberOfTests)
            {
                var numberOfPoints = 20 + numberOfTests * 10;
                var arr            = new PointD2DAnnotated[numberOfPoints];

                hash.Clear();
                for (var i = 0; i < numberOfPoints;)
                {
                    var x = _random.Next(-1000, 1000);
                    var y = _random.Next(-1000, 1000);

                    if (!hash.Contains((x, y)))
                    {
                        hash.Add((x, y));
                        arr[i] = new PointD2DAnnotated(x, y, i);
                        ++i;
                    }
                }

                var convexHull = GrahamScan.GetConvexHull(arr);

                IncludenessTest(convexHull, arr);
            }
        }
Exemplo n.º 4
0
        private static double GetAngle(PointD2DAnnotated p1, PointD2DAnnotated p2)
        {
            var xDiff = p2.X - p1.X;
            var yDiff = p2.Y - p1.Y;

            return(Math.Atan2(yDiff, xDiff) * 180.0 / Math.PI);
        }
Exemplo n.º 5
0
        private static double getCos(PointD2DAnnotated a, PointD2DAnnotated b, PointD2DAnnotated o)
        {
            /* Law of cosines */
            var aPow2 = Pow2(a.X - o.X) + Pow2(a.Y - o.Y);
            var bPow2 = Pow2(b.X - o.X) + Pow2(b.Y - o.Y);
            var cPow2 = Pow2(a.X - b.X) + Pow2(a.Y - b.Y);

            return(Math.Round((aPow2 + bPow2 - cPow2) / (2 * Math.Sqrt(aPow2 * bPow2)), 4));
        }
Exemplo n.º 6
0
 private static void KeepLeft(List <PointD2DAnnotated> hull, PointD2DAnnotated r)
 {
     while (hull.Count > 1 && Turn(hull[hull.Count - 2], hull[hull.Count - 1], r) != TURN_LEFT)
     {
         hull.RemoveAt(hull.Count - 1);
     }
     if (hull.Count == 0 || hull[hull.Count - 1].ID != r.ID)
     {
         hull.Add(r);
     }
 }
Exemplo n.º 7
0
        /// <summary>
        /// Gets the convex hull of a set of points
        /// </summary>
        /// <param name="points">The points.</param>
        /// <returns>The ordered set of points that forms the hull.</returns>
        public static IReadOnlyList <PointD2DAnnotated> GetConvexHull(IEnumerable <PointD2DAnnotated> points)
        {
            PointD2DAnnotated p0  = default;
            var is_p0_initialized = false;

            foreach (var value in points)
            {
                if (!is_p0_initialized)
                {
                    p0 = value;
                    is_p0_initialized = true;
                }
                else
                {
                    if (p0.Y > value.Y)
                    {
                        p0 = value;
                    }
                }
            }

            if (!is_p0_initialized)
            {
                throw new ArgumentException("Enumeration is empty", nameof(points));
            }

            var order = new List <PointD2DAnnotated>();

            foreach (var value in points)
            {
                if (p0.ID != value.ID)
                {
                    order.Add(value);
                }
            }

            order = MergeSort(p0, order);
            var result = new List <PointD2DAnnotated>
            {
                p0,
                order[0],
                order[1]
            };

            order.RemoveAt(0);
            order.RemoveAt(0);
            foreach (var value in order)
            {
                KeepLeft(result, value);
            }
            return(result);
        }
Exemplo n.º 8
0
        private static bool tangentToHull(LineD2DAnnotated line_treated, PointD2DAnnotated node, double cos1, double cos2, List <LineD2DAnnotated> concave_hull)
        {
            /* A new middlepoint could (rarely) make a segment that's tangent to the hull.
             * This method detects these situations
             * I suggest turning this method of if you are not using square grids or if you have a high dot density
             * */
            var               isTangent = false;
            double            current_cos1;
            double            current_cos2;
            double            edge_length;
            var               nodes_searched = new List <int>();
            LineD2DAnnotated  line;
            PointD2DAnnotated node_in_hull;
            var               count_line = 0;
            var               count_node = 0;

            edge_length = LineD2DAnnotated.GetDistance(node, line_treated.P0) + LineD2DAnnotated.GetDistance(node, line_treated.P1);


            while (!isTangent && count_line < concave_hull.Count)
            {
                line = concave_hull[count_line];
                while (!isTangent && count_node < 2)
                {
                    node_in_hull = line[count_node];
                    if (!nodes_searched.Contains(node_in_hull.ID))
                    {
                        if (node_in_hull.ID != line_treated.P0.ID && node_in_hull.ID != line_treated.P1.ID)
                        {
                            current_cos1 = getCos(node_in_hull, line_treated.P0, line_treated.P1);
                            current_cos2 = getCos(node_in_hull, line_treated.P1, line_treated.P0);
                            if (current_cos1 == cos1 || current_cos2 == cos2)
                            {
                                isTangent = (LineD2DAnnotated.GetDistance(node_in_hull, line_treated.P0) + LineD2DAnnotated.GetDistance(node_in_hull, line_treated.P1) < edge_length);
                            }
                        }
                    }
                    nodes_searched.Add(node_in_hull.ID);
                    count_node++;
                }
                count_node = 0;
                count_line++;
            }
            return(isTangent);
        }
Exemplo n.º 9
0
        private static List <PointD2DAnnotated> MergeSort(PointD2DAnnotated p0, List <PointD2DAnnotated> arrPoint)
        {
            if (arrPoint.Count == 1)
            {
                return(arrPoint);
            }
            var arrSortedInt = new List <PointD2DAnnotated>();
            var middle       = arrPoint.Count / 2;
            var leftArray    = arrPoint.GetRange(0, middle);
            var rightArray   = arrPoint.GetRange(middle, arrPoint.Count - middle);

            leftArray  = MergeSort(p0, leftArray);
            rightArray = MergeSort(p0, rightArray);
            var leftptr  = 0;
            var rightptr = 0;

            for (var i = 0; i < leftArray.Count + rightArray.Count; i++)
            {
                if (leftptr == leftArray.Count)
                {
                    arrSortedInt.Add(rightArray[rightptr]);
                    rightptr++;
                }
                else if (rightptr == rightArray.Count)
                {
                    arrSortedInt.Add(leftArray[leftptr]);
                    leftptr++;
                }
                else if (GetAngle(p0, leftArray[leftptr]) < GetAngle(p0, rightArray[rightptr]))
                {
                    arrSortedInt.Add(leftArray[leftptr]);
                    leftptr++;
                }
                else
                {
                    arrSortedInt.Add(rightArray[rightptr]);
                    rightptr++;
                }
            }
            return(arrSortedInt);
        }
Exemplo n.º 10
0
        private static PointD2DAnnotated[] getHullNearbyNodes(LineD2DAnnotated line, List <LineD2DAnnotated> concave_hull)
        {
            /* Return previous and next nodes to a line in the hull */
            var nearbyHullNodes = new PointD2DAnnotated[2];
            var leftNodeID      = line.P0.ID;
            var rightNodeID     = line.P1.ID;
            int currentID;
            var nodesFound        = 0;
            var line_count        = 0;
            var position          = 0;
            var opposite_position = 1;

            while (nodesFound < 2)
            {
                position          = 0;
                opposite_position = 1;
                while (position < 2)
                {
                    currentID = concave_hull[line_count][position].ID;
                    if (currentID == leftNodeID &&
                        concave_hull[line_count][opposite_position].ID != rightNodeID)
                    {
                        nearbyHullNodes[0] = concave_hull[line_count][opposite_position];
                        nodesFound++;
                    }
                    else if (currentID == rightNodeID &&
                             concave_hull[line_count][opposite_position].ID != leftNodeID)
                    {
                        nearbyHullNodes[1] = concave_hull[line_count][opposite_position];
                        nodesFound++;
                    }
                    position++;
                    opposite_position--;
                }
                line_count++;
            }
            return(nearbyHullNodes);
        }
Exemplo n.º 11
0
 public LineD2DAnnotated(PointD2DAnnotated p0, PointD2DAnnotated p1)
 {
     P0 = p0;
     P1 = p1;
 }
Exemplo n.º 12
0
 private static int Turn(PointD2DAnnotated p, PointD2DAnnotated q, PointD2DAnnotated r)
 {
     return(((q.X - p.X) * (r.Y - p.Y) - (r.X - p.X) * (q.Y - p.Y)).CompareTo(0));
 }