コード例 #1
0
 /// <summary>
 /// Closest point on circle (including interior points).
 /// </summary>
 public Point3d ClosestPoint(Circle3d c)
 {
     return(c.ClosestPoint(this));
 }
コード例 #2
0
ファイル: Circle3D.cs プロジェクト: vnvizitiu/GeometRi.CSharp
        private double _distance_cicle_to_circle(Circle3d c1, Circle3d c2, out Point3d p1, out Point3d p2)
        // Use quadratic interpolation to find closest point on one circle to other
        // p1 and p2 - closest points on both circles
        {
            double  d1 = 1e20;
            double  t1 = 0;
            Point3d p;

            for (int i = 0; i < 16; i++)
            {
                double t = i * Math.PI / 8;
                p = c1.ParametricForm(t);
                double dist = p.DistanceTo(c2);
                if (dist < d1)
                {
                    d1 = dist;
                    t1 = t;
                }
            }
            double t2 = t1 - Math.PI / 8;

            p = c1.ParametricForm(t2);
            double d2 = p.DistanceTo(c2);
            double t3 = t1 + Math.PI / 8;

            p = c1.ParametricForm(t3);
            double d3 = p.DistanceTo(c2);

            int  iter = 0;
            bool flag = false;

            while (d2 - d1 > 0.2 * GeometRi3D.DefaultTolerance && d1 > GeometRi3D.DefaultTolerance)
            {
                if (++iter > 100)
                {
                    break;
                }

                double ax = 2.0 * d1 / (t1 - t2) / (t1 - t3);
                double aa = 0.5 * ax * (t2 + t3);
                double bx = 2.0 * d2 / (t2 - t1) / (t2 - t3);
                double bb = 0.5 * bx * (t1 + t3);
                double cx = 2.0 * d3 / (t3 - t1) / (t3 - t2);
                double cc = 0.5 * cx * (t1 + t2);

                double t = (aa + bb + cc) / (ax + bx + cx);
                p = c1.ParametricForm(t);
                double d = p.DistanceTo(c2);

                if (d > d1)
                // Possible special case, non-smooth function ( f(t)=|t| )
                {
                    flag = true;
                    break;
                }

                if (t > t2 & t < t1)
                {
                    t3 = t1; d3 = d1;
                }
                else
                {
                    t2 = t1; d2 = d1;
                }
                t1 = t; d1 = d;
            }

            if (flag)
            // Possible special case, non-smooth function ( f(t)=|t| )
            {
                while (d2 - d1 > 0.2 * GeometRi3D.DefaultTolerance && d1 > GeometRi3D.DefaultTolerance)
                {
                    if (++iter > 100)
                    {
                        break;
                    }

                    double t = (t2 + t1) / 2;
                    p = c1.ParametricForm(t);
                    double d = p.DistanceTo(c2);
                    if (d < d1)
                    {
                        t3 = t1; d3 = d1;
                        t1 = t;  d1 = d;
                    }
                    else
                    {
                        t2 = t; d2 = d;
                    }

                    t = (t3 + t1) / 2;
                    p = c1.ParametricForm(t);
                    d = p.DistanceTo(c2);
                    if (d < d1)
                    {
                        t2 = t1; d2 = d1;
                        t1 = t; d1 = d;
                    }
                    else
                    {
                        t3 = t; d3 = d;
                    }
                }
            }

            p1 = c1.ParametricForm(t1);
            p2 = c2.ClosestPoint(p1);
            return(d1);
        }