Пример #1
0
        public static double GetArea(Polyline pline)
        {
            CircularArc2d arc  = new CircularArc2d();
            double        area = 0.0;
            int           last = pline.NumberOfVertices - 1;
            Point2d       p0   = pline.GetPoint2dAt(0);

            if (pline.GetBulgeAt(0) != 0.0)
            {
                area += pline.GetArcSegment2dAt(0).GetArea();
            }
            for (int i = 1; i < last; i++)
            {
                area += GetArea(p0, pline.GetPoint2dAt(i), pline.GetPoint2dAt(i + 1));
                if (pline.GetBulgeAt(i) != 0.0)
                {
                    area += pline.GetArcSegment2dAt(i).GetArea();;
                }
            }
            if ((pline.GetBulgeAt(last) != 0.0) && pline.Closed)
            {
                area += pline.GetArcSegment2dAt(last).GetArea();
            }
            return(area);
        }
Пример #2
0
        /// <summary>
        /// Gets the algebraic (signed) area of the circular arc.
        /// </summary>
        /// <param name="arc">The instance to which the method applies.</param>
        /// <returns>The algebraic area.</returns>
        public static double AlgebricArea([NotNull] this CircularArc2d arc)
        {
            var rad = arc.Radius;
            var ang = arc.IsClockWise ? arc.StartAngle - arc.EndAngle : arc.EndAngle - arc.StartAngle;

            return(rad * rad * (ang - Math.Sin(ang)) / 2.0);
        }
Пример #3
0
        public static LineSegment2d[] GetTangentsTo([NotNull] this CircularArc2d arc, Point2d pt)
        {
            // check if the point is inside the circle
            var center = arc.Center;

            if (pt.GetDistanceTo(center) <= arc.Radius)
            {
                return(null);
            }

            var vec    = center.GetVectorTo(pt) / 2.0;
            var tmp    = new CircularArc2d(center + vec, vec.Length);
            var inters = arc.IntersectWith(tmp);

            if (inters == null)
            {
                return(null);
            }
            var result = new LineSegment2d[2];
            var v1     = inters[0] - center;
            var i      = vec.X * v1.Y - vec.Y - v1.X > 0 ? 0 : 1;
            var j      = i ^ 1;

            result[i] = new LineSegment2d(inters[0], pt);
            result[j] = new LineSegment2d(inters[1], pt);
            return(result);
        }
Пример #4
0
        /// <summary>
        /// Returns the tangents between the active CircularArc3d instance complete circle and another one.
        /// </summary>
        /// <remarks>
        /// Tangents start points are on the object to which this method applies, end points on the one passed as argument.
        /// Tangents are always returned in the same order: outer tangents before inner tangents, and for both,
        /// the tangent on the left side of the line from this circular arc center to the other one before the one on the right side.
        /// </remarks>
        /// <param name="arc">The instance to which this method applies.</param>
        /// <param name="other">The CircularArc3d to which searched for tangents.</param>
        /// <param name="flags">An enum value specifying which type of tangent is returned.</param>
        /// <returns>An array of LineSegment3d representing the tangents (maybe 2 or 4) or null if there is none.</returns>
        /// <exception cref="Autodesk.AutoCAD.Runtime.Exception">
        /// eNonCoplanarGeometry is thrown if the objects do not lies on the same plane.</exception>
        public static LineSegment3d[] GetTangentsTo(this CircularArc3d arc, CircularArc3d other, TangentType flags)
        {
            // check if circles lies on the same plane
            Vector3d normal    = arc.Normal;
            Matrix3d WCS2OCS   = Matrix3d.WorldToPlane(normal);
            double   elevation = arc.Center.TransformBy(WCS2OCS).Z;

            if (!(normal.IsParallelTo(other.Normal) &&
                  Math.Abs(elevation - other.Center.TransformBy(WCS2OCS).Z) < Tolerance.Global.EqualPoint))
            {
                throw new Autodesk.AutoCAD.Runtime.Exception(
                          Autodesk.AutoCAD.Runtime.ErrorStatus.NonCoplanarGeometry);
            }

            Plane         plane   = new Plane(Point3d.Origin, normal);
            Matrix3d      OCS2WCS = Matrix3d.PlaneToWorld(plane);
            CircularArc2d ca2d1   = new CircularArc2d(arc.Center.Convert2d(plane), arc.Radius);
            CircularArc2d ca2d2   = new CircularArc2d(other.Center.Convert2d(plane), other.Radius);

            LineSegment2d[] lines2d = ca2d1.GetTangentsTo(ca2d2, flags);

            if (lines2d == null)
            {
                return(null);
            }

            LineSegment3d[] result = new LineSegment3d[lines2d.Length];
            for (int i = 0; i < lines2d.Length; i++)
            {
                LineSegment2d ls2d = lines2d[i];
                result[i] = new LineSegment3d(ls2d.StartPoint.Convert3d(normal, elevation), ls2d.EndPoint.Convert3d(normal, elevation));
            }
            return(result);
        }
Пример #5
0
        public Arc GetArc2(Point2d pit1, Point2d pit2, Point2d pit3, ref CircularArc2d arc2d)
        {
            arc2d = new CircularArc2d(pit1, pit2, pit3);

            Point2d pitCenter = arc2d.Center;

            double radius = arc2d.Radius;

            double startAngle = AngleFromXAxis(pit1, pitCenter);

            double endAngle = AngleFromXAxis(pit3, pitCenter);

            double sangle = (startAngle / (2 * Math.PI * radius) * 360);
            double eangle = (endAngle / (2 * Math.PI * radius) * 360);

            double temp = 0;

            if ((endAngle - startAngle) >= Math.PI || (startAngle > endAngle && Math.Abs(startAngle - endAngle) < Math.PI))
            {
                temp = startAngle;

                startAngle = endAngle;

                endAngle = temp;
            }

            Arc arc = new Arc(new Point3d(pitCenter.X, pitCenter.Y, 0), radius, startAngle, endAngle);

            return(arc);
        }
Пример #6
0
        /// <summary>
        /// Returns the tangents between the active CircularArc3d instance complete circle and another one.
        /// </summary>
        /// <remarks>
        /// Tangents start points are on the object to which this method applies, end points on the one passed as argument.
        /// Tangents are always returned in the same order: outer tangents before inner tangents, and for both,
        /// the tangent on the left side of the line from this circular arc center to the other one before the one on the right side. 
        /// </remarks>
        /// <param name="arc">The instance to which this method applies.</param>
        /// <param name="other">The CircularArc3d to which searched for tangents.</param>
        /// <param name="flags">An enum value specifying which type of tangent is returned.</param>
        /// <returns>An array of LineSegment3d representing the tangents (maybe 2 or 4) or null if there is none.</returns>
        /// <exception cref="Autodesk.AutoCAD.Runtime.Exception">
        /// eNonCoplanarGeometry is thrown if the objects do not lies on the same plane.</exception>
        public static LineSegment3d[] GetTangentsTo(this CircularArc3d arc, CircularArc3d other, TangentType flags)
        {
            // check if circles lies on the same plane
            Vector3d normal = arc.Normal;
            Matrix3d WCS2OCS = Matrix3d.WorldToPlane(normal);
            double elevation = arc.Center.TransformBy(WCS2OCS).Z;
            if (!(normal.IsParallelTo(other.Normal) &&
                Math.Abs(elevation - other.Center.TransformBy(WCS2OCS).Z) < Tolerance.Global.EqualPoint))
                throw new Autodesk.AutoCAD.Runtime.Exception(
                    Autodesk.AutoCAD.Runtime.ErrorStatus.NonCoplanarGeometry);

            Plane plane = new Plane(Point3d.Origin, normal);
            Matrix3d OCS2WCS = Matrix3d.PlaneToWorld(plane);
            CircularArc2d ca2d1 = new CircularArc2d(arc.Center.Convert2d(plane), arc.Radius);
            CircularArc2d ca2d2 = new CircularArc2d(other.Center.Convert2d(plane), other.Radius);
            LineSegment2d[] lines2d = ca2d1.GetTangentsTo(ca2d2, flags);

            if (lines2d == null)
                return null;

            LineSegment3d[] result = new LineSegment3d[lines2d.Length];
            for (int i = 0; i < lines2d.Length; i++)
            {
                LineSegment2d ls2d = lines2d[i];
                result[i] = new LineSegment3d(ls2d.StartPoint.Convert3d(normal, elevation), ls2d.EndPoint.Convert3d(normal, elevation));
            }
            return result;
        }
Пример #7
0
        /// <summary>
        /// Returns the tangents between the active CircularArc3d instance complete circle and a point.
        /// </summary>
        /// <remarks>
        /// Tangents start points are on the object to which this method applies, end points on the point passed as argument.
        /// Tangents are always returned in the same order: the tangent on the left side of the line from the circular arc center
        /// to the point before the one on the right side.
        /// </remarks>
        /// <param name="arc">The instance to which this method applies.</param>
        /// <param name="pt">The Point3d to which tangents are searched</param>
        /// <returns>An array of LineSegement3d representing the tangents (2) or null if there is none.</returns>
        /// <exception cref="Autodesk.AutoCAD.Runtime.Exception">
        /// eNonCoplanarGeometry is thrown if the objects do not lies on the same plane.</exception>
        public static LineSegment3d[]? GetTangentsTo([NotNull] this CircularArc3d arc, Point3d pt)
        {
            // check if arc and point lies on the plane
            var normal    = arc.Normal;
            var WCS2OCS   = Matrix3d.WorldToPlane(normal);
            var elevation = arc.Center.TransformBy(WCS2OCS).Z;

            if (Math.Abs(elevation - pt.TransformBy(WCS2OCS).Z) < Tolerance.Global.EqualPoint)
            {
                throw new Autodesk.AutoCAD.Runtime.Exception(
                          Autodesk.AutoCAD.Runtime.ErrorStatus.NonCoplanarGeometry);
            }

            var plane   = new Plane(Point3d.Origin, normal);
            var ca2d    = new CircularArc2d(arc.Center.Convert2d(plane), arc.Radius);
            var lines2d = ca2d.GetTangentsTo(pt.Convert2d(plane));

            if (lines2d == null)
            {
                return(null);
            }

            var result = new LineSegment3d[lines2d.Length];

            for (var i = 0; i < lines2d.Length; i++)
            {
                var ls2d = lines2d[i];
                result[i] = new LineSegment3d(ls2d.StartPoint.Convert3d(normal, elevation),
                                              ls2d.EndPoint.Convert3d(normal, elevation));
            }

            return(result);
        }
Пример #8
0
        /// <summary>
        ///     Returns the tangents between the active CircularArc3d instance complete circle and a point.
        /// </summary>
        /// <remarks>
        ///     Tangents start points are on the object to which this method applies, end points on the point passed as argument.
        ///     Tangents are always returned in the same order: the tangent on the left side of the line from the circular arc
        ///     center
        ///     to the point before the one on the right side.
        /// </remarks>
        /// <param name="arc">The instance to which this method applies.</param>
        /// <param name="pt">The Point3d to which tangents are searched</param>
        /// <returns>An array of LineSegement3d representing the tangents (2) or null if there is none.</returns>
        /// <exception cref="Autodesk.AutoCAD.Runtime.Exception">
        ///     eNonCoplanarGeometry is thrown if the objects do not lies on the same plane.
        /// </exception>
        public static LineSegment3d[] GetTangentsTo(this CircularArc3d arc, Point3d pt)
        {
            // check if arc and point lies on the plane
            var normal    = arc.Normal;
            var wcs2Ocs   = Matrix3d.WorldToPlane(normal);
            var elevation = arc.Center.TransformBy(wcs2Ocs).Z;

            if (Math.Abs(elevation - pt.TransformBy(wcs2Ocs).Z) < Tolerance.Global.EqualPoint)
            {
                throw new Exception(
                          ErrorStatus.NonCoplanarGeometry);
            }

            var plane = new Plane(Point3d.Origin, normal);

            _ = Matrix3d.PlaneToWorld(plane);
            var ca2D    = new CircularArc2d(arc.Center.Convert2d(plane), arc.Radius);
            var lines2D = ca2D.GetTangentsTo(pt.Convert2d(plane));

            if (lines2D == null)
            {
                return(null);
            }

            var result = new LineSegment3d[lines2D.Length];

            for (var i = 0; i < lines2D.Length; i++)
            {
                var ls2D = lines2D[i];
                result[i] = new LineSegment3d(ls2D.StartPoint.Convert3D(normal, elevation),
                                              ls2D.EndPoint.Convert3D(normal, elevation));
            }

            return(result);
        }
Пример #9
0
        public static Polyline ConvertToPolyline([NotNull] this CircularArc2d arc)
        {
            var poly = new Polyline();

            poly.AddVertexAt(0, new Point2d(arc.StartPoint.X, arc.StartPoint.Y), GetBulge(arc, arc.IsClockWise), 0, 0);
            poly.AddVertexAt(1, new Point2d(arc.EndPoint.X, arc.EndPoint.Y), 0, 0, 0);
            return(poly);
        }
Пример #10
0
        /// <summary>
        /// Initializes a new instance of the <see cref="ConstructionRow"/> class.
        /// </summary>
        /// <param name="arc">The arc segment taken from a polyline.</param>
        /// <param name="index">The vertex index.</param>
        /// <param name="cumulativeDistance">The cumulative distance.</param>
        public ConstructionRow(CircularArc2d arc, int index, Double cumulativeDistance = 0) :
            this((arc as Curve2d), index, cumulativeDistance)
        {
            Arc a = new Arc(arc.Center.ToPoint3d(), arc.Radius, arc.StartAngle, arc.EndAngle);

            this.Distance           = a.Length;
            this.CumulativeDistance = cumulativeDistance + this.Distance;
        }
Пример #11
0
        /// <summary>
        /// Gets the area of an arc segment.
        /// </summary>
        /// <param name="arc"></param>
        /// <returns></returns>
        public static double GetArea(this CircularArc2d arc)
        {
            double ang = arc.IsClockWise ?
                         arc.StartAngle - arc.EndAngle :
                         arc.EndAngle - arc.StartAngle;

            return((ang - Math.Sin(ang)) * arc.Radius * arc.Radius / 2.0);
        }
Пример #12
0
        /// <summary>
        ///     Gets the centroid of the polyline 2d.
        /// </summary>
        /// <param name="pl">The instance to which the method applies.</param>
        /// <returns>The centroid of the polyline 2d (WCS coordinates).</returns>
        public static Point3d Centroid(this Polyline2d pl)
        {
            var vertices = pl.GetVertices().ToArray();
            var last     = vertices.Length - 1;
            var vertex   = vertices[0];
            var p0       = vertex.Position.Convert2D();

            _ = pl.Elevation;
            var     cen   = new Point2d(0.0, 0.0);
            var     area  = 0.0;
            var     bulge = vertex.Bulge;
            double  tmpArea;
            Point2d tmpPt;
            var     tri = new Triangle2D();
            var     arc = new CircularArc2d();

            if (bulge != 0.0)
            {
                arc     = pl.GetArcSegment2DAt(0);
                tmpArea = arc.AlgebricArea();
                tmpPt   = arc.Centroid();
                area   += tmpArea;
                cen    += (new Point2d(tmpPt.X, tmpPt.Y) * tmpArea).GetAsVector();
            }

            for (var i = 1; i < last; i++)
            {
                var p1 = vertices[i].Position.Convert2D();
                var p2 = vertices[i + 1].Position.Convert2D();
                tri.Set(p0, p1, p2);
                tmpArea = tri.AlgebricArea;
                area   += tmpArea;
                cen    += (tri.Centroid * tmpArea).GetAsVector();
                bulge   = vertices[i].Bulge;
                if (bulge != 0.0)
                {
                    arc     = pl.GetArcSegment2DAt(i);
                    tmpArea = arc.AlgebricArea();
                    tmpPt   = arc.Centroid();
                    area   += tmpArea;
                    cen    += (new Point2d(tmpPt.X, tmpPt.Y) * tmpArea).GetAsVector();
                }
            }

            bulge = vertices[last].Bulge;
            if (bulge != 0.0 && pl.Closed)
            {
                arc     = pl.GetArcSegment2DAt(last);
                tmpArea = arc.AlgebricArea();
                tmpPt   = arc.Centroid();
                area   += tmpArea;
                cen    += (new Point2d(tmpPt.X, tmpPt.Y) * tmpArea).GetAsVector();
            }

            cen = cen.DivideBy(area);
            return(new Point3d(cen.X, cen.Y, pl.Elevation).TransformBy(Matrix3d.PlaneToWorld(pl.Normal)));
        }
Пример #13
0
        /// <summary>
        /// Gets the signed area of the circular arc.
        /// </summary>
        /// <param name="arc">The instance to which the method applies.</param>
        /// <returns>The signed area.</returns>
        public static double SignedArea(this CircularArc2d arc)
        {
            double rad = arc.Radius;
            double ang = arc.IsClockWise ?
                         arc.StartAngle - arc.EndAngle :
                         arc.EndAngle - arc.StartAngle;

            return(rad * rad * (ang - Math.Sin(ang)) / 2.0);
        }
Пример #14
0
        /// <summary>
        /// Gets the centroid of the circular arc.
        /// </summary>
        /// <param name="arc">The instance to which the method applies.</param>
        /// <returns>The centroid of the arc.</returns>
        public static Point2d Centroid([NotNull] this CircularArc2d arc)
        {
            var start = arc.StartPoint;
            var end   = arc.EndPoint;
            var area  = arc.AlgebricArea();
            var chord = start.GetDistanceTo(end);
            var angle = (end - start).Angle;

            return(arc.Center.Polar(angle - Math.PI / 2.0, chord * chord * chord / (12.0 * area)));
        }
Пример #15
0
        /// <summary>
        /// Gets the centroid of the circular arc.
        /// </summary>
        /// <param name="arc">The instance to which the method applies.</param>
        /// <returns>The centroid of the arc.</returns>
        public static Point2d Centroid(this CircularArc2d arc)
        {
            Point2d start = arc.StartPoint;
            Point2d end   = arc.EndPoint;
            double  area  = arc.SignedArea();
            double  chord = start.GetDistanceTo(end);
            double  angle = (end - start).Angle;

            return(arc.Center.Polar(angle - (Math.PI / 2.0), (chord * chord * chord) / (12.0 * area)));
        }
 /// <summary>
 /// Creates a new instance of PolylineSegment from a CircularArc2d
 /// </summary>
 /// <param name="arc">A CircularArc2d instance.</param>
 public PolylineSegment(CircularArc2d arc)
 {
     _startPoint = arc.StartPoint;
     _endPoint   = arc.EndPoint;
     _bulge      = Math.Tan((arc.EndAngle - arc.StartAngle) / 4.0);
     if (arc.IsClockWise)
     {
         _bulge = -_bulge;
     }
     _startWidth = 0.0;
     _endWidth   = 0.0;
 }
        // 多段线和直线求交点
        private void PolyIntersectWithLine(Polyline poly, Line line, double tol, ref Point3dCollection points)
        {
            Point2dCollection intPoints2d = new Point2dCollection();

            // 获得直线对应的几何类
            LineSegment2d geLine = new LineSegment2d(ToPoint2d(line.StartPoint), ToPoint2d(line.EndPoint));

            // 每一段分别计算交点
            Tolerance tolerance = new Tolerance(tol, tol);

            for (int i = 0; i < poly.NumberOfVertices; i++)
            {
                if (i < poly.NumberOfVertices - 1 || poly.Closed)
                {
                    SegmentType st = poly.GetSegmentType(i);
                    if (st == SegmentType.Line)
                    {
                        LineSegment2d geLineSeg = poly.GetLineSegment2dAt(i);
                        Point2d[]     pts       = geLineSeg.IntersectWith(geLine, tolerance);
                        if (pts != null)
                        {
                            for (int j = 0; j < pts.Length; j++)
                            {
                                if (FindPointIn(intPoints2d, pts[j], tol) < 0)
                                {
                                    intPoints2d.Add(pts[j]);
                                }
                            }
                        }
                    }
                    else if (st == SegmentType.Arc)
                    {
                        CircularArc2d geArcSeg = poly.GetArcSegment2dAt(i);
                        Point2d[]     pts      = geArcSeg.IntersectWith(geLine, tolerance);
                        if (pts != null)
                        {
                            for (int j = 0; j < pts.Length; j++)
                            {
                                if (FindPointIn(intPoints2d, pts[j], tol) < 0)
                                {
                                    intPoints2d.Add(pts[j]);
                                }
                            }
                        }
                    }
                }
            }

            for (int i = 0; i < intPoints2d.Count; i++)
            {
                points.Add(ToPoint3d(intPoints2d[i]));
            }
        }
        private static double CalculateMidPointDistance(Point2d fromPoint, Point2d endPoint, Point2d centerPoint, double theta, bool IsCounterClockwise)
        {
            double num = Math.Tan(theta / 4.0);

            if (!IsCounterClockwise)
            {
                num *= -1.0;
            }
            CircularArc2d circularArc2d = new CircularArc2d(fromPoint, endPoint, num, false);

            return(circularArc2d.Radius);
        }
Пример #19
0
        /// <summary>
        /// Gets the centroid of the polyline 2d.
        /// </summary>
        /// <param name="pl">The instance to which the method applies.</param>
        /// <returns>The centroid of the polyline 2d (WCS coordinates).</returns>
        public static Point3d Centroid(this Polyline2d pl)
        {
            Vertex2d[]    vertices = pl.GetVertices().ToArray();
            int           last     = vertices.Length - 1;
            Vertex2d      vertex   = vertices[0];
            Point2d       p0       = vertex.Position.Convert2d();
            double        elev     = pl.Elevation;
            Point2d       cen      = new Point2d(0.0, 0.0);
            double        area     = 0.0;
            double        bulge    = vertex.Bulge;
            double        tmpArea;
            Point2d       tmpPt;
            Triangle2d    tri = new Triangle2d();
            CircularArc2d arc = new CircularArc2d();

            if (bulge != 0.0)
            {
                arc     = pl.GetArcSegment2dAt(0);
                tmpArea = arc.SignedArea();
                tmpPt   = arc.Centroid();
                area   += tmpArea;
                cen    += ((new Point2d(tmpPt.X, tmpPt.Y)) * tmpArea).GetAsVector();
            }
            for (int i = 1; i < last; i++)
            {
                Point2d p1 = vertices[i].Position.Convert2d();
                Point2d p2 = vertices[i + 1].Position.Convert2d();
                tri.Set(p0, p1, p2);
                tmpArea = tri.SignedArea;
                area   += tmpArea;
                cen    += (tri.Centroid * tmpArea).GetAsVector();
                bulge   = vertices[i].Bulge;
                if (bulge != 0.0)
                {
                    arc     = pl.GetArcSegment2dAt(i);
                    tmpArea = arc.SignedArea();
                    tmpPt   = arc.Centroid();
                    area   += tmpArea;
                    cen    += ((new Point2d(tmpPt.X, tmpPt.Y)) * tmpArea).GetAsVector();
                }
            }
            bulge = vertices[last].Bulge;
            if ((bulge != 0.0) && (pl.Closed == true))
            {
                arc     = pl.GetArcSegment2dAt(last);
                tmpArea = arc.SignedArea();
                tmpPt   = arc.Centroid();
                area   += tmpArea;
                cen    += ((new Point2d(tmpPt.X, tmpPt.Y)) * tmpArea).GetAsVector();
            }
            cen = cen.DivideBy(area);
            return(new Point3d(cen.X, cen.Y, pl.Elevation).TransformBy(Matrix3d.PlaneToWorld(pl.Normal)));
        }
Пример #20
0
 /// <summary>
 /// Creates a new instance of PolylineSegment from a CircularArc2d
 /// </summary>
 /// <param name="arc">A CircularArc2d instance.</param>
 public PolylineSegment([NotNull] CircularArc2d arc)
 {
     _startPoint = arc.StartPoint;
     _endPoint   = arc.EndPoint;
     Bulge       = Math.Tan((arc.EndAngle - arc.StartAngle) / 4.0);
     if (arc.IsClockWise)
     {
         Bulge = -Bulge;
     }
     StartWidth = 0.0;
     EndWidth   = 0.0;
 }
        private static Entity DrawCircularArc(CircularArc arc, double defaultElevation, Point[] densifiedPoints)
        {
            PointN  pointN      = arc.FromPoint as PointN;
            PointN  pointN2     = arc.ToPoint as PointN;
            PointN  pointN3     = arc.CenterPoint as PointN;
            Point3d point3d     = new Point3d(pointN.X, pointN.Y, pointN.Z);
            Point3d point3d2    = new Point3d(pointN3.X, pointN3.Y, pointN3.Z);
            Point3d point3d3    = new Point3d(pointN2.X, pointN2.Y, pointN2.Z);
            Point2d centerPoint = new Point2d(pointN3.X, pointN3.Y);
            Point2d point2d     = new Point2d(pointN.X, pointN.Y);

            Math.Abs(centerPoint.GetDistanceTo(point2d));
            CircularArc3d circArc;

            if (densifiedPoints != null)
            {
                int    num     = densifiedPoints.Length / 2;
                PointN pointN4 = (PointN)densifiedPoints[num];
                if (arc.IsCounterClockwise)
                {
                    PointN arg_CC_0 = (PointN)densifiedPoints[0];
                    PointN arg_D9_0 = (PointN)densifiedPoints[densifiedPoints.Length - 1];
                }
                else
                {
                    PointN arg_E4_0 = (PointN)densifiedPoints[0];
                    PointN arg_F1_0 = (PointN)densifiedPoints[densifiedPoints.Length - 1];
                }
                Point3d point3d4 = new Point3d(pointN4.X, pointN4.Y, pointN4.Z);
                circArc = new CircularArc3d(point3d, point3d4, point3d3);
            }
            else
            {
                Point2d point2d2 = new Point2d(point3d.X, point3d.Y);
                Point2d point2d3 = new Point2d(point3d3.X, point3d3.Y);
                double  num2     = GIS2CAD.CalcThetaFromVectors(point2d2, point2d3, centerPoint, arc.IsCounterClockwise);
                double  num3     = Math.Tan(num2 / 4.0);
                if (!arc.IsCounterClockwise)
                {
                    num3 *= -1.0;
                }
                CircularArc2d circularArc2d = new CircularArc2d(point2d2, point2d3, num3, false);
                Point2d[]     samplePoints  = circularArc2d.GetSamplePoints(3);
                Point3d       point3d5      = new Point3d(samplePoints[1].X, samplePoints[1].Y, point3d2.Z);
                circArc = new CircularArc3d(point3d, point3d5, point3d3);
            }
            new Point3d(pointN3.X, pointN3.Y, pointN3.Z);
            Arc arc2 = GIS2CAD.CreateFromCircularArc(circArc);

            arc2.ColorIndex = (256);
            return(arc2);
        }
Пример #22
0
 public CircularArc2d GetArcSegment2dAt(int index)
 {
     if (base.isInstanced())
     {
         CircularArc2d GetArcSegment2dAt = BasePolyline.GetArcSegment2dAt(index);
         tr.Dispose();
         return(GetArcSegment2dAt);
     }
     else
     {
         return(BasePolyline.GetArcSegment2dAt(index));
     }
 }
Пример #23
0
        Coordinate[] GetTessellatedCurveCoordinates(Matrix3d parentEcs, CircularArc2d curve)
        {
            Matrix3d matrix3d = parentEcs.Inverse();

            Point2d[] samplePoints = curve.GetSamplePoints(3);
            var       point3d      = new Point3d(samplePoints[0].X, samplePoints[0].Y, 0.0);
            var       point3d2     = new Point3d(samplePoints[1].X, samplePoints[1].Y, 0.0);
            var       point3d3     = new Point3d(samplePoints[2].X, samplePoints[2].Y, 0.0);

            point3d.TransformBy(matrix3d);
            point3d2.TransformBy(matrix3d);
            point3d3.TransformBy(matrix3d);
            return(this.GetTessellatedCurveCoordinates(new CircularArc3d(point3d, point3d2, point3d3)));
        }
Пример #24
0
        private void GetEdgeInformation(Polyline pline, ref Curve2dCollection plCurves, ref IntegerCollection edgeTypes)
        {
            int segCount = pline.NumberOfVertices;

            for (int cnt = 0; cnt < segCount; cnt++)
            {
                SegmentType type = pline.GetSegmentType(cnt);

                switch (type)
                {
                case SegmentType.Arc:

                    CircularArc2d arc2d = pline.GetArcSegment2dAt(cnt);

                    plCurves.Add(arc2d);

                    edgeTypes.Add((int)Enum.Parse(typeof(HatchEdgeType),

                                                  HatchEdgeType.CircularArc.ToString()));

                    break;

                case SegmentType.Line:

                    LineSegment2d line2d = pline.GetLineSegment2dAt(cnt);

                    plCurves.Add(line2d);

                    edgeTypes.Add((int)Enum.Parse(typeof(HatchEdgeType),

                                                  HatchEdgeType.Line.ToString()));

                    break;

                case SegmentType.Coincident:

                    break;

                case SegmentType.Empty:

                    break;

                case SegmentType.Point:

                    break;
                }
            }
        }
 /// <summary>
 /// Returns the parameter value of point.
 /// </summary>
 /// <param name="pt">The Point 2d whose get the PolylineSegment parameter at.</param>
 /// <returns>A double between 0.0 and 1.0, or -1.0 if the point does not lie on the segment.</returns>
 public double GetParameterOf(Point2d pt)
 {
     if (IsLinear)
     {
         LineSegment2d line = ToLineSegment();
         return(line.IsOn(pt) ? _startPoint.GetDistanceTo(pt) / line.Length : -1.0);
     }
     else
     {
         CircularArc2d arc = ToCircularArc();
         return(arc.IsOn(pt) ?
                arc.GetLength(arc.GetParameterOf(_startPoint), arc.GetParameterOf(pt)) /
                arc.GetLength(arc.GetParameterOf(_startPoint), arc.GetParameterOf(_endPoint)) :
                -1.0);
     }
 }
Пример #26
0
        public override void Input(List <Entity> objects)
        {
            foreach (Entity ent in objects)
            {
                if (ent is Line)
                {
                    segments.Add(new StraitItemSegment(((Line)ent).Length));
                }
                else if (ent is Arc)
                {
                    segments.Add(new RadiusItemSegment(ent as Arc));
                }
                else if (ent is Polyline)
                {
                    Polyline pl = ent as Polyline;
                    int      count;
                    if (pl.Closed)
                    {
                        count = pl.NumberOfVertices;
                    }
                    else
                    {
                        count = pl.NumberOfVertices - 1;
                    }

                    for (int j = 0; j < count; j++)
                    {
                        SegmentType st = pl.GetSegmentType(j);
                        if (st == SegmentType.Line)
                        {
                            LineSegment2d lsd = pl.GetLineSegment2dAt(j);
                            segments.Add(new StraitItemSegment(lsd.Length));
                        }
                        else if (st == SegmentType.Arc)
                        {
                            CircularArc2d arc_s = pl.GetArcSegment2dAt(j);
                            Plane         pn    = new Plane(Point3d.Origin, Vector3d.XAxis, Vector3d.YAxis);
                            Arc           arc   = new Arc(new Point3d(pn, arc_s.Center), Vector3d.ZAxis, arc_s.Radius, arc_s.StartAngle, arc_s.EndAngle);
                            segments.Add(new RadiusItemSegment(arc));
                        }
                    }
                }
            }
            base.count = ItemInput.ItemCount();
            status     = true;
        }
Пример #27
0
        /// <summary>
        ///     Gets the centroid of the polyline.
        /// </summary>
        /// <param name="pl">The instance to which the method applies.</param>
        /// <returns>The centroid of the polyline (OCS coordinates).</returns>
        public static Point2d Centroid2D(this Polyline pl)
        {
            var    cen = new Point2d();
            var    tri = new Triangle2D();
            var    arc = new CircularArc2d();
            double tmpArea;
            var    area  = 0.0;
            var    last  = pl.NumberOfVertices - 1;
            var    p0    = pl.GetPoint2dAt(0);
            var    bulge = pl.GetBulgeAt(0);

            if (bulge != 0.0)
            {
                arc  = pl.GetArcSegment2dAt(0);
                area = arc.AlgebricArea();
                cen  = arc.Centroid() * area;
            }

            for (var i = 1; i < last; i++)
            {
                tri.Set(p0, pl.GetPoint2dAt(i), pl.GetPoint2dAt(i + 1));
                tmpArea = tri.AlgebricArea;
                cen    += (tri.Centroid * tmpArea).GetAsVector();
                area   += tmpArea;
                bulge   = pl.GetBulgeAt(i);
                if (bulge != 0.0)
                {
                    arc     = pl.GetArcSegment2dAt(i);
                    tmpArea = arc.AlgebricArea();
                    area   += tmpArea;
                    cen    += (arc.Centroid() * tmpArea).GetAsVector();
                }
            }

            bulge = pl.GetBulgeAt(last);
            if (bulge != 0.0 && pl.Closed)
            {
                arc     = pl.GetArcSegment2dAt(last);
                tmpArea = arc.AlgebricArea();
                area   += tmpArea;
                cen    += (arc.Centroid() * tmpArea).GetAsVector();
            }

            return(cen.DivideBy(area));
        }
        /// <summary>
        /// Gets the centroid of the polyline.
        /// </summary>
        /// <param name="pl">The instance to which the method applies.</param>
        /// <returns>The centroid of the polyline (OCS coordinates).</returns>
        public static Point2d Centroid2d(this Polyline pl)
        {
            Point2d       cen = new Point2d();
            Triangle2d    tri = new Triangle2d();
            CircularArc2d arc = new CircularArc2d();
            double        tmpArea;
            double        area  = 0.0;
            int           last  = pl.NumberOfVertices - 1;
            Point2d       p0    = pl.GetPoint2dAt(0);
            double        bulge = pl.GetBulgeAt(0);

            if (bulge != 0.0)
            {
                arc  = pl.GetArcSegment2dAt(0);
                area = arc.AlgebricArea();
                cen  = arc.Centroid() * area;
            }
            for (int i = 1; i < last; i++)
            {
                tri.Set(p0, pl.GetPoint2dAt(i), pl.GetPoint2dAt(i + 1));
                tmpArea = tri.AlgebricArea;
                cen    += (tri.Centroid * tmpArea).GetAsVector();
                area   += tmpArea;
                bulge   = pl.GetBulgeAt(i);
                if (bulge != 0.0)
                {
                    arc     = pl.GetArcSegment2dAt(i);
                    tmpArea = arc.AlgebricArea();
                    area   += tmpArea;
                    cen    += (arc.Centroid() * tmpArea).GetAsVector();
                }
            }
            bulge = pl.GetBulgeAt(last);
            if ((bulge != 0.0) && (pl.Closed == true))
            {
                arc     = pl.GetArcSegment2dAt(last);
                tmpArea = arc.AlgebricArea();
                area   += tmpArea;
                cen    += (arc.Centroid() * tmpArea).GetAsVector();
            }
            return(cen.DivideBy(area));
        }
Пример #29
0
        /// <summary>
        /// Returns the tangents between the active CircularArc2d instance complete circle and a point.
        /// </summary>
        /// <remarks>
        /// Tangents start points are on the object to which this method applies, end points on the point passed as argument.
        /// Tangents are always returned in the same order: the tangent on the left side of the line from the circular arc center
        /// to the point before the other one. 
        /// </remarks>
        /// <param name="arc">The instance to which this method applies.</param>
        /// <param name="pt">The Point2d to which tangents are searched</param>
        /// <returns>An array of LineSegement2d representing the tangents (2) or null if there is none.</returns>
        public static LineSegment2d[] GetTangentsTo(this CircularArc2d arc, Point2d pt)
        {
            // check if the point is inside the circle
            Point2d center = arc.Center;
            if (pt.GetDistanceTo(center) <= arc.Radius)
                return null;

            Vector2d vec = center.GetVectorTo(pt) / 2.0;
            CircularArc2d tmp = new CircularArc2d(center + vec, vec.Length);
            Point2d[] inters = arc.IntersectWith(tmp);
            if (inters == null)
                return null;
            LineSegment2d[] result = new LineSegment2d[2];
            Vector2d v1 = inters[0] - center;
            Vector2d v2 = inters[1] - center;
            int i = vec.X * v1.Y - vec.Y - v1.X > 0 ? 0 : 1;
            int j = i ^ 1;
            result[i] = new LineSegment2d(inters[0], pt);
            result[j] = new LineSegment2d(inters[1], pt);
            return result;
        }
Пример #30
0
        // 由给定圆上三点创建圆的函数.
        public static ObjectId AddCircle(Point2d pt1, Point2d pt2, Point2d pt3)
        {
            const double pi = Math.PI;
            Vector2d     va = pt1.GetVectorTo(pt2);
            Vector2d     vb = pt1.GetVectorTo(pt3);

            if (va.GetAngleTo(vb) == 0 | va.GetAngleTo(vb) == pi)
            {
                ObjectId nullId = ObjectId.Null;
                return(nullId);
            }
            else
            {
                CircularArc2d geoArc = new CircularArc2d(pt1, pt2, pt3);
                Point3d       cenPt  = new Point3d(geoArc.Center.X, geoArc.Center.Y, 0);
                double        radius = geoArc.Radius;
                Circle        ent    = new Circle(cenPt, Vector3d.ZAxis, radius);
                ObjectId      entId  = AppendEntity(ent);
                return(entId);
            }
        }
Пример #31
0
        public static ObjectId AddCircle(Point2d pt1, Point2d pt2, Point2d pt3)
        {
            Vector2d vectorTo  = pt1.GetVectorTo(pt2);
            Vector2d vectorTo2 = pt1.GetVectorTo(pt3);
            ObjectId result;

            if (vectorTo.GetAngleTo(vectorTo2) == 0.0 | vectorTo.GetAngleTo(vectorTo2) == 3.1415926535897931)
            {
                ObjectId @null = ObjectId.Null;
                result = @null;
            }
            else
            {
                CircularArc2d circularArc2d = new CircularArc2d(pt1, pt2, pt3);
                Point3d       point3d;
                point3d..ctor(circularArc2d.Center.X, circularArc2d.Center.Y, 0.0);
                double   radius   = circularArc2d.Radius;
                Circle   ent      = new Circle(point3d, Vector3d.ZAxis, radius);
                ObjectId objectId = ModelSpace.AddEnt(ent);
                result = objectId;
            }
            return(result);
        }
Пример #32
0
 /// <summary>
 /// Creates a new instance of PolylineSegment from a CircularArc2d
 /// </summary>
 /// <param name="arc">A CircularArc2d instance.</param>
 public PolylineSegment(CircularArc2d arc)
 {
     _startPoint = arc.StartPoint;
     _endPoint = arc.EndPoint;
     _bulge = Math.Tan((arc.EndAngle - arc.StartAngle) / 4.0);
     if (arc.IsClockWise) _bulge = -_bulge;
     _startWidth = 0.0;
     _endWidth = 0.0;
 }
Пример #33
0
        public void GetLine()
        {
            var doc = Application.DocumentManager.MdiActiveDocument;
            var ed  = doc.Editor;
            var db  = doc.Database;

            var intOpts = new PromptIntegerOptions("\n请输入每隔多少毫米进行点的合并");

            var intRes = ed.GetInteger(intOpts);

            int intCmeter = 2000;

            if (intRes.Status == PromptStatus.OK)
            {
                intCmeter = intRes.Value;
            }

            var selectRes = ed.GetSelection(new SelectionFilter(new[] { new TypedValue((int)DxfCode.Start, "POLYLINE") }));

            if (selectRes.Status == PromptStatus.OK)
            {
                var selectSet = selectRes.Value;

                List <Polyline3d> listPl = new List <Polyline3d>();

                List <Polyline3d> listPlold = MyForeach(selectSet);

                Point3dCollection p3dcoll = new Point3dCollection();

                if (null == listPlold || listPlold.Count < 1)
                {
                    return;
                }

                var pl3d1 = listPlold[0];

                foreach (var pl3d in listPlold)
                {
                    if (pl3d != null)
                    {
                        using (var trans = db.TransactionManager.StartTransaction())
                        {
                            foreach (ObjectId objId in pl3d)
                            {
                                var vertex3d = trans.GetObject(objId, OpenMode.ForRead) as PolylineVertex3d;

                                p3dcoll.Add(vertex3d.Position);
                            }
                        }
                    }
                }

                Polyline             pline       = new Polyline();
                Point3dCollection    p3dColl2    = new Point3dCollection();
                List <Entity>        listEntity  = new List <Entity>();
                List <Entity>        listEntity2 = new List <Entity>();
                List <CircularArc2d> listC2d     = new List <CircularArc2d>();
                for (int i = 0; i < p3dcoll.Count; i++)
                {
                    int startIndex = i;

                    Point2d pit1 = new Point2d(p3dcoll[i].X, p3dcoll[i].Y);
                    Point2d pit2 = Point2d.Origin;
                    Point2d pit3 = Point2d.Origin;

                    if (i + 1 < p3dcoll.Count)
                    {
                        pit2 = new Point2d(p3dcoll[i + 1].X, p3dcoll[i + 1].Y);
                        i    = i + 1;
                    }

                    if (i + 1 < p3dcoll.Count)
                    {
                        pit3 = new Point2d(p3dcoll[i + 1].X, p3dcoll[i + 1].Y);
                        i    = i + 1;
                    }

                    double length = (pit2 - pit1).Length + (pit3 - pit2).Length;

                    int mid = 0;

                    while (length < intCmeter)
                    {
                        if (i + 1 < p3dcoll.Count)
                        {
                            pit2 = pit3;
                            pit3 = new Point2d(p3dcoll[i + 1].X, p3dcoll[i + 1].Y);
                        }
                        else
                        {
                            break;
                        }
                        i = i + 1;

                        mid++;

                        length = (pit2 - pit1).Length + (pit3 - pit2).Length;
                    }
                    Point2d pitMid = Point2d.Origin;

                    if (mid / 2 > 0)
                    {
                        pitMid = new Point2d(p3dcoll[startIndex + mid / 2].X, p3dcoll[startIndex + mid / 2].Y);
                    }
                    else
                    {
                        pitMid = pit2;
                    }

                    pline.AddVertexAt(pline.NumberOfVertices, pit1, 0, 0, 0);

                    p3dColl2.Add(new Point3d(pit1.X, pit1.Y, 0));

                    if (i < p3dcoll.Count)
                    {
                        pline.AddVertexAt(pline.NumberOfVertices, pitMid, 0, 0, 0);
                        pline.AddVertexAt(pline.NumberOfVertices, pit3, 0, 0, 0);

                        p3dColl2.Add(new Point3d(pitMid.X, pitMid.Y, 0));
                        p3dColl2.Add(new Point3d(pit3.X, pit3.Y, 0));
                    }

                    if (i < p3dcoll.Count)
                    {
                        Arc           arc  = GetArc(pit1, pitMid, pit3);
                        CircularArc2d c2d  = null;
                        Arc           arc2 = GetArc2(pit1, pitMid, pit3, ref c2d);
                        arc.ColorIndex  = 0;
                        arc2.ColorIndex = 0;
                        listEntity.Add(arc);
                        listEntity2.Add(arc2);
                        listC2d.Add(c2d);
                    }

                    if (i == p3dcoll.Count - 1)
                    {
                        break;
                    }
                    i = i - 1;
                }
                pline.Closed     = true;
                pline.ColorIndex = pl3d1.ColorIndex;



                PromptKeywordOptions pkOpts = new PromptKeywordOptions("请输入是否进行弧长优化[Y/N]", "Y N");

                var keyRes = ed.GetKeywords(pkOpts);

                List <Entity> listEntsOptimize = new List <Entity>();

                if (keyRes.Status == PromptStatus.OK && keyRes.StringResult == "Y")
                {
                    ed.WriteMessage("进行弧长优化");


                    for (int i = 0; i < listEntity2.Count; i++)
                    {
                        Arc arc = listEntity2[i] as Arc;

                        Arc arc2 = null;

                        if (!listEntsOptimize.Contains(arc))
                        {
                            listEntsOptimize.Add(arc);
                        }

                        if (i + 1 < listEntity2.Count)
                        {
                            arc2 = listEntity2[i + 1] as Arc;

                            if (!listEntsOptimize.Contains(arc2))
                            {
                                listEntsOptimize.Add(arc2);
                            }

                            i = i + 1;
                        }

                        List <CircularArc2d> tempArc = new List <CircularArc2d>();

                        if (arc != null && arc2 != null)
                        {
                            double angle1 = arc.EndAngle - arc.StartAngle;

                            double angle2 = arc2.EndAngle - arc.StartAngle;

                            while (Math.Abs(angle1 - angle2) <= Math.PI * (30.0 / 180))
                            {
                                if (listEntsOptimize.Contains(arc))
                                {
                                    listEntsOptimize.Remove(arc);
                                }

                                if (listEntsOptimize.Contains(arc2))
                                {
                                    listEntsOptimize.Remove(arc2);
                                }

                                int index = listEntity2.IndexOf(arc);

                                int index2 = listEntity2.IndexOf(arc2);

                                tempArc.Add(listC2d[index]);
                                tempArc.Add(listC2d[index2]);

                                if (i + 1 < listEntity2.Count)
                                {
                                    arc2 = listEntity2[i + 1] as Arc;
                                    i    = i + 1;
                                }
                                else
                                {
                                    arc2 = null;
                                    break;
                                }

                                angle1 = arc.EndAngle - arc.StartAngle;

                                angle2 = arc2.EndAngle - arc.StartAngle;
                            }
                        }
                        List <Polyline> listpolytemp = new List <Polyline>();

                        if (tempArc.Count > 1)
                        {
                            Arc     newTempArc = null;
                            Point2d startPoint = tempArc[0].StartPoint;
                            Point2d endPoint   = tempArc[tempArc.Count - 1].EndPoint;
                            if (tempArc.Count == 2)
                            {
                                Point2d centerPoint = tempArc[0].EndPoint;

                                newTempArc = GetArc(startPoint,
                                                    centerPoint, endPoint);
                            }
                            else
                            {
                                Point2d centerPoint = tempArc[0].EndPoint;

                                newTempArc = GetArc(startPoint,
                                                    centerPoint, endPoint);
                            }
                            newTempArc.Color = Autodesk.AutoCAD.Colors.Color.FromColor(System.Drawing.Color.Red);

                            Polyline l = new Polyline();

                            listEntsOptimize.Add(newTempArc);
                        }

                        if (i == listEntity2.Count - 1)
                        {
                            break;
                        }
                        i = i - 1;
                    }
                }

                List <Polyline> listPoly  = ArcToPolyline(listEntity);
                List <Polyline> listPoly2 = ArcToPolyline(listEntsOptimize);

                Polyline poly  = GetPolyline(listPoly);
                Polyline poly2 = GetPolyline(listPoly2);


                if (keyRes.Status == PromptStatus.OK && keyRes.StringResult == "Y")
                {
                    poly2.ToSpace();
                }
                else
                {
                    poly.ToSpace();
                }

                //List<Polyline> listpolyOptimize = ArcToPolyline(listEntsOptimize);

                // Polyline poly = GetPolyline(listpolyOptimize);


                //var newDoc = Application.DocumentManager.Add("");
                //using (var lock1 = newDoc.LockDocument())
                //{
                //    var newDb = newDoc.Database;

                //    if (keyRes.Status == PromptStatus.OK && keyRes.StringResult == "Y")
                //        poly2.ToSpace(newDb);
                //    else
                //        poly.ToSpace(newDb);


                //}
            }
        }
Пример #34
0
        /// <summary>
        /// Gets the centroid of the polyline.
        /// </summary>
        /// <param name="pl">The instance to which the method applies.</param>
        /// <returns>The centroid of the polyline (OCS coordinates).</returns>
        public static Point2d Centroid2d(this Polyline pl)
        {
            Point2d cen = new Point2d();
            Triangle2d tri = new Triangle2d();
            CircularArc2d arc = new CircularArc2d();
            double tmpArea;
            double area = 0.0;
            int last = pl.NumberOfVertices - 1;
            Point2d p0 = pl.GetPoint2dAt(0);
            double bulge = pl.GetBulgeAt(0);

            if (bulge != 0.0)
            {
                arc = pl.GetArcSegment2dAt(0);
                area = arc.AlgebricArea();
                cen = arc.Centroid() * area;
            }
            for (int i = 1; i < last; i++)
            {
                tri.Set(p0, pl.GetPoint2dAt(i), pl.GetPoint2dAt(i + 1));
                tmpArea = tri.AlgebricArea;
                cen += (tri.Centroid * tmpArea).GetAsVector();
                area += tmpArea;
                bulge = pl.GetBulgeAt(i);
                if (bulge != 0.0)
                {
                    arc = pl.GetArcSegment2dAt(i);
                    tmpArea = arc.AlgebricArea();
                    area += tmpArea;
                    cen += (arc.Centroid() * tmpArea).GetAsVector();
                }
            }
            bulge = pl.GetBulgeAt(last);
            if ((bulge != 0.0) && (pl.Closed == true))
            {
                arc = pl.GetArcSegment2dAt(last);
                tmpArea = arc.AlgebricArea();
                area += tmpArea;
                cen += (arc.Centroid() * tmpArea).GetAsVector();
            }
            return cen.DivideBy(area);
        }
Пример #35
0
        /// <summary>
        /// Returns the tangents between the active CircularArc2d instance complete circle and another one.
        /// </summary>
        /// <remarks>
        /// Tangents start points are on the object to which this method applies, end points on the one passed as argument.
        /// Tangents are always returned in the same order: outer tangents before inner tangents, and for both,
        /// the tangent on the left side of the line from this circular arc center to the other one before the other one.
        /// </remarks>
        /// <param name="arc">The instance to which this method applies.</param>
        /// <param name="other">The CircularArc2d to which searched for tangents.</param>
        /// <param name="flags">An enum value specifying which type of tangent is returned.</param>
        /// <returns>An array of LineSegment2d representing the tangents (maybe 2 or 4) or null if there is none.</returns>
        public static LineSegment2d[] GetTangentsTo(this CircularArc2d arc, CircularArc2d other, TangentType flags)
        {
            // check if a circle is inside the other
            double dist = arc.Center.GetDistanceTo(other.Center);
            if (dist - Math.Abs(arc.Radius - other.Radius) <= Tolerance.Global.EqualPoint)
                return null;

            // check if circles overlap
            bool overlap = arc.Radius + other.Radius >= dist;
            if (overlap && flags == TangentType.Inner)
                return null;

            CircularArc2d tmp1, tmp2;
            Point2d[] inters;
            Vector2d vec1, vec2, vec = other.Center - arc.Center;
            int i, j;
            LineSegment2d[] result = new LineSegment2d[(int)flags == 3 && !overlap ? 4 : 2];

            // outer tangents
            if ((flags & TangentType.Outer) > 0)
            {
                if (arc.Radius == other.Radius)
                {
                    Line2d perp = new Line2d(arc.Center, vec.GetPerpendicularVector());
                    inters = arc.IntersectWith(perp);
                    if (inters == null)
                        return null;
                    vec1 = (inters[0] - arc.Center).GetNormal();
                    vec2 = (inters[1] - arc.Center).GetNormal();
                    i = vec.X * vec1.Y - vec.Y - vec1.X > 0 ? 0 : 1;
                    j = i ^ 1;
                    result[i] = new LineSegment2d(inters[0], inters[0] + vec);
                    result[j] = new LineSegment2d(inters[1], inters[1] + vec);
                }
                else
                {
                    Point2d center = arc.Radius < other.Radius ? other.Center : arc.Center;
                    tmp1 = new CircularArc2d(center, Math.Abs(arc.Radius - other.Radius));
                    tmp2 = new CircularArc2d(arc.Center + vec / 2.0, dist / 2.0);
                    inters = tmp1.IntersectWith(tmp2);
                    if (inters == null)
                        return null;
                    vec1 = (inters[0] - center).GetNormal();
                    vec2 = (inters[1] - center).GetNormal();
                    i = vec.X * vec1.Y - vec.Y - vec1.X > 0 ? 0 : 1;
                    j = i ^ 1;
                    result[i] = new LineSegment2d(arc.Center + vec1 * arc.Radius, other.Center + vec1 * other.Radius);
                    result[j] = new LineSegment2d(arc.Center + vec2 * arc.Radius, other.Center + vec2 * other.Radius);
                }
            }

            // inner tangents
            if ((flags & TangentType.Inner) > 0 && !overlap)
            {
                double ratio = (arc.Radius / (arc.Radius + other.Radius)) / 2.0;
                tmp1 = new CircularArc2d(arc.Center + vec * ratio, dist * ratio);
                inters = arc.IntersectWith(tmp1);
                if (inters == null)
                    return null;
                vec1 = (inters[0] - arc.Center).GetNormal();
                vec2 = (inters[1] - arc.Center).GetNormal();
                i = vec.X * vec1.Y - vec.Y - vec1.X > 0 ? 2 : 3;
                j = i == 2 ? 3 : 2;
                result[i] = new LineSegment2d(arc.Center + vec1 * arc.Radius, other.Center + vec1.Negate() * other.Radius);
                result[j] = new LineSegment2d(arc.Center + vec2 * arc.Radius, other.Center + vec2.Negate() * other.Radius);
            }
            return result;
        }