コード例 #1
0
ファイル: Ellipse2D.cs プロジェクト: SOFAgh/CADability
        private static void RefineIntersectionPoint(Ellipse2D e1, Ellipse2D e2, ref GeoPoint2DWithParameter ip)
        {   // hier mir Param arbeiten, da es sich auch um einen Ellipsenbogen handeln kann
            double     par1    = e1.ParamOf(ip.p);
            double     par2    = e2.ParamOf(ip.p);
            GeoPoint2D p1      = e1.PointAtParam(par1);
            GeoPoint2D p2      = e2.PointAtParam(par2);
            int        counter = 0;

            while (!Precision.IsEqual(p1, p2))
            {
                GeoVector2D d1 = e1.DirectionAtParam(par1);
                GeoVector2D d2 = e2.DirectionAtParam(par2);
                GeoPoint2D  p;
                if (Geometry.IntersectLL(p1, d1, p2, d2, out p))
                {
                    par1 = e1.ParamOf(p);
                    par2 = e2.ParamOf(p);
                    p1   = e1.PointAtParam(par1);
                    p2   = e2.PointAtParam(par2);
                    ip.p = p;
                }
                else
                {
                    break;
                }
                ++counter;
                if (counter > 100)
                {
                    break;
                }
            }
            ip.par1 = e1.PositionOf(ip.p); // richtige Werte auch für Arc
            ip.par2 = e2.PositionOf(ip.p);
        }
コード例 #2
0
ファイル: Ellipse2D.cs プロジェクト: SOFAgh/CADability
        public static Ellipse2D FromFivePoints(GeoPoint2D[] p, bool isFull)
        {
            Ellipse2D res = FromFivePoints(p);

            if (res != null)
            {
                double mindist = double.MaxValue;
                double p0      = res.PositionOf(p[0]);
                for (int i = 1; i < 5; i++)
                {
                    double p1 = res.PositionOf(p[i]);
                    if (Math.Abs(p1 - p0) < Math.Abs(mindist))
                    {
                        mindist = p1 - p0;
                    }
                    p0 = p1;
                }
                if (mindist < 0)
                {
                    res.Reverse();
                }
                if (!isFull)
                {
                    double sp = res.PositionOf(p[0]);
                    double ep = res.PositionOf(p[4]);
                    double mp = res.PositionOf(p[2]);
                    if (sp < ep)
                    {
                        if (sp < mp && mp < ep)
                        {
                            res = res.Trim(sp, ep) as Ellipse2D;
                        }
                        else
                        {
                            res = res.Trim(ep, sp) as Ellipse2D;
                        }
                    }
                    else
                    {   // to be tested!
                        if (sp < mp && mp < ep)
                        {
                            res = res.Trim(ep, sp) as Ellipse2D;
                        }
                        else
                        {
                            res = res.Trim(sp, ep) as Ellipse2D;
                        }
                    }
                }
            }
            return(res);
        }
コード例 #3
0
        /// <summary>
        /// Overrides <see cref="CADability.Curve2D.GeneralCurve2D.Intersect (ICurve2D)"/>
        /// </summary>
        /// <param name="IntersectWith"></param>
        /// <returns></returns>
        public override GeoPoint2DWithParameter[] Intersect(ICurve2D IntersectWith)
        {   // gesucht sind alle Schnittpunkte, also auch in der Verlängerung!
            Line2D l2d = IntersectWith as Line2D;

            if (l2d != null)
            {
                GeoPoint2D ip;
                if (Geometry.IntersectLL(startPoint, endPoint, l2d.StartPoint, l2d.EndPoint, out ip))
                {
                    double pos1 = this.PositionOf(ip);
                    double pos2 = l2d.PositionOf(ip);
                    GeoPoint2DWithParameter pwp = new GeoPoint2DWithParameter();
                    pwp.p    = ip;
                    pwp.par1 = pos1;
                    pwp.par2 = pos2;
                    return(new GeoPoint2DWithParameter[] { pwp });
                }
                else
                {
                    return(new GeoPoint2DWithParameter[0]);
                }
            }
            Circle2D c2d = IntersectWith as Circle2D;

            if (c2d != null)
            {
                GeoPoint2D[] isp = Geometry.IntersectLC(startPoint, endPoint, c2d.Center, c2d.Radius);
                GeoPoint2DWithParameter[] res = new GeoPoint2DWithParameter[isp.Length];
                for (int i = 0; i < isp.Length; ++i)
                {
                    res[i].p    = isp[i];
                    res[i].par1 = this.PositionOf(isp[i]);
                    res[i].par2 = c2d.PositionOf(isp[i]);
                }
                return(res);
            }
            Ellipse2D e2d = IntersectWith as Ellipse2D;

            if (e2d != null)
            {
                GeoPoint2D[] isp = Geometry.IntersectEL(e2d.center, e2d.majorAxis.Length, e2d.minorAxis.Length, e2d.majorAxis.Angle, startPoint, endPoint);
                GeoPoint2DWithParameter[] res = new GeoPoint2DWithParameter[isp.Length];
                for (int i = 0; i < isp.Length; ++i)
                {
                    res[i].p    = isp[i];
                    res[i].par1 = this.PositionOf(isp[i]);
                    res[i].par2 = e2d.PositionOf(isp[i]);
                }
                return(res);
            }
            Polyline2D p2d = IntersectWith as Polyline2D;

            if (p2d != null)
            {
                GeoPoint2DWithParameter[] res = p2d.Intersect(this); // sorum geht es
                for (int i = 0; i < res.Length; ++i)
                {
                    double t = res[i].par1;
                    res[i].par1 = res[i].par2;
                    res[i].par2 = t;
                }
                return(res);
            }
            Path2D pa2d = IntersectWith as Path2D;

            if (pa2d != null)
            {
                GeoPoint2DWithParameter[] res = pa2d.Intersect(this); // sorum geht es
                for (int i = 0; i < res.Length; ++i)
                {
                    double t = res[i].par1;
                    res[i].par1 = res[i].par2;
                    res[i].par2 = t;
                }
                return(res);
            }
            BSpline2D b2d = IntersectWith as BSpline2D;

            if (b2d != null)
            {
                GeoPoint2DWithParameter[] res = b2d.Intersect(this); // sorum geht es
                for (int i = 0; i < res.Length; ++i)
                {
                    double t = res[i].par1;
                    res[i].par1 = res[i].par2;
                    res[i].par2 = t;
                }
                return(res);
            }
            return(base.Intersect(IntersectWith));
        }
コード例 #4
0
ファイル: Ellipse2D.cs プロジェクト: SOFAgh/CADability
        /// <summary>
        /// Overrides <see cref="CADability.Curve2D.GeneralCurve2D.Intersect (ICurve2D)"/>
        /// </summary>
        /// <param name="IntersectWith"></param>
        /// <returns></returns>
        public override GeoPoint2DWithParameter[] Intersect(ICurve2D IntersectWith)
        {       // gesucht sind alle Schnittpunkte, also auch in der Verlängerung!
            Line2D l2d = IntersectWith as Line2D;

            if (l2d != null)
            {
                GeoPoint2DWithParameter[] res = l2d.Intersect(this); // die Linie kanns
                // aber noch die Rollen vertauschen
                for (int i = 0; i < res.Length; ++i)
                {       // par1 und par2 vertauschen
                    double tmp = res[i].par1;
                    res[i].par1 = res[i].par2;
                    res[i].par2 = tmp;
                }
                return(res);
            }
            else if (IntersectWith is Circle2D) // geht auch für Arc2D
            {
                GeoPoint2D[] ip = Geometry.IntersectEC(center, majrad, minrad, majorAxis.Angle, (IntersectWith as Circle2D).Center, (IntersectWith as Circle2D).Radius);
                GeoPoint2DWithParameter[] res = new GeoPoint2DWithParameter[ip.Length];
                double error = 0.0;
                for (int i = 0; i < ip.Length; ++i)
                {
                    GeoPoint2D p0 = toUnitCircle * ip[i];
                    error      += Math.Abs(1.0 - p0.ToVector().Length);
                    error      += Math.Abs(1.0 - (ip[i] | (IntersectWith as Circle2D).Center) / (IntersectWith as Circle2D).Radius);
                    res[i].p    = ip[i];
                    res[i].par1 = PositionOf(ip[i]);
                    res[i].par2 = IntersectWith.PositionOf(ip[i]); // liefert auch für Arc2D den richtigen Wert
                }
                if (error < 1e-7)                                  // auf Radius 1 normierter fehler
                {                                                  // wenn nicht, dann unten mit dreiecksschnitten lösen
                    return(res);
                }
            }
            else if (IntersectWith is Ellipse2D) // geht auch für EllipseArc2D
            {
                Ellipse2D    elli             = (IntersectWith as Ellipse2D);
                Ellipse2D    ellinorm         = this.GetModified(elli.toUnitCircle) as Ellipse2D;
                GeoPoint2D[] ip               = Geometry.IntersectEC(ellinorm.center, ellinorm.majrad, ellinorm.minrad, ellinorm.majorAxis.Angle, elli.toUnitCircle * elli.center, 1.0);
                GeoPoint2DWithParameter[] res = new GeoPoint2DWithParameter[ip.Length];
                for (int i = 0; i < ip.Length; ++i)
                {
                    res[i].p    = elli.fromUnitCircle * ip[i];
                    res[i].par1 = PositionOf(res[i].p);
                    res[i].par2 = IntersectWith.PositionOf(res[i].p);
                }
                for (int i = 0; i < res.Length; i++)
                {
                    RefineIntersectionPoint(this, elli, ref res[i]);
                }
                if (((ellinorm.Center | GeoPoint2D.Origin) < Precision.eps) && res.Length == 0)
                {   // gleicher Mittelpunkt und keine Lösung, könnte zusammenhängender Bogen zweier identischen Ellipsen sein
                    bool       connected = false;
                    GeoPoint2D p         = GeoPoint2D.Origin;
                    double     par0      = 0.0;
                    double     par1      = 0.0;
                    if ((this.EndPoint | elli.StartPoint) < Precision.eps)
                    {
                        p         = this.EndPoint;
                        par0      = 1.0;
                        par1      = 0.0;
                        connected = true;
                    }
                    if ((this.EndPoint | elli.EndPoint) < Precision.eps)
                    {
                        p         = this.EndPoint;
                        par0      = 1.0;
                        par1      = 1.0;
                        connected = true;
                    }
                    if ((this.StartPoint | elli.StartPoint) < Precision.eps)
                    {
                        p         = this.StartPoint;
                        par0      = 0.0;
                        par1      = 0.0;
                        connected = true;
                    }
                    if ((this.StartPoint | elli.EndPoint) < Precision.eps)
                    {
                        p         = this.StartPoint;
                        par0      = 0.0;
                        par1      = 1.0;
                        connected = true;
                    }
                    if (connected)
                    {
                        res    = new GeoPoint2DWithParameter[1];
                        res[0] = new GeoPoint2DWithParameter(p, par0, par1);
                    }
                }
                return(res);
            }
            // auch wenn die Ellipsenschnittpunkte schlecht waren
            return(base.Intersect(IntersectWith));
        }
コード例 #5
0
ファイル: Ellipse2D.cs プロジェクト: SOFAgh/CADability
        public static Ellipse2D FromFivePoints(GeoPoint2D[] p)
        {
            Matrix m = new DenseMatrix(5, 5);
            Vector b = new DenseVector(5);

            for (int i = 0; i < 5; ++i)
            {
                m[i, 0] = 1;
                m[i, 1] = 2 * p[i].x;
                m[i, 2] = 2 * p[i].y;
                m[i, 3] = 2 * p[i].x * p[i].y;
                m[i, 4] = p[i].y * p[i].y;
                b[i]    = -p[i].x * p[i].x;
            }
            Vector x = (Vector)m.Solve(b);

            if (!x.IsValid())
            {
                return(null);
            }
            double l1, l2;

            if (Geometry.quadgl(1, -(1 + x[4]), x[4] - x[3] * x[3], out l1, out l2) == 0)
            {
                l1 = l2 = (1 + x[4]) / 2.0;
            }
            if (l1 == 0.0 || l2 == 0.0)
            {
                return(null);
            }

            Angle MajorAngle;

            if (Math.Abs(l1 - 1) > Math.Abs(l2 - 1))
            {
                MajorAngle = Math.Atan2(l1 - 1, x[3]);
            }
            else
            {
                MajorAngle = Math.Atan2(l2 - 1, x[3]) + Math.PI / 2.0;
            }
            double b1          = x[1] * Math.Cos(MajorAngle) + x[2] * Math.Sin(MajorAngle);
            double b2          = -x[1] * Math.Sin(MajorAngle) + x[2] * Math.Cos(MajorAngle);
            double MajorRadius = Math.Sqrt(Math.Abs((b1 * b1 / l1 + b2 * b2 / l2 - x[0]) / l1));
            double MinorRadius = Math.Sqrt(Math.Abs((b1 * b1 / l1 + b2 * b2 / l2 - x[0]) / l2));
            Matrix a           = new DenseMatrix(2, 2);
            Vector c           = new DenseVector(2);

            a[0, 0] = 1;
            a[1, 0] = a[0, 1] = x[3];
            a[1, 1] = x[4];
            c[0]    = -x[1];
            c[1]    = -x[2];
            Vector mp = (Vector)a.Solve(c);

            if (!mp.IsValid())
            {
                return(null);
            }


            //{	// ein Test, ob die Lösung auch stimmt. Es gibt Lösungen
            //    // die wohl eher Hyperbeln oder so was liefern und trotzdem alle
            //    // durch die Gleichungen gegebenen Bedingungen erfüllen
            //    if (MajorRadius < 1e-13) return null;
            //    if (MinorRadius < 1e-13) return null;
            //    double s = Math.Sin(MajorAngle);
            //    double cos = Math.Cos(MajorAngle);
            //    ModOp2D tuc = new ModOp2D(cos / MajorRadius, s / MajorRadius, (-cos * mp[0, 0] - s * mp[1, 0]) / MajorRadius,
            //                 -s / MinorRadius, cos / MinorRadius, (s * mp[0, 0] - cos * mp[1, 0]) / MinorRadius);
            //    // bildet auf den Einheitskreis ab
            //    for (int i = 0; i < 5; ++i)
            //    {
            //        GeoPoint2D pp = tuc * p[i];
            //        double e = Math.Abs(pp.x * pp.x + pp.y * pp.y - 1.0);
            //        if (e > 1e-5) return null;
            //    }
            //}

            // hier ist nun alles bestimmt:
            Angle     MinorAngle = MajorAngle + SweepAngle.ToLeft;
            Ellipse2D res        = new Ellipse2D(new GeoPoint2D(mp[0], mp[1]), MajorRadius * new GeoVector2D(MajorAngle), MinorRadius * new GeoVector2D(MinorAngle));

            return(res);
        }