diff --git a/src/ACadSharp.Tests/Entities/ArcTests.cs b/src/ACadSharp.Tests/Entities/ArcTests.cs index 45250e62..ce201169 100644 --- a/src/ACadSharp.Tests/Entities/ArcTests.cs +++ b/src/ACadSharp.Tests/Entities/ArcTests.cs @@ -29,6 +29,19 @@ public void CreateFromBulgeTest() Assert.Equal(Math.PI / 2, arc.EndAngle); } + [Fact] + public void GetBoundingBoxTest() + { + Arc arc = new Arc(); + arc.Radius = 5; + arc.EndAngle = Math.PI / 2; + + BoundingBox boundingBox = arc.GetBoundingBox(); + + Assert.Equal(new XYZ(0, 0, 0), boundingBox.Min); + Assert.Equal(new XYZ(5, 5, 0), boundingBox.Max); + } + [Fact] public void GetCenter() { diff --git a/src/ACadSharp.Tests/Entities/CircleTests.cs b/src/ACadSharp.Tests/Entities/CircleTests.cs new file mode 100644 index 00000000..5944f84e --- /dev/null +++ b/src/ACadSharp.Tests/Entities/CircleTests.cs @@ -0,0 +1,21 @@ +using ACadSharp.Entities; +using CSMath; +using Xunit; + +namespace ACadSharp.Tests.Entities +{ + public class CircleTests + { + [Fact] + public void GetBoundingBoxTest() + { + Circle circle = new Circle(); + circle.Radius = 5; + + BoundingBox boundingBox = circle.GetBoundingBox(); + + Assert.Equal(new XYZ(-5, -5, 0), boundingBox.Min); + Assert.Equal(new XYZ(5, 5, 0), boundingBox.Max); + } + } +} diff --git a/src/ACadSharp.Tests/Entities/EllipseTests.cs b/src/ACadSharp.Tests/Entities/EllipseTests.cs new file mode 100644 index 00000000..e0f59a7f --- /dev/null +++ b/src/ACadSharp.Tests/Entities/EllipseTests.cs @@ -0,0 +1,23 @@ +using ACadSharp.Entities; +using CSMath; +using System; +using Xunit; + +namespace ACadSharp.Tests.Entities +{ + public class EllipseTests + { + [Fact] + public void GetBoundingBoxTest() + { + //Ellipse size: x = 1, y = 0.5 + Ellipse ellipse = new(); + ellipse.RadiusRatio = 0.5d; + + BoundingBox boundingBox = ellipse.GetBoundingBox(); + + Assert.Equal(new XYZ(-1, -0.5, 0), boundingBox.Min); + Assert.Equal(new XYZ(1, 0.5, 0), boundingBox.Max); + } + } +} diff --git a/src/ACadSharp.Tests/Entities/HatchTests.cs b/src/ACadSharp.Tests/Entities/HatchTests.cs index c92b04d1..4ae79b72 100644 --- a/src/ACadSharp.Tests/Entities/HatchTests.cs +++ b/src/ACadSharp.Tests/Entities/HatchTests.cs @@ -113,5 +113,30 @@ public void PolylineHatchNotAllowMoreEdges() } ); } + + [Fact] + public void GetBoundingBoxTest() + { + Hatch hatch = new Hatch(); + hatch.IsSolid = true; + + Hatch.BoundaryPath path = new Hatch.BoundaryPath(); + + Hatch.BoundaryPath.Polyline pline = new Hatch.BoundaryPath.Polyline(); + pline.Vertices.Add(new XYZ(0, 0, 0)); + pline.Vertices.Add(new XYZ(1, 0, 0)); + pline.Vertices.Add(new XYZ(1, 1, 0)); + pline.Vertices.Add(new XYZ(0, 1, 0)); + pline.Vertices.Add(new XYZ(0, 0, 0)); + + path.Edges.Add(pline); + + hatch.Paths.Add(path); + + var box = hatch.GetBoundingBox(); + + Assert.Equal(new XYZ(0, 0, 0), box.Min); + Assert.Equal(new XYZ(1, 1, 0), box.Max); + } } } diff --git a/src/ACadSharp.Tests/Entities/LineTests.cs b/src/ACadSharp.Tests/Entities/LineTests.cs new file mode 100644 index 00000000..572e8ae4 --- /dev/null +++ b/src/ACadSharp.Tests/Entities/LineTests.cs @@ -0,0 +1,21 @@ +using ACadSharp.Entities; +using CSMath; +using Xunit; + +namespace ACadSharp.Tests.Entities +{ + public class LineTests + { + [Fact] + public void GetBoundingBoxTest() + { + Line line = new Line(); + line.EndPoint = new XYZ(10, 10, 0); + + BoundingBox boundingBox = line.GetBoundingBox(); + + Assert.Equal(new XYZ(0, 0, 0), boundingBox.Min); + Assert.Equal(new XYZ(10, 10, 0), boundingBox.Max); + } + } +} diff --git a/src/ACadSharp.Tests/IO/WriterSingleObjectTests.cs b/src/ACadSharp.Tests/IO/WriterSingleObjectTests.cs index d3c7151b..e0614709 100644 --- a/src/ACadSharp.Tests/IO/WriterSingleObjectTests.cs +++ b/src/ACadSharp.Tests/IO/WriterSingleObjectTests.cs @@ -3,6 +3,7 @@ using ACadSharp.Tables; using CSMath; using CSUtilities.Extensions; +using System; using System.Collections.Generic; using System.IO; using System.Linq; @@ -107,6 +108,16 @@ public void CurrentEntityByBlock() this.Document.Header.CurrentEntityColor = Color.ByBlock; } + public void SingleEllipse() + { + Ellipse ellipse = new Ellipse(); + ellipse.RadiusRatio = 0.5d; + ellipse.StartParameter = 0.0d; + ellipse.EndParameter = Math.PI * 2; + + this.Document.Entities.Add(ellipse); + } + public void SingleLine() { Line line = new Line(XYZ.Zero, new XYZ(100, 100, 0)); @@ -452,6 +463,7 @@ static WriterSingleObjectTests() } Data.Add(new(nameof(SingleCaseGenerator.Empty))); + Data.Add(new(nameof(SingleCaseGenerator.SingleEllipse))); Data.Add(new(nameof(SingleCaseGenerator.SingleLine))); Data.Add(new(nameof(SingleCaseGenerator.SingleMLine))); Data.Add(new(nameof(SingleCaseGenerator.EntityColorByLayer))); diff --git a/src/ACadSharp/CadObject.cs b/src/ACadSharp/CadObject.cs index 612edf04..487cbd84 100644 --- a/src/ACadSharp/CadObject.cs +++ b/src/ACadSharp/CadObject.cs @@ -106,7 +106,7 @@ public CadDictionary CreateExtendedDictionary() /// Creates a new object that is a copy of the current instance. /// /// - /// The copy will be unatached from the document or any reference + /// The copy will be unattached from the document or any reference. /// /// A new object that is a copy of this instance. public virtual CadObject Clone() diff --git a/src/ACadSharp/Entities/Arc.cs b/src/ACadSharp/Entities/Arc.cs index b6d723ac..4d7c19b8 100644 --- a/src/ACadSharp/Entities/Arc.cs +++ b/src/ACadSharp/Entities/Arc.cs @@ -2,6 +2,7 @@ using CSMath; using System; using System.Collections.Generic; +using System.Linq; namespace ACadSharp.Entities { @@ -126,5 +127,13 @@ public List PolygonalVertexes(int precision) return ocsVertexes; } + + /// + public override BoundingBox GetBoundingBox() + { + List vertices = this.PolygonalVertexes(256); + + return BoundingBox.FromPoints(vertices.Select(v => (XYZ)v)); + } } } diff --git a/src/ACadSharp/Entities/Dimension.cs b/src/ACadSharp/Entities/Dimension.cs index e98fb879..11904f55 100644 --- a/src/ACadSharp/Entities/Dimension.cs +++ b/src/ACadSharp/Entities/Dimension.cs @@ -128,8 +128,8 @@ public bool IsTextUserDefinedLocation /// true if the arrow is to be flipped; otherwise, false. /// /// - /// Arrows are by default drawn inside the extension lines if there is enaugh - /// space; otherwise, outside. This flag overrules the standard behaviour. + /// Arrows are by default drawn inside the extension lines if there is enough + /// space; otherwise, outside. This flag overrules the standard behavior. /// [DxfCodeValue(74)] public bool FlipArrow1 { get; set; } @@ -142,8 +142,8 @@ public bool IsTextUserDefinedLocation /// true if the arrow is to be flipped; otherwise, false. /// /// - /// Arrows are by default drawn inside the extension lines if there is enaugh - /// space; otherwise, outside. This flag overrules the standard behaviour. + /// Arrows are by default drawn inside the extension lines if there is enough + /// space; otherwise, outside. This flag overrules the standard behavior. /// [DxfCodeValue(75)] public bool FlipArrow2 { get; set; } diff --git a/src/ACadSharp/Entities/Ellipse.cs b/src/ACadSharp/Entities/Ellipse.cs index 32716e56..60751e13 100644 --- a/src/ACadSharp/Entities/Ellipse.cs +++ b/src/ACadSharp/Entities/Ellipse.cs @@ -1,6 +1,8 @@ using ACadSharp.Attributes; using CSMath; using System; +using System.Collections.Generic; +using System.Linq; namespace ACadSharp.Entities { @@ -45,8 +47,11 @@ public class Ellipse : Entity /// /// Endpoint of major axis, relative to the center (in WCS). /// + /// + /// Axis X is set as default. + /// [DxfCodeValue(11, 21, 31)] - public XYZ EndPoint { get; set; } = XYZ.Zero; + public XYZ EndPoint { get; set; } = XYZ.AxisX; /// /// Ratio of minor axis to major axis. @@ -70,12 +75,120 @@ public class Ellipse : Entity /// The valid range is 0 to 2 * PI. /// [DxfCodeValue(42)] - public double EndParameter { get; set; } = Math.PI * 2; + public double EndParameter { get; set; } = MathUtils.TwoPI; + + /// + /// Rotation of the major axis from the world X axis. + /// + public double Rotation + { + get + { + return ((XY)this.EndPoint).GetAngle(); + } + } + + /// + /// Length of the major axis. + /// + public double MajorAxis { get { return 2 * this.EndPoint.GetLength(); } } + + /// + /// Length of the minor axis. + /// + public double MinorAxis { get { return this.MajorAxis * this.RadiusRatio; } } + + /// + /// Flag that indicates weather this ellipse is closed or not. + /// + public bool IsFullEllipse { get { return this.StartParameter == 0 && this.EndParameter == MathUtils.TwoPI; } } + + /// + /// Calculate the local point on the ellipse for a given angle relative to the center. + /// + /// Angle in radians. + /// A local point on the ellipse for the given angle relative to the center. + public XY PolarCoordinateRelativeToCenter(double angle) + { + double a = this.MajorAxis * 0.5; + double b = this.MinorAxis * 0.5; + + double a1 = a * Math.Sin((double)angle); + double b1 = b * Math.Cos((double)angle); + + double radius = a * b / Math.Sqrt(b1 * b1 + a1 * a1); + + // convert the radius back to Cartesian coordinates + return new XY(radius * Math.Cos((double)angle), radius * Math.Sin((double)angle)); + } + + /// + /// Converts the ellipse in a list of vertexes. + /// + /// Number of vertexes generated. + /// A list vertexes that represents the ellipse expressed in object coordinate system. + public List PolygonalVertexes(int precision) + { + if (precision < 2) + { + throw new ArgumentOutOfRangeException(nameof(precision), precision, "The arc precision must be equal or greater than two."); + } + + List points = new List(); + double beta = this.Rotation; + double sinBeta = Math.Sin(beta); + double cosBeta = Math.Cos(beta); + double start; + double end; + double steps; + + if (this.IsFullEllipse) + { + start = 0; + end = MathUtils.TwoPI; + steps = precision; + } + else + { + XY startPoint = this.PolarCoordinateRelativeToCenter(this.StartParameter); + XY endPoint = this.PolarCoordinateRelativeToCenter(this.EndParameter); + double a = 1 / (0.5 * this.MajorAxis); + double b = 1 / (0.5 * this.MinorAxis); + start = Math.Atan2(startPoint.Y * b, startPoint.X * a); + end = Math.Atan2(endPoint.Y * b, endPoint.X * a); + + if (end < start) + { + end += MathUtils.TwoPI; + } + steps = precision - 1; + } + + double delta = (end - start) / steps; + + for (int i = 0; i < precision; i++) + { + double angle = start + delta * i; + double sinAlpha = Math.Sin(angle); + double cosAlpha = Math.Cos(angle); + + double pointX = 0.5 * (this.MajorAxis * cosAlpha * cosBeta - this.MinorAxis * sinAlpha * sinBeta); + double pointY = 0.5 * (this.MajorAxis * cosAlpha * sinBeta + this.MinorAxis * sinAlpha * cosBeta); + + pointX = MathUtils.FixZero(pointX); + pointY = MathUtils.FixZero(pointY); + + points.Add(new XY(pointX, pointY)); + } + + return points; + } /// public override BoundingBox GetBoundingBox() { - return BoundingBox.Null; + List pts = this.PolygonalVertexes(100); + return BoundingBox.FromPoints(pts.Select(p => (XYZ)p)); } } } diff --git a/src/ACadSharp/Entities/Entity.cs b/src/ACadSharp/Entities/Entity.cs index 0e1d9f2c..9b2ce7a7 100644 --- a/src/ACadSharp/Entities/Entity.cs +++ b/src/ACadSharp/Entities/Entity.cs @@ -92,10 +92,7 @@ public LineType LineType /// public Entity() : base() { } - /// - /// Gets the bounding box aligned with the axis XYZ that ocupies this entity - /// - /// + /// public abstract BoundingBox GetBoundingBox(); /// diff --git a/src/ACadSharp/Entities/Hatch.BoundaryPath.Arc.cs b/src/ACadSharp/Entities/Hatch.BoundaryPath.Arc.cs index 021d6990..a6bd6ba2 100644 --- a/src/ACadSharp/Entities/Hatch.BoundaryPath.Arc.cs +++ b/src/ACadSharp/Entities/Hatch.BoundaryPath.Arc.cs @@ -13,37 +13,43 @@ public class Arc : Edge public override EdgeType Type => EdgeType.CircularArc; /// - /// Center point (in OCS) + /// Center point (in OCS). /// [DxfCodeValue(10, 20)] public XY Center { get; set; } /// - /// Radius + /// Radius. /// /// - /// For the ellispe this is the length of minor axis (percentage of major axis length) + /// For the ellipse this is the length of minor axis (percentage of major axis length). /// [DxfCodeValue(40)] public double Radius { get; set; } /// - /// Start angle + /// Start angle. /// [DxfCodeValue(50)] public double StartAngle { get; set; } /// - /// End angle + /// End angle. /// [DxfCodeValue(51)] public double EndAngle { get; set; } /// - /// Is counterclockwise flag + /// Is counterclockwise flag. /// [DxfCodeValue(73)] public bool CounterClockWise { get; set; } + + /// + public override BoundingBox GetBoundingBox() + { + throw new System.NotImplementedException(); + } } } } diff --git a/src/ACadSharp/Entities/Hatch.BoundaryPath.Edge.cs b/src/ACadSharp/Entities/Hatch.BoundaryPath.Edge.cs index 5fdb91b8..b5418b20 100644 --- a/src/ACadSharp/Entities/Hatch.BoundaryPath.Edge.cs +++ b/src/ACadSharp/Entities/Hatch.BoundaryPath.Edge.cs @@ -1,4 +1,6 @@ -namespace ACadSharp.Entities +using CSMath; + +namespace ACadSharp.Entities { public partial class Hatch { @@ -10,7 +12,7 @@ public partial class BoundaryPath public enum EdgeType { /// - /// Not included in the documentation + /// Not included in the documentation. /// Polyline = 0, Line = 1, @@ -19,12 +21,24 @@ public enum EdgeType Spline = 4, } - public abstract class Edge + public abstract class Edge : IGeometricEntity { /// - /// Edge type + /// Edge type. /// public abstract EdgeType Type { get; } + + /// + /// Creates a new object that is a copy of the current instance. + /// + /// + public Edge Clone() + { + return (Edge)this.MemberwiseClone(); + } + + /// + public abstract BoundingBox GetBoundingBox(); } } } diff --git a/src/ACadSharp/Entities/Hatch.BoundaryPath.Ellipse.cs b/src/ACadSharp/Entities/Hatch.BoundaryPath.Ellipse.cs index b538e424..4d0b971d 100644 --- a/src/ACadSharp/Entities/Hatch.BoundaryPath.Ellipse.cs +++ b/src/ACadSharp/Entities/Hatch.BoundaryPath.Ellipse.cs @@ -47,6 +47,12 @@ public class Ellipse : Edge /// [DxfCodeValue(73)] public bool CounterClockWise { get; set; } + + /// + public override BoundingBox GetBoundingBox() + { + throw new System.NotImplementedException(); + } } } } diff --git a/src/ACadSharp/Entities/Hatch.BoundaryPath.Line.cs b/src/ACadSharp/Entities/Hatch.BoundaryPath.Line.cs index 40ec81e2..ee034be4 100644 --- a/src/ACadSharp/Entities/Hatch.BoundaryPath.Line.cs +++ b/src/ACadSharp/Entities/Hatch.BoundaryPath.Line.cs @@ -22,6 +22,13 @@ public class Line : Edge /// [DxfCodeValue(11, 21)] public XY End { get; set; } + + + /// + public override BoundingBox GetBoundingBox() + { + return BoundingBox.FromPoints([(XYZ)this.Start, (XYZ)this.End]); + } } } } diff --git a/src/ACadSharp/Entities/Hatch.BoundaryPath.Polyline.cs b/src/ACadSharp/Entities/Hatch.BoundaryPath.Polyline.cs index 93298c77..9af200aa 100644 --- a/src/ACadSharp/Entities/Hatch.BoundaryPath.Polyline.cs +++ b/src/ACadSharp/Entities/Hatch.BoundaryPath.Polyline.cs @@ -43,6 +43,12 @@ public class Polyline : Edge /// [DxfCodeValue(DxfReferenceType.Count, 93)] public List Vertices { get; set; } = new(); + + /// + public override BoundingBox GetBoundingBox() + { + return BoundingBox.FromPoints(this.Vertices); + } } } } diff --git a/src/ACadSharp/Entities/Hatch.BoundaryPath.Spline.cs b/src/ACadSharp/Entities/Hatch.BoundaryPath.Spline.cs index 842a55db..859c3236 100644 --- a/src/ACadSharp/Entities/Hatch.BoundaryPath.Spline.cs +++ b/src/ACadSharp/Entities/Hatch.BoundaryPath.Spline.cs @@ -14,53 +14,59 @@ public class Spline : Edge public override EdgeType Type => EdgeType.Spline; /// - /// Degree + /// Degree. /// [DxfCodeValue(94)] public int Degree { get; set; } /// - /// Rational + /// Rational. /// [DxfCodeValue(73)] public bool Rational { get; set; } /// - /// Periodic + /// Periodic. /// [DxfCodeValue(74)] public bool Periodic { get; set; } /// - /// Number of knots + /// Number of knots. /// [DxfCodeValue(95)] public List Knots { get; set; } = new List(); /// - /// Position values are only X and Y, Z represents the weight + /// Position values are only X and Y, Z represents the weight. /// [DxfCodeValue(96)] //42 Weights(optional, default = 1) ?? public List ControlPoints { get; set; } = new List(); /// - /// Number of fit data + /// Number of fit data. /// [DxfCodeValue(97)] public List FitPoints { get; set; } = new List(); /// - /// Start tangent + /// Start tangent. /// [DxfCodeValue(12, 22)] public XY StartTangent { get; set; } /// - /// End tangent + /// End tangent. /// [DxfCodeValue(13, 23)] public XY EndTangent { get; set; } + + /// + public override BoundingBox GetBoundingBox() + { + return BoundingBox.FromPoints(this.ControlPoints); + } } } } diff --git a/src/ACadSharp/Entities/Hatch.BoundaryPath.cs b/src/ACadSharp/Entities/Hatch.BoundaryPath.cs index 084381d9..71ea397e 100644 --- a/src/ACadSharp/Entities/Hatch.BoundaryPath.cs +++ b/src/ACadSharp/Entities/Hatch.BoundaryPath.cs @@ -1,4 +1,5 @@ using ACadSharp.Attributes; +using CSMath; using CSUtilities.Extensions; using System.Collections.Generic; using System.Collections.ObjectModel; @@ -9,8 +10,11 @@ namespace ACadSharp.Entities { public partial class Hatch { - public partial class BoundaryPath + public partial class BoundaryPath : IGeometricEntity { + /// + /// Flag that indicates that this boundary path is formed by a polyline. + /// public bool IsPolyline { get { return this.Edges.OfType().Any(); } } /// @@ -39,30 +43,60 @@ public BoundaryPathFlags Flags } /// - /// Number of edges in this boundary path + /// Number of edges in this boundary path. /// /// - /// only if boundary is not a polyline + /// Only if boundary is not a polyline. /// [DxfCodeValue(DxfReferenceType.Count, 93)] - public ObservableCollection Edges { get; } = new(); + public ObservableCollection Edges { get; private set; } = new(); /// - /// Source boundary objects + /// Source boundary objects. /// [DxfCodeValue(DxfReferenceType.Count, 97)] public List Entities { get; set; } = new List(); private BoundaryPathFlags _flags; + /// + /// Default constructor. + /// public BoundaryPath() { - Edges.CollectionChanged += this.onEdgesCollectionChanged; + this.Edges.CollectionChanged += this.onEdgesCollectionChanged; } + /// + public BoundingBox GetBoundingBox() + { + BoundingBox box = BoundingBox.Null; + + foreach (Edge edge in this.Edges) + { + box = box.Merge(edge.GetBoundingBox()); + } + + foreach (Entity entity in this.Entities) + { + box = box.Merge(entity.GetBoundingBox()); + } + + return box; + } + + /// public BoundaryPath Clone() { - throw new System.NotImplementedException(); + BoundaryPath path = (BoundaryPath)this.MemberwiseClone(); + + path.Entities = new List(); + path.Entities.AddRange(this.Entities.Select(e => (Entity)e.Clone())); + + path.Edges = new ObservableCollection( + this.Edges.Select(e => e.Clone())); + + return path; } private void onEdgesCollectionChanged(object sender, NotifyCollectionChangedEventArgs e) @@ -70,7 +104,7 @@ private void onEdgesCollectionChanged(object sender, NotifyCollectionChangedEven switch (e.Action) { case System.Collections.Specialized.NotifyCollectionChangedAction.Add: - onAdd(e); + this.onAdd(e); break; case System.Collections.Specialized.NotifyCollectionChangedAction.Remove: break; diff --git a/src/ACadSharp/Entities/Hatch.cs b/src/ACadSharp/Entities/Hatch.cs index 0772261a..a90c5180 100644 --- a/src/ACadSharp/Entities/Hatch.cs +++ b/src/ACadSharp/Entities/Hatch.cs @@ -127,15 +127,20 @@ public partial class Hatch : Entity [DxfCodeValue(DxfReferenceType.Count, 91)] public List Paths { get; set; } = new List(); - private HatchPattern _pattern = HatchPattern.Solid; - /// public Hatch() : base() { } /// public override BoundingBox GetBoundingBox() { - return BoundingBox.FromPoints(this.SeedPoints.Select(x=>(XYZ)x)); + BoundingBox box = BoundingBox.Null; + + foreach (BoundaryPath bp in this.Paths) + { + box = box.Merge(bp.GetBoundingBox()); + } + + return box; } /// diff --git a/src/ACadSharp/Entities/IEntity.cs b/src/ACadSharp/Entities/IEntity.cs index 70b9a812..13469091 100644 --- a/src/ACadSharp/Entities/IEntity.cs +++ b/src/ACadSharp/Entities/IEntity.cs @@ -3,7 +3,7 @@ namespace ACadSharp.Entities { - public interface IEntity : IHandledCadObject + public interface IEntity : IHandledCadObject, IGeometricEntity { /// /// Specifies the layer for an object. diff --git a/src/ACadSharp/Entities/IGeometricEntity.cs b/src/ACadSharp/Entities/IGeometricEntity.cs new file mode 100644 index 00000000..82f63970 --- /dev/null +++ b/src/ACadSharp/Entities/IGeometricEntity.cs @@ -0,0 +1,16 @@ +using CSMath; + +namespace ACadSharp.Entities +{ + /// + /// Objects with geometric qualities in the drawing. + /// + public interface IGeometricEntity + { + /// + /// Gets the bounding box aligned with the axis XYZ that occupies this entity. + /// + /// The bounding box where this entity resides. + BoundingBox GetBoundingBox(); + } +} diff --git a/src/ACadSharp/Entities/Viewport.cs b/src/ACadSharp/Entities/Viewport.cs index 6536e4d8..fbd9c1c5 100644 --- a/src/ACadSharp/Entities/Viewport.cs +++ b/src/ACadSharp/Entities/Viewport.cs @@ -32,25 +32,25 @@ public class Viewport : Entity public override string SubclassMarker => DxfSubclassMarker.Viewport; /// - /// Center point(in WCS) + /// Center point(in WCS). /// [DxfCodeValue(10, 20, 30)] public XYZ Center { get; set; } /// - /// Width in paper space units + /// Width in paper space units. /// [DxfCodeValue(40)] public double Width { get; set; } /// - /// Height in paper space units + /// Height in paper space units. /// [DxfCodeValue(41)] public double Height { get; set; } /// - /// Viewport ID + /// Viewport ID. /// [DxfCodeValue(69)] public short Id @@ -75,7 +75,7 @@ public short Id } /// - /// View center point(in DCS) + /// View center point(in DCS). /// [DxfCodeValue(12, 22)] public XY ViewCenter { get; set; } @@ -334,9 +334,16 @@ public override CadObject Clone() /// public override BoundingBox GetBoundingBox() { - XYZ min = new XYZ(this.Center.X - this.Width / 2, this.Center.Y - this.Height / 2, this.Center.Z); - XYZ max = new XYZ(this.Center.X + this.Width / 2, this.Center.Y + this.Height / 2, this.Center.Z); + XYZ min = new XYZ(this.Center.X - this.Width, this.Center.Y - this.Height, this.Center.Z); + XYZ max = new XYZ(this.Center.X + this.Width, this.Center.Y + this.Height, this.Center.Z); + return new BoundingBox(min, max); + } + /// + public BoundingBox GetModelBoundingBox() + { + XYZ min = new XYZ(this.ViewCenter.X - this.ViewWidth / 2, this.ViewCenter.Y - this.ViewHeight / 2, 0); + XYZ max = new XYZ(this.ViewCenter.X + this.ViewWidth / 2, this.ViewCenter.Y + this.ViewHeight / 2, 0); return new BoundingBox(min, max); } } diff --git a/src/ACadSharp/MathUtils.cs b/src/ACadSharp/MathUtils.cs index e593616a..134d9de3 100644 --- a/src/ACadSharp/MathUtils.cs +++ b/src/ACadSharp/MathUtils.cs @@ -17,6 +17,8 @@ public static class MathUtils public const double Epsilon = 1e-12; + public const double TwoPI = Math.PI * 2; + /// /// Checks if a number is close to zero. /// @@ -38,6 +40,16 @@ public static bool IsZero(double number, double threshold) return number >= -threshold && number <= threshold; } + public static double FixZero(double number) + { + return FixZero(number, Epsilon); + } + + public static double FixZero(double number, double threshold) + { + return IsZero(number, threshold) ? 0 : number; + } + public static double RadToDeg(double value) { return value * RadToDegFactor;