Esempio n. 1
0
        private void ComputeCirclePoints()
        {
            Coordinate[] pts;
            // handle degenerate or trivial cases
            if (_input.IsEmpty)
            {
                _extremalPts = new Coordinate[0];
                return;
            }
            if (_input.NumPoints == 1)
            {
                pts          = _input.Coordinates;
                _extremalPts = new[] { pts[0].Copy() };
                return;
            }

            /**
             * The problem is simplified by reducing to the convex hull.
             * Computing the convex hull also has the useful effect of eliminating duplicate points
             */
            var convexHull = _input.ConvexHull();

            // check for degenerate or trivial cases
            var hullPts = convexHull.Coordinates;

            // strip duplicate final point, if any
            pts = hullPts;
            if (hullPts[0].Equals2D(hullPts[hullPts.Length - 1]))
            {
                pts = new Coordinate[hullPts.Length - 1];
                CoordinateArrays.CopyDeep(hullPts, 0, pts, 0, hullPts.Length - 1);
            }

            /**
             * Optimization for the trivial case where the CH has fewer than 3 points
             */
            if (pts.Length <= 2)
            {
                _extremalPts = CoordinateArrays.CopyDeep(pts);
                return;
            }

            // find a point P with minimum Y ordinate
            var P = LowestPoint(pts);

            // find a point Q such that the angle that PQ makes with the x-axis is minimal
            var Q = PointWitMinAngleWithX(pts, P);

            /**
             * Iterate over the remaining points to find
             * a pair or triplet of points which determine the minimal circle.
             * By the design of the algorithm,
             * at most <tt>pts.length</tt> iterations are required to terminate
             * with a correct result.
             */
            for (int i = 0; i < pts.Length; i++)
            {
                var R = PointWithMinAngleWithSegment(pts, P, Q);

                // if PRQ is obtuse, then MBC is determined by P and Q
                if (AngleUtility.IsObtuse(P, R, Q))
                {
                    _extremalPts = new Coordinate[] { P.Copy(), Q.Copy() };
                    return;
                }
                // if RPQ is obtuse, update baseline and iterate
                if (AngleUtility.IsObtuse(R, P, Q))
                {
                    P = R;
                    continue;
                }
                // if RQP is obtuse, update baseline and iterate
                if (AngleUtility.IsObtuse(R, Q, P))
                {
                    Q = R;
                    continue;
                }
                // otherwise all angles are acute, and the MBC is determined by the triangle PQR
                _extremalPts = new Coordinate[] { P.Copy(), Q.Copy(), R.Copy() };
                return;
            }
            Assert.ShouldNeverReachHere("Logic failure in Minimum Bounding Circle algorithm!");
        }