Exemple #1
0
        public Spline(netDxf.Entities.Spline inputSpline)
        {
            InputSpline = inputSpline;


            double polygonLength = 0;

            for (var i = 0; i < InputSpline.ControlPoints.Count() - 1; i++)
            {
                polygonLength += (InputSpline.ControlPoints[i + 1].Position - InputSpline.ControlPoints[i].Position)
                                 .Modulus();
            }

            chordVariable = (int)(polygonLength * 20);
            var DotsList = inputSpline.PolygonalVertexes(chordVariable);

            MinXMinY = DotsList.First();
            MaxXMaxY = DotsList.First();
            foreach (var item in DotsList)
            {
                CheckIfNewPointExtendArea(item);
            }

            Length = 0;
            for (var i = 0; i < DotsList.Count - 1; i++)
            {
                Length += (DotsList[i + 1] - DotsList[i]).Modulus();
            }
        }
Exemple #2
0
        public Polyline GetCanvasSpline(netDxf.Entities.Spline InputSpline, Vector3 startVector, double canvasHeight)
        {
            var transformedControlPointsList = new PointCollection();

            foreach (var item in InputSpline.PolygonalVertexes(chordVariable))
            {
                transformedControlPointsList.Add(new Point(item.X - startVector.X,
                                                           -item.Y + canvasHeight + startVector.Y));
            }

            var g = new StreamGeometry();
            StreamGeometryContext gc;

            using (gc = g.Open())
            {
                gc.BeginFigure(
                    transformedControlPointsList.First(),
                    false,
                    false);


                gc.PolyLineTo(transformedControlPointsList, false, false);
            }

            var path = new Path
            {
                Stroke          = Brushes.Black,
                StrokeThickness = 1,
                Data            = g
            };


            //return path;
            var temp = new Polyline();

            temp.Stroke          = Brushes.Black;
            temp.StrokeThickness = 1;
            temp.Points          = transformedControlPointsList;
            return(temp);
        }
Exemple #3
0
 /// <summary>
 /// Convert a netDXF spline to a Nucleus curve.
 /// Currently, as no spline implementation yet exists in Nucleus,
 /// the Polyline representation is used.
 /// </summary>
 /// <param name="spline"></param>
 /// <returns></returns>
 public static Curve Convert(netDxf.Entities.Spline spline)
 {
     return(Convert(spline.ToPolyline(50))); //TEMP?
 }
        private void SetInternalInfo(IEnumerable <EntityObject> contour, bool clearEdges)
        {
            bool containsPolyline = false;

            if (clearEdges)
            {
                this.edges.Clear();
            }

            foreach (EntityObject entity in contour)
            {
                if (containsPolyline)
                {
                    throw new ArgumentException("Closed polylines cannot be combined with other entities to make a hatch boundary path.");
                }

                // it seems that AutoCad does not have problems on creating loops that theoretically does not make sense,
                // like, for example, an internal loop that is made of a single arc.
                // so if AutoCAD is OK with that I am too, the program that make use of this information will take care of this inconsistencies
                switch (entity.Type)
                {
                case EntityType.Arc:
                    this.edges.Add(Arc.ConvertFrom(entity));
                    break;

                case EntityType.Circle:
                    this.edges.Add(Arc.ConvertFrom(entity));
                    break;

                case EntityType.Ellipse:
                    this.edges.Add(Ellipse.ConvertFrom(entity));
                    break;

                case EntityType.Line:
                    this.edges.Add(Line.ConvertFrom(entity));
                    break;

                case EntityType.Polyline2D:
                    Entities.Polyline2D lwpoly = (Entities.Polyline2D)entity;
                    if (lwpoly.IsClosed)
                    {
                        if (this.edges.Count != 0)
                        {
                            throw new ArgumentException("Closed polylines cannot be combined with other entities to make a hatch boundary path.");
                        }
                        this.edges.Add(Polyline.ConvertFrom(entity));
                        this.pathType   |= HatchBoundaryPathTypeFlags.Polyline;
                        containsPolyline = true;
                    }
                    else
                    {
                        this.SetInternalInfo(lwpoly.Explode(), false);     // open polylines will always be exploded, only one polyline can be present in a path
                    }
                    break;

                case EntityType.Polyline3D:
                    Entities.Polyline3D poly = (Entities.Polyline3D)entity;
                    if (poly.IsClosed)
                    {
                        if (this.edges.Count != 0)
                        {
                            throw new ArgumentException("Closed polylines cannot be combined with other entities to make a hatch boundary path.");
                        }
                        this.edges.Add(Polyline.ConvertFrom(entity));
                        this.pathType   |= HatchBoundaryPathTypeFlags.Polyline;
                        containsPolyline = true;
                    }
                    else
                    {
                        this.SetInternalInfo(poly.Explode(), false);     // open polylines will always be exploded, only one polyline can be present in a path
                    }
                    break;

                case EntityType.Spline:
                    this.edges.Add(Spline.ConvertFrom(entity));
                    break;

                default:
                    throw new ArgumentException(string.Format("The entity type {0} cannot be part of a hatch boundary. Only Arc, Circle, Ellipse, Line, Polyline2D, Polyline3D, and Spline entities are allowed.", entity.Type));
                }
            }
        }
 public override object Clone()
 {
     Spline copy = new Spline
     {
         Degree = this.Degree,
         IsRational = this.IsRational,
         IsPeriodic = this.IsPeriodic,
         Knots = new double[this.Knots.Length],
         ControlPoints = new Vector3[this.ControlPoints.Length],
         
     };
     for (int i = 0; i < this.Knots.Length; i++)
     {
         copy.Knots[i] = this.Knots[i];
     }
     for (int i = 0; i < this.ControlPoints.Length; i++)
     {
         copy.ControlPoints[i] = this.ControlPoints[i];
     }
     return copy;
 }
Exemple #6
0
        private void WriteSpline(Spline spline)
        {
            this.chunk.Write(100, SubclassMarker.Spline);

            short flag = (short) spline.Flags;
            if (spline.IsClosed) flag += (short) SplineTypeFlags.Unknown4;
            this.chunk.Write(70, flag);
            this.chunk.Write(71, spline.Degree);

            // the next two codes are purely cosmetic and writing them causes more bad than good.
            // internally AutoCad allows for an INT number of knots and control points,
            // but for some dumb decision Autodesk decided to define them in the dxf with codes 72 and 73 (16-bit integer value), this is a SHORT in net.
            // I guess this is the result of legacy code, AutoCad do not use those values when importing the Spline entity
            //this.chunk.Write(72, (short)spline.Knots.Length);
            //this.chunk.Write(73, (short)spline.ControlPoints.Count);

            //this.chunk.Write(74, 0); Number of fit points (if any).

            //this.chunk.Write(42, 0); 42 Knot tolerance (default = 0.0000001)
            //this.chunk.Write(43, 0); 43 Control-point tolerance (default = 0.0000001)
            //this.chunk.Write(44, 0); 44 Fit tolerance (default = 0.0000000001)


            foreach (double knot in spline.Knots)
                this.chunk.Write(40, knot);

            foreach (SplineVertex point in spline.ControlPoints)
            {
                this.chunk.Write(41, point.Weigth);
                this.chunk.Write(10, point.Location.X);
                this.chunk.Write(20, point.Location.Y);
                this.chunk.Write(30, point.Location.Z);
            }

            this.WriteXData(spline.XData);
        }
Exemple #7
0
        private static Spline ProcessSpline(Spline spline, Matrix3 trans, Vector3 pos)
        {
            foreach (SplineVertex vertex in spline.ControlPoints)
                vertex.Location = trans*vertex.Location + pos;

            spline.Normal = trans*spline.Normal;
            return spline;
        }
Exemple #8
0
        /// <summary>
        /// Creates a new Spline that is a copy of the current instance.
        /// </summary>
        /// <returns>A new Spline that is a copy of this instance.</returns>
        public override object Clone()
        {
            Spline entity;
            if (this.creationMethod == SplineCreationMethod.FitPoints)
            {
                entity = new Spline(new List<Vector3>(this.fitPoints))
                {
                    //EntityObject properties
                    Layer = (Layer) this.Layer.Clone(),
                    Linetype = (Linetype) this.Linetype.Clone(),
                    Color = (AciColor) this.Color.Clone(),
                    Lineweight = this.Lineweight,
                    Transparency = (Transparency) this.Transparency.Clone(),
                    LinetypeScale = this.LinetypeScale,
                    Normal = this.Normal,
                    IsVisible = this.IsVisible,
                    //Spline properties
                    KnotParameterization = this.KnotParameterization,
                    StartTangent = this.startTangent,
                    EndTangent = this.endTangent
                };
            }
            else
            {
                List<SplineVertex> copyControlPoints = new List<SplineVertex>(this.controlPoints.Count);
                foreach (SplineVertex vertex in this.controlPoints)
                {
                    copyControlPoints.Add((SplineVertex) vertex.Clone());
                }
                List<double> copyKnots = new List<double>(this.knots);

                entity = new Spline(copyControlPoints, copyKnots, this.degree)
                {
                    //EntityObject properties
                    Layer = (Layer) this.Layer.Clone(),
                    Linetype = (Linetype) this.Linetype.Clone(),
                    Color = (AciColor) this.Color.Clone(),
                    Lineweight = this.Lineweight,
                    Transparency = (Transparency) this.Transparency.Clone(),
                    LinetypeScale = this.LinetypeScale,
                    Normal = this.Normal
                    //Spline properties
                };
            }

            foreach (XData data in this.XData.Values)
                entity.XData.Add((XData) data.Clone());

            return entity;
        }
        private static void SplineFitPoints()
        {
            // this will be the list of fit points, the resulting spline will pass through them.
            List<Vector3> points = new List<Vector3>
            {
                new Vector3(0, 0, 0),
                new Vector3(5, 5, 0),
                new Vector3(10, 0, 0),
                new Vector3(15, 5, 0),
                new Vector3(20, 0, 0),
                new Vector3(0, 0, 0)
            };

            // splines crated from a set of fit points are cubic curves (degree 3) and non periodic.
            // to close the spline just repeat the last fit point.
            // note: at the moment splines created this way cannot be used as a boundary path in a hatch, or converted to a polyline or to a list of vertexes,
            // the control point information is not calculated when an spline is created using a list of fit points.
            Spline spline = new Spline(points);

            // to make the spline continuous at the end points we can adjust the start and end tangents.
            spline.StartTangent = new Vector3(0, 1, 0);
            spline.EndTangent = new Vector3(0, 1, 0);

            DxfDocument doc = new DxfDocument();
            doc.AddEntity(spline);

            Spline cloned = (Spline) spline.Clone();
            cloned.Reverse();
            doc.AddEntity(cloned);


            // and this is a spline created with control points
            List<SplineVertex> ctrlPoints = new List<SplineVertex>
                                                {
                                                    new SplineVertex(new Vector3(0, 0, 0), 1.0),
                                                    new SplineVertex(new Vector3(25, 50, 50), 2.0),
                                                    new SplineVertex(new Vector3(50, 0, 100), 3.0),
                                                    new SplineVertex(new Vector3(75, 50, 50), 4.0),
                                                    new SplineVertex(new Vector3(100, 0, 0), 5.0)
                                                };

            // the constructor will generate a uniform knot vector 
            Spline openSpline = new Spline(ctrlPoints, 3);
            Spline cloned2 = (Spline) openSpline.Clone();
            
            cloned2.Reverse();
            doc.AddEntity(openSpline);
            doc.AddEntity(cloned2);

            doc.Save("SplineFitPoints.dxf");
        }
        public static void NurbsEvaluator()
        {
            Layer result = new Layer("Nurbs evaluator");
            result.Color = AciColor.Red;

            List<SplineVertex> ctrlPoints = new List<SplineVertex>
                                                {
                                                    new SplineVertex(new Vector3(0, 0, 0), 1.0),
                                                    new SplineVertex(new Vector3(25, 50, 50), 2.0),
                                                    new SplineVertex(new Vector3(50, 0, 100), 3.0),
                                                    new SplineVertex(new Vector3(75, 50, 50), 4.0),
                                                    new SplineVertex(new Vector3(100, 0, 0), 5.0)
                                                };

            // the constructor will generate a uniform knot vector 
            Spline openSpline = new Spline(ctrlPoints, 3);

            List<SplineVertex> ctrlPointsClosed = new List<SplineVertex>
                                                {
                                                    new SplineVertex(new Vector3(0, 0, 0)),
                                                    new SplineVertex(new Vector3(25, 50, 0)),
                                                    new SplineVertex(new Vector3(50, 0, 0)),
                                                    new SplineVertex(new Vector3(75, 50, 0)),
                                                    new SplineVertex(new Vector3(100, 0, 0)),
                                                    new SplineVertex(new Vector3(0, 0, 0)) // closed spline non periodic we repeat the last control point
                                                };
            Spline closedNonPeriodicSpline = new Spline(ctrlPointsClosed, 3);

            // the periodic spline will generate a periodic (unclamped) closed curve,
            // as far as my tests have gone not all programs handle them correctly, most of them only handle clamped splines
            Spline closedPeriodicSpline = new Spline(ctrlPoints, 4, true);
            // always use spline vertex weights of 1.0 (default value) looks like that AutoCAD does not handle them correctly for periodic splines,
            // but they work fine for non periodic splines
            closedPeriodicSpline.SetUniformWeights(1.0);

            // manually defining the control points and the knot vector (example a circle created with nurbs)
            List<SplineVertex> circle = new List<SplineVertex>
                                                {
                                                    new SplineVertex(new Vector3(50, 0, 0), 1.0),
                                                    new SplineVertex(new Vector3(100, 0, 0), 0.5),
                                                    new SplineVertex(new Vector3(100, 100, 0), 0.5),
                                                    new SplineVertex(new Vector3(50, 100, 0), 1.0),
                                                    new SplineVertex(new Vector3(0, 100, 0), 0.5),
                                                    new SplineVertex(new Vector3(0, 0, 0), 0.5),
                                                    new SplineVertex(new Vector3(50, 0, 0), 1.0) // repeat the first point to close the circle
                                                };

            // the number of knots must be control points number + degree + 1
            // Conics are 2nd degree curves
            List<double> knots = new List<double>{ 0.0, 0.0, 0.0, 1.0 / 4.0, 1.0 / 2.0, 1.0 / 2.0, 3.0 / 4.0, 1.0, 1.0, 1.0 };
            Spline splineCircle = new Spline(circle, knots, 2);

            DxfDocument dxf = new DxfDocument();

            Polyline pol;

            dxf.AddEntity(openSpline);
            // we will convert the Spline to a Polyline
            pol = openSpline.ToPolyline(100);
            pol.Layer = result;
            dxf.AddEntity(pol);

            dxf.AddEntity(closedNonPeriodicSpline);
            pol = closedNonPeriodicSpline.ToPolyline(100);
            pol.Layer = result;
            dxf.AddEntity(pol);

            dxf.AddEntity(closedPeriodicSpline);
            pol = closedPeriodicSpline.ToPolyline(100);
            pol.Layer = result;
            dxf.AddEntity(pol);
      
            dxf.AddEntity(splineCircle);
            pol = splineCircle.ToPolyline(100);
            pol.Layer = result;
            dxf.AddEntity(pol);

            dxf.Save("spline.dxf");

        }
Exemple #11
0
        private Spline ReadSpline()
        {
            SplineTypeFlags flags = SplineTypeFlags.None;
            Vector3 normal = Vector3.UnitZ;
            short degree = 3;
            int ctrlPointIndex = -1;

            List<double> knots = new List<double>();
            List<SplineVertex> ctrlPoints = new List<SplineVertex>();
            double ctrlX = 0;
            double ctrlY = 0;
            double ctrlZ = 0;
            double ctrlWeigth = -1;

            // tolerances (not used)
            double knotTolerance = 0.0000001;
            double ctrlPointTolerance = 0.0000001;
            double fitTolerance = 0.0000000001;

            // start and end tangents (not used)
            double stX = 0;
            double stY = 0;
            double stZ = 0;
            Vector3? startTangent = null;
            double etX = 0;
            double etY = 0;
            double etZ = 0;
            Vector3? endTangent = null;

            // fit points variable (not used)
            //int numFitPoints = 0;
            List<Vector3> fitPoints = new List<Vector3>();
            double fitX = 0;
            double fitY = 0;
            double fitZ = 0;

            List<XData> xData = new List<XData>();

            this.chunk.Next();
            while (this.chunk.Code != 0)
            {
                switch (this.chunk.Code)
                {
                    case 210:
                        normal.X = this.chunk.ReadDouble();
                        this.chunk.Next();
                        break;
                    case 220:
                        normal.Y = this.chunk.ReadDouble();
                        this.chunk.Next();
                        break;
                    case 230:
                        normal.Z = this.chunk.ReadDouble();
                        this.chunk.Next();
                        break;
                    case 70:
                        flags = (SplineTypeFlags) this.chunk.ReadShort();
                        this.chunk.Next();
                        break;
                    case 71:
                        degree = this.chunk.ReadShort();
                        this.chunk.Next();
                        break;
                    case 72:
                        // the spline entity can actually hold a larger number of knots, we cannot use this information it might be wrong.
                        //short numKnots = this.chunk.ReadShort();
                        this.chunk.Next();
                        break;
                    case 73:
                        // the spline entity can actually hold a larger number of control points
                        //short numCtrlPoints = this.chunk.ReadShort();
                        this.chunk.Next();
                        break;
                    case 74:
                        // the spline entity can actually hold a larger number of fit points, we cannot use this information it might be wrong.
                        //numFitPoints = this.chunk.ReadShort();
                        this.chunk.Next();
                        break;
                    case 42:
                        knotTolerance = this.chunk.ReadDouble();
                        this.chunk.Next();
                        break;
                    case 43:
                        ctrlPointTolerance = this.chunk.ReadDouble();
                        this.chunk.Next();
                        break;
                    case 44:
                        fitTolerance = this.chunk.ReadDouble();
                        this.chunk.Next();
                        break;
                    case 12:
                        stX = this.chunk.ReadDouble();
                        this.chunk.Next();
                        break;
                    case 22:
                        stY = this.chunk.ReadDouble();
                        this.chunk.Next();
                        break;
                    case 32:
                        stZ = this.chunk.ReadDouble();
                        startTangent = new Vector3(stX, stY, stZ);
                        this.chunk.Next();
                        break;
                    case 13:
                        etX = this.chunk.ReadDouble();
                        this.chunk.Next();
                        break;
                    case 23:
                        etY = this.chunk.ReadDouble();
                        this.chunk.Next();
                        break;
                    case 33:
                        etZ = this.chunk.ReadDouble();
                        endTangent = new Vector3(stX, stY, stZ);
                        this.chunk.Next();
                        break;
                    case 40:
                        // multiple code 40 entries, one per knot value
                        knots.Add(this.chunk.ReadDouble());
                        this.chunk.Next();
                        break;
                    case 10:
                        ctrlX = this.chunk.ReadDouble();
                        this.chunk.Next();
                        break;
                    case 20:
                        ctrlY = this.chunk.ReadDouble();
                        this.chunk.Next();
                        break;
                    case 30:
                        ctrlZ = this.chunk.ReadDouble();

                        if (ctrlWeigth <= 0)
                        {
                            ctrlPoints.Add(new SplineVertex(ctrlX, ctrlY, ctrlZ));
                            ctrlPointIndex = ctrlPoints.Count - 1;
                        }
                        else
                        {
                            ctrlPoints.Add(new SplineVertex(ctrlX, ctrlY, ctrlZ, ctrlWeigth));
                            ctrlPointIndex = -1;
                        }
                        this.chunk.Next();
                        break;
                    case 41:
                        // code 41 might appear before or after the control point coordinates.
                        double weigth = this.chunk.ReadDouble();
                        if (weigth <= 0.0) weigth = 1.0;

                        if (ctrlPointIndex == -1)
                        {
                            ctrlWeigth = weigth;
                        }
                        else
                        {
                            ctrlPoints[ctrlPointIndex].Weigth = weigth;
                            ctrlWeigth = -1;
                        }
                        this.chunk.Next();
                        break;
                    case 11:
                        fitX = this.chunk.ReadDouble();
                        this.chunk.Next();
                        break;
                    case 21:
                        fitY = this.chunk.ReadDouble();
                        this.chunk.Next();
                        break;
                    case 31:
                        fitZ = this.chunk.ReadDouble();
                        fitPoints.Add(new Vector3(fitX, fitY, fitZ));
                        this.chunk.Next();
                        break;
                    case 1001:
                        string appId = this.DecodeEncodedNonAsciiCharacters(this.chunk.ReadString());
                        XData data = this.ReadXDataRecord(appId);
                        xData.Add(data);
                        break;
                    default:
                        if (this.chunk.Code >= 1000 && this.chunk.Code <= 1071)
                            throw new DxfInvalidCodeValueEntityException(this.chunk.Code, this.chunk.ReadString(),
                                "The extended data of an entity must start with the application registry code.");

                        this.chunk.Next();
                        break;
                }
            }

            Spline entity = new Spline(ctrlPoints, knots.ToArray(), degree);

            entity.XData.AddRange(xData);

            return entity;
        }
Exemple #12
0
        /// <summary>
        /// Obtains a list of vertexes that represent the polyline approximating the curve segments as necessary.
        /// </summary>
        /// <param name="bulgePrecision">Curve segments precision. The number of vertexes created, a value of zero means that no approximation will be made.</param>
        /// <param name="weldThreshold">Tolerance to consider if two new generated vertexes are equal.</param>
        /// <param name="bulgeThreshold">Minimum distance from which approximate curved segments of the polyline.</param>
        /// <returns>A list of vertexes expressed in object coordinate system.</returns>
        public List <Vector2> PolygonalVertexes(int bulgePrecision, double weldThreshold, double bulgeThreshold)
        {
            if (bulgePrecision < 0)
            {
                throw new ArgumentOutOfRangeException(nameof(bulgePrecision), bulgePrecision, "The bulgePrecision must be equal or greater than zero.");
            }

            List <Vector2> ocsVertexes = new List <Vector2>();
            int            degree;

            if (this.smoothType == PolylineSmoothType.Quadratic)
            {
                degree = 2;
            }
            else if (this.smoothType == PolylineSmoothType.Cubic)
            {
                degree = 3;
            }
            else
            {
                int index = 0;

                foreach (Polyline2DVertex vertex in this.Vertexes)
                {
                    double  bulge = vertex.Bulge;
                    Vector2 p1;
                    Vector2 p2;

                    if (index == this.Vertexes.Count - 1)
                    {
                        p1 = new Vector2(vertex.Position.X, vertex.Position.Y);
                        if (!this.IsClosed)
                        {
                            ocsVertexes.Add(p1);
                            continue;
                        }
                        p2 = new Vector2(this.vertexes[0].Position.X, this.vertexes[0].Position.Y);
                    }
                    else
                    {
                        p1 = new Vector2(vertex.Position.X, vertex.Position.Y);
                        p2 = new Vector2(this.vertexes[index + 1].Position.X, this.vertexes[index + 1].Position.Y);
                    }

                    if (!p1.Equals(p2, weldThreshold))
                    {
                        if (MathHelper.IsZero(bulge) || bulgePrecision == 0)
                        {
                            ocsVertexes.Add(p1);
                        }
                        else
                        {
                            double c = Vector2.Distance(p1, p2) * 0.5;
                            if (c >= bulgeThreshold)
                            {
                                double  s      = c * Math.Abs(bulge);
                                double  r      = (c * c + s * s) / (2.0 * s);
                                double  theta  = 4 * Math.Atan(Math.Abs(bulge));
                                double  gamma  = (Math.PI - theta) * 0.5;
                                double  phi    = Vector2.Angle(p1, p2) + Math.Sign(bulge) * gamma;
                                Vector2 center = new Vector2(p1.X + r * Math.Cos(phi), p1.Y + r * Math.Sin(phi));
                                Vector2 a1     = p1 - center;
                                double  angle  = Math.Sign(bulge) * theta / (bulgePrecision + 1);
                                ocsVertexes.Add(p1);
                                Vector2 prevCurvePoint = p1;
                                for (int i = 1; i <= bulgePrecision; i++)
                                {
                                    Vector2 curvePoint = new Vector2
                                    {
                                        X = center.X + Math.Cos(i * angle) * a1.X - Math.Sin(i * angle) * a1.Y,
                                        Y = center.Y + Math.Sin(i * angle) * a1.X + Math.Cos(i * angle) * a1.Y
                                    };

                                    if (!curvePoint.Equals(prevCurvePoint, weldThreshold) && !curvePoint.Equals(p2, weldThreshold))
                                    {
                                        ocsVertexes.Add(curvePoint);
                                        prevCurvePoint = curvePoint;
                                    }
                                }
                            }
                            else
                            {
                                ocsVertexes.Add(p1);
                            }
                        }
                    }
                    index++;
                }

                return(ocsVertexes);
            }

            List <SplineVertex> ctrlPoints = new List <SplineVertex>();

            foreach (Polyline2DVertex vertex in this.vertexes)
            {
                ctrlPoints.Add(new SplineVertex(vertex.Position));
            }

            // closed polylines will be considered as closed and periodic
            List <Vector3> points = Spline.NurbsEvaluator(ctrlPoints, null, degree, false, this.IsClosed, bulgePrecision);

            foreach (Vector3 point in points)
            {
                ocsVertexes.Add(new Vector2(point.X, point.Y));
            }

            return(ocsVertexes);
        }
Exemple #13
0
        /// <summary>
        /// Decompose the actual polyline in its internal entities, <see cref="Line">lines</see> and <see cref="Arc">arcs</see>.
        /// </summary>
        /// <returns>A list of <see cref="Line">lines</see> and <see cref="Arc">arcs</see> that made up the polyline.</returns>
        public List <EntityObject> Explode()
        {
            List <EntityObject> entities = new List <EntityObject>();

            if (this.smoothType == PolylineSmoothType.NoSmooth)
            {
                int index = 0;
                foreach (Polyline2DVertex vertex in this.Vertexes)
                {
                    double  bulge = vertex.Bulge;
                    Vector2 p1;
                    Vector2 p2;

                    if (index == this.Vertexes.Count - 1)
                    {
                        if (!this.IsClosed)
                        {
                            break;
                        }
                        p1 = new Vector2(vertex.Position.X, vertex.Position.Y);
                        p2 = new Vector2(this.vertexes[0].Position.X, this.vertexes[0].Position.Y);
                    }
                    else
                    {
                        p1 = new Vector2(vertex.Position.X, vertex.Position.Y);
                        p2 = new Vector2(this.vertexes[index + 1].Position.X, this.vertexes[index + 1].Position.Y);
                    }

                    if (MathHelper.IsZero(bulge))
                    {
                        // the polyline edge is a line
                        Vector3 start = MathHelper.Transform(new Vector3(p1.X, p1.Y, this.elevation), this.Normal, CoordinateSystem.Object, CoordinateSystem.World);
                        Vector3 end   = MathHelper.Transform(new Vector3(p2.X, p2.Y, this.elevation), this.Normal, CoordinateSystem.Object, CoordinateSystem.World);

                        entities.Add(new Line
                        {
                            Layer         = (Layer)this.Layer.Clone(),
                            Linetype      = (Linetype)this.Linetype.Clone(),
                            Color         = (AciColor)this.Color.Clone(),
                            Lineweight    = this.Lineweight,
                            Transparency  = (Transparency)this.Transparency.Clone(),
                            LinetypeScale = this.LinetypeScale,
                            Normal        = this.Normal,
                            StartPoint    = start,
                            EndPoint      = end,
                            Thickness     = this.Thickness
                        });
                    }
                    else
                    {
                        // the polyline edge is an arc
                        double theta = 4 * Math.Atan(Math.Abs(bulge));
                        double c     = Vector2.Distance(p1, p2) / 2.0;
                        double r     = c / Math.Sin(theta / 2.0);

                        // avoid arcs with very small radius, draw a line instead
                        if (MathHelper.IsZero(r))
                        {
                            // the polyline edge is a line
                            List <Vector3> points = MathHelper.Transform(
                                new []
                            {
                                new Vector3(p1.X, p1.Y, this.elevation),
                                new Vector3(p2.X, p2.Y, this.elevation)
                            },
                                this.Normal,
                                CoordinateSystem.Object, CoordinateSystem.World);

                            entities.Add(new Line
                            {
                                Layer         = (Layer)this.Layer.Clone(),
                                Linetype      = (Linetype)this.Linetype.Clone(),
                                Color         = (AciColor)this.Color.Clone(),
                                Lineweight    = this.Lineweight,
                                Transparency  = (Transparency)this.Transparency.Clone(),
                                LinetypeScale = this.LinetypeScale,
                                Normal        = this.Normal,
                                StartPoint    = points[0],
                                EndPoint      = points[1],
                                Thickness     = this.Thickness,
                            });
                        }
                        else
                        {
                            double  gamma  = (Math.PI - theta) / 2;
                            double  phi    = Vector2.Angle(p1, p2) + Math.Sign(bulge) * gamma;
                            Vector2 center = new Vector2(p1.X + r * Math.Cos(phi), p1.Y + r * Math.Sin(phi));
                            double  startAngle;
                            double  endAngle;
                            if (bulge > 0)
                            {
                                startAngle = MathHelper.RadToDeg * Vector2.Angle(p1 - center);
                                endAngle   = startAngle + MathHelper.RadToDeg * theta;
                            }
                            else
                            {
                                endAngle   = MathHelper.RadToDeg * Vector2.Angle(p1 - center);
                                startAngle = endAngle - MathHelper.RadToDeg * theta;
                            }
                            Vector3 point = MathHelper.Transform(new Vector3(center.X, center.Y,
                                                                             this.elevation),
                                                                 this.Normal,
                                                                 CoordinateSystem.Object,
                                                                 CoordinateSystem.World);

                            entities.Add(new Arc
                            {
                                Layer         = (Layer)this.Layer.Clone(),
                                Linetype      = (Linetype)this.Linetype.Clone(),
                                Color         = (AciColor)this.Color.Clone(),
                                Lineweight    = this.Lineweight,
                                Transparency  = (Transparency)this.Transparency.Clone(),
                                LinetypeScale = this.LinetypeScale,
                                Normal        = this.Normal,
                                Center        = point,
                                Radius        = r,
                                StartAngle    = startAngle,
                                EndAngle      = endAngle,
                                Thickness     = this.Thickness,
                            });
                        }
                    }
                    index++;
                }
                return(entities);
            }

            List <SplineVertex> wcsVertexes = new List <SplineVertex>();
            Matrix3             trans       = MathHelper.ArbitraryAxis(this.Normal);

            foreach (Polyline2DVertex vertex in this.vertexes)
            {
                Vector3 wcsVertex = trans * new Vector3(vertex.Position.X, vertex.Position.Y, this.elevation);
                wcsVertexes.Add(new SplineVertex(wcsVertex));
            }

            int            degree       = this.smoothType == PolylineSmoothType.Quadratic ? 2 : 3;
            int            splineSegs   = this.Owner == null ? DefaultSplineSegs : this.Owner.Record.Owner.Owner.DrawingVariables.SplineSegs;
            int            precision    = this.IsClosed ? splineSegs * this.Vertexes.Count : splineSegs * (this.Vertexes.Count - 1);
            List <Vector3> splinePoints = Spline.NurbsEvaluator(wcsVertexes, null, degree, false, this.IsClosed, precision);

            for (int i = 1; i < splinePoints.Count; i++)
            {
                Vector3 start = splinePoints[i - 1];
                Vector3 end   = splinePoints[i];
                entities.Add(new Line
                {
                    Layer         = (Layer)this.Layer.Clone(),
                    Linetype      = (Linetype)this.Linetype.Clone(),
                    Color         = (AciColor)this.Color.Clone(),
                    Lineweight    = this.Lineweight,
                    Transparency  = (Transparency)this.Transparency.Clone(),
                    LinetypeScale = this.LinetypeScale,
                    Normal        = this.Normal,
                    StartPoint    = start,
                    EndPoint      = end,
                    Thickness     = this.Thickness
                });
            }

            if (this.IsClosed)
            {
                entities.Add(new Line
                {
                    Layer         = (Layer)this.Layer.Clone(),
                    Linetype      = (Linetype)this.Linetype.Clone(),
                    Color         = (AciColor)this.Color.Clone(),
                    Lineweight    = this.Lineweight,
                    Transparency  = (Transparency)this.Transparency.Clone(),
                    LinetypeScale = this.LinetypeScale,
                    Normal        = this.Normal,
                    StartPoint    = splinePoints[splinePoints.Count - 1],
                    EndPoint      = splinePoints[0],
                    Thickness     = this.Thickness
                });
            }

            return(entities);
        }
Exemple #14
0
        /// <summary>
        /// Creates a new Spline that is a copy of the current instance.
        /// </summary>
        /// <returns>A new Spline that is a copy of this instance.</returns>
        public override object Clone()
        {
            List<SplineVertex> copyControlPoints = new List<SplineVertex>(this.controlPoints.Count);
            foreach (SplineVertex vertex in this.controlPoints)
            {
                copyControlPoints.Add((SplineVertex) vertex.Clone());
            }
            double[] copyKnots = new double[this.knots.Length];
            this.knots.CopyTo(copyKnots, 0);

            Spline entity = new Spline(copyControlPoints, copyKnots, this.degree)
            {
                //EntityObject properties
                Layer = (Layer) this.layer.Clone(),
                LineType = (LineType) this.lineType.Clone(),
                Color = (AciColor) this.color.Clone(),
                Lineweight = (Lineweight) this.lineweight.Clone(),
                Transparency = (Transparency) this.transparency.Clone(),
                LineTypeScale = this.lineTypeScale,
                Normal = this.normal
                //Spline properties
            };

            foreach (XData data in this.XData.Values)
                entity.XData.Add((XData) data.Clone());

            return entity;
        }
        private void SetInternalInfo(IEnumerable <EntityObject> entities)
        {
            bool containsClosedPolyline = false;

            foreach (EntityObject entity in entities)
            {
                if ((pathTypeFlag & HatchBoundaryPathTypeFlag.Polyline) == HatchBoundaryPathTypeFlag.Polyline)
                {
                    if (this.edges.Count >= 1)
                    {
                        throw new ArgumentException("Closed polylines cannot be combined with other entities to make a hatch boundary path.");
                    }
                }

                // it seems that AutoCad does not have problems on creating loops that theorically does not make sense, like, for example an internal loop that is made of a single arc.
                // so if AutoCAD is ok with that I am too, the program that make use of this information will take care of this inconsistencies
                switch (entity.Type)
                {
                case EntityType.Arc:
                    if (containsClosedPolyline)
                    {
                        throw new ArgumentException("Closed polylines cannot be combined with other entities to make a hatch boundary path.");
                    }
                    this.edges.Add(Arc.ConvertFrom(entity));
                    break;

                case EntityType.Circle:
                    if (containsClosedPolyline)
                    {
                        throw new ArgumentException("Closed polylines cannot be combined with other entities to make a hatch boundary path.");
                    }
                    this.edges.Add(Arc.ConvertFrom(entity));
                    break;

                case EntityType.Ellipse:
                    if (containsClosedPolyline)
                    {
                        throw new ArgumentException("Closed polylines cannot be combined with other entities to make a hatch boundary path.");
                    }
                    this.edges.Add(Ellipse.ConvertFrom(entity));
                    break;

                case EntityType.Line:
                    if (containsClosedPolyline)
                    {
                        throw new ArgumentException("Closed polylines cannot be combined with other entities to make a hatch boundary path.");
                    }
                    this.edges.Add(Line.ConvertFrom(entity));
                    break;

                case EntityType.LightWeightPolyline:
                    if (containsClosedPolyline)
                    {
                        throw new ArgumentException("Closed polylines cannot be combined with other entities to make a hatch boundary path.");
                    }
                    LwPolyline poly = (LwPolyline)entity;
                    if (poly.IsClosed)
                    {
                        this.edges.Add(Polyline.ConvertFrom(entity));     // A polyline HatchBoundaryPath must be closed
                        this.pathTypeFlag     |= HatchBoundaryPathTypeFlag.Polyline;
                        containsClosedPolyline = true;
                    }
                    else
                    {
                        this.SetInternalInfo(poly.Explode());     // open polylines will always be exploded, only one polyline can be present in a path
                    }
                    break;

                case EntityType.Spline:
                    if (containsClosedPolyline)
                    {
                        throw new ArgumentException("Closed polylines cannot be combined with other entities to make a hatch boundary path.");
                    }
                    this.edges.Add(Spline.ConvertFrom(entity));
                    break;

                default:
                    throw new ArgumentException("The entity type " + entity.Type + " unknown or not implemented as part of a hatch boundary.");
                }
            }
        }
Exemple #16
0
        /// <summary>
        /// Decompose the actual polyline in a list of <see cref="Line">lines</see>.
        /// </summary>
        /// <returns>A list of <see cref="Line">lines</see> that made up the polyline.</returns>
        public List <EntityObject> Explode()
        {
            List <EntityObject> entities = new List <EntityObject>();

            if (this.smoothType == PolylineSmoothType.NoSmooth)
            {
                int index = 0;
                foreach (Vector3 vertex in this.Vertexes)
                {
                    Vector3 start;
                    Vector3 end;

                    if (index == this.Vertexes.Count - 1)
                    {
                        if (!this.IsClosed)
                        {
                            break;
                        }
                        start = vertex;
                        end   = this.vertexes[0];
                    }
                    else
                    {
                        start = vertex;
                        end   = this.vertexes[index + 1];
                    }

                    entities.Add(new Line
                    {
                        Layer         = (Layer)this.Layer.Clone(),
                        Linetype      = (Linetype)this.Linetype.Clone(),
                        Color         = (AciColor)this.Color.Clone(),
                        Lineweight    = this.Lineweight,
                        Transparency  = (Transparency)this.Transparency.Clone(),
                        LinetypeScale = this.LinetypeScale,
                        Normal        = this.Normal,
                        StartPoint    = start,
                        EndPoint      = end,
                    });

                    index++;
                }

                return(entities);
            }

            int            degree       = this.smoothType == PolylineSmoothType.Quadratic ? 2 : 3;
            int            splineSegs   = this.Owner == null ? DefaultSplineSegs : this.Owner.Record.Owner.Owner.DrawingVariables.SplineSegs;
            int            precision    = this.IsClosed ? splineSegs * this.Vertexes.Count : splineSegs * (this.Vertexes.Count - 1);
            List <Vector3> splinePoints = Spline.NurbsEvaluator(this.vertexes.ToArray(), null, null, degree, false, this.IsClosed, precision);

            for (int i = 1; i < splinePoints.Count; i++)
            {
                Vector3 start = splinePoints[i - 1];
                Vector3 end   = splinePoints[i];
                entities.Add(new Line
                {
                    Layer         = (Layer)this.Layer.Clone(),
                    Linetype      = (Linetype)this.Linetype.Clone(),
                    Color         = (AciColor)this.Color.Clone(),
                    Lineweight    = this.Lineweight,
                    Transparency  = (Transparency)this.Transparency.Clone(),
                    LinetypeScale = this.LinetypeScale,
                    Normal        = this.Normal,
                    StartPoint    = start,
                    EndPoint      = end
                });
            }

            if (this.IsClosed)
            {
                entities.Add(new Line
                {
                    Layer         = (Layer)this.Layer.Clone(),
                    Linetype      = (Linetype)this.Linetype.Clone(),
                    Color         = (AciColor)this.Color.Clone(),
                    Lineweight    = this.Lineweight,
                    Transparency  = (Transparency)this.Transparency.Clone(),
                    LinetypeScale = this.LinetypeScale,
                    Normal        = this.Normal,
                    StartPoint    = splinePoints[splinePoints.Count - 1],
                    EndPoint      = splinePoints[0]
                });
            }

            return(entities);
        }
        private static void WriteSplineBoundaryHatch()
        {

            List<SplineVertex> ctrlPoints = new List<SplineVertex>
                                                {
                                                    new SplineVertex(new Vector3(0, 0, 0)),
                                                    new SplineVertex(new Vector3(25, 50, 0)),
                                                    new SplineVertex(new Vector3(50, 0, 0)),
                                                    new SplineVertex(new Vector3(75, 50, 0)),
                                                    new SplineVertex(new Vector3(100, 0, 0))
                                                };

            // hatch with single closed spline boundary path
            Spline spline = new Spline(ctrlPoints, 3, true); // closed periodic

            List<HatchBoundaryPath> boundary = new List<HatchBoundaryPath>();

            HatchBoundaryPath path = new HatchBoundaryPath(new List<EntityObject> {spline});
            boundary.Add(path);
            Hatch hatch = new Hatch(HatchPattern.Line, boundary, true);
            hatch.Pattern.Angle = 45;
            hatch.Pattern.Scale = 10;

            DxfDocument dxf = new DxfDocument();
            dxf.AddEntity(hatch);
            dxf.AddEntity(spline);
            dxf.Save("hatch closed spline.dxf");
            dxf = DxfDocument.Load("hatch closed spline.dxf");
            dxf.DrawingVariables.AcadVer = DxfVersion.AutoCad2010;
            dxf.Save("hatch closed spline 2010.dxf");

            // hatch boundary path with spline and line
            Spline openSpline = new Spline(ctrlPoints, 3);
            Line line = new Line(ctrlPoints[0].Position, ctrlPoints[ctrlPoints.Count - 1].Position);

            List<HatchBoundaryPath> boundary2 = new List<HatchBoundaryPath>();
            HatchBoundaryPath path2 = new HatchBoundaryPath(new List<EntityObject> { openSpline, line });
            boundary2.Add(path2);
            Hatch hatch2 = new Hatch(HatchPattern.Line, boundary2, true);
            hatch2.Pattern.Angle = 45;
            hatch2.Pattern.Scale = 10;

            DxfDocument dxf2 = new DxfDocument();
            dxf2.AddEntity(hatch2);
            dxf2.AddEntity(openSpline);
            dxf2.AddEntity(line);
            dxf2.Save("hatch open spline.dxf");
            dxf2 = DxfDocument.Load("hatch open spline.dxf");
            dxf.DrawingVariables.AcadVer = DxfVersion.AutoCad2010;
            dxf2.Save("hatch open spline 2010.dxf");

        }
        private void WriteSpline(Spline spline)
        {
            this.chunk.Write(100, SubclassMarker.Spline);

            short flags = (short) spline.Flags;

            if (spline.CreationMethod == SplineCreationMethod.FitPoints)
            {
                flags += (short) SplineTypeFlags.FitPointCreationMethod;
                flags += (short) spline.KnotParameterization;
            }

            if (spline.IsPeriodic)
                flags += (short) SplineTypeFlags.ClosedPeriodicSpline;

            this.chunk.Write(70, flags);
            this.chunk.Write(71, spline.Degree);

            // the next two codes are purely cosmetic and writing them causes more bad than good.
            // internally AutoCad allows for an INT number of knots and control points,
            // but for some dumb decision Autodesk decided to define them in the dxf with codes 72 and 73 (16-bit integer value), this is a SHORT in net.
            // I guess this is the result of legacy code, AutoCad do not use those values when importing Spline entities
            //this.chunk.Write(72, (short)spline.Knots.Length);
            //this.chunk.Write(73, (short)spline.ControlPoints.Count);
            //this.chunk.Write(74, (short)spline.FitPoints.Count);

            this.chunk.Write(42, spline.KnotTolerance);
            this.chunk.Write(43, spline.CtrlPointTolerance);
            this.chunk.Write(44, spline.FitTolerance);

            if (spline.StartTangent != null)
            {
                this.chunk.Write(12, spline.StartTangent.Value.X);
                this.chunk.Write(22, spline.StartTangent.Value.Y);
                this.chunk.Write(32, spline.StartTangent.Value.Z);
            }

            if (spline.EndTangent != null)
            {
                this.chunk.Write(13, spline.EndTangent.Value.X);
                this.chunk.Write(23, spline.EndTangent.Value.Y);
                this.chunk.Write(33, spline.EndTangent.Value.Z);
            }

            foreach (double knot in spline.Knots)
                this.chunk.Write(40, knot);

            foreach (SplineVertex point in spline.ControlPoints)
            {
                this.chunk.Write(41, point.Weigth);
                this.chunk.Write(10, point.Position.X);
                this.chunk.Write(20, point.Position.Y);
                this.chunk.Write(30, point.Position.Z);
            }

            foreach (Vector3 point in spline.FitPoints)
            {
                this.chunk.Write(11, point.X);
                this.chunk.Write(21, point.Y);
                this.chunk.Write(31, point.Z);
            }


            this.WriteXData(spline.XData);
        }
Exemple #19
0
        private Spline ReadSpline()
        {
            SplinetypeFlags flags = SplinetypeFlags.None;
            Vector3 normal = Vector3.UnitZ;
            short degree = 3;
            int ctrlPointIndex = -1;

            List<double> knots = new List<double>();
            List<SplineVertex> ctrlPoints = new List<SplineVertex>();
            double ctrlX = 0;
            double ctrlY = 0;
            double ctrlZ;
            double ctrlWeigth = -1;

            // tolerances (not used)
            double knotTolerance = 0.0000001;
            double ctrlPointTolerance = 0.0000001;
            double fitTolerance = 0.0000000001;

            // start and end tangents
            double stX = 0;
            double stY = 0;
            double stZ;
            Vector3? startTangent = null;
            double etX = 0;
            double etY = 0;
            double etZ;
            Vector3? endTangent = null;

            // fit points variable
            List<Vector3> fitPoints = new List<Vector3>();
            double fitX = 0;
            double fitY = 0;
            double fitZ;

            List<XData> xData = new List<XData>();

            this.chunk.Next();
            while (this.chunk.Code != 0)
            {
                switch (this.chunk.Code)
                {
                    case 210:
                        normal.X = this.chunk.ReadDouble();
                        this.chunk.Next();
                        break;
                    case 220:
                        normal.Y = this.chunk.ReadDouble();
                        this.chunk.Next();
                        break;
                    case 230:
                        normal.Z = this.chunk.ReadDouble();
                        this.chunk.Next();
                        break;
                    case 70:
                        flags = (SplinetypeFlags) this.chunk.ReadShort();
                        this.chunk.Next();
                        break;
                    case 71:
                        degree = this.chunk.ReadShort();
                        this.chunk.Next();
                        break;
                    case 72:
                        // the spline entity can actually hold a larger number of knots, we cannot use this information it might be wrong.
                        //short numKnots = this.chunk.ReadShort();
                        this.chunk.Next();
                        break;
                    case 73:
                        // the spline entity can actually hold a larger number of control points
                        //short numCtrlPoints = this.chunk.ReadShort();
                        this.chunk.Next();
                        break;
                    case 74:
                        // the spline entity can actually hold a larger number of fit points, we cannot use this information it might be wrong.
                        //numFitPoints = this.chunk.ReadShort();
                        this.chunk.Next();
                        break;
                    case 42:
                        knotTolerance = this.chunk.ReadDouble();
                        this.chunk.Next();
                        break;
                    case 43:
                        ctrlPointTolerance = this.chunk.ReadDouble();
                        this.chunk.Next();
                        break;
                    case 44:
                        fitTolerance = this.chunk.ReadDouble();
                        this.chunk.Next();
                        break;
                    case 12:
                        stX = this.chunk.ReadDouble();
                        this.chunk.Next();
                        break;
                    case 22:
                        stY = this.chunk.ReadDouble();
                        this.chunk.Next();
                        break;
                    case 32:
                        stZ = this.chunk.ReadDouble();
                        startTangent = new Vector3(stX, stY, stZ);
                        this.chunk.Next();
                        break;
                    case 13:
                        etX = this.chunk.ReadDouble();
                        this.chunk.Next();
                        break;
                    case 23:
                        etY = this.chunk.ReadDouble();
                        this.chunk.Next();
                        break;
                    case 33:
                        etZ = this.chunk.ReadDouble();
                        endTangent = new Vector3(etX, etY, etZ);
                        this.chunk.Next();
                        break;
                    case 40:
                        // multiple code 40 entries, one per knot value
                        knots.Add(this.chunk.ReadDouble());
                        this.chunk.Next();
                        break;
                    case 10:
                        ctrlX = this.chunk.ReadDouble();
                        this.chunk.Next();
                        break;
                    case 20:
                        ctrlY = this.chunk.ReadDouble();
                        this.chunk.Next();
                        break;
                    case 30:
                        ctrlZ = this.chunk.ReadDouble();
                        if (ctrlWeigth <= 0)
                        {
                            ctrlPoints.Add(new SplineVertex(ctrlX, ctrlY, ctrlZ));
                            ctrlPointIndex = ctrlPoints.Count - 1;
                        }
                        else
                        {
                            ctrlPoints.Add(new SplineVertex(ctrlX, ctrlY, ctrlZ, ctrlWeigth));
                            ctrlPointIndex = -1;
                        }
                        this.chunk.Next();
                        break;
                    case 41:
                        // code 41 might appear before or after the control point coordinates.
                        double weigth = this.chunk.ReadDouble();
                        if (weigth <= 0.0)
                            weigth = 1.0;

                        if (ctrlPointIndex == -1)
                        {
                            ctrlWeigth = weigth;
                        }
                        else
                        {
                            ctrlPoints[ctrlPointIndex].Weigth = weigth;
                            ctrlWeigth = -1;
                        }
                        this.chunk.Next();
                        break;
                    case 11:
                        fitX = this.chunk.ReadDouble();
                        this.chunk.Next();
                        break;
                    case 21:
                        fitY = this.chunk.ReadDouble();
                        this.chunk.Next();
                        break;
                    case 31:
                        fitZ = this.chunk.ReadDouble();
                        fitPoints.Add(new Vector3(fitX, fitY, fitZ));
                        this.chunk.Next();
                        break;
                    case 1001:
                        string appId = this.DecodeEncodedNonAsciiCharacters(this.chunk.ReadString());
                        XData data = this.ReadXDataRecord(this.GetApplicationRegistry(appId));
                        xData.Add(data);
                        break;
                    default:
                        if (this.chunk.Code >= 1000 && this.chunk.Code <= 1071)
                            throw new Exception("The extended data of an entity must start with the application registry code.");

                        this.chunk.Next();
                        break;
                }
            }

            SplineCreationMethod method = flags.HasFlag(SplinetypeFlags.FitPointCreationMethod) ? SplineCreationMethod.FitPoints : SplineCreationMethod.ControlPoints;
            bool isPeriodic = flags.HasFlag(SplinetypeFlags.ClosedPeriodicSpline) || flags.HasFlag(SplinetypeFlags.Periodic);
            Spline entity = new Spline(ctrlPoints, knots, degree, fitPoints, method, isPeriodic)
            {
                KnotTolerance = knotTolerance,
                CtrlPointTolerance = ctrlPointTolerance,
                FitTolerance = fitTolerance,
                StartTangent = startTangent,
                EndTangent = endTangent
            };

            if (flags.HasFlag(SplinetypeFlags.FitChord))
                entity.KnotParameterization = SplineKnotParameterization.FitChord;
            else if (flags.HasFlag(SplinetypeFlags.FitSqrtChord))
                entity.KnotParameterization = SplineKnotParameterization.FitSqrtChord;
            else if (flags.HasFlag(SplinetypeFlags.FitUniform))
                entity.KnotParameterization = SplineKnotParameterization.FitUniform;
            else if (flags.HasFlag(SplinetypeFlags.FitCustom))
                entity.KnotParameterization = SplineKnotParameterization.FitCustom;

            entity.XData.AddRange(xData);

            return entity;
        }