コード例 #1
0
 public void AddCircle(Circle2d circle, Style style)
 {
     Objects.Add(circle);
     Styles[circle] = style;
     Bounds.Contain(circle.Bounds);
 }
コード例 #2
0
 public void AddCircle(Circle2d circle)
 {
     Objects.Add(circle);
     Bounds.Contain(circle.Bounds);
 }
コード例 #3
0
 public DistPoint2Circle2(Vector2d PointIn, Circle2d circleIn)
 {
     point = PointIn; circle = circleIn;
 }
コード例 #4
0
        public ContMinCircle2(IList <Vector2d> pointsIn, double epsilon = 1e-05)
        {
            mEpsilon = epsilon;

            mUpdate[0] = null;
            mUpdate[1] = UpdateSupport1;
            mUpdate[2] = UpdateSupport2;
            mUpdate[3] = UpdateSupport3;

            Circle minimal;

            var    support  = new Support();
            double distDiff = 0;

            Points = pointsIn;
            int numPoints = pointsIn.Count;

            int[] permutation = null;
            var   r           = new Random();

            if (numPoints >= 1)
            {
                // Create identity permutation (0,1,..,numPoints-1).
                permutation = new int[numPoints];
                for (int i = 0; i < numPoints; ++i)
                {
                    permutation[i] = i;
                }

                // Generate random permutation.
                for (int i = numPoints - 1; i > 0; --i)
                {
                    int j = r.Next() % (i + 1);
                    if (j != i)
                    {
                        int save = permutation[i];
                        permutation[i] = permutation[j];
                        permutation[j] = save;
                    }
                }

                minimal          = new Circle(Points[permutation[0]], 0);
                support.Quantity = 1;
                support.Index[0] = 0;

                // The previous version of the processing loop is
                //  i = 1;
                //  while (i < numPoints)
                //  {
                //      if (!support.Contains(i, permutation, mEpsilon))
                //      {
                //          if (!Contains(*permutation[i], minimal, distDiff))
                //          {
                //              UpdateFunction update = mUpdate[support.Quantity];
                //              Circle circle = (this->*update)(i, permutation,
                //                  support);
                //              if (circle.Radius > minimal.Radius)
                //              {
                //                  minimal = circle;
                //                  i = 0;
                //                  continue;
                //              }
                //          }
                //      }
                //      ++i;
                //  }
                // This loop restarts from the beginning of the point list each time
                // the circle needs updating.  Linus Källberg (Computer Science at
                // Mälardalen University in Sweden) discovered that performance is
                // better when the remaining points in the array are processed before
                // restarting.  The points processed before the point that caused the
                // update are likely to be enclosed by the new circle (or near the
                // circle boundary) because they were enclosed by the previous circle.
                // The chances are better that points after the current one will cause
                // growth of the bounding circle.
                for (int i = 1 % numPoints, n = 0; i != n; i = (i + 1) % numPoints)
                {
                    if (!support.Contains(i, Points, permutation, mEpsilon))
                    {
                        if (!Contains(Points[permutation[i]], ref minimal, ref distDiff))
                        {
                            var    updateF = mUpdate[support.Quantity];
                            Circle circle  = updateF(i, permutation, support);
                            if (circle.Radius > minimal.Radius)
                            {
                                minimal = circle;
                                n       = i;
                            }
                        }
                    }
                }
            }
            else
            {
                throw new Exception("ContMinCircle2: Input must contain points\n");
            }

            Result = new Circle2d(minimal.Center, Math.Sqrt(minimal.Radius));
        }
コード例 #5
0
 public void AddCircle(Circle2d circle)
 {
     CurrentLayer.Objects.Add(circle);
     Bounds.Contain(circle.Bounds);
 }
コード例 #6
0
        // If you think your points are nearly circular, use this.  The circle is of
        // the form C'[0]+C'[1]*X+C'[2]*Y+C'[3]*(X^2+Y^2), where Length(C') = 1.  The
        // function returns C = (C'[0]/C'[3],C'[1]/C'[3],C'[2]/C'[3]), so the fitted
        // circle is C[0]+C[1]*X+C[2]*Y+X^2+Y^2.  The center is (xc,yc) =
        // -0.5*(C[1],C[2]) and the radius is r = sqrt(xc*xc+yc*yc-C[0]).
        public static double FitCircle2(Vector2d[] points, out Circle2d circle)
        {
            DenseMatrix A         = new DenseMatrix(4, 4);
            int         numPoints = points.Length;

            for (int i = 0; i < numPoints; ++i)
            {
                double x   = points[i].x;
                double y   = points[i].y;
                double x2  = x * x;
                double y2  = y * y;
                double xy  = x * y;
                double r2  = x2 + y2;
                double xr2 = x * r2;
                double yr2 = y * r2;
                double r4  = r2 * r2;

                A[0, 1] += x;
                A[0, 2] += y;
                A[0, 3] += r2;
                A[1, 1] += x2;
                A[1, 2] += xy;
                A[1, 3] += xr2;
                A[2, 2] += y2;
                A[2, 3] += yr2;
                A[3, 3] += r4;
            }

            A[0, 0] = (double)numPoints;

            for (int row = 0; row < 4; ++row)
            {
                for (int col = 0; col < row; ++col)
                {
                    A[row, col] = A[col, row];
                }
            }

            double invNumPoints = 1.0 / (double)numPoints;

            for (int row = 0; row < 4; ++row)
            {
                for (int col = 0; col < 4; ++col)
                {
                    A[row, col] *= invNumPoints;
                }
            }

            SymmetricEigenSolver es = new SymmetricEigenSolver(4, 1024);

            es.Solve(A.Buffer, SymmetricEigenSolver.SortType.Increasing);
            double[] evector = new double[4];
            es.GetEigenvector(0, evector);

            double   inv          = 1.0 / evector[3];   // TODO: Guard against zero divide?
            Vector3d coefficients = Vector3d.Zero;

            for (int row = 0; row < 3; ++row)
            {
                coefficients[row] = inv * evector[row];
            }

            Vector2d center = new Vector2d(-0.5 * coefficients[1], -0.5 * coefficients[2]);
            double   r      = Math.Sqrt(Math.Abs(center.LengthSquared - coefficients[0]));

            circle = new Circle2d(center, r);

            // For an exact fit, numeric round-off errors might make the minimum
            // eigenvalue just slightly negative.  Return the absolute value since
            // the application might rely on the return value being nonnegative.
            return(Math.Abs(es.GetEigenvalue(0)));
        }