From 148a0d32e5951b761a81d0e1a4a261df97706afd Mon Sep 17 00:00:00 2001 From: DomCR Date: Wed, 7 Aug 2024 18:20:20 +0200 Subject: [PATCH 01/15] Arc n Circle test --- ACadSharp.Tests/Entities/ArcTests.cs | 13 +++++++++++++ ACadSharp.Tests/Entities/CircleTests.cs | 21 +++++++++++++++++++++ ACadSharp.Tests/Entities/EntityTests.cs | 2 +- ACadSharp.Tests/Entities/LineTests.cs | 21 +++++++++++++++++++++ ACadSharp/CadObject.cs | 2 +- ACadSharp/Entities/Circle.cs | 4 ++-- ACadSharp/Entities/Entity.cs | 2 +- 7 files changed, 60 insertions(+), 5 deletions(-) create mode 100644 ACadSharp.Tests/Entities/CircleTests.cs create mode 100644 ACadSharp.Tests/Entities/LineTests.cs diff --git a/ACadSharp.Tests/Entities/ArcTests.cs b/ACadSharp.Tests/Entities/ArcTests.cs index 41e28804..89ba625f 100644 --- a/ACadSharp.Tests/Entities/ArcTests.cs +++ b/ACadSharp.Tests/Entities/ArcTests.cs @@ -27,5 +27,18 @@ public void CreateFromBulgeTest() Assert.Equal(0, arc.StartAngle); Assert.Equal(Math.PI / 2, arc.EndAngle); } + + [Fact(Skip = "Needs a dedicated implementation for Arc")] + 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); + } } } diff --git a/ACadSharp.Tests/Entities/CircleTests.cs b/ACadSharp.Tests/Entities/CircleTests.cs new file mode 100644 index 00000000..5944f84e --- /dev/null +++ b/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/ACadSharp.Tests/Entities/EntityTests.cs b/ACadSharp.Tests/Entities/EntityTests.cs index bb2dd290..afdcc320 100644 --- a/ACadSharp.Tests/Entities/EntityTests.cs +++ b/ACadSharp.Tests/Entities/EntityTests.cs @@ -24,7 +24,7 @@ static EntityTests() [Theory] [MemberData(nameof(EntityTypes))] - public void BoundingBoxTest(Type entityType) + public void GetBoundingBoxImplementation(Type entityType) { Entity entity = EntityFactory.Create(entityType); diff --git a/ACadSharp.Tests/Entities/LineTests.cs b/ACadSharp.Tests/Entities/LineTests.cs new file mode 100644 index 00000000..572e8ae4 --- /dev/null +++ b/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/ACadSharp/CadObject.cs b/ACadSharp/CadObject.cs index ca0ce563..612edf04 100644 --- a/ACadSharp/CadObject.cs +++ b/ACadSharp/CadObject.cs @@ -84,7 +84,7 @@ public CadDocument Document private CadDictionary _xdictionary = null; /// - /// Default constructor + /// Default constructor. /// public CadObject() { } diff --git a/ACadSharp/Entities/Circle.cs b/ACadSharp/Entities/Circle.cs index 468be68e..165b1c2d 100644 --- a/ACadSharp/Entities/Circle.cs +++ b/ACadSharp/Entities/Circle.cs @@ -69,8 +69,8 @@ public Circle() : base() { } /// public override BoundingBox GetBoundingBox() { - XYZ min = new XYZ(Math.Min(this.Center.X - this.Radius, this.Center.X + this.Radius), Math.Min(this.Center.Y - this.Radius, this.Center.Y + this.Radius), Math.Min(this.Center.Z - this.Radius, this.Center.Z + this.Radius)); - XYZ max = new XYZ(Math.Max(this.Center.X - this.Radius, this.Center.X + this.Radius), Math.Max(this.Center.Y - this.Radius, this.Center.Y + this.Radius), Math.Max(this.Center.Z - this.Radius, this.Center.Z + this.Radius)); + XYZ min = new XYZ(Math.Min(this.Center.X - this.Radius, this.Center.X + this.Radius), Math.Min(this.Center.Y - this.Radius, this.Center.Y + this.Radius), Math.Min(this.Center.Z, this.Center.Z)); + XYZ max = new XYZ(Math.Max(this.Center.X - this.Radius, this.Center.X + this.Radius), Math.Max(this.Center.Y - this.Radius, this.Center.Y + this.Radius), Math.Max(this.Center.Z, this.Center.Z)); return new BoundingBox(min, max); } diff --git a/ACadSharp/Entities/Entity.cs b/ACadSharp/Entities/Entity.cs index b9f9f1a2..7615317e 100644 --- a/ACadSharp/Entities/Entity.cs +++ b/ACadSharp/Entities/Entity.cs @@ -95,7 +95,7 @@ public LineType LineType public Entity() : base() { } /// - /// Gets the bounding box aligned with the axis XYZ that ocupies this entity + /// Gets the bounding box aligned with the axis XYZ that ocupies this entity. /// /// public abstract BoundingBox GetBoundingBox(); From fa24b810d74126ab5ab2a993574664d5bf153fa4 Mon Sep 17 00:00:00 2001 From: DomCR Date: Fri, 13 Sep 2024 08:33:09 +0200 Subject: [PATCH 02/15] added hatch test --- src/ACadSharp.Tests/Entities/HatchTests.cs | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/src/ACadSharp.Tests/Entities/HatchTests.cs b/src/ACadSharp.Tests/Entities/HatchTests.cs index c92b04d1..505c239b 100644 --- a/src/ACadSharp.Tests/Entities/HatchTests.cs +++ b/src/ACadSharp.Tests/Entities/HatchTests.cs @@ -113,5 +113,26 @@ 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)); + + var box = hatch.GetBoundingBox(); + + Assert.Equal(new XYZ(0, 0, 0), box.Min); + Assert.Equal(new XYZ(1, 1, 0), box.Max); + } } } From cbf28379ee4a104b5bfbce5504a7570ed1cc10ee Mon Sep 17 00:00:00 2001 From: DomCR Date: Tue, 24 Sep 2024 18:18:51 +0200 Subject: [PATCH 03/15] hatch boundingbox --- src/ACadSharp.Tests/Entities/HatchTests.cs | 4 ++ src/ACadSharp/CadObject.cs | 2 +- src/ACadSharp/Entities/Entity.cs | 5 +- .../Entities/Hatch.BoundaryPath.Arc.cs | 18 ++++--- .../Entities/Hatch.BoundaryPath.Edge.cs | 22 ++++++-- .../Entities/Hatch.BoundaryPath.Ellipse.cs | 6 +++ .../Entities/Hatch.BoundaryPath.Line.cs | 7 +++ .../Entities/Hatch.BoundaryPath.Polyline.cs | 6 +++ .../Entities/Hatch.BoundaryPath.Spline.cs | 22 +++++--- src/ACadSharp/Entities/Hatch.BoundaryPath.cs | 50 ++++++++++++++++--- src/ACadSharp/Entities/Hatch.cs | 9 +++- src/ACadSharp/Entities/IEntity.cs | 2 +- src/ACadSharp/Entities/IGeometricEntity.cs | 16 ++++++ 13 files changed, 136 insertions(+), 33 deletions(-) create mode 100644 src/ACadSharp/Entities/IGeometricEntity.cs diff --git a/src/ACadSharp.Tests/Entities/HatchTests.cs b/src/ACadSharp.Tests/Entities/HatchTests.cs index 505c239b..4ae79b72 100644 --- a/src/ACadSharp.Tests/Entities/HatchTests.cs +++ b/src/ACadSharp.Tests/Entities/HatchTests.cs @@ -129,6 +129,10 @@ public void GetBoundingBoxTest() 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); 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/Entity.cs b/src/ACadSharp/Entities/Entity.cs index 55127800..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..2185570a 100644 --- a/src/ACadSharp/Entities/Hatch.cs +++ b/src/ACadSharp/Entities/Hatch.cs @@ -135,7 +135,14 @@ 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(); + } +} From 8ab140096db7eba88d635e9f5e9f9476167da649 Mon Sep 17 00:00:00 2001 From: DomCR Date: Thu, 26 Sep 2024 12:45:02 +0200 Subject: [PATCH 04/15] cleanup --- src/ACadSharp/Entities/Hatch.cs | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/ACadSharp/Entities/Hatch.cs b/src/ACadSharp/Entities/Hatch.cs index 2185570a..a90c5180 100644 --- a/src/ACadSharp/Entities/Hatch.cs +++ b/src/ACadSharp/Entities/Hatch.cs @@ -127,8 +127,6 @@ public partial class Hatch : Entity [DxfCodeValue(DxfReferenceType.Count, 91)] public List Paths { get; set; } = new List(); - private HatchPattern _pattern = HatchPattern.Solid; - /// public Hatch() : base() { } From 352dd4516b33eb0542e0705b23eec045ee5efd6e Mon Sep 17 00:00:00 2001 From: DomCR Date: Fri, 27 Sep 2024 11:58:26 +0200 Subject: [PATCH 05/15] viewport --- src/ACadSharp/Entities/ViewPort.cs | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/src/ACadSharp/Entities/ViewPort.cs b/src/ACadSharp/Entities/ViewPort.cs index 17049b09..b32836fa 100644 --- a/src/ACadSharp/Entities/ViewPort.cs +++ b/src/ACadSharp/Entities/ViewPort.cs @@ -27,31 +27,31 @@ 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 { get; set; } = 1; /// - /// View center point(in DCS) + /// View center point(in DCS). /// [DxfCodeValue(12, 22)] public XY ViewCenter { get; set; } @@ -299,9 +299,16 @@ public override CadObject Clone() /// public override BoundingBox GetBoundingBox() { - XYZ min = new XYZ(Center.X - this.Width, Center.Y - this.Height, Center.Z); - XYZ max = new XYZ(Center.X + this.Width, Center.Y + this.Height, Center.Z); + 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); + return new BoundingBox(min, max); + } + /// + public BoundingBox GetModelBoundingBox() + { + XYZ min = new XYZ(this.ViewCenter.X - this.Width / 2, this.ViewCenter.Y - this.ViewHeight / 2, 0); + XYZ max = new XYZ(this.ViewCenter.X + this.Width / 2, this.ViewCenter.Y + this.ViewHeight / 2, 0); return new BoundingBox(min, max); } } From ec99fbb90d7989ac3e2a8fdd07e96de3173899bb Mon Sep 17 00:00:00 2001 From: DomCR Date: Fri, 27 Sep 2024 12:00:02 +0200 Subject: [PATCH 06/15] use ViewWidth --- src/ACadSharp/Entities/Viewport.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/ACadSharp/Entities/Viewport.cs b/src/ACadSharp/Entities/Viewport.cs index 5a5bfb00..812e5d75 100644 --- a/src/ACadSharp/Entities/Viewport.cs +++ b/src/ACadSharp/Entities/Viewport.cs @@ -318,8 +318,8 @@ public override BoundingBox GetBoundingBox() /// public BoundingBox GetModelBoundingBox() { - XYZ min = new XYZ(this.ViewCenter.X - this.Width / 2, this.ViewCenter.Y - this.ViewHeight / 2, 0); - XYZ max = new XYZ(this.ViewCenter.X + this.Width / 2, this.ViewCenter.Y + this.ViewHeight / 2, 0); + 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); } } From c7290a9133e77791e4ee564b3319191744c8195e Mon Sep 17 00:00:00 2001 From: DomCR Date: Tue, 1 Oct 2024 11:31:03 +0200 Subject: [PATCH 07/15] fix --- src/ACadSharp/Entities/Arc.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ACadSharp/Entities/Arc.cs b/src/ACadSharp/Entities/Arc.cs index dc7cbba2..b6d723ac 100644 --- a/src/ACadSharp/Entities/Arc.cs +++ b/src/ACadSharp/Entities/Arc.cs @@ -121,7 +121,7 @@ public List PolygonalVertexes(int precision) cosine = MathUtils.IsZero(cosine) ? 0 : cosine; sine = MathUtils.IsZero(sine) ? 0 : sine; - ocsVertexes.Add(new XY(cosine, sine)); + ocsVertexes.Add(new XY(cosine + this.Center.X, sine + this.Center.Y)); } return ocsVertexes; From 589c52d3fe6d9559dc513369251a55561c356a0a Mon Sep 17 00:00:00 2001 From: DomCR Date: Tue, 1 Oct 2024 11:57:21 +0200 Subject: [PATCH 08/15] arc bounding box --- src/ACadSharp.Tests/Entities/ArcTests.cs | 2 +- src/ACadSharp/Entities/Arc.cs | 9 +++++++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/src/ACadSharp.Tests/Entities/ArcTests.cs b/src/ACadSharp.Tests/Entities/ArcTests.cs index ad7f57ca..ce201169 100644 --- a/src/ACadSharp.Tests/Entities/ArcTests.cs +++ b/src/ACadSharp.Tests/Entities/ArcTests.cs @@ -29,7 +29,7 @@ public void CreateFromBulgeTest() Assert.Equal(Math.PI / 2, arc.EndAngle); } - [Fact(Skip = "Needs a dedicated implementation for Arc")] + [Fact] public void GetBoundingBoxTest() { Arc arc = new Arc(); diff --git a/src/ACadSharp/Entities/Arc.cs b/src/ACadSharp/Entities/Arc.cs index dc7cbba2..67f41991 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)); + } } } From 468605fbf82ee654144320fa71c7ee979e5de4f4 Mon Sep 17 00:00:00 2001 From: DomCR Date: Tue, 1 Oct 2024 13:02:40 +0200 Subject: [PATCH 09/15] refactor --- src/ACadSharp/Entities/Viewport.cs | 32 ++++++++++++++++--- .../DWG/DwgStreamReaders/DwgObjectReader.cs | 2 +- .../DwgObjectWriter.Entities.cs | 2 +- 3 files changed, 30 insertions(+), 6 deletions(-) diff --git a/src/ACadSharp/Entities/Viewport.cs b/src/ACadSharp/Entities/Viewport.cs index 42ec53a5..6536e4d8 100644 --- a/src/ACadSharp/Entities/Viewport.cs +++ b/src/ACadSharp/Entities/Viewport.cs @@ -17,6 +17,11 @@ namespace ACadSharp.Entities [DxfSubClass(DxfSubclassMarker.Viewport)] public class Viewport : Entity { + /// + /// Paper view Id, it indicates that the viewport acts as a paper size. + /// + public const int PaperViewId = 1; + /// public override ObjectType ObjectType => ObjectType.VIEWPORT; @@ -48,7 +53,26 @@ public class Viewport : Entity /// Viewport ID /// [DxfCodeValue(69)] - public short Id { get; set; } = 1; + public short Id + { + get + { + if (this.Owner is BlockRecord record) + { + short id = 0; + foreach (Viewport viewport in record.Viewports) + { + id += 1; + if (viewport == this) + { + return id; + } + } + } + + return 0; + } + } /// /// View center point(in DCS) @@ -274,7 +298,7 @@ public double ViewWidth /// View contrast /// [DxfCodeValue(142)] - public double Constrast { get; set; } + public double Contrast { get; set; } /// /// Ambient light color.Write only if not black color. @@ -310,8 +334,8 @@ public override CadObject Clone() /// public override BoundingBox GetBoundingBox() { - XYZ min = new XYZ(Center.X - this.Width, Center.Y - this.Height, Center.Z); - XYZ max = new XYZ(Center.X + this.Width, Center.Y + this.Height, Center.Z); + 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); return new BoundingBox(min, max); } diff --git a/src/ACadSharp/IO/DWG/DwgStreamReaders/DwgObjectReader.cs b/src/ACadSharp/IO/DWG/DwgStreamReaders/DwgObjectReader.cs index dac09e25..7d98092a 100644 --- a/src/ACadSharp/IO/DWG/DwgStreamReaders/DwgObjectReader.cs +++ b/src/ACadSharp/IO/DWG/DwgStreamReaders/DwgObjectReader.cs @@ -2305,7 +2305,7 @@ private CadTemplate readViewport() //Brightness BD 141 viewport.Brightness = this._objectReader.ReadBitDouble(); //Contrast BD 142 - viewport.Constrast = this._objectReader.ReadBitDouble(); + viewport.Contrast = this._objectReader.ReadBitDouble(); //Ambient light color CMC 63 viewport.AmbientLightColor = this._objectReader.ReadCmColor(); } diff --git a/src/ACadSharp/IO/DWG/DwgStreamWriters/DwgObjectWriter.Entities.cs b/src/ACadSharp/IO/DWG/DwgStreamWriters/DwgObjectWriter.Entities.cs index 2fd799a6..7cab5414 100644 --- a/src/ACadSharp/IO/DWG/DwgStreamWriters/DwgObjectWriter.Entities.cs +++ b/src/ACadSharp/IO/DWG/DwgStreamWriters/DwgObjectWriter.Entities.cs @@ -2346,7 +2346,7 @@ private void writeViewport(Viewport viewport) //Brightness BD 141 this._writer.WriteBitDouble(viewport.Brightness); //Contrast BD 142 - this._writer.WriteBitDouble(viewport.Constrast); + this._writer.WriteBitDouble(viewport.Contrast); //Ambient light color CMC 63 this._writer.WriteCmColor(viewport.AmbientLightColor); } From 752c2695d77aa3339e2a46fc09c4f20da3260955 Mon Sep 17 00:00:00 2001 From: DomCR Date: Tue, 1 Oct 2024 13:03:26 +0200 Subject: [PATCH 10/15] minor layer fix --- src/ACadSharp/Tables/Layer.cs | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/src/ACadSharp/Tables/Layer.cs b/src/ACadSharp/Tables/Layer.cs index 354bcd1a..dd756bea 100644 --- a/src/ACadSharp/Tables/Layer.cs +++ b/src/ACadSharp/Tables/Layer.cs @@ -46,10 +46,22 @@ public class Layer : TableEntry /// if the index is negative, layer is off /// [DxfCodeValue(62, 420, 430)] - public Color Color { get; set; } = new Color(7); + public Color Color + { + get { return this._color; } + set + { + if (value.IsByLayer || value.IsByBlock) + { + throw new ArgumentException("The layer color cannot be ByLayer or ByBlock", nameof(value)); + } + + this._color = value; + } + } /// - /// The linetype of an object. The default linetype is the linetype of the layer (ByLayer). + /// The line type of an object. The default line type is the line type of the layer (ByLayer). /// [DxfCodeValue(DxfReferenceType.Name, 6)] public LineType LineType @@ -80,7 +92,7 @@ public LineType LineType public bool PlotFlag { get; set; } = true; /// - /// Specifies the lineweight of an individual object or the default lineweight for the drawing. + /// Specifies the line weight of an individual object or the default line weight for the drawing. /// [DxfCodeValue(370)] public LineweightType LineWeight { get; set; } = LineweightType.Default; @@ -104,6 +116,8 @@ public LineType LineType private LineType _lineType = LineType.Continuous; + private Color _color = new Color(7); + internal Layer() : base() { } public Layer(string name) : base(name) { } From 5ed2c8f1b1abbab388754a150b82b526244d52ca Mon Sep 17 00:00:00 2001 From: DomCR Date: Wed, 2 Oct 2024 11:20:12 +0200 Subject: [PATCH 11/15] CreateCircleHatch --- .../IO/WriterSingleObjectTests.cs | 27 +++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/src/ACadSharp.Tests/IO/WriterSingleObjectTests.cs b/src/ACadSharp.Tests/IO/WriterSingleObjectTests.cs index 381b7ab5..d3c7151b 100644 --- a/src/ACadSharp.Tests/IO/WriterSingleObjectTests.cs +++ b/src/ACadSharp.Tests/IO/WriterSingleObjectTests.cs @@ -361,6 +361,32 @@ public void CreateHatch() this.Document.Entities.Add(hatch); } + public void CreateCircleHatch() + { + Hatch hatch = new Hatch(); + hatch.IsSolid = true; + + hatch.SeedPoints.Add(new XY()); + + List edges = new List(); + + //edges + Hatch.BoundaryPath.Polyline polyline = new Hatch.BoundaryPath.Polyline(); + polyline.IsClosed = true; + polyline.Vertices.Add(new XYZ(0, 2.5, 1)); + polyline.Vertices.Add(new XYZ(10, 2.5, 1)); + + Hatch.BoundaryPath path = new Hatch.BoundaryPath(); + foreach (var item in edges) + { + path.Edges.Add(item); + } + + hatch.Paths.Add(path); + + this.Document.Entities.Add(hatch); + } + public void ChangedEncoding() { this.Document.Header.CodePage = "gb2312"; @@ -450,6 +476,7 @@ static WriterSingleObjectTests() Data.Add(new(nameof(SingleCaseGenerator.LineTypeWithSegments))); Data.Add(new(nameof(SingleCaseGenerator.CreateHatchPolyline))); Data.Add(new(nameof(SingleCaseGenerator.CreateHatch))); + Data.Add(new(nameof(SingleCaseGenerator.CreateCircleHatch))); Data.Add(new(nameof(SingleCaseGenerator.ChangedEncoding))); Data.Add(new(nameof(SingleCaseGenerator.AddBlockWithAttributes))); } From eb4b2d576ec4ff3dde69421a3b814b12162dc18b Mon Sep 17 00:00:00 2001 From: DomCR Date: Wed, 2 Oct 2024 11:22:19 +0200 Subject: [PATCH 12/15] version 1.0.1 --- src/ACadSharp/ACadSharp.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ACadSharp/ACadSharp.csproj b/src/ACadSharp/ACadSharp.csproj index 8e8616d8..c1f62844 100644 --- a/src/ACadSharp/ACadSharp.csproj +++ b/src/ACadSharp/ACadSharp.csproj @@ -17,7 +17,7 @@ true README.md - 1.0.0 + 1.0.1 ../nupkg From 2eb736fd46732dd6bafdeb772d1f82921bf599ae Mon Sep 17 00:00:00 2001 From: DomCR Date: Wed, 2 Oct 2024 11:53:33 +0200 Subject: [PATCH 13/15] ellipse tests --- src/ACadSharp.Tests/Entities/EllipseTests.cs | 23 +++++++++++++++++++ .../IO/WriterSingleObjectTests.cs | 12 ++++++++++ src/ACadSharp/Entities/Ellipse.cs | 5 +++- 3 files changed, 39 insertions(+), 1 deletion(-) create mode 100644 src/ACadSharp.Tests/Entities/EllipseTests.cs 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/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/Entities/Ellipse.cs b/src/ACadSharp/Entities/Ellipse.cs index 32716e56..56ec80c0 100644 --- a/src/ACadSharp/Entities/Ellipse.cs +++ b/src/ACadSharp/Entities/Ellipse.cs @@ -45,8 +45,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. From 58010e998b640078386397d934feed136cae0be5 Mon Sep 17 00:00:00 2001 From: DomCR Date: Thu, 3 Oct 2024 12:15:26 +0200 Subject: [PATCH 14/15] ellipse --- src/ACadSharp/Entities/Ellipse.cs | 114 +++++++++++++++++++++++++++++- src/ACadSharp/MathUtils.cs | 12 ++++ 2 files changed, 124 insertions(+), 2 deletions(-) diff --git a/src/ACadSharp/Entities/Ellipse.cs b/src/ACadSharp/Entities/Ellipse.cs index 56ec80c0..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 { @@ -73,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/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; From 74418da19bac127cdde954dcc724cc04d5a853f9 Mon Sep 17 00:00:00 2001 From: DomCR Date: Thu, 3 Oct 2024 12:30:17 +0200 Subject: [PATCH 15/15] spelling --- src/ACadSharp/Entities/Dimension.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) 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; }