diff --git a/ACadSharp.Tests/CadDocumentTests.cs b/ACadSharp.Tests/CadDocumentTests.cs index de86766d..64430760 100644 --- a/ACadSharp.Tests/CadDocumentTests.cs +++ b/ACadSharp.Tests/CadDocumentTests.cs @@ -170,6 +170,16 @@ public void RemoveCadObject() Assert.Null(l.LineType.Document); } + [Fact] + public void Get0HandleObject() + { + CadDocument doc = new CadDocument(); + + Assert.Null(doc.GetCadObject(0)); + Assert.False(doc.TryGetCadObject(0, out CadObject cadObject)); + Assert.Null(cadObject); + } + [Fact(Skip = "Implementation in branch : table-operations")] public void RemoveLayer() { diff --git a/ACadSharp.Tests/Entities/PolylineTest.cs b/ACadSharp.Tests/Entities/PolylineTest.cs new file mode 100644 index 00000000..363225c3 --- /dev/null +++ b/ACadSharp.Tests/Entities/PolylineTest.cs @@ -0,0 +1,35 @@ +using ACadSharp.Entities; +using CSMath; +using System.Collections.Generic; +using Xunit; + +namespace ACadSharp.Tests.Entities +{ + public class PolylineTest + { + [Fact] + public void ClearVertrticesTest() + { + CadDocument doc = new CadDocument(); + + Polyline2D polyline = new Polyline2D(); + List vertices = new List + { + new Vertex2D(), + new Vertex2D(new XY(1,1)), + new Vertex2D(new XY(2,2)) + }; + polyline.Vertices.AddRange(vertices); + + doc.Entities.Add(polyline); + + polyline.Vertices.Clear(); + + foreach (var item in vertices) + { + Assert.True(item.Handle == 0); + Assert.False(doc.TryGetCadObject(item.Handle, out Vertex2D _)); + } + } + } +} diff --git a/ACadSharp.Tests/Entities/SeqendTests.cs b/ACadSharp.Tests/Entities/SeqendTests.cs new file mode 100644 index 00000000..92af2bd5 --- /dev/null +++ b/ACadSharp.Tests/Entities/SeqendTests.cs @@ -0,0 +1,91 @@ +using ACadSharp.Entities; +using Xunit; + +namespace ACadSharp.Tests.Entities +{ + public class SeqendTests + { + [Fact] + public void NullTest() + { + Polyline2D polyline = new Polyline2D(); + + Assert.Null(polyline.Vertices.Seqend); + } + + [Fact] + public void CreatedTest() + { + Polyline2D polyline = new Polyline2D(); + polyline.Vertices.Add(new Vertex2D()); + + Assert.NotNull(polyline.Vertices.Seqend); + Assert.True(polyline.Vertices.Seqend.Handle == 0); + Assert.NotEmpty(polyline.Vertices); + } + + [Fact] + public void RemovedTest() + { + Polyline2D polyline = new Polyline2D(); + polyline.Vertices.Add(new Vertex2D()); + + Assert.NotNull(polyline.Vertices.Seqend); + Assert.True(polyline.Vertices.Seqend.Handle == 0); + Assert.NotEmpty(polyline.Vertices); + + polyline.Vertices.Clear(); // Empty collection + + Assert.Null(polyline.Vertices.Seqend); + } + + [Fact] + public void AddToDocumentTest() + { + CadDocument doc = new CadDocument(); + + Polyline2D polyline = new Polyline2D(); + polyline.Vertices.Add(new Vertex2D()); + + doc.Entities.Add(polyline); + + Assert.False(polyline.Vertices.Seqend.Handle == 0); + Seqend inner = doc.GetCadObject(polyline.Vertices.Seqend.Handle); + Assert.NotNull(inner); + } + + [Fact] + public void OnSeqendAddedTest() + { + CadDocument doc = new CadDocument(); + + Polyline2D polyline = new Polyline2D(); + + doc.Entities.Add(polyline); + + polyline.Vertices.Add(new Vertex2D()); + + Assert.False(polyline.Vertices.Seqend.Handle == 0); + Assert.True(doc.TryGetCadObject(polyline.Vertices.Seqend.Handle, out Seqend inner)); + Assert.NotNull(inner); + } + + [Fact] + public void OnSeqendRemovedTest() + { + CadDocument doc = new CadDocument(); + + Polyline2D polyline = new Polyline2D(); + polyline.Vertices.Add(new Vertex2D()); + Seqend holder = polyline.Vertices.Seqend; + + doc.Entities.Add(polyline); + + polyline.Vertices.Clear(); + + Assert.True(holder.Handle == 0); + Assert.False(doc.TryGetCadObject(holder.Handle, out Seqend inner)); + Assert.Null(inner); + } + } +} diff --git a/ACadSharp/CadDocument.cs b/ACadSharp/CadDocument.cs index da1816fb..60a4e6b2 100644 --- a/ACadSharp/CadDocument.cs +++ b/ACadSharp/CadDocument.cs @@ -225,6 +225,10 @@ public bool TryGetCadObject(ulong handle, out T cadObject) where T : CadObject { cadObject = null; + + if (handle == this.Handle) + return false; + if (this._cadObjects.TryGetValue(handle, out IHandledCadObject obj)) { cadObject = obj as T; @@ -429,9 +433,15 @@ internal void RegisterCollection(IObservableCollection collection, bool ad this.addCadObject(cadObject); } - if (collection is ISeqendColleciton seqendColleciton) + if (collection is ISeqendCollection seqendColleciton) { - this.addCadObject(seqendColleciton.Seqend); + seqendColleciton.OnSeqendAdded += this.onAdd; + seqendColleciton.OnSeqendRemoved += this.onRemove; + + if (seqendColleciton.Seqend != null) + { + this.addCadObject(seqendColleciton.Seqend); + } } if (addElements) @@ -475,9 +485,15 @@ internal void UnregisterCollection(IObservableCollection collection, bool this.removeCadObject(cadObject); } - if (collection is ISeqendColleciton seqendColleciton) + if (collection is ISeqendCollection seqendColleciton) { - this.removeCadObject(seqendColleciton.Seqend); + seqendColleciton.OnSeqendAdded -= this.onAdd; + seqendColleciton.OnSeqendRemoved -= this.onRemove; + + if (seqendColleciton.Seqend != null) + { + this.removeCadObject(seqendColleciton.Seqend); + } } if (removeElements) diff --git a/ACadSharp/CadObjectCollection.cs b/ACadSharp/CadObjectCollection.cs index ea6779d0..388ef9ab 100644 --- a/ACadSharp/CadObjectCollection.cs +++ b/ACadSharp/CadObjectCollection.cs @@ -1,6 +1,8 @@ -using System; +using CSUtilities.Extensions; +using System; using System.Collections; using System.Collections.Generic; +using System.Linq; namespace ACadSharp { @@ -21,7 +23,7 @@ public class CadObjectCollection : IObservableCollection /// public int Count { get { return this._entries.Count; } } - private readonly HashSet _entries = new HashSet(); + protected readonly HashSet _entries = new HashSet(); public CadObjectCollection(CadObject owner) { @@ -34,7 +36,7 @@ public CadObjectCollection(CadObject owner) /// /// /// - public void Add(T item) + public virtual void Add(T item) { if (item is null) throw new ArgumentNullException(nameof(item)); @@ -67,7 +69,11 @@ public void AddRange(IEnumerable items) /// public void Clear() { - this._entries.Clear(); + Queue q = new(this._entries.ToList()); + while (q.TryDequeue(out T entry)) + { + this.Remove(entry); + } } /// @@ -75,7 +81,7 @@ public void Clear() /// /// /// The removed - public T Remove(T item) + public virtual T Remove(T item) { if (!this._entries.Remove(item)) return null; diff --git a/ACadSharp/Entities/Vertex2D.cs b/ACadSharp/Entities/Vertex2D.cs index dba8ea70..5fed6b05 100644 --- a/ACadSharp/Entities/Vertex2D.cs +++ b/ACadSharp/Entities/Vertex2D.cs @@ -1,4 +1,5 @@ using ACadSharp.Attributes; +using CSMath; namespace ACadSharp.Entities { @@ -18,5 +19,12 @@ public class Vertex2D : Vertex /// public override string SubclassMarker => DxfSubclassMarker.PolylineVertex; + + public Vertex2D() { } + + public Vertex2D(XY location) + { + this.Location = (XYZ)location; + } } } diff --git a/ACadSharp/IO/DXF/DxfStreamWriter/DxfSectionWriterBase.cs b/ACadSharp/IO/DXF/DxfStreamWriter/DxfSectionWriterBase.cs index 9edaddbc..67654ade 100644 --- a/ACadSharp/IO/DXF/DxfStreamWriter/DxfSectionWriterBase.cs +++ b/ACadSharp/IO/DXF/DxfStreamWriter/DxfSectionWriterBase.cs @@ -148,9 +148,9 @@ protected void writeCollection(IEnumerable arr, DxfCode[] codes = null) } } - if (arr is ISeqendColleciton colleciton) + if (arr is ISeqendCollection collection && collection.Seqend != null) { - this.writeMappedObject(colleciton.Seqend); + this.writeMappedObject(collection.Seqend); } } @@ -239,12 +239,12 @@ private void writeSegment(LineType.Segment segment) return; this._writer.Write(75, segment.ShapeNumber); - + if (segment.Style != null) { this._writer.Write(340, segment.Style.Handle); } - + this._writer.Write(46, segment.Scale); this._writer.Write(50, segment.Rotation); this._writer.Write(44, segment.Offset.X); diff --git a/ACadSharp/IO/Templates/CadInsertTemplate.cs b/ACadSharp/IO/Templates/CadInsertTemplate.cs index b16c4db8..d8329a83 100644 --- a/ACadSharp/IO/Templates/CadInsertTemplate.cs +++ b/ACadSharp/IO/Templates/CadInsertTemplate.cs @@ -44,6 +44,11 @@ public override void Build(CadDocumentBuilder builder) insert.Block = block; } + if (builder.TryGetCadObject(this.SeqendHandle, out Seqend seqend)) + { + insert.Attributes.Seqend = seqend; + } + if (this.FirstAttributeHandle.HasValue) { var attributes = getEntitiesCollection(builder, FirstAttributeHandle.Value, EndAttributeHandle.Value); @@ -59,11 +64,6 @@ public override void Build(CadDocumentBuilder builder) } } } - - if (builder.TryGetCadObject(this.SeqendHandle, out Seqend seqend)) - { - insert.Attributes.Seqend = seqend; - } } } } diff --git a/ACadSharp/IO/Templates/CadPolyLineTemplate.cs b/ACadSharp/IO/Templates/CadPolyLineTemplate.cs index b5da5152..422f7e5f 100644 --- a/ACadSharp/IO/Templates/CadPolyLineTemplate.cs +++ b/ACadSharp/IO/Templates/CadPolyLineTemplate.cs @@ -24,6 +24,11 @@ public override void Build(CadDocumentBuilder builder) Polyline polyLine = this.CadObject as Polyline; + if (builder.TryGetCadObject(this.SeqendHandle, out Seqend seqend)) + { + polyLine.Vertices.Seqend = seqend; + } + if (this.FirstVertexHandle.HasValue) { IEnumerable vertices = this.getEntitiesCollection(builder, this.FirstVertexHandle.Value, this.LastVertexHandle.Value); @@ -43,11 +48,6 @@ public override void Build(CadDocumentBuilder builder) } } } - - if (builder.TryGetCadObject(this.SeqendHandle, out Seqend seqend)) - { - polyLine.Vertices.Seqend = seqend; - } } public void SetPolyLineObject(Polyline polyLine) diff --git a/ACadSharp/IO/Templates/CadPolyfaceMeshTemplate.cs b/ACadSharp/IO/Templates/CadPolyfaceMeshTemplate.cs index a4ff4d84..47433472 100644 --- a/ACadSharp/IO/Templates/CadPolyfaceMeshTemplate.cs +++ b/ACadSharp/IO/Templates/CadPolyfaceMeshTemplate.cs @@ -21,6 +21,11 @@ public override void Build(CadDocumentBuilder builder) PolyfaceMesh polyfaceMesh = (PolyfaceMesh)this.CadObject; + if (builder.TryGetCadObject(this.SeqendHandle, out Seqend seqend)) + { + polyfaceMesh.Vertices.Seqend = seqend; + } + if (this.FirstVerticeHandle.HasValue) { IEnumerable vertices = this.getEntitiesCollection(builder, this.FirstVerticeHandle.Value, this.LastVerticeHandle.Value); @@ -39,11 +44,6 @@ public override void Build(CadDocumentBuilder builder) } } } - - if (builder.TryGetCadObject(this.SeqendHandle, out Seqend seqend)) - { - polyfaceMesh.Vertices.Seqend = seqend; - } } private void addItemToPolyface(CadObject item, CadDocumentBuilder builder) diff --git a/ACadSharp/ISeqendColleciton.cs b/ACadSharp/ISeqendColleciton.cs index 1e266a7e..0ca68d45 100644 --- a/ACadSharp/ISeqendColleciton.cs +++ b/ACadSharp/ISeqendColleciton.cs @@ -1,9 +1,15 @@ using ACadSharp.Entities; +using System; +using System.Collections; namespace ACadSharp { - public interface ISeqendColleciton + public interface ISeqendCollection : IEnumerable { + public event EventHandler OnSeqendAdded; + + public event EventHandler OnSeqendRemoved; + Seqend Seqend { get; } } } diff --git a/ACadSharp/SeqendCollection.cs b/ACadSharp/SeqendCollection.cs index 448282d0..e47b5ccf 100644 --- a/ACadSharp/SeqendCollection.cs +++ b/ACadSharp/SeqendCollection.cs @@ -1,4 +1,6 @@ using ACadSharp.Entities; +using System; +using System.Linq; namespace ACadSharp { @@ -6,12 +8,22 @@ namespace ACadSharp /// Represents a collection of ended by a entity /// /// - public class SeqendCollection : CadObjectCollection, ISeqendColleciton + public class SeqendCollection : CadObjectCollection, ISeqendCollection where T : CadObject { + public event EventHandler OnSeqendAdded; + + public event EventHandler OnSeqendRemoved; + public Seqend Seqend { - get { return _seqend; } + get + { + if (this._entries.Any()) + return this._seqend; + else + return null; + } internal set { this._seqend = value; @@ -23,7 +35,38 @@ internal set public SeqendCollection(CadObject owner) : base(owner) { - this.Seqend = new Seqend(); + this._seqend = new Seqend(); + this._seqend.Owner = owner; + } + + /// + public override void Add(T item) + { + bool addSeqend = false; + if (!this._entries.Any()) + { + addSeqend = true; + } + + base.Add(item); + + // The add could fail due an Exception + if (addSeqend && this._entries.Any()) + { + this.OnSeqendAdded?.Invoke(this, new CollectionChangedEventArgs(this._seqend)); + } + } + + /// + public override T Remove(T item) + { + var e = base.Remove(item); + if(e != null) + { + this.OnSeqendRemoved?.Invoke(this, new CollectionChangedEventArgs(this._seqend)); + } + + return e; } } }