diff --git a/.config/dotnet-tools.json b/.config/dotnet-tools.json index c6de02b2..eee84bcb 100644 --- a/.config/dotnet-tools.json +++ b/.config/dotnet-tools.json @@ -3,7 +3,7 @@ "isRoot": true, "tools": { "netdocgen.runner": { - "version": "0.1.0", + "version": "0.1.1", "commands": [ "netdocgen" ], diff --git a/.github/workflows/coveralls.yml b/.github/workflows/coveralls.yml new file mode 100644 index 00000000..6ae3bbd4 --- /dev/null +++ b/.github/workflows/coveralls.yml @@ -0,0 +1,35 @@ +name: Coveralls + +on: + push: + branches: [ master ] + pull_request: + branches: [ master ] + +env: + SAMPLES_FOLDER: "../../../../samples" + OUTPUT_SAMPLES_FOLDER: "../../../../samples/out" + OUTPUT_SINGLE_CASES_FOLDER: "../../../../samples/out/single_cases" + LOCAL_ENV: "false" + DELTA: "0.00001" + DECIMAL_PRECISION: "5" + RUN_DWG_WRITER_SINGLE_CASES_TEST: "false" + +jobs: + build: + runs-on: windows-latest + steps: + - uses: actions/checkout@v2 + with: + submodules: true + - name: Restore dependencies + run: dotnet restore + - name: Build + run: dotnet build --no-restore + - name: Test + run: dotnet test -p:CollectCoverage=true -p:CoverletOutput=TestResults/ -p:CoverletOutputFormat=lcov --no-build --verbosity normal ACadSharp.Tests/ + - name: Coveralls action + uses: coverallsapp/github-action@master + with: + github-token: ${{ github.token }} + path-to-lcov: ACadSharp.Tests/TestResults/coverage.info \ No newline at end of file diff --git a/.gitmodules b/.gitmodules index 5323431e..c3ea5891 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,6 +1,3 @@ [submodule "CSUtilities"] path = CSUtilities url = https://github.com/DomCR/CSUtilities -[submodule "wiki"] - path = wiki - url = https://github.com/DomCR/ACadSharp.wiki.git diff --git a/ACadSharp.Tests/ACadSharp.Tests.csproj b/ACadSharp.Tests/ACadSharp.Tests.csproj index 72585c0a..0dad927e 100644 --- a/ACadSharp.Tests/ACadSharp.Tests.csproj +++ b/ACadSharp.Tests/ACadSharp.Tests.csproj @@ -12,10 +12,14 @@ + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + - + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/ACadSharp.Tests/CadDocumentTests.cs b/ACadSharp.Tests/CadDocumentTests.cs index 258766ea..bd7acd63 100644 --- a/ACadSharp.Tests/CadDocumentTests.cs +++ b/ACadSharp.Tests/CadDocumentTests.cs @@ -5,6 +5,7 @@ using ACadSharp.Entities; using Xunit.Abstractions; using ACadSharp.Blocks; +using System.Linq; namespace ACadSharp.Tests { @@ -50,6 +51,11 @@ public void CadDocumentDefaultTest() this._docIntegrity.AssertDocumentDefaults(doc); this._docIntegrity.AssertTableHirearchy(doc); this._docIntegrity.AssertBlockRecords(doc); + + Assert.Equal(2, doc.BlockRecords.Count); + Assert.Equal(1, doc.Layers.Count); + Assert.Equal(3, doc.LineTypes.Count); + Assert.Equal(2, doc.Layouts.Count()); } [Fact] diff --git a/ACadSharp.Tests/Common/DocumentIntegrity.cs b/ACadSharp.Tests/Common/DocumentIntegrity.cs index c9fe9168..af98270b 100644 --- a/ACadSharp.Tests/Common/DocumentIntegrity.cs +++ b/ACadSharp.Tests/Common/DocumentIntegrity.cs @@ -59,8 +59,10 @@ public void AssertDocumentDefaults(CadDocument doc) this.entryNotNull(doc.VPorts, "*Active"); //Assert Model layout - var layout = doc.Layouts.FirstOrDefault(l => l.Name == Layout.LayoutModelName); + var layout = doc.Layouts.FirstOrDefault(l => l.Name == Layout.ModelLayoutName); + this.notNull(layout, "Layout Model is null"); + Assert.True(layout.AssociatedBlock == doc.ModelSpace); } diff --git a/ACadSharp.Tests/Entities/EntityTests.cs b/ACadSharp.Tests/Entities/EntityTests.cs index 0854a38b..bb2dd290 100644 --- a/ACadSharp.Tests/Entities/EntityTests.cs +++ b/ACadSharp.Tests/Entities/EntityTests.cs @@ -22,6 +22,15 @@ static EntityTests() } } + [Theory] + [MemberData(nameof(EntityTypes))] + public void BoundingBoxTest(Type entityType) + { + Entity entity = EntityFactory.Create(entityType); + + entity.GetBoundingBox(); + } + [Theory] [MemberData(nameof(EntityTypes))] public void Clone(Type entityType) diff --git a/ACadSharp.Tests/IO/CadReaderTestsBase.cs b/ACadSharp.Tests/IO/CadReaderTestsBase.cs index 11ac17cc..f4b3e417 100644 --- a/ACadSharp.Tests/IO/CadReaderTestsBase.cs +++ b/ACadSharp.Tests/IO/CadReaderTestsBase.cs @@ -1,16 +1,14 @@ -using ACadSharp.Entities; -using ACadSharp.Header; +using ACadSharp.Header; using ACadSharp.IO; using System; using System.Collections.Generic; -using System.Linq; using Xunit; using Xunit.Abstractions; namespace ACadSharp.Tests.IO { public abstract class CadReaderTestsBase : IOTestsBase, IDisposable - where T : CadReaderBase + where T : ICadReader { protected readonly Dictionary _documents = new Dictionary(); //TODO: this does not store the document readed @@ -38,6 +36,8 @@ public virtual void AssertDocumentDefaults(string test) { CadDocument doc = this.getDocument(test); + Assert.NotNull(doc.SummaryInfo); + if (doc.Header.Version < ACadVersion.AC1012) { //Older version do not keep the handles for tables and other objects like block_records diff --git a/ACadSharp.Tests/IO/DWG/DwgWriterSingleObjectTests.cs b/ACadSharp.Tests/IO/DWG/DwgWriterSingleObjectTests.cs index 07acc9ef..dc093d16 100644 --- a/ACadSharp.Tests/IO/DWG/DwgWriterSingleObjectTests.cs +++ b/ACadSharp.Tests/IO/DWG/DwgWriterSingleObjectTests.cs @@ -45,7 +45,7 @@ protected virtual void writeDwgFile(SingleCaseGenerator data, ACadVersion versio string path = this.getPath(data.Name, "dwg", version); data.Document.Header.Version = version; - DwgWriter.Write(path, data.Document, this.onNotification); + DwgWriter.Write(path, data.Document, notification: this.onNotification); } } } \ No newline at end of file diff --git a/ACadSharp.Tests/IO/IOTests.cs b/ACadSharp.Tests/IO/IOTests.cs index 54ab8aa6..d0215b7a 100644 --- a/ACadSharp.Tests/IO/IOTests.cs +++ b/ACadSharp.Tests/IO/IOTests.cs @@ -56,7 +56,7 @@ public void DxfToDxf(string test) { CadDocument doc = DxfReader.Read(test); - if(doc.Header.Version < ACadVersion.AC1012) + if (doc.Header.Version < ACadVersion.AC1012) { return; } diff --git a/ACadSharp.Tests/IO/LocalSampleTests.cs b/ACadSharp.Tests/IO/LocalSampleTests.cs index 1a53ed01..9b13bc3b 100644 --- a/ACadSharp.Tests/IO/LocalSampleTests.cs +++ b/ACadSharp.Tests/IO/LocalSampleTests.cs @@ -50,7 +50,6 @@ public void ReadUserDxf(string test) } } - [Theory] [MemberData(nameof(StressFiles))] public void ReadStressFiles(string test) diff --git a/ACadSharp.Tests/IO/WriterSingleObjectTests.cs b/ACadSharp.Tests/IO/WriterSingleObjectTests.cs index ab356d3a..12282329 100644 --- a/ACadSharp.Tests/IO/WriterSingleObjectTests.cs +++ b/ACadSharp.Tests/IO/WriterSingleObjectTests.cs @@ -176,6 +176,40 @@ public void SingleRasterImage() this.Document.Entities.Add(raster); } + public void CreateLayout() + { + //Draw a cross in the model + this.Document.Entities.Add(new Line(XYZ.Zero, new XYZ(100, 100, 0))); + this.Document.Entities.Add(new Line(new XYZ(0, 100, 0), new XYZ(100, 0, 0))); + + Layout layout = new Layout("my_layout"); + + this.Document.Layouts.Add(layout); + } + + public void LineTypeWithSegments() + { + LineType lt = new LineType("segmented"); + lt.Description = "hello"; + + LineType.Segment s1 = new LineType.Segment + { + Length = 12, + //Style = this.Document.TextStyles[TextStyle.DefaultName] + }; + + LineType.Segment s2 = new LineType.Segment + { + Length = -3, + //Style = this.Document.TextStyles[TextStyle.DefaultName] + }; + + lt.AddSegment(s1); + lt.AddSegment(s2); + + this.Document.LineTypes.Add(lt); + } + public void ClosedLwPolyline() { List vertices = new List() { @@ -208,12 +242,21 @@ public void ClosedPolyline2DTest() new Vertex2D() { Location = new XYZ(4, 4, 0) } }; - var Pline = new Polyline2D(); - Pline.Vertices.AddRange(vector2d); - Pline.IsClosed = true; - Pline.Vertices.ElementAt(3).Bulge = 1; + var pline = new Polyline2D(); + pline.Vertices.AddRange(vector2d); + pline.IsClosed = true; + pline.Vertices.ElementAt(3).Bulge = 1; + + this.Document.Entities.Add(pline); + } - this.Document.Entities.Add(Pline); + public void EntityTransparency() + { + Line line = new Line(XYZ.Zero, new XYZ(100, 100, 0)); + + line.Transparency = new Transparency(50); + + this.Document.Entities.Add(line); } public void Deserialize(IXunitSerializationInfo info) @@ -257,6 +300,9 @@ static WriterSingleObjectTests() Data.Add(new(nameof(SingleCaseGenerator.ClosedPolyline2DTest))); Data.Add(new(nameof(SingleCaseGenerator.SingleRasterImage))); Data.Add(new(nameof(SingleCaseGenerator.SingleWipeout))); + Data.Add(new(nameof(SingleCaseGenerator.CreateLayout))); + Data.Add(new(nameof(SingleCaseGenerator.EntityTransparency))); + Data.Add(new(nameof(SingleCaseGenerator.LineTypeWithSegments))); } protected string getPath(string name, string ext, ACadVersion version) diff --git a/ACadSharp.Tests/Objects/CadDictionaryTests.cs b/ACadSharp.Tests/Objects/CadDictionaryTests.cs index f95c0dab..37cc85b1 100644 --- a/ACadSharp.Tests/Objects/CadDictionaryTests.cs +++ b/ACadSharp.Tests/Objects/CadDictionaryTests.cs @@ -16,9 +16,25 @@ public void AvoidDuplicatedEntries() cadDictionary.Add(scale); Scale scale1 = new Scale(); + scale1.Name = "scale_test"; + + Assert.Throws(() => cadDictionary.Add(scale1)); + + scale.Name = "changed_name"; + scale1.Name = "changed_name"; + + Assert.Throws(() => cadDictionary.Add(scale1)); + } + + [Fact] + public void TryAddTest() + { + CadDictionary cadDictionary = new CadDictionary(); + Scale scale = new Scale(); scale.Name = "scale_test"; - Assert.Throws(() => cadDictionary.Add(scale)); + Assert.True(cadDictionary.TryAdd(scale)); + Assert.False(cadDictionary.TryAdd(scale)); } } } diff --git a/ACadSharp.Tests/Objects/Collections/ScaleCollectionTests.cs b/ACadSharp.Tests/Objects/Collections/ScaleCollectionTests.cs index af5d8943..a612734a 100644 --- a/ACadSharp.Tests/Objects/Collections/ScaleCollectionTests.cs +++ b/ACadSharp.Tests/Objects/Collections/ScaleCollectionTests.cs @@ -4,7 +4,7 @@ namespace ACadSharp.Tests.Objects.Collections { public class ScaleCollectionTests { - [Fact(Skip = "test needed for root dictionary")] + [Fact] public void InitScaleCollection() { CadDocument doc = new CadDocument(); diff --git a/ACadSharp.Tests/Objects/LayoutTests.cs b/ACadSharp.Tests/Objects/LayoutTests.cs new file mode 100644 index 00000000..fed56f48 --- /dev/null +++ b/ACadSharp.Tests/Objects/LayoutTests.cs @@ -0,0 +1,67 @@ +using ACadSharp.Objects; +using System; +using System.Linq; +using Xunit; + +namespace ACadSharp.Tests.Objects +{ + public class LayoutTests + { + [Fact] + public void AddLayout() + { + CadDocument document = new CadDocument(); + + string layoutName = "my_layout"; + Layout layout = new Layout(layoutName); + + document.Layouts.Add(layout); + + Assert.Equal(layoutName, layout.AssociatedBlock.Name); + Assert.Equal(3, document.Layouts.Count()); + Assert.True(document.BlockRecords.Contains(layoutName)); + } + + [Fact] + public void RemoveBlockRecordTest() + { + var document = new CadDocument(); + + string layoutName = "my_layout"; + Layout layout = new Layout(layoutName); + + document.Layouts.Add(layout); + + document.BlockRecords.Remove(layoutName); + + Assert.Equal(2, document.Layouts.Count()); + Assert.False(document.Layouts.ContainsKey(layoutName)); + Assert.False(document.BlockRecords.Contains(layoutName)); + } + + [Fact] + public void RemoveTest() + { + var document = new CadDocument(); + + string layoutName = "my_layout"; + Layout layout = new Layout(layoutName); + + document.Layouts.Add(layout); + + Assert.True(document.Layouts.Remove(layoutName)); + Assert.Equal(2, document.Layouts.Count()); + Assert.True(document.BlockRecords.Contains(layoutName)); + Assert.NotEqual(document.BlockRecords[layoutName], layout.AssociatedBlock); + } + + [Fact] + public void CannotRemoveDefaultLayouts() + { + var document = new CadDocument(); + + Assert.Throws(() => document.Layouts.Remove(Layout.ModelLayoutName)); + Assert.Throws(() => document.Layouts.Remove(Layout.PaperLayoutName)); + } + } +} diff --git a/ACadSharp.Tests/Objects/ScaleCollectionTests.cs b/ACadSharp.Tests/Objects/ScaleCollectionTests.cs deleted file mode 100644 index 6e42b58d..00000000 --- a/ACadSharp.Tests/Objects/ScaleCollectionTests.cs +++ /dev/null @@ -1,20 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using Xunit; - -namespace ACadSharp.Tests.Objects -{ - public class ScaleCollectionTests - { - [Fact] - public void InitScaleCollection() - { - CadDocument doc = new CadDocument(); - - Assert.NotNull(doc.Scales); - } - } -} diff --git a/ACadSharp.sln b/ACadSharp.sln index b54d7ca0..70b880ca 100644 --- a/ACadSharp.sln +++ b/ACadSharp.sln @@ -38,6 +38,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "workflows", "workflows", "{ .github\workflows\build.yml = .github\workflows\build.yml .github\workflows\build_n_test.yml = .github\workflows\build_n_test.yml publish.yml = publish.yml + .github\workflows\coveralls.yml = .github\workflows\coveralls.yml .github\workflows\wiki-gen.yml = .github\workflows\wiki-gen.yml EndProjectSection EndProject diff --git a/ACadSharp/ACadSharp.csproj b/ACadSharp/ACadSharp.csproj index 3911c0f7..04165eac 100644 --- a/ACadSharp/ACadSharp.csproj +++ b/ACadSharp/ACadSharp.csproj @@ -17,7 +17,7 @@ true README.md - 2.3.2-beta + 2.4.0-beta diff --git a/ACadSharp/Blocks/Block.cs b/ACadSharp/Blocks/Block.cs index ce201ce1..84e1be2b 100644 --- a/ACadSharp/Blocks/Block.cs +++ b/ACadSharp/Blocks/Block.cs @@ -85,5 +85,16 @@ public override CadObject Clone() return clone; } + + public override BoundingBox GetBoundingBox() + { + BoundingBox box = BoundingBox.Null; + foreach (var item in this.BlockOwner.Entities) + { + box = box.Merge(item.GetBoundingBox()); + } + + return box; + } } } diff --git a/ACadSharp/Blocks/BlockEnd.cs b/ACadSharp/Blocks/BlockEnd.cs index 35a45e35..9629d02d 100644 --- a/ACadSharp/Blocks/BlockEnd.cs +++ b/ACadSharp/Blocks/BlockEnd.cs @@ -1,6 +1,7 @@ using ACadSharp.Attributes; using ACadSharp.Entities; using ACadSharp.Tables; +using CSMath; namespace ACadSharp.Blocks { @@ -36,5 +37,11 @@ public override CadObject Clone() clone.Owner = new BlockRecord((this.Owner as BlockRecord).Name); return clone; } + + /// + public override BoundingBox GetBoundingBox() + { + return BoundingBox.Null; + } } } diff --git a/ACadSharp/CadDocument.cs b/ACadSharp/CadDocument.cs index 01428023..0f4f9059 100644 --- a/ACadSharp/CadDocument.cs +++ b/ACadSharp/CadDocument.cs @@ -263,7 +263,15 @@ public void CreateDefaults() this.AppIds ??= new AppIdsTable(this); //Root dictionary - this.RootDictionary ??= CadDictionary.CreateRoot(); + if (this.RootDictionary == null) + { + this.RootDictionary = CadDictionary.CreateRoot(); + } + else + { + CadDictionary.CreateDefaultEntries(this.RootDictionary); + } + this.UpdateCollections(true); //Default variables @@ -278,15 +286,13 @@ public void CreateDefaults() if (!this.BlockRecords.Contains(BlockRecord.ModelSpaceName)) { BlockRecord model = BlockRecord.ModelSpace; - model.Layout = this.Layouts[Layout.LayoutModelName]; - this.BlockRecords.Add(model); + this.Layouts.Add(model.Layout); } if (!this.BlockRecords.Contains(BlockRecord.PaperSpaceName)) { BlockRecord pspace = BlockRecord.PaperSpace; - pspace.Layout = this.Layouts["Layout1"]; - this.BlockRecords.Add(pspace); + this.Layouts.Add(pspace.Layout); } } diff --git a/ACadSharp/DxfPropertyBase.cs b/ACadSharp/DxfPropertyBase.cs index 5e03d23c..4b090287 100644 --- a/ACadSharp/DxfPropertyBase.cs +++ b/ACadSharp/DxfPropertyBase.cs @@ -130,7 +130,7 @@ public void SetValue(int code, TCadObject obj, object value) } else if (this._property.PropertyType.IsEquivalentTo(typeof(Transparency))) { - this._property.SetValue(obj, Transparency.FromValue((int)value)); + this._property.SetValue(obj, Transparency.FromAlphaValue((int)value)); } else if (this._property.PropertyType.IsEquivalentTo(typeof(bool))) { diff --git a/ACadSharp/Entities/Arc.cs b/ACadSharp/Entities/Arc.cs index e701aba4..a83c6d6b 100644 --- a/ACadSharp/Entities/Arc.cs +++ b/ACadSharp/Entities/Arc.cs @@ -39,6 +39,9 @@ public class Arc : Circle [DxfCodeValue(DxfReferenceType.IsAngle, 51)] public double EndAngle { get; set; } = Math.PI; + /// + /// Default constructor + /// public Arc() : base() { } /// @@ -73,5 +76,45 @@ public static Arc CreateFromBulge(XY p1, XY p2, double bulge) EndAngle = endAngle, }; } + + /// + /// Process the 2 points limiting the arc segment + /// + /// Start point of the arc segment + /// End point of the arc segment + public void GetEndVertices(out XYZ start, out XYZ end) + { + if (this.Normal != XYZ.AxisZ) + { + throw new NotImplementedException("GetBoundPoints box for not aligned Normal is not implemented"); + } + + double tmpEndAngle = this.EndAngle; + + if (this.EndAngle < this.StartAngle) + { + tmpEndAngle += 2 * Math.PI; + } + + double delta = tmpEndAngle - this.StartAngle; + + double angle = this.StartAngle + delta; + double startX = this.Radius * Math.Sin(angle); + double startY = this.Radius * Math.Cos(angle); + + startX = MathUtils.IsZero(startX) ? 0 : startX; + startY = MathUtils.IsZero(startY) ? 0 : startY; + + start = new XYZ(startX, startY, 0); + + double angle2 = this.StartAngle + delta * 2; + double endX = (this.Radius * Math.Sin(angle2)); + double endY = (this.Radius * Math.Cos(angle2)); + + endX = MathUtils.IsZero(endX) ? 0 : endX; + endY = MathUtils.IsZero(endY) ? 0 : endY; + + end = new XYZ(endX, endY, 0); + } } } diff --git a/ACadSharp/Entities/CadImageBase.cs b/ACadSharp/Entities/CadImageBase.cs index 952af89a..d917d42e 100644 --- a/ACadSharp/Entities/CadImageBase.cs +++ b/ACadSharp/Entities/CadImageBase.cs @@ -3,9 +3,13 @@ using System.Collections.Generic; using System; using ACadSharp.Objects; +using System.Linq; namespace ACadSharp.Entities { + /// + /// Common base class for and . + /// [DxfSubClass(null, true)] public abstract class CadImageBase : Entity { @@ -185,6 +189,28 @@ internal ImageDefinitionReactor DefinitionReactor private ImageDefinition _definition; private ImageDefinitionReactor _definitionReactor; + /// + public override BoundingBox GetBoundingBox() + { + if (!this.ClipBoundaryVertices.Any()) + { + return BoundingBox.Null; + } + + double minX = this.ClipBoundaryVertices.Select(v => v.X).Min(); + double minY = this.ClipBoundaryVertices.Select(v => v.Y).Min(); + XYZ min = new XYZ(minX, minY, 0) + this.InsertPoint; + + double maxX = this.ClipBoundaryVertices.Select(v => v.X).Max(); + double maxY = this.ClipBoundaryVertices.Select(v => v.Y).Max(); + XYZ max = new XYZ(maxX, maxY, 0) + this.InsertPoint; + + BoundingBox box = new BoundingBox(min, max); + + return box; + } + + /// public override CadObject Clone() { CadImageBase clone = (CadImageBase)base.Clone(); diff --git a/ACadSharp/Entities/Circle.cs b/ACadSharp/Entities/Circle.cs index a73a9188..468be68e 100644 --- a/ACadSharp/Entities/Circle.cs +++ b/ACadSharp/Entities/Circle.cs @@ -1,5 +1,6 @@ using ACadSharp.Attributes; using CSMath; +using System; namespace ACadSharp.Entities { @@ -22,7 +23,7 @@ public class Circle : Entity /// public override string SubclassMarker => DxfSubclassMarker.Circle; - + /// /// Specifies the three-dimensional normal unit vector for the object. /// @@ -45,11 +46,33 @@ public class Circle : Entity /// Specifies the radius of an arc, circle, or position marker. /// [DxfCodeValue(40)] - public double Radius { get; set; } = 1.0; + public double Radius + { + get { return this._radius; } + set + { + if (value <= 0) + { + throw new ArgumentOutOfRangeException(nameof(value), value, "The radius must be greater than 0."); + } + this._radius = value; + } + } + + private double _radius = 1.0; /// /// Default constructor /// 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)); + + return new BoundingBox(min, max); + } } } diff --git a/ACadSharp/Entities/Dimension.cs b/ACadSharp/Entities/Dimension.cs index e7dd304e..e98fb879 100644 --- a/ACadSharp/Entities/Dimension.cs +++ b/ACadSharp/Entities/Dimension.cs @@ -213,6 +213,7 @@ protected Dimension(DimensionType type) this._flags |= DimensionType.BlockReference; } + /// public override CadObject Clone() { Dimension clone = (Dimension)base.Clone(); diff --git a/ACadSharp/Entities/DimensionAligned.cs b/ACadSharp/Entities/DimensionAligned.cs index beb0617c..74beb1ae 100644 --- a/ACadSharp/Entities/DimensionAligned.cs +++ b/ACadSharp/Entities/DimensionAligned.cs @@ -54,6 +54,15 @@ public override double Measurement protected DimensionAligned(DimensionType type) : base(type) { } + /// + /// Default constructor. + /// public DimensionAligned() : base(DimensionType.Aligned) { } + + /// + public override BoundingBox GetBoundingBox() + { + return new BoundingBox(this.FirstPoint, this.SecondPoint); + } } } diff --git a/ACadSharp/Entities/DimensionAngular2Line.cs b/ACadSharp/Entities/DimensionAngular2Line.cs index 02249ede..ada1b1e2 100644 --- a/ACadSharp/Entities/DimensionAngular2Line.cs +++ b/ACadSharp/Entities/DimensionAngular2Line.cs @@ -59,8 +59,17 @@ public override double Measurement } } + /// + /// Default constructor. + /// public DimensionAngular2Line() : base(DimensionType.Angular) { } + + /// + public override BoundingBox GetBoundingBox() + { + return new BoundingBox(this.FirstPoint, this.SecondPoint); + } } } diff --git a/ACadSharp/Entities/DimensionAngular3Pt.cs b/ACadSharp/Entities/DimensionAngular3Pt.cs index 6437b94d..3cc87510 100644 --- a/ACadSharp/Entities/DimensionAngular3Pt.cs +++ b/ACadSharp/Entities/DimensionAngular3Pt.cs @@ -64,6 +64,15 @@ public override double Measurement } } + /// + /// Default constructor. + /// public DimensionAngular3Pt() : base(DimensionType.Angular3Point) { } + + /// + public override BoundingBox GetBoundingBox() + { + return new BoundingBox(this.FirstPoint, this.SecondPoint); + } } } diff --git a/ACadSharp/Entities/DimensionDiameter.cs b/ACadSharp/Entities/DimensionDiameter.cs index 986dfa0c..bd8972df 100644 --- a/ACadSharp/Entities/DimensionDiameter.cs +++ b/ACadSharp/Entities/DimensionDiameter.cs @@ -44,6 +44,15 @@ public override double Measurement } } + /// + /// Default constructor. + /// public DimensionDiameter() : base(DimensionType.Diameter) { } + + /// + public override BoundingBox GetBoundingBox() + { + return new BoundingBox(this.InsertionPoint - this.AngleVertex, this.InsertionPoint + this.AngleVertex); + } } } diff --git a/ACadSharp/Entities/DimensionOrdinate.cs b/ACadSharp/Entities/DimensionOrdinate.cs index 98b3241f..72d03850 100644 --- a/ACadSharp/Entities/DimensionOrdinate.cs +++ b/ACadSharp/Entities/DimensionOrdinate.cs @@ -77,6 +77,15 @@ public bool IsOrdinateTypeX } } + /// + /// Default constructor. + /// public DimensionOrdinate() : base(DimensionType.Ordinate) { } + + /// + public override BoundingBox GetBoundingBox() + { + return new BoundingBox(this.FeatureLocation, this.LeaderEndpoint); + } } } diff --git a/ACadSharp/Entities/DimensionRadius.cs b/ACadSharp/Entities/DimensionRadius.cs index e4a90675..f8a0b5c6 100644 --- a/ACadSharp/Entities/DimensionRadius.cs +++ b/ACadSharp/Entities/DimensionRadius.cs @@ -44,6 +44,15 @@ public override double Measurement } } + /// + /// Default constructor. + /// public DimensionRadius() : base(DimensionType.Radius) { } + + /// + public override BoundingBox GetBoundingBox() + { + return new BoundingBox(this.InsertionPoint - this.AngleVertex, this.InsertionPoint + this.AngleVertex); + } } } diff --git a/ACadSharp/Entities/Ellipse.cs b/ACadSharp/Entities/Ellipse.cs index f5b31447..32716e56 100644 --- a/ACadSharp/Entities/Ellipse.cs +++ b/ACadSharp/Entities/Ellipse.cs @@ -1,5 +1,4 @@ using ACadSharp.Attributes; -using ACadSharp.IO.Templates; using CSMath; using System; @@ -32,31 +31,31 @@ public class Ellipse : Entity public double Thickness { get; set; } = 0.0; /// - /// Extrusion direction + /// Extrusion direction. /// [DxfCodeValue(210, 220, 230)] public XYZ Normal { get; set; } = XYZ.AxisZ; /// - /// Center point (in WCS) + /// Center point (in WCS). /// [DxfCodeValue(10, 20, 30)] public XYZ Center { get; set; } = XYZ.Zero; /// - /// Endpoint of major axis, relative to the center (in WCS) + /// Endpoint of major axis, relative to the center (in WCS). /// [DxfCodeValue(11, 21, 31)] public XYZ EndPoint { get; set; } = XYZ.Zero; /// - /// Ratio of minor axis to major axis + /// Ratio of minor axis to major axis. /// [DxfCodeValue(40)] public double RadiusRatio { get; set; } = 0.0; /// - /// Start parameter + /// Start parameter. /// /// /// The valid range is 0 to 2 * PI. @@ -65,7 +64,7 @@ public class Ellipse : Entity public double StartParameter { get; set; } = 0.0; /// - /// End parameter + /// End parameter. /// /// /// The valid range is 0 to 2 * PI. @@ -73,9 +72,10 @@ public class Ellipse : Entity [DxfCodeValue(42)] public double EndParameter { get; set; } = Math.PI * 2; - /// - /// Default constructor - /// - public Ellipse() : base() { } + /// + public override BoundingBox GetBoundingBox() + { + return BoundingBox.Null; + } } } diff --git a/ACadSharp/Entities/Entity.cs b/ACadSharp/Entities/Entity.cs index 2f7c84d9..b9f9f1a2 100644 --- a/ACadSharp/Entities/Entity.cs +++ b/ACadSharp/Entities/Entity.cs @@ -1,7 +1,7 @@ using ACadSharp.Attributes; using ACadSharp.Objects; using ACadSharp.Tables; -using ACadSharp.Tables.Collections; +using CSMath; using System; namespace ACadSharp.Entities @@ -56,7 +56,7 @@ public Layer Layer /// [DxfCodeValue(440)] - public Transparency Transparency { get; set; } + public Transparency Transparency { get; set; } = Transparency.ByLayer; /// [DxfCodeValue(DxfReferenceType.Name, 6)] @@ -94,6 +94,12 @@ public LineType LineType /// public Entity() : base() { } + /// + /// Gets the bounding box aligned with the axis XYZ that ocupies this entity + /// + /// + public abstract BoundingBox GetBoundingBox(); + /// public void MatchProperties(IEntity entity) { diff --git a/ACadSharp/Entities/Face3D.cs b/ACadSharp/Entities/Face3D.cs index d56ba5ac..8c80a8ae 100644 --- a/ACadSharp/Entities/Face3D.cs +++ b/ACadSharp/Entities/Face3D.cs @@ -1,5 +1,6 @@ using ACadSharp.Attributes; using CSMath; +using System.Collections.Generic; namespace ACadSharp.Entities { @@ -24,19 +25,19 @@ public class Face3D : Entity public override string SubclassMarker => DxfSubclassMarker.Face3d; /// - /// First corner(in WCS) + /// First corner(in WCS). /// [DxfCodeValue(10, 20, 30)] public XYZ FirstCorner { get; set; } /// - /// Second corner(in WCS) + /// Second corner(in WCS). /// [DxfCodeValue(11, 21, 31)] public XYZ SecondCorner { get; set; } /// - /// Third corner(in WCS) + /// Third corner(in WCS). /// [DxfCodeValue(12, 22, 32)] public XYZ ThirdCorner { get; set; } @@ -51,11 +52,17 @@ public class Face3D : Entity public XYZ FourthCorner { get; set; } /// - /// Invisible edge flags + /// Invisible edge flags. /// [DxfCodeValue(70)] public InvisibleEdgeFlags Flags { get; set; } public Face3D() : base() { } + + /// + public override BoundingBox GetBoundingBox() + { + return BoundingBox.FromPoints(new List { this.FirstCorner, this.SecondCorner, this.ThirdCorner, this.FourthCorner }); + } } } diff --git a/ACadSharp/Entities/Hatch.cs b/ACadSharp/Entities/Hatch.cs index 31335f8b..df982834 100644 --- a/ACadSharp/Entities/Hatch.cs +++ b/ACadSharp/Entities/Hatch.cs @@ -1,6 +1,7 @@ using ACadSharp.Attributes; using CSMath; using System.Collections.Generic; +using System.Linq; namespace ACadSharp.Entities { @@ -128,8 +129,18 @@ public partial class Hatch : Entity private HatchPattern _pattern = HatchPattern.Solid; + /// + /// Default constructor. + /// public Hatch() : base() { } + /// + public override BoundingBox GetBoundingBox() + { + return BoundingBox.FromPoints(this.SeedPoints.Cast()); + } + + /// public override CadObject Clone() { Hatch clone = base.Clone() as Hatch; diff --git a/ACadSharp/Entities/Insert.cs b/ACadSharp/Entities/Insert.cs index aed70e81..879f53b1 100644 --- a/ACadSharp/Entities/Insert.cs +++ b/ACadSharp/Entities/Insert.cs @@ -168,6 +168,18 @@ public void UpdateAttributes() throw new NotImplementedException(); } + /// + public override BoundingBox GetBoundingBox() + { + BoundingBox box = this.Block.BlockEntity.GetBoundingBox(); + + var scale = new XYZ(this.XScale, this.YScale, this.ZScale); + var min = box.Min * scale + this.InsertPoint; + var max = box.Max * scale + this.InsertPoint; + + return new BoundingBox(min, max); + } + /// public override CadObject Clone() { diff --git a/ACadSharp/Entities/Leader.cs b/ACadSharp/Entities/Leader.cs index 3c68eef6..1392ea11 100644 --- a/ACadSharp/Entities/Leader.cs +++ b/ACadSharp/Entities/Leader.cs @@ -27,7 +27,7 @@ public class Leader : Entity public override string SubclassMarker => DxfSubclassMarker.Leader; /// - /// Dimension Style + /// Dimension Style. /// [DxfCodeValue(DxfReferenceType.Name, 3)] public DimensionStyle Style @@ -52,13 +52,13 @@ public DimensionStyle Style } /// - /// Arrowhead flag + /// Arrowhead flag. /// [DxfCodeValue(71)] public bool ArrowHeadEnabled { get; set; } /// - /// Leader Path Type + /// Leader Path Type. /// /// /// 0 = straight lines @@ -68,7 +68,7 @@ public DimensionStyle Style public LeaderPathType PathType { get; set; } /// - /// Leader creation flag, AssociatedAnnotation type + /// Leader creation flag, AssociatedAnnotation type. /// /// /// 0 = mtext @@ -80,7 +80,7 @@ public DimensionStyle Style public LeaderCreationType CreationType { get; set; } = LeaderCreationType.CreatedWithoutAnnotation; /// - /// Hookline direction flag + /// Hookline direction flag. /// /// /// 0 = Hookline(or end of tangent for a splined leader) is the opposite direction from the horizontal vector
@@ -90,25 +90,25 @@ public DimensionStyle Style public bool HookLineDirection { get; set; } /// - /// Hookline flag + /// Hookline flag. /// [DxfCodeValue(75)] public bool HasHookline { get; set; } /// - /// Text annotation height + /// Text annotation height. /// [DxfCodeValue(40)] public double TextHeight { get; set; } /// - /// Text annotation width + /// Text annotation width. /// [DxfCodeValue(41)] public double TextWidth { get; set; } /// - /// Vertices in leader + /// Vertices in leader. /// [DxfCodeValue(DxfReferenceType.Count, 76)] [DxfCollectionCodeValue(10, 20, 30)] @@ -117,38 +117,50 @@ public DimensionStyle Style //77 Color to use if leader's DIMCLRD = BYBLOCK /// - /// Hard reference to associated annotation (mtext, tolerance, or insert entity) + /// Hard reference to associated annotation (mtext, tolerance, or insert entity). /// [DxfCodeValue(DxfReferenceType.Handle, 340)] public Entity AssociatedAnnotation { get; internal set; } /// - /// Normal vector + /// Normal vector. /// [DxfCodeValue(210, 220, 230)] public XYZ Normal { get; set; } = XYZ.AxisZ; /// - /// Horizontal direction for leader + /// Horizontal direction for leader. /// [DxfCodeValue(211, 221, 231)] public XYZ HorizontalDirection { get; set; } = XYZ.AxisX; /// - /// Offset of last leader vertex from block reference insertion point + /// Offset of last leader vertex from block reference insertion point. /// [DxfCodeValue(212, 222, 232)] public XYZ BlockOffset { get; set; } = XYZ.Zero; /// - /// Offset of last leader vertex from annotation placement point + /// Offset of last leader vertex from annotation placement point. /// [DxfCodeValue(213, 223, 233)] public XYZ AnnotationOffset { get; set; } = XYZ.Zero; - private DimensionStyle _style = DimensionStyle.Default; + /// + public override CadObject Clone() + { + Leader clone = (Leader)base.Clone(); + clone.Style = (DimensionStyle)(this.Style?.Clone()); + return clone; + } + + /// + public override BoundingBox GetBoundingBox() + { + return BoundingBox.FromPoints(this.Vertices); + } internal override void AssignDocument(CadDocument doc) { @@ -177,12 +189,5 @@ protected override void tableOnRemove(object sender, CollectionChangedEventArgs this.Style = this.Document.DimensionStyles[DimensionStyle.DefaultName]; } } - - public override CadObject Clone() - { - Leader clone = (Leader)base.Clone(); - clone.Style = (DimensionStyle)(this.Style?.Clone()); - return clone; - } } } diff --git a/ACadSharp/Entities/Line.cs b/ACadSharp/Entities/Line.cs index fa24a305..959732ca 100644 --- a/ACadSharp/Entities/Line.cs +++ b/ACadSharp/Entities/Line.cs @@ -62,5 +62,14 @@ public Line(XYZ start, XYZ end) : base() this.StartPoint = start; this.EndPoint = end; } + + /// + public override BoundingBox GetBoundingBox() + { + var min = new XYZ(System.Math.Min(this.StartPoint.X, this.EndPoint.X), System.Math.Min(this.StartPoint.Y, this.EndPoint.Y), System.Math.Min(this.StartPoint.Z, this.EndPoint.Z)); + var max = new XYZ(System.Math.Max(this.StartPoint.X, this.EndPoint.X), System.Math.Max(this.StartPoint.Y, this.EndPoint.Y), System.Math.Max(this.StartPoint.Z, this.EndPoint.Z)); + + return new BoundingBox(min, max); + } } } diff --git a/ACadSharp/Entities/LwPolyLine.cs b/ACadSharp/Entities/LwPolyLine.cs index 082032e6..dfa48268 100644 --- a/ACadSharp/Entities/LwPolyLine.cs +++ b/ACadSharp/Entities/LwPolyLine.cs @@ -90,5 +90,29 @@ public IEnumerable Explode() { return Polyline.Explode(this); } + + public override BoundingBox GetBoundingBox() + { + if (this.Vertices.Count < 2) + { + return BoundingBox.Null; + } + + XYZ first = (XYZ)this.Vertices[0].Location; + XYZ second = (XYZ)this.Vertices[1].Location; + + XYZ min = new XYZ(System.Math.Min(first.X, second.X), System.Math.Min(first.Y, second.Y), System.Math.Min(first.Z, second.Z)); + XYZ max = new XYZ(System.Math.Max(first.X, second.X), System.Math.Max(first.Y, second.Y), System.Math.Max(first.Z, second.Z)); + + for (int i = 2; i < this.Vertices.Count; i++) + { + XYZ curr = (XYZ)this.Vertices[i].Location; + + min = new XYZ(System.Math.Min(min.X, curr.X), System.Math.Min(min.Y, curr.Y), System.Math.Min(min.Z, curr.Z)); + max = new XYZ(System.Math.Max(max.X, curr.X), System.Math.Max(max.Y, curr.Y), System.Math.Max(max.Z, curr.Z)); + } + + return new BoundingBox(min, max); + } } } diff --git a/ACadSharp/Entities/MLine.cs b/ACadSharp/Entities/MLine.cs index 81da21c0..79154276 100644 --- a/ACadSharp/Entities/MLine.cs +++ b/ACadSharp/Entities/MLine.cs @@ -94,8 +94,7 @@ public MLineStyle Style private MLineStyle _style = MLineStyle.Default; - public MLine() : base() { } - + /// public override CadObject Clone() { MLine clone = (MLine)base.Clone(); @@ -111,6 +110,12 @@ public override CadObject Clone() return clone; } + /// + public override BoundingBox GetBoundingBox() + { + return BoundingBox.FromPoints(Vertices.Select(v => v.Position)); + } + internal override void AssignDocument(CadDocument doc) { base.AssignDocument(doc); diff --git a/ACadSharp/Entities/MText.cs b/ACadSharp/Entities/MText.cs index 4b656dc5..7f55e5ba 100644 --- a/ACadSharp/Entities/MText.cs +++ b/ACadSharp/Entities/MText.cs @@ -52,13 +52,13 @@ public double Height } /// - /// Reference rectangle width + /// Reference rectangle width. /// [DxfCodeValue(41)] public double RectangleWidth { get; set; } /// - /// Reference rectangle height + /// Reference rectangle height. /// [DxfCodeValue(46)] public double RectangleHeight { get; set; } @@ -212,6 +212,13 @@ public double Rotation /// public MText() : base() { } + /// + public override BoundingBox GetBoundingBox() + { + return new BoundingBox(this.InsertPoint); + } + + /// public override CadObject Clone() { MText clone = (MText)base.Clone(); diff --git a/ACadSharp/Entities/Mesh.Edge.cs b/ACadSharp/Entities/Mesh.Edge.cs index eb34eb01..0cbbc3ed 100644 --- a/ACadSharp/Entities/Mesh.Edge.cs +++ b/ACadSharp/Entities/Mesh.Edge.cs @@ -19,6 +19,17 @@ public struct Edge /// public double? Crease { get; set; } + /// + /// Edge constructor with the start and end of the edge. + /// + /// + /// + public Edge(int start, int end) + { + this.Start = start; + this.End = end; + } + public override string ToString() { string str = $"{this.Start}|{this.End}"; diff --git a/ACadSharp/Entities/Mesh.cs b/ACadSharp/Entities/Mesh.cs index bd66c7a2..b1a10223 100644 --- a/ACadSharp/Entities/Mesh.cs +++ b/ACadSharp/Entities/Mesh.cs @@ -74,5 +74,11 @@ public partial class Mesh : Entity //1 = Material //2 = Transparency //3 = Material mapper + + /// + public override BoundingBox GetBoundingBox() + { + return BoundingBox.FromPoints(this.Vertices); + } } } diff --git a/ACadSharp/Entities/MultiLeader.cs b/ACadSharp/Entities/MultiLeader.cs index a21e823d..71daafa9 100644 --- a/ACadSharp/Entities/MultiLeader.cs +++ b/ACadSharp/Entities/MultiLeader.cs @@ -574,6 +574,7 @@ public object Clone() /// public bool ExtendedToText { get; set; } + /// public override CadObject Clone() { MultiLeader clone = (MultiLeader)base.Clone(); @@ -588,5 +589,11 @@ public override CadObject Clone() return clone; } + + /// + public override BoundingBox GetBoundingBox() + { + return BoundingBox.Null; + } } } diff --git a/ACadSharp/Entities/Point.cs b/ACadSharp/Entities/Point.cs index 1eacb782..fb2f1479 100644 --- a/ACadSharp/Entities/Point.cs +++ b/ACadSharp/Entities/Point.cs @@ -1,5 +1,6 @@ using ACadSharp.Attributes; using CSMath; +using System; namespace ACadSharp.Entities { @@ -63,5 +64,11 @@ public Point(XYZ location) : base() { this.Location = location; } + + /// + public override BoundingBox GetBoundingBox() + { + return new BoundingBox(this.Location); + } } } diff --git a/ACadSharp/Entities/PolyFaceMesh.cs b/ACadSharp/Entities/PolyFaceMesh.cs index 1062c0ac..c24c9057 100644 --- a/ACadSharp/Entities/PolyFaceMesh.cs +++ b/ACadSharp/Entities/PolyFaceMesh.cs @@ -1,4 +1,5 @@ using ACadSharp.Attributes; +using CSMath; using System; using System.Collections.Generic; diff --git a/ACadSharp/Entities/PolyLine.cs b/ACadSharp/Entities/PolyLine.cs index e8029d01..82eb3d53 100644 --- a/ACadSharp/Entities/PolyLine.cs +++ b/ACadSharp/Entities/PolyLine.cs @@ -96,6 +96,32 @@ public Polyline() : base() public abstract IEnumerable Explode(); + /// + public override BoundingBox GetBoundingBox() + { + //TODO: can a polyline have only 1 vertex? + if (this.Vertices.Count < 2) + { + return BoundingBox.Null; + } + + XYZ first = this.Vertices[0].Location; + XYZ second = this.Vertices[1].Location; + + XYZ min = new XYZ(System.Math.Min(first.X, second.X), System.Math.Min(first.Y, second.Y), System.Math.Min(first.Z, second.Z)); + XYZ max = new XYZ(System.Math.Max(first.X, second.X), System.Math.Max(first.Y, second.Y), System.Math.Max(first.Z, second.Z)); + + for (int i = 2; i < this.Vertices.Count; i++) + { + XYZ curr = this.Vertices[i].Location; + + min = new XYZ(System.Math.Min(min.X, curr.X), System.Math.Min(min.Y, curr.Y), System.Math.Min(min.Z, curr.Z)); + max = new XYZ(System.Math.Max(max.X, curr.X), System.Math.Max(max.Y, curr.Y), System.Math.Max(max.Z, curr.Z)); + } + + return new BoundingBox(min, max); + } + internal static IEnumerable Explode(IPolyline polyline) { //Generic explode method for Polyline2D and LwPolyline diff --git a/ACadSharp/Entities/PolyLine2D.cs b/ACadSharp/Entities/PolyLine2D.cs index 05fa3b50..8aa28421 100644 --- a/ACadSharp/Entities/PolyLine2D.cs +++ b/ACadSharp/Entities/PolyLine2D.cs @@ -1,4 +1,5 @@ using ACadSharp.Attributes; +using CSMath; using System; using System.Collections.Generic; diff --git a/ACadSharp/Entities/PolyLine3D.cs b/ACadSharp/Entities/PolyLine3D.cs index f71ea13f..0ee6ed9e 100644 --- a/ACadSharp/Entities/PolyLine3D.cs +++ b/ACadSharp/Entities/PolyLine3D.cs @@ -1,4 +1,5 @@ using ACadSharp.Attributes; +using CSMath; using System; using System.Collections.Generic; diff --git a/ACadSharp/Entities/PolyfaceMesh.cs b/ACadSharp/Entities/PolyfaceMesh.cs index 1062c0ac..c24c9057 100644 --- a/ACadSharp/Entities/PolyfaceMesh.cs +++ b/ACadSharp/Entities/PolyfaceMesh.cs @@ -1,4 +1,5 @@ using ACadSharp.Attributes; +using CSMath; using System; using System.Collections.Generic; diff --git a/ACadSharp/Entities/RasterImage.cs b/ACadSharp/Entities/RasterImage.cs index c0e4e413..e1bd76db 100644 --- a/ACadSharp/Entities/RasterImage.cs +++ b/ACadSharp/Entities/RasterImage.cs @@ -29,14 +29,5 @@ public RasterImage(ImageDefinition definition) { this.Definition = definition; } - - /// - /// Set the image definition - /// - /// - public void SetImageDefinition(ImageDefinition definition) - { - this.Definition = definition; - } } } diff --git a/ACadSharp/Entities/Ray.cs b/ACadSharp/Entities/Ray.cs index e242184b..044251db 100644 --- a/ACadSharp/Entities/Ray.cs +++ b/ACadSharp/Entities/Ray.cs @@ -24,15 +24,21 @@ public class Ray : Entity public override string SubclassMarker => DxfSubclassMarker.Ray; /// - /// Start point(in WCS) + /// Start point(in WCS). /// [DxfCodeValue(10, 20, 30)] public XYZ StartPoint { get; set; } = XYZ.Zero; /// - /// Unit direction vector(in WCS) + /// Unit direction vector(in WCS). /// [DxfCodeValue(11, 21, 31)] public XYZ Direction { get; set; } = XYZ.Zero; + + /// + public override BoundingBox GetBoundingBox() + { + return BoundingBox.Infinite; + } } } diff --git a/ACadSharp/Entities/Seqend.cs b/ACadSharp/Entities/Seqend.cs index c1d9681f..ee70858b 100644 --- a/ACadSharp/Entities/Seqend.cs +++ b/ACadSharp/Entities/Seqend.cs @@ -1,4 +1,5 @@ using ACadSharp.Attributes; +using CSMath; namespace ACadSharp.Entities { @@ -23,5 +24,11 @@ internal Seqend(CadObject owner) { this.Owner = owner; } + + /// + public override BoundingBox GetBoundingBox() + { + return BoundingBox.Null; + } } } diff --git a/ACadSharp/Entities/Shape.cs b/ACadSharp/Entities/Shape.cs index d9fe2b71..c36561cd 100644 --- a/ACadSharp/Entities/Shape.cs +++ b/ACadSharp/Entities/Shape.cs @@ -26,25 +26,25 @@ public class Shape : Entity public override string SubclassMarker => DxfSubclassMarker.Shape; /// - /// Thickness + /// Thickness. /// [DxfCodeValue(39)] public double Thickness { get; set; } = 0.0; /// - /// Insertion point (in WCS) + /// Insertion point (in WCS). /// [DxfCodeValue(10, 20, 30)] public XYZ InsertionPoint { get; set; } /// - /// Size + /// Size. /// [DxfCodeValue(40)] public double Size { get; set; } = 1.0; /// - /// Shape name + /// Shape name. /// [DxfCodeValue(DxfReferenceType.Name, 2)] public TextStyle ShapeStyle @@ -69,25 +69,25 @@ public TextStyle ShapeStyle } /// - /// Rotation angle + /// Rotation angle. /// [DxfCodeValue(DxfReferenceType.IsAngle, 50)] public double Rotation { get; set; } = 0; /// - /// Relative X scale factor + /// Relative X scale factor. /// [DxfCodeValue(41)] public double RelativeXScale { get; set; } = 1; /// - /// Oblique angle + /// Oblique angle. /// [DxfCodeValue(DxfReferenceType.IsAngle, 51)] public double ObliqueAngle { get; set; } = 0; /// - /// Extrusion direction + /// Extrusion direction. /// [DxfCodeValue(210, 220, 230)] public XYZ Normal { get; set; } = XYZ.AxisZ; @@ -107,6 +107,7 @@ public Shape(TextStyle textStyle) this.ShapeStyle = textStyle; } + /// public override CadObject Clone() { Shape clone = (Shape)base.Clone(); @@ -115,5 +116,11 @@ public override CadObject Clone() return clone; } + + /// + public override BoundingBox GetBoundingBox() + { + return new BoundingBox(this.InsertionPoint); + } } } diff --git a/ACadSharp/Entities/Solid.cs b/ACadSharp/Entities/Solid.cs index d8d8dce3..646029bd 100644 --- a/ACadSharp/Entities/Solid.cs +++ b/ACadSharp/Entities/Solid.cs @@ -15,7 +15,7 @@ namespace ACadSharp.Entities public class Solid : Entity { /// - public override ObjectType ObjectType => ObjectType.SOLID; //Replaces also TRACE + public override ObjectType ObjectType => ObjectType.SOLID; //Replaces also TRACE /// public override string ObjectName => DxfFileToken.EntitySolid; @@ -48,6 +48,9 @@ public class Solid : Entity [DxfCodeValue(210, 220, 230)] public XYZ Normal { get; set; } = XYZ.AxisZ; - public Solid() : base() { } + public override BoundingBox GetBoundingBox() + { + return BoundingBox.Null; + } } } diff --git a/ACadSharp/Entities/Solid3D.cs b/ACadSharp/Entities/Solid3D.cs index 9df7844a..727e89ba 100644 --- a/ACadSharp/Entities/Solid3D.cs +++ b/ACadSharp/Entities/Solid3D.cs @@ -1,4 +1,5 @@ using ACadSharp.Attributes; +using CSMath; namespace ACadSharp.Entities { @@ -21,5 +22,11 @@ public class Solid3D : Entity /// public override string SubclassMarker => DxfSubclassMarker.ModelerGeometry; + + /// + public override BoundingBox GetBoundingBox() + { + return BoundingBox.Null; + } } } diff --git a/ACadSharp/Entities/Spline.cs b/ACadSharp/Entities/Spline.cs index 002b3a11..ce3f4b31 100644 --- a/ACadSharp/Entities/Spline.cs +++ b/ACadSharp/Entities/Spline.cs @@ -28,76 +28,76 @@ public class Spline : Entity /// Specifies the three-dimensional normal unit vector for the object. /// /// - /// omitted if the spline is nonplanar + /// Omitted if the spline is nonplanar. /// [DxfCodeValue(210, 220, 230)] public XYZ Normal { get; set; } = XYZ.AxisZ; /// - /// Spline flags + /// Spline flags. /// [DxfCodeValue(70)] public SplineFlags Flags { get; set; } /// - /// Degree of the spline curve + /// Degree of the spline curve. /// [DxfCodeValue(71)] public int Degree { get; set; } /// - /// Number of knots + /// Number of knots. /// [DxfCodeValue(DxfReferenceType.Count, 72)] [DxfCollectionCodeValue(40)] public List Knots { get; } = new List(); /// - /// Number of control points (in WCS) + /// Number of control points (in WCS). /// [DxfCodeValue(DxfReferenceType.Count, 73)] [DxfCollectionCodeValue(10, 20, 30)] public List ControlPoints { get; } = new List(); /// - /// Number of fit points (in WCS) + /// Number of fit points (in WCS). /// [DxfCodeValue(DxfReferenceType.Count, 74)] [DxfCollectionCodeValue(11, 21, 31)] public List FitPoints { get; } = new List(); /// - /// Knot tolerance + /// Knot tolerance. /// [DxfCodeValue(42)] public double KnotTolerance { get; set; } = 0.0000001; /// - /// Control-point tolerance + /// Control-point tolerance. /// [DxfCodeValue(43)] public double ControlPointTolerance { get; set; } = 0.0000001; /// - /// Fit tolerance + /// Fit tolerance. /// [DxfCodeValue(44)] public double FitTolerance { get; set; } = 0.0000000001; /// - /// Start tangent—may be omitted in WCS + /// Start tangent—may be omitted in WCS. /// [DxfCodeValue(12, 22, 32)] public XYZ StartTangent { get; set; } /// - /// End tangent—may be omitted in WCS + /// End tangent—may be omitted in WCS. /// [DxfCodeValue(13, 23, 33)] public XYZ EndTangent { get; set; } /// - /// Weight(if not 1); with multiple group pairs, they are present if all are not 1 + /// Weight(if not 1); with multiple group pairs, they are present if all are not 1. /// [DxfCodeValue(DxfReferenceType.Count, 41)] public List Weights { get; } = new List(); @@ -106,6 +106,13 @@ public class Spline : Entity internal KnotParameterization KnotParameterization { get; set; } + /// public Spline() : base() { } + + /// + public override BoundingBox GetBoundingBox() + { + return BoundingBox.FromPoints(this.ControlPoints); + } } } diff --git a/ACadSharp/Entities/TextEntity.cs b/ACadSharp/Entities/TextEntity.cs index 3290289b..0f1e5613 100644 --- a/ACadSharp/Entities/TextEntity.cs +++ b/ACadSharp/Entities/TextEntity.cs @@ -162,6 +162,13 @@ public TextStyle Style public TextEntity() : base() { } + /// + public override BoundingBox GetBoundingBox() + { + return new BoundingBox(this.InsertPoint); + } + + /// public override CadObject Clone() { TextEntity clone = (TextEntity)base.Clone(); diff --git a/ACadSharp/Entities/Tolerance.cs b/ACadSharp/Entities/Tolerance.cs index 79445cf7..ece5f9fc 100644 --- a/ACadSharp/Entities/Tolerance.cs +++ b/ACadSharp/Entities/Tolerance.cs @@ -75,5 +75,11 @@ public DimensionStyle Style public string Text { get; set; } private DimensionStyle _style = DimensionStyle.Default; + + /// + public override BoundingBox GetBoundingBox() + { + return new BoundingBox(this.InsertionPoint); + } } } diff --git a/ACadSharp/Entities/UnknownEntity.cs b/ACadSharp/Entities/UnknownEntity.cs index 49f3878c..65022e73 100644 --- a/ACadSharp/Entities/UnknownEntity.cs +++ b/ACadSharp/Entities/UnknownEntity.cs @@ -1,4 +1,5 @@ using ACadSharp.Classes; +using CSMath; namespace ACadSharp.Entities { @@ -54,5 +55,14 @@ internal UnknownEntity(DxfClass dxfClass) { this.DxfClass = dxfClass; } + + /// + /// + /// An Unknown Entity does not have any geometric shape, therfore it's bounding box will be always 0 + /// + public override BoundingBox GetBoundingBox() + { + return default; + } } } diff --git a/ACadSharp/Entities/Vertex.cs b/ACadSharp/Entities/Vertex.cs index f0915654..8dfd466c 100644 --- a/ACadSharp/Entities/Vertex.cs +++ b/ACadSharp/Entities/Vertex.cs @@ -49,11 +49,15 @@ public abstract class Vertex : Entity, IVertex /// /// Vertex identifier /// - [DxfCodeValue(DxfReferenceType.Ignored, 91)] //TODO: for some versions this code is invalid + [DxfCodeValue(DxfReferenceType.Ignored, 91)] //TODO: for some versions this code is invalid public int Id { get; set; } IVector IVertex.Location { get { return this.Location; } } - public Vertex() : base() { } + /// + public override BoundingBox GetBoundingBox() + { + return new BoundingBox(this.Location); + } } } diff --git a/ACadSharp/Entities/ViewPort.cs b/ACadSharp/Entities/ViewPort.cs index 24772f8f..17049b09 100644 --- a/ACadSharp/Entities/ViewPort.cs +++ b/ACadSharp/Entities/ViewPort.cs @@ -286,8 +286,7 @@ public class Viewport : Entity //Soft pointer reference to viewport object (for layer VP property override) - public Viewport() : base() { } - + /// public override CadObject Clone() { Viewport clone = (Viewport)base.Clone(); @@ -296,5 +295,14 @@ public override CadObject Clone() return 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); + + return new BoundingBox(min, max); + } } } diff --git a/ACadSharp/Entities/XLine.cs b/ACadSharp/Entities/XLine.cs index 9aede1db..b77d97f0 100644 --- a/ACadSharp/Entities/XLine.cs +++ b/ACadSharp/Entities/XLine.cs @@ -24,17 +24,21 @@ public class XLine : Entity public override string SubclassMarker => DxfSubclassMarker.XLine; /// - /// First point(in WCS) + /// First point(in WCS). /// [DxfCodeValue(10, 20, 30)] public XYZ FirstPoint { get; set; } /// - /// Unit direction vector(in WCS) + /// Unit direction vector(in WCS). /// [DxfCodeValue(11, 21, 31)] public XYZ Direction { get; set; } - public XLine() : base() { } + /// + public override BoundingBox GetBoundingBox() + { + return BoundingBox.Infinite; + } } } diff --git a/ACadSharp/GroupCodeValue.cs b/ACadSharp/GroupCodeValue.cs index 3807bd8c..6123b8c4 100644 --- a/ACadSharp/GroupCodeValue.cs +++ b/ACadSharp/GroupCodeValue.cs @@ -72,7 +72,7 @@ public static GroupCodeValueType TransformValue(int code) return GroupCodeValueType.Int16; if (code >= 390 && code <= 399) - return GroupCodeValueType.Handle; + return GroupCodeValueType.ObjectId; if (code >= 400 && code <= 409) return GroupCodeValueType.Int16; diff --git a/ACadSharp/INamedCadObject.cs b/ACadSharp/INamedCadObject.cs index f72b55db..f73b31ca 100644 --- a/ACadSharp/INamedCadObject.cs +++ b/ACadSharp/INamedCadObject.cs @@ -10,7 +10,7 @@ public interface INamedCadObject event EventHandler OnNameChanged; /// - /// Name identifier for this object + /// Name identifier for this object. /// string Name { get; } } diff --git a/ACadSharp/IO/CadReaderBase.cs b/ACadSharp/IO/CadReaderBase.cs index ac7f46c2..888ef66e 100644 --- a/ACadSharp/IO/CadReaderBase.cs +++ b/ACadSharp/IO/CadReaderBase.cs @@ -7,10 +7,21 @@ namespace ACadSharp.IO { - public abstract class CadReaderBase : ICadReader + /// + /// Base class for the DWG and DXF readers. + /// + /// Configuration type for the reader. + public abstract class CadReaderBase : ICadReader + where T : CadReaderConfiguration, new() { + /// public event NotificationEventHandler OnNotification; + /// + /// Reader configuration. + /// + public T Configuration { get; set; } = new(); + protected CadDocument _document = new CadDocument(false); protected Encoding _encoding = Encoding.Default; @@ -22,9 +33,8 @@ protected CadReaderBase(NotificationEventHandler notification) this.OnNotification += notification; } - protected CadReaderBase(string filename, NotificationEventHandler notification = null) : this(notification) + protected CadReaderBase(string filename, NotificationEventHandler notification = null) : this(File.OpenRead(filename), notification) { - this._fileStream = new StreamIO(filename, FileMode.Open, FileAccess.Read); } protected CadReaderBase(Stream stream, NotificationEventHandler notification = null) : this(notification) diff --git a/ACadSharp/IO/CadReaderConfiguration.cs b/ACadSharp/IO/CadReaderConfiguration.cs index 49b9da93..eaea2a22 100644 --- a/ACadSharp/IO/CadReaderConfiguration.cs +++ b/ACadSharp/IO/CadReaderConfiguration.cs @@ -1,7 +1,8 @@ -using ACadSharp.IO; - -namespace ACadSharp.IO +namespace ACadSharp.IO { + /// + /// Base configuration for all the classes. + /// public abstract class CadReaderConfiguration { /// diff --git a/ACadSharp/IO/CadWriterBase.cs b/ACadSharp/IO/CadWriterBase.cs index c180d22f..0774de97 100644 --- a/ACadSharp/IO/CadWriterBase.cs +++ b/ACadSharp/IO/CadWriterBase.cs @@ -6,17 +6,24 @@ namespace ACadSharp.IO { - public abstract class CadWriterBase : ICadWriter + /// + /// Base class for the CAD writers. + /// + public abstract class CadWriterBase : ICadWriter + where T : CadWriterConfiguration, new() { + /// + /// Notification event to get information about the writing process. + /// + /// + /// The notification system informs about any issue or non critical errors during the writing. + /// public event NotificationEventHandler OnNotification; /// - /// Notifies the writer to close the stream once the operation is completed + /// Configuration for the writer. /// - /// - /// true - /// - public bool CloseStream { get; set; } = true; + public T Configuration { get; set; } = new T(); protected Stream _stream; diff --git a/ACadSharp/IO/CadWriterConfiguration.cs b/ACadSharp/IO/CadWriterConfiguration.cs new file mode 100644 index 00000000..68175f93 --- /dev/null +++ b/ACadSharp/IO/CadWriterConfiguration.cs @@ -0,0 +1,27 @@ +namespace ACadSharp.IO +{ + /// + /// Configuration for the class. + /// + public class CadWriterConfiguration + { + /// + /// The writer will close the stream once the operation is completed. + /// + /// + /// default: true + /// + public bool CloseStream { get; set; } = true; + + /// + /// Will not ignore the objects in the document. + /// + /// + /// Due the complexity of XRecords, if this flag is set to true, it may cause a corruption of the file if the records have been modified manually. + /// + /// + /// default: false + /// + public bool WriteXRecords { get; set; } = false; + } +} diff --git a/ACadSharp/IO/DWG/DwgReader.cs b/ACadSharp/IO/DWG/DwgReader.cs index 5d69542a..a9d0054a 100644 --- a/ACadSharp/IO/DWG/DwgReader.cs +++ b/ACadSharp/IO/DWG/DwgReader.cs @@ -14,12 +14,12 @@ namespace ACadSharp.IO { - public class DwgReader : CadReaderBase + /// + /// Class for reading a DWG file into a . + /// + public class DwgReader : CadReaderBase { - public DwgReaderConfiguration Configuration { get; set; } = new DwgReaderConfiguration(); - private DwgDocumentBuilder _builder; - private DwgFileHeader _fileHeader; /// @@ -68,7 +68,7 @@ public static CadDocument Read(Stream stream, DwgReaderConfiguration configurati } /// - /// Read a dwg document from a file + /// Read a dwg document from a file. /// /// /// Notification handler, sends any message or notification about the reading process. @@ -79,7 +79,7 @@ public static CadDocument Read(string filename, NotificationEventHandler notific } /// - /// Read a dwg document from a file + /// Read a dwg document from a file. /// /// /// @@ -137,11 +137,11 @@ public CadSummaryInfo ReadSummaryInfo() //Older versions than 2004 don't have summaryinfo in it's file if (this._fileHeader.AcadVersion < ACadVersion.AC1018) - return null; + return new CadSummaryInfo(); IDwgStreamReader reader = this.getSectionStream(DwgSectionDefinition.SummaryInfo); if (reader == null) - return null; + return new CadSummaryInfo(); DwgSummaryInfoReader summaryReader = new DwgSummaryInfoReader(this._fileHeader.AcadVersion, reader); return summaryReader.Read(); @@ -401,7 +401,7 @@ private void readObjects() IDwgStreamReader sreader = null; if (this._fileHeader.AcadVersion <= ACadVersion.AC1015) { - sreader = DwgStreamReaderBase.GetStreamHandler(this._fileHeader.AcadVersion, this._fileStream.Stream); + sreader = DwgStreamReaderBase.GetStreamHandler(this._fileHeader.AcadVersion, this._fileStream.Stream, this._encoding); //Handles are in absolute offset for this versions sreader.Position = 0; } diff --git a/ACadSharp/IO/DWG/DwgReaderConfiguration.cs b/ACadSharp/IO/DWG/DwgReaderConfiguration.cs index 8c89a803..511c1938 100644 --- a/ACadSharp/IO/DWG/DwgReaderConfiguration.cs +++ b/ACadSharp/IO/DWG/DwgReaderConfiguration.cs @@ -1,5 +1,8 @@ namespace ACadSharp.IO { + /// + /// Configuration for reading DWG files. + /// public class DwgReaderConfiguration : CadReaderConfiguration { /// diff --git a/ACadSharp/IO/DWG/DwgStreamReaders/DwgObjectReader.cs b/ACadSharp/IO/DWG/DwgStreamReaders/DwgObjectReader.cs index dcb97843..0fa0d385 100644 --- a/ACadSharp/IO/DWG/DwgStreamReaders/DwgObjectReader.cs +++ b/ACadSharp/IO/DWG/DwgStreamReaders/DwgObjectReader.cs @@ -3316,7 +3316,7 @@ private CadTemplate readMultiLeaderStyle() mLeaderStyle.TextAngle = (TextAngleType)this._objectReader.ReadBitShort(); } // END IF IsNewFormat OR DXF file - // BS 176 Text alignment type + // BS 176 Text alignment type mLeaderStyle.TextAlignment = (TextAlignmentType)this._objectReader.ReadBitShort(); // CMC 93 Text color mLeaderStyle.TextColor = this._mergedReaders.ReadCmColor(); @@ -3329,7 +3329,7 @@ private CadTemplate readMultiLeaderStyle() // B 297 Always align text left mLeaderStyle.TextAlignAlwaysLeft = this._objectReader.ReadBit(); }// END IF IsNewFormat OR DXF file - // BD 46 Align space + // BD 46 Align space mLeaderStyle.AlignSpace = this._objectReader.ReadBitDouble(); // H 343 Block handle (hard pointer) template.BlockContentHandle = this.handleReference(); @@ -5347,7 +5347,6 @@ private CadTemplate readMesh() Mesh mesh = new Mesh(); CadMeshTemplate template = new CadMeshTemplate(mesh); -#if TEST this.readCommonEntityData(template); //Same order as dxf? @@ -5355,12 +5354,54 @@ private CadTemplate readMesh() //71 BS Version mesh.Version = this._objectReader.ReadBitShort(); //72 BS BlendCrease - mesh.BlendCrease = this._objectReader.ReadBitShort(); + mesh.BlendCrease = this._objectReader.ReadBit(); + //91 BL SubdivisionLevel + mesh.SubdivisionLevel = this._objectReader.ReadBitLong(); - var dict = DwgStreamReaderBase.Explore(this._objectReader); -#endif + //92 BL nvertices + int nvertices = this._objectReader.ReadBitLong(); + for (int i = 0; i < nvertices; i++) + { + //10 3BD vertice + XYZ v = this._objectReader.Read3BitDouble(); + mesh.Vertices.Add(v); + } - return null; + //Faces + int nfaces = this._objectReader.ReadBitLong(); + for (int i = 0; i < nfaces; i++) + { + int faceSize = _objectReader.ReadBitLong(); + int[] arr = new int[faceSize]; + for (int j = 0; j < faceSize; j++) + { + arr[j] = _objectReader.ReadBitLong(); + } + + i += faceSize; + + mesh.Faces.Add(arr.ToArray()); + } + + //Edges + int nedges = _objectReader.ReadBitLong(); + for (int k = 0; k < nedges; k++) + { + int start = _objectReader.ReadBitLong(); + int end = _objectReader.ReadBitLong(); + mesh.Edges.Add(new Mesh.Edge(start, end)); + } + + //Crease + int ncrease = _objectReader.ReadBitLong(); + for (int l = 0; l < ncrease; l++) + { + Mesh.Edge edge = mesh.Edges[l]; + edge.Crease = _objectReader.ReadBitDouble(); + mesh.Edges[l] = edge; + } + + return template; } private CadTemplate readPlaceHolder() diff --git a/ACadSharp/IO/DWG/DwgStreamReaders/DwgStreamReaderAC18.cs b/ACadSharp/IO/DWG/DwgStreamReaders/DwgStreamReaderAC18.cs index 0a8ca198..60ab7ea6 100644 --- a/ACadSharp/IO/DWG/DwgStreamReaders/DwgStreamReaderAC18.cs +++ b/ACadSharp/IO/DWG/DwgStreamReaders/DwgStreamReaderAC18.cs @@ -104,7 +104,7 @@ public override Color ReadEnColor(out Transparency transparency, out bool flag) //1 = BYBLOCK, //3 = the transparency value in the last byte. int value = this.ReadBitLong(); - transparency = Transparency.FromValue(value); + transparency = Transparency.FromAlphaValue(value); } else { diff --git a/ACadSharp/IO/DWG/DwgStreamWriters/DwgMergedStreamWriter.cs b/ACadSharp/IO/DWG/DwgStreamWriters/DwgMergedStreamWriter.cs index 98851d91..b2f6bcb6 100644 --- a/ACadSharp/IO/DWG/DwgStreamWriters/DwgMergedStreamWriter.cs +++ b/ACadSharp/IO/DWG/DwgStreamWriters/DwgMergedStreamWriter.cs @@ -1,11 +1,14 @@ using CSMath; using System; using System.IO; +using System.Text; namespace ACadSharp.IO.DWG { internal class DwgMergedStreamWriter : IDwgStreamWriter { + public Encoding Encoding { get { return this.Main.Encoding; } } + public IDwgStreamWriter Main { get; } public IDwgStreamWriter TextWriter { get; } diff --git a/ACadSharp/IO/DWG/DwgStreamWriters/DwgObjectWriter.Objects.cs b/ACadSharp/IO/DWG/DwgStreamWriters/DwgObjectWriter.Objects.cs index dcca76e4..1a9274a3 100644 --- a/ACadSharp/IO/DWG/DwgStreamWriters/DwgObjectWriter.Objects.cs +++ b/ACadSharp/IO/DWG/DwgStreamWriters/DwgObjectWriter.Objects.cs @@ -1,8 +1,8 @@ using ACadSharp.Objects; +using CSMath; using CSUtilities.Converters; using CSUtilities.IO; using System; -using System.Collections.Generic; using System.IO; using System.Linq; @@ -26,13 +26,18 @@ private void writeObject(CadObject obj) { case Material: case MultiLeaderAnnotContext: + case MultiLeaderStyle: case SortEntitiesTable: case VisualStyle: - case XRecord: this.notify($"Object type not implemented {obj.GetType().FullName}", NotificationType.NotImplemented); return; } + if (obj is XRecord && !this.WriteXRecords) + { + return; + } + this.writeCommonNonEntityData(obj); switch (obj) @@ -120,14 +125,15 @@ private void writeDictionary(CadDictionary dictionary) } //Common: - foreach (var name in dictionary.EntryNames) + foreach (var item in dictionary) { - this._writer.WriteVariableText(name); - } + if (item is XRecord && !this.WriteXRecords) + { + return; + } - foreach (var handle in dictionary.EntryHandles) - { - this._writer.HandleReference(DwgReferenceType.SoftOwnership, handle); + this._writer.WriteVariableText(item.Name); + this._writer.HandleReference(DwgReferenceType.SoftOwnership, item.Handle); } this.addEntriesToWriter(dictionary); @@ -337,6 +343,9 @@ private void writeMLineStyle(MLineStyle mlineStyle) private void writeMultiLeaderStyle(MultiLeaderStyle mLeaderStyle) { + //TODO: Remove this line when MultiLeaderStyle is fixed for writing + return; + if (!R2010Plus) { return; @@ -551,7 +560,7 @@ private void writeSortEntitiesTable(SortEntitiesTable sortEntitiesTable) { //parenthandle (soft pointer) this._writer.HandleReference(DwgReferenceType.SoftPointer, sortEntitiesTable.BlockOwner); - + //Common: //Numentries BL number of entries this._writer.WriteBitLong(sortEntitiesTable.Sorters.Count()); @@ -586,44 +595,73 @@ private void writeXRecord(XRecord xrecord) switch (groupValueType) { - case GroupCodeValueType.None: - break; - case GroupCodeValueType.String: - break; - case GroupCodeValueType.Point3D: - break; - case GroupCodeValueType.Double: + case GroupCodeValueType.Byte: + case GroupCodeValueType.Bool: + ms.Write(Convert.ToByte(entry.Value, System.Globalization.CultureInfo.InvariantCulture)); break; case GroupCodeValueType.Int16: + case GroupCodeValueType.ExtendedDataInt16: + ms.Write(Convert.ToInt16(entry.Value, System.Globalization.CultureInfo.InvariantCulture)); break; case GroupCodeValueType.Int32: + case GroupCodeValueType.ExtendedDataInt32: + ms.Write(Convert.ToInt32(entry.Value, System.Globalization.CultureInfo.InvariantCulture)); break; case GroupCodeValueType.Int64: + ms.Write(Convert.ToInt64(entry.Value, System.Globalization.CultureInfo.InvariantCulture)); break; - case GroupCodeValueType.Handle: - break; - case GroupCodeValueType.ObjectId: + case GroupCodeValueType.Double: + case GroupCodeValueType.ExtendedDataDouble: + double d = (entry.Value as double?).Value; + ms.Write(d); break; - case GroupCodeValueType.Bool: + case GroupCodeValueType.Point3D: + XYZ xyz = (entry.Value as XYZ?).Value; + ms.Write(xyz.X); + ms.Write(xyz.Y); + ms.Write(xyz.Z); break; case GroupCodeValueType.Chunk: + case GroupCodeValueType.ExtendedDataChunk: + byte[] array = (byte[])entry.Value; + ms.Write((byte)array.Length); + ms.WriteBytes(array); break; - case GroupCodeValueType.Comment: - break; + case GroupCodeValueType.String: case GroupCodeValueType.ExtendedDataString: + case GroupCodeValueType.Handle: + string text = (string)entry.Value; + + if (this.R2007Plus) + { + if (string.IsNullOrEmpty(text)) + { + ms.Write(0); + return; + } + + ms.Write((short)text.Length); + ms.Write(text, System.Text.Encoding.Unicode); + } + else if (string.IsNullOrEmpty(text)) + { + ms.Write(0); + ms.Write((byte)this._writer.Encoding.CodePage); + } + else + { + ms.Write((short)text.Length); + ms.Write((byte)this._writer.Encoding.CodePage); + ms.Write(text, this._writer.Encoding); + } break; - case GroupCodeValueType.ExtendedDataChunk: - break; + case GroupCodeValueType.ObjectId: case GroupCodeValueType.ExtendedDataHandle: - break; - case GroupCodeValueType.ExtendedDataDouble: - break; - case GroupCodeValueType.ExtendedDataInt16: - break; - case GroupCodeValueType.ExtendedDataInt32: + ulong u = (entry.Value as ulong?).Value; + ms.Write(u); break; default: - break; + throw new NotSupportedException(); } } diff --git a/ACadSharp/IO/DWG/DwgStreamWriters/DwgObjectWriter.cs b/ACadSharp/IO/DWG/DwgStreamWriters/DwgObjectWriter.cs index 288fc231..9d9ba6c6 100644 --- a/ACadSharp/IO/DWG/DwgStreamWriters/DwgObjectWriter.cs +++ b/ACadSharp/IO/DWG/DwgStreamWriters/DwgObjectWriter.cs @@ -21,6 +21,8 @@ internal partial class DwgObjectWriter : DwgSectionIO /// public Dictionary Map { get; } = new Dictionary(); + public bool WriteXRecords { get; } + private Dictionary _dictionaries = new(); private Queue _objects = new(); @@ -37,13 +39,14 @@ internal partial class DwgObjectWriter : DwgSectionIO private Entity _next; - public DwgObjectWriter(Stream stream, CadDocument document) : base(document.Header.Version) + public DwgObjectWriter(Stream stream, CadDocument document, bool writeXRecords = true) : base(document.Header.Version) { this._stream = stream; this._document = document; this._msmain = new MemoryStream(); this._writer = DwgStreamWriterBase.GetMergedWriter(document.Header.Version, this._msmain, TextEncoding.Windows1252()); + this.WriteXRecords = writeXRecords; } public void Write() @@ -512,8 +515,8 @@ private void writeLineType(LineType ltype) //X - offset RD 44 (0.0 for a simple dash.) //Y - offset RD 45(0.0 for a simple dash.) - this._writer.WriteBitDouble(segment.Offset.X); - this._writer.WriteBitDouble(segment.Offset.Y); + this._writer.WriteRawDouble(segment.Offset.X); + this._writer.WriteRawDouble(segment.Offset.Y); //Scale BD 46 (1.0 for a simple dash.) this._writer.WriteBitDouble(segment.Scale); @@ -548,7 +551,6 @@ private void writeLineType(LineType ltype) //TODO: Write the line type text area this._writer.WriteByte(0); } - //TODO: Read the line type text area } //Common: @@ -558,7 +560,7 @@ private void writeLineType(LineType ltype) foreach (var segment in ltype.Segments) { //340 shapefile for dash/shape (1 each) (hard pointer) - this._writer.HandleReference(DwgReferenceType.HardPointer, 0); + this._writer.HandleReference(DwgReferenceType.HardPointer, segment.Style); } this.registerObject(ltype); diff --git a/ACadSharp/IO/DWG/DwgStreamWriters/DwgStreamWriterAC18.cs b/ACadSharp/IO/DWG/DwgStreamWriters/DwgStreamWriterAC18.cs index 83171f1c..577052ce 100644 --- a/ACadSharp/IO/DWG/DwgStreamWriters/DwgStreamWriterAC18.cs +++ b/ACadSharp/IO/DWG/DwgStreamWriters/DwgStreamWriterAC18.cs @@ -73,7 +73,8 @@ public override void WriteEnColor(Color color, Transparency transparency) if (color.IsTrueColor) { - uint rgb = (uint)(0b1100_0010_0000_0000_0000_0000_0000_0000 | color.TrueColor); + byte[] arr = new byte[] { color.B, color.G, color.R, 0b11000010 }; + uint rgb = LittleEndianConverter.Instance.ToUInt32(arr); base.WriteBitLong((int)rgb); } @@ -83,7 +84,7 @@ public override void WriteEnColor(Color color, Transparency transparency) //0 = BYLAYER, //1 = BYBLOCK, //3 = the transparency value in the last byte. - base.WriteBitLong((int)transparency.Value); + base.WriteBitLong(Transparency.ToAlphaValue(transparency)); } } } diff --git a/ACadSharp/IO/DWG/DwgStreamWriters/DwgStreamWriterBase.cs b/ACadSharp/IO/DWG/DwgStreamWriters/DwgStreamWriterBase.cs index faec8b8a..57af479a 100644 --- a/ACadSharp/IO/DWG/DwgStreamWriters/DwgStreamWriterBase.cs +++ b/ACadSharp/IO/DWG/DwgStreamWriters/DwgStreamWriterBase.cs @@ -18,8 +18,6 @@ internal abstract class DwgStreamWriterBase : StreamIO, IDwgStreamWriter public long SavedPositionInBits { get; } = 0; - public Encoding Encoding { get; } - public int BitShift { get; private set; } = 0; private byte _lastByte; diff --git a/ACadSharp/IO/DWG/DwgStreamWriters/IDwgStreamWriter.cs b/ACadSharp/IO/DWG/DwgStreamWriters/IDwgStreamWriter.cs index 4f107fe1..6d172512 100644 --- a/ACadSharp/IO/DWG/DwgStreamWriters/IDwgStreamWriter.cs +++ b/ACadSharp/IO/DWG/DwgStreamWriters/IDwgStreamWriter.cs @@ -1,6 +1,7 @@ using CSMath; using System; using System.IO; +using System.Text; namespace ACadSharp.IO.DWG { @@ -9,6 +10,8 @@ namespace ACadSharp.IO.DWG /// internal interface IDwgStreamWriter { + Encoding Encoding { get; } + IDwgStreamWriter Main { get; } Stream Stream { get; } diff --git a/ACadSharp/IO/DWG/DwgWriter.cs b/ACadSharp/IO/DWG/DwgWriter.cs index 38e8e60f..e38e4108 100644 --- a/ACadSharp/IO/DWG/DwgWriter.cs +++ b/ACadSharp/IO/DWG/DwgWriter.cs @@ -9,7 +9,10 @@ namespace ACadSharp.IO { - public class DwgWriter : CadWriterBase + /// + /// Class for writing a DWG from a . + /// + public class DwgWriter : CadWriterBase { private ACadVersion _version { get { return this._document.Header.Version; } } @@ -20,7 +23,7 @@ public class DwgWriter : CadWriterBase private Dictionary _handlesMap = new Dictionary(); /// - /// + /// Initializes a new instance of the class. /// /// /// @@ -30,7 +33,7 @@ public DwgWriter(string filename, CadDocument document) } /// - /// + /// Initializes a new instance of the class. /// /// /// @@ -69,7 +72,7 @@ public override void Write() this._stream.Flush(); - if (this.CloseStream) + if (this.Configuration.CloseStream) { this._stream.Close(); } @@ -86,11 +89,17 @@ public override void Dispose() /// /// /// + /// /// - public static void Write(string filename, CadDocument document, NotificationEventHandler notification = null) + public static void Write(string filename, CadDocument document, CadWriterConfiguration configuration = null, NotificationEventHandler notification = null) { using (DwgWriter writer = new DwgWriter(filename, document)) { + if(configuration != null) + { + writer.Configuration = configuration; + } + writer.OnNotification += notification; writer.Write(); } @@ -284,7 +293,7 @@ private void writeRevHistory() private void writeObjects() { MemoryStream stream = new MemoryStream(); - DwgObjectWriter writer = new DwgObjectWriter(stream, this._document); + DwgObjectWriter writer = new DwgObjectWriter(stream, this._document, this.Configuration.WriteXRecords); writer.OnNotification += this.triggerNotification; writer.Write(); diff --git a/ACadSharp/IO/DXF/DxfReader.cs b/ACadSharp/IO/DXF/DxfReader.cs index 815e8ad7..971075d5 100644 --- a/ACadSharp/IO/DXF/DxfReader.cs +++ b/ACadSharp/IO/DXF/DxfReader.cs @@ -14,10 +14,11 @@ namespace ACadSharp.IO { - public class DxfReader : CadReaderBase + /// + /// Class for reading a DXF file into a . + /// + public class DxfReader : CadReaderBase { - public DxfReaderConfiguration Configuration { get; set; } = new DxfReaderConfiguration(); - private ACadVersion _version; private DxfDocumentBuilder _builder; private IDxfStreamReader _reader; @@ -108,20 +109,14 @@ public static CadDocument Read(Stream stream, NotificationEventHandler notificat /// public static CadDocument Read(string filename, NotificationEventHandler notification = null) { - CadDocument doc = null; - - using (DxfReader reader = new DxfReader(filename, notification)) - { - doc = reader.Read(); - } - - return doc; + return Read(File.OpenRead(filename)); } /// public override CadDocument Read() { this._document = new CadDocument(false); + this._document.SummaryInfo = new CadSummaryInfo(); this._reader = this._reader ?? this.getReader(); diff --git a/ACadSharp/IO/DXF/DxfReaderConfiguration.cs b/ACadSharp/IO/DXF/DxfReaderConfiguration.cs index c7aecdba..bb0f2897 100644 --- a/ACadSharp/IO/DXF/DxfReaderConfiguration.cs +++ b/ACadSharp/IO/DXF/DxfReaderConfiguration.cs @@ -1,5 +1,8 @@ namespace ACadSharp.IO { + /// + /// Configuration for reading DXF files. + /// public class DxfReaderConfiguration : CadReaderConfiguration { /// diff --git a/ACadSharp/IO/DXF/DxfStreamReader/DxfReaderBase.cs b/ACadSharp/IO/DXF/DxfStreamReader/DxfReaderBase.cs index 582e015e..4f42473a 100644 --- a/ACadSharp/IO/DXF/DxfStreamReader/DxfReaderBase.cs +++ b/ACadSharp/IO/DXF/DxfStreamReader/DxfReaderBase.cs @@ -42,13 +42,13 @@ public string ValueAsString public double ValueAsDouble { get { return Convert.ToDouble(this.Value); } } - public double ValueAsAngle { get { return (double)(Convert.ToDouble(this.Value) * MathUtils.DegToRad); } } + public double ValueAsAngle { get { return MathUtils.DegToRad(Convert.ToDouble(this.Value)); } } public ulong ValueAsHandle { get { return (ulong)this.Value; } } public byte[] ValueAsBinaryChunk { get { return this.Value as byte[]; } } - protected abstract Stream _baseStream { get; } + protected abstract Stream baseStream { get; } public virtual void ReadNext() { @@ -78,7 +78,7 @@ protected virtual void start() this.DxfCode = DxfCode.Invalid; this.Value = string.Empty; - this._baseStream.Position = 0; + this.baseStream.Position = 0; this.Position = 0; } diff --git a/ACadSharp/IO/DXF/DxfStreamReader/DxfSectionReaderBase.cs b/ACadSharp/IO/DXF/DxfStreamReader/DxfSectionReaderBase.cs index 2963419c..08afccb3 100644 --- a/ACadSharp/IO/DXF/DxfStreamReader/DxfSectionReaderBase.cs +++ b/ACadSharp/IO/DXF/DxfStreamReader/DxfSectionReaderBase.cs @@ -1375,7 +1375,7 @@ protected bool tryAssignCurrentValue(CadObject cadObject, DxfClassMap map) if (dxfProperty.ReferenceType.HasFlag(DxfReferenceType.IsAngle)) { - value = (double)value * MathUtils.DegToRad; + value = (double)value * MathUtils.DegToRadFactor; } dxfProperty.SetValue(this._reader.Code, cadObject, value); diff --git a/ACadSharp/IO/DXF/DxfStreamReader/DxfStreamReaderBase.cs b/ACadSharp/IO/DXF/DxfStreamReader/DxfStreamReaderBase.cs index 401f703e..748a8499 100644 --- a/ACadSharp/IO/DXF/DxfStreamReader/DxfStreamReaderBase.cs +++ b/ACadSharp/IO/DXF/DxfStreamReader/DxfStreamReaderBase.cs @@ -42,7 +42,7 @@ public string ValueAsString public double ValueAsDouble { get { return Convert.ToDouble(this.Value); } } - public double ValueAsAngle { get { return (double)(Convert.ToDouble(this.Value) * MathUtils.DegToRad); } } + public double ValueAsAngle { get { return (double)(Convert.ToDouble(this.Value) * MathUtils.RadToDegFactor); } } public ulong ValueAsHandle { get { return (ulong)this.Value; } } diff --git a/ACadSharp/IO/DXF/DxfStreamWriter/DxfHeaderSectionWriter.cs b/ACadSharp/IO/DXF/DxfStreamWriter/DxfHeaderSectionWriter.cs index 4a5ddf6c..2e1de8fc 100644 --- a/ACadSharp/IO/DXF/DxfStreamWriter/DxfHeaderSectionWriter.cs +++ b/ACadSharp/IO/DXF/DxfStreamWriter/DxfHeaderSectionWriter.cs @@ -10,9 +10,9 @@ internal class DxfHeaderSectionWriter : DxfSectionWriterBase public CadHeader Header { get { return this._document.Header; } } - public DxfWriterOptions Options { get; } + public DxfWriterConfiguration Options { get; } - public DxfHeaderSectionWriter(IDxfStreamWriter writer, CadDocument document, CadObjectHolder holder, DxfWriterOptions options) : base(writer, document, holder) + public DxfHeaderSectionWriter(IDxfStreamWriter writer, CadDocument document, CadObjectHolder holder, DxfWriterConfiguration options) : base(writer, document, holder) { this.Options = options; } diff --git a/ACadSharp/IO/DXF/DxfStreamWriter/DxfObjectsSectionWriter.cs b/ACadSharp/IO/DXF/DxfStreamWriter/DxfObjectsSectionWriter.cs index ae73ccd6..fc1c80a8 100644 --- a/ACadSharp/IO/DXF/DxfStreamWriter/DxfObjectsSectionWriter.cs +++ b/ACadSharp/IO/DXF/DxfStreamWriter/DxfObjectsSectionWriter.cs @@ -9,6 +9,8 @@ internal class DxfObjectsSectionWriter : DxfSectionWriterBase { public override string SectionName { get { return DxfFileToken.ObjectsSection; } } + public bool WriteXRecords { get; set; } = false; + public DxfObjectsSectionWriter(IDxfStreamWriter writer, CadDocument document, CadObjectHolder holder) : base(writer, document, holder) { } @@ -38,6 +40,12 @@ protected void writeObject(T co) return; } + + if (co is XRecord && !this.WriteXRecords) + { + return; + } + this._writer.Write(DxfCode.Start, co.ObjectName); this.writeCommonObjectData(co); @@ -91,11 +99,15 @@ protected void writeDictionary(CadDictionary e) this._writer.Write(280, e.HardOwnerFlag); this._writer.Write(281, (int)e.ClonningFlags); - System.Diagnostics.Debug.Assert(e.EntryNames.Length == e.EntryHandles.Length); - for (int i = 0; i < e.EntryNames.Length; i++) + foreach (NonGraphicalObject item in e) { - this._writer.Write(3, e.EntryNames[i]); - this._writer.Write(350, e.EntryHandles[i]); + if (item is XRecord && !this.WriteXRecords) + { + return; + } + + this._writer.Write(3, item.Name); + this._writer.Write(350, item.Handle); } //Add the entries as objects @@ -310,7 +322,7 @@ protected void writeMultiLeaderStyle(MultiLeaderStyle style) this._writer.Write(271, (short)style.TextAttachmentDirection, map); this._writer.Write(272, (short)style.TextBottomAttachment, map); this._writer.Write(273, (short)style.TextTopAttachment, map); - this._writer.Write(298, false); // undocumented + this._writer.Write(298, false); // undocumented } private void writeSortentsTable(SortEntitiesTable e) diff --git a/ACadSharp/IO/DXF/DxfStreamWriter/DxfSectionWriterBase.Entities.cs b/ACadSharp/IO/DXF/DxfStreamWriter/DxfSectionWriterBase.Entities.cs index 34b3515f..91bbb806 100644 --- a/ACadSharp/IO/DXF/DxfStreamWriter/DxfSectionWriterBase.Entities.cs +++ b/ACadSharp/IO/DXF/DxfStreamWriter/DxfSectionWriterBase.Entities.cs @@ -406,7 +406,7 @@ private void writeHatchPattern(Hatch hatch, HatchPattern pattern) if (!hatch.IsSolid) { - this._writer.Write(52, pattern.Angle * MathUtils.RadToDeg); + this._writer.Write(52, pattern.Angle * MathUtils.RadToDegFactor); this._writer.Write(41, pattern.Scale); this._writer.Write(77, (short)(hatch.IsDouble ? 1 : 0)); this._writer.Write(78, (short)pattern.Lines.Count); diff --git a/ACadSharp/IO/DXF/DxfStreamWriter/DxfSectionWriterBase.cs b/ACadSharp/IO/DXF/DxfStreamWriter/DxfSectionWriterBase.cs index decefcc6..1a7c308d 100644 --- a/ACadSharp/IO/DXF/DxfStreamWriter/DxfSectionWriterBase.cs +++ b/ACadSharp/IO/DXF/DxfStreamWriter/DxfSectionWriterBase.cs @@ -58,14 +58,16 @@ protected void writeCommonObjectData(CadObject cadObject) this.Holder.Objects.Enqueue(cadObject.XDictionary); } - if (cadObject.Reactors != null && cadObject.Reactors.Count > 0) { - this._writer.Write(DxfCode.ControlString,DxfFileToken.ReactorsToken); - foreach (ulong reactorHandle in cadObject.Reactors.Keys) { + if (cadObject.Reactors != null && cadObject.Reactors.Count > 0) + { + this._writer.Write(DxfCode.ControlString, DxfFileToken.ReactorsToken); + foreach (ulong reactorHandle in cadObject.Reactors.Keys) + { this._writer.Write(DxfCode.SoftPointerId, reactorHandle); } this._writer.Write(DxfCode.ControlString, "}"); } - + this._writer.Write(DxfCode.SoftPointerId, cadObject.Owner.Handle); //TODO: Write exended data @@ -102,7 +104,7 @@ protected void writeCommonEntityData(Entity entity) if (entity.Transparency.Value >= 0) { - //this._writer.Write(440, entity.Transparency.Value); + this._writer.Write(440, Transparency.ToAlphaValue(entity.Transparency)); } this._writer.Write(48, entity.LinetypeScale, map); diff --git a/ACadSharp/IO/DXF/DxfStreamWriter/DxfStreamWriterBase.cs b/ACadSharp/IO/DXF/DxfStreamWriter/DxfStreamWriterBase.cs index 1eeb2171..d996f6d4 100644 --- a/ACadSharp/IO/DXF/DxfStreamWriter/DxfStreamWriterBase.cs +++ b/ACadSharp/IO/DXF/DxfStreamWriter/DxfStreamWriterBase.cs @@ -92,7 +92,7 @@ public void Write(int code, object value, DxfClassMap map) if (prop.ReferenceType.HasFlag(DxfReferenceType.IsAngle)) { - value = (double)value * MathUtils.RadToDeg; + value = (double)value * MathUtils.RadToDegFactor; } } diff --git a/ACadSharp/IO/DXF/DxfStreamWriter/DxfTablesSectionWriter.cs b/ACadSharp/IO/DXF/DxfStreamWriter/DxfTablesSectionWriter.cs index 5dcf4a3a..e68dc619 100644 --- a/ACadSharp/IO/DXF/DxfStreamWriter/DxfTablesSectionWriter.cs +++ b/ACadSharp/IO/DXF/DxfStreamWriter/DxfTablesSectionWriter.cs @@ -276,7 +276,7 @@ private void writeLineType(LineType linetype, DxfClassMap map) } this._writer.Write(46, s.Scale); - this._writer.Write(50, s.Rotation * MathUtils.DegToRad); + this._writer.Write(50, s.Rotation * MathUtils.DegToRadFactor); this._writer.Write(44, s.Offset.X); this._writer.Write(45, s.Offset.Y); this._writer.Write(9, s.Text); diff --git a/ACadSharp/IO/DXF/DxfWriter.cs b/ACadSharp/IO/DXF/DxfWriter.cs index 15f58e35..f0ee6ade 100644 --- a/ACadSharp/IO/DXF/DxfWriter.cs +++ b/ACadSharp/IO/DXF/DxfWriter.cs @@ -4,15 +4,16 @@ namespace ACadSharp.IO { - public class DxfWriter : CadWriterBase + /// + /// Class for writing a DXF from a . + /// + public class DxfWriter : CadWriterBase { /// /// Flag indicating if the dxf will be writen as a binary file /// public bool IsBinary { get; } - public DxfWriterOptions Options { get; set; } = new DxfWriterOptions(); - private IDxfStreamWriter _writer; private CadObjectHolder _objectHolder = new CadObjectHolder(); @@ -65,7 +66,7 @@ public override void Write() this._writer.Flush(); - if (this.CloseStream) + if (this.Configuration.CloseStream) { this._writer.Close(); } @@ -124,7 +125,7 @@ private void createStreamWriter() private void writeHeader() { - var writer = new DxfHeaderSectionWriter(this._writer, this._document, this._objectHolder, this.Options); + var writer = new DxfHeaderSectionWriter(this._writer, this._document, this._objectHolder, this.Configuration); writer.OnNotification += this.triggerNotification; writer.Write(); @@ -165,6 +166,7 @@ private void writeEntities() private void writeObjects() { var writer = new DxfObjectsSectionWriter(this._writer, this._document, this._objectHolder); + writer.WriteXRecords = this.Configuration.WriteXRecords; writer.OnNotification += this.triggerNotification; writer.Write(); diff --git a/ACadSharp/IO/DXF/DxfWriterOptions.cs b/ACadSharp/IO/DXF/DxfWriterConfiguration.cs similarity index 94% rename from ACadSharp/IO/DXF/DxfWriterOptions.cs rename to ACadSharp/IO/DXF/DxfWriterConfiguration.cs index 02febb8d..209c9fea 100644 --- a/ACadSharp/IO/DXF/DxfWriterOptions.cs +++ b/ACadSharp/IO/DXF/DxfWriterConfiguration.cs @@ -5,7 +5,10 @@ namespace ACadSharp.IO { - public class DxfWriterOptions + /// + /// Configuration for writing DWG files. + /// + public class DxfWriterConfiguration : CadWriterConfiguration { /// /// Variables that must be writen in a dxf file @@ -72,7 +75,7 @@ public class DxfWriterOptions private HashSet _headerVariables; - public DxfWriterOptions() + public DxfWriterConfiguration() { this._headerVariables = new HashSet(Variables); } diff --git a/ACadSharp/IO/ICadReader.cs b/ACadSharp/IO/ICadReader.cs index a0e20e73..c452d15b 100644 --- a/ACadSharp/IO/ICadReader.cs +++ b/ACadSharp/IO/ICadReader.cs @@ -1,22 +1,28 @@ using ACadSharp.Header; -using CSUtilities.IO; using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; namespace ACadSharp.IO { + /// + /// Common interface for the different Cad readers. + /// public interface ICadReader : IDisposable { /// - /// Read the Cad header section of the file + /// Notification event to get information about the reading process. + /// + /// + /// The notification system informs about any issue or non critical errors during the reading. + /// + event NotificationEventHandler OnNotification; + + /// + /// Read the Cad header section of the file. /// CadHeader ReadHeader(); /// - /// Read the cad document + /// Read the cad document. /// CadDocument Read(); } diff --git a/ACadSharp/IO/Templates/CadArcTemplate.cs b/ACadSharp/IO/Templates/CadArcTemplate.cs index c34dddf4..4ee4cfe7 100644 --- a/ACadSharp/IO/Templates/CadArcTemplate.cs +++ b/ACadSharp/IO/Templates/CadArcTemplate.cs @@ -21,8 +21,8 @@ public override void Build(CadDocumentBuilder builder) if (builder is DxfDocumentBuilder && this.CadObject is Arc arc) { - arc.StartAngle *= MathUtils.DegToRad; - arc.EndAngle *= MathUtils.DegToRad; + arc.StartAngle *= MathUtils.DegToRadFactor; + arc.EndAngle *= MathUtils.DegToRadFactor; } } } diff --git a/ACadSharp/IO/Templates/CadDimensionTemplate.cs b/ACadSharp/IO/Templates/CadDimensionTemplate.cs index 798867df..cca9c23b 100644 --- a/ACadSharp/IO/Templates/CadDimensionTemplate.cs +++ b/ACadSharp/IO/Templates/CadDimensionTemplate.cs @@ -1,6 +1,6 @@ -using ACadSharp.Blocks; -using ACadSharp.Entities; +using ACadSharp.Entities; using ACadSharp.Tables; +using CSMath; namespace ACadSharp.IO.Templates { @@ -42,6 +42,11 @@ public class DimensionPlaceholder : Dimension public override double Measurement { get; } public DimensionPlaceholder() : base(DimensionType.Linear) { } + + public override BoundingBox GetBoundingBox() + { + throw new System.InvalidOperationException(); + } } public void SetDimensionFlags(DimensionType flags) diff --git a/ACadSharp/IO/Templates/CadUnknownEntity.cs b/ACadSharp/IO/Templates/CadUnknownEntity.cs deleted file mode 100644 index 4b8b366f..00000000 --- a/ACadSharp/IO/Templates/CadUnknownEntity.cs +++ /dev/null @@ -1,19 +0,0 @@ -using ACadSharp.Classes; -using ACadSharp.Entities; - -namespace ACadSharp.IO.Templates -{ - internal class CadUnknownEntity : CadEntityTemplate - { - public CadUnknownEntity(UnkownEntity entity) : base(entity) - { - } - - internal class UnkownEntity : Entity - { - public override ObjectType ObjectType => ObjectType.UNLISTED; - - public DxfClass DxfClass { get; } - } - } -} diff --git a/ACadSharp/MathUtils.cs b/ACadSharp/MathUtils.cs index 16f6cc4f..75e4c051 100644 --- a/ACadSharp/MathUtils.cs +++ b/ACadSharp/MathUtils.cs @@ -8,12 +8,45 @@ public static class MathUtils /// /// Factor for converting radians to degrees. /// - public const double RadToDeg = (180 / Math.PI); + public const double RadToDegFactor = (180 / Math.PI); /// /// Factor for converting degrees to radians. /// - public const double DegToRad = (Math.PI / 180); + public const double DegToRadFactor = (Math.PI / 180); + + public const double Epsilon = 1e-12; + + /// + /// Checks if a number is close to zero. + /// + /// Double precision number. + /// True if its close to one or false in any other case. + public static bool IsZero(double number) + { + return IsZero(number, Epsilon); + } + + /// + /// Checks if a number is close to zero. + /// + /// Double precision number. + /// Tolerance. + /// True if its close to one or false in any other case. + public static bool IsZero(double number, double threshold) + { + return number >= -threshold && number <= threshold; + } + + public static double RadToDeg(double value) + { + return value * RadToDegFactor; + } + + public static double DegToRad(double value) + { + return value * DegToRadFactor; + } public static XY GetCenter(XY start, XY end, double bulge) { diff --git a/ACadSharp/Objects/CadDictionary.cs b/ACadSharp/Objects/CadDictionary.cs index 34378b85..684d1715 100644 --- a/ACadSharp/Objects/CadDictionary.cs +++ b/ACadSharp/Objects/CadDictionary.cs @@ -150,12 +150,20 @@ public static CadDictionary CreateRoot() { CadDictionary root = new CadDictionary(Root); + CreateDefaultEntries(root); + + return root; + } + + /// + /// Create the default entries for the root dictionary. + /// + public static void CreateDefaultEntries(CadDictionary root) + { root.TryAdd(new CadDictionary(AcadColor)); root.TryAdd(new CadDictionary(AcadGroup)); CadDictionary layouts = root.ensureCadDictionaryExist(AcadLayout); - layouts.TryAdd(Layout.Default); - layouts.TryAdd(new Layout("Layout1")); root.TryAdd(new CadDictionary(AcadMaterial)); root.TryAdd(new CadDictionary(AcadSortEnts)); @@ -195,8 +203,6 @@ public static CadDictionary CreateRoot() root.TryAdd(new CadDictionary(AcadVisualStyle)); root.TryAdd(new CadDictionary(AcadFieldList)); root.TryAdd(new CadDictionary(AcadImageDict)); - - return root; } /// @@ -228,6 +234,8 @@ public void Add(string key, NonGraphicalObject value) this._entries.Add(key, value); value.Owner = this; + value.OnNameChanged += this.onEntryNameChanged; + OnAdd?.Invoke(this, new CollectionChangedEventArgs(value)); } @@ -242,29 +250,29 @@ public void Add(NonGraphicalObject value) } /// - /// Tries to add the entry if the key doesn't exits. + /// Tries to add the entry using the name as key. /// - /// /// /// true if the element is successfully added; otherwise, false. - public bool TryAdd(string key, NonGraphicalObject value) + public bool TryAdd(NonGraphicalObject value) { - if (!this._entries.ContainsKey(key)) + if (!this._entries.ContainsKey(value.Name)) { - this.Add(key, value); + this.Add(value.Name, value); + return true; } return false; } /// - /// Tries to add the entry using the name as key. + /// Determines whether the contains the specified key. /// - /// - /// true if the element is successfully added; otherwise, false. - public bool TryAdd(NonGraphicalObject value) + /// The key to locate in the + /// + public bool ContainsKey(string key) { - return this.TryAdd(value.Name, value); + return this._entries.ContainsKey(key); } /// @@ -343,5 +351,13 @@ private CadDictionary ensureCadDictionaryExist(string name) return entry; } + + private void onEntryNameChanged(object sender, OnNameChangedArgs e) + { + + var entry = this._entries[e.OldName]; + this._entries.Add(e.NewName, entry); + this._entries.Remove(e.OldName); + } } } diff --git a/ACadSharp/Objects/Collections/LayoutCollection.cs b/ACadSharp/Objects/Collections/LayoutCollection.cs index 8b1851df..f754a06e 100644 --- a/ACadSharp/Objects/Collections/LayoutCollection.cs +++ b/ACadSharp/Objects/Collections/LayoutCollection.cs @@ -1,4 +1,6 @@ -namespace ACadSharp.Objects.Collections +using System; + +namespace ACadSharp.Objects.Collections { public class LayoutCollection : ObjectDictionaryCollection { @@ -6,5 +8,17 @@ public LayoutCollection(CadDictionary dictionary) : base(dictionary) { this._dictionary = dictionary; } + + /// + public override bool Remove(string name, out Layout entry) + { + if (name.Equals(Layout.ModelLayoutName, StringComparison.InvariantCultureIgnoreCase) + || name.Equals(Layout.PaperLayoutName, StringComparison.InvariantCultureIgnoreCase)) + { + throw new ArgumentException($"The Layout {name} cannot be removed."); + } + + return base.Remove(name, out entry); + } } } diff --git a/ACadSharp/Objects/Collections/ObjectDictionaryCollection.cs b/ACadSharp/Objects/Collections/ObjectDictionaryCollection.cs index 54fe9e62..ea2874d5 100644 --- a/ACadSharp/Objects/Collections/ObjectDictionaryCollection.cs +++ b/ACadSharp/Objects/Collections/ObjectDictionaryCollection.cs @@ -36,6 +36,16 @@ public void Add(T entry) this._dictionary.Add(entry); } + /// + /// Determines whether the contains the specified key. + /// + /// The key to locate in the + /// + public bool ContainsKey(string key) + { + return this._dictionary.ContainsKey(key); + } + /// /// Gets the value associated with the specific key /// @@ -47,13 +57,23 @@ public bool TryGetValue(string name, out T entry) return this._dictionary.TryGetEntry(name, out entry); } + /// + /// Remove an entry from the collection. + /// + /// + /// + public bool Remove(string name) + { + return this.Remove(name, out _); + } + /// /// Remove an entry from the collection. /// /// /// /// - public bool Remove(string name, out T entry) + public virtual bool Remove(string name, out T entry) { bool result = this._dictionary.Remove(name, out NonGraphicalObject n); entry = (T)n; diff --git a/ACadSharp/Objects/Layout.cs b/ACadSharp/Objects/Layout.cs index 79505ea9..032a17d2 100644 --- a/ACadSharp/Objects/Layout.cs +++ b/ACadSharp/Objects/Layout.cs @@ -18,9 +18,9 @@ namespace ACadSharp.Objects [DxfSubClass(DxfSubclassMarker.Layout)] public class Layout : PlotSettings { - public const string LayoutModelName = "Model"; + public const string ModelLayoutName = "Model"; - public static Layout Default { get { return new Layout(LayoutModelName); } } + public const string PaperLayoutName = "Layout1"; /// public override ObjectType ObjectType => ObjectType.LAYOUT; @@ -128,32 +128,13 @@ public BlockRecord AssociatedBlock get { return this._blockRecord; } internal set { - this._blockRecord = value; - if (this._blockRecord == null) - return; - - if (this._blockRecord.Name.Equals(BlockRecord.ModelSpaceName, System.StringComparison.OrdinalIgnoreCase)) - { - this.Viewport = null; - base.Flags = - PlotFlags.Initializing | - PlotFlags.UpdatePaper | - PlotFlags.ModelType | - PlotFlags.DrawViewportsFirst | - PlotFlags.PrintLineweights | - PlotFlags.PlotPlotStyles | - PlotFlags.UseStandardScale; - } - else + if (value == null) { - this.Viewport = new Viewport(); - this.Viewport.ViewCenter = new XY(50.0, 100.0); - this.Viewport.Status = - ViewportStatusFlags.AdaptiveGridDisplay | - ViewportStatusFlags.DisplayGridBeyondDrawingLimits | - ViewportStatusFlags.CurrentlyAlwaysEnabled | - ViewportStatusFlags.UcsIconVisibility; + throw new System.ArgumentNullException(nameof(value)); } + + this._blockRecord = value; + this._blockRecord.Layout = this; } } @@ -194,20 +175,39 @@ internal set [DxfCodeValue(DxfReferenceType.Handle, 346)] public UCS BaseUCS { get; set; } - //333 Shade plot ID - public IEnumerable Viewports { get { return this.AssociatedBlock?.Viewports; } } + public IEnumerable Viewports + { + get + { + return this.AssociatedBlock?.Viewports; + } + } private Viewport _lastViewport; private BlockRecord _blockRecord; - public Layout() : this(null) { } + internal Layout() : base() + { + } + + public Layout(string name) : this(name, name) { } - public Layout(string name) : base() + public Layout(string name, string blockName) : base() { this.Name = name; + this._blockRecord = new BlockRecord(blockName); + } + + public override CadObject Clone() + { + Layout clone = (Layout)base.Clone(); + + clone._blockRecord = (BlockRecord)this._blockRecord?.Clone(); + + return clone; } /// @@ -215,5 +215,38 @@ public override string ToString() { return $"{this.ObjectName}:{this.Name}"; } + + internal override void AssignDocument(CadDocument doc) + { + base.AssignDocument(doc); + + if (this.AssociatedBlock != null) + { + doc.BlockRecords.Add(this.AssociatedBlock); + doc.BlockRecords.OnRemove += this.onRemoveBlockRecord; + } + } + + internal override void UnassignDocument() + { + this.Document.BlockRecords.OnRemove -= this.onRemoveBlockRecord; + + if (this.AssociatedBlock != null) + { + this.AssociatedBlock.Layout = null; + this.Document.BlockRecords.OnRemove -= this.onRemoveBlockRecord; + this._blockRecord = (BlockRecord)this._blockRecord?.Clone(); + } + + base.UnassignDocument(); + } + + private void onRemoveBlockRecord(object sender, CollectionChangedEventArgs e) + { + if (this.AssociatedBlock.Equals(e.Item)) + { + this.Document.Layouts.Remove(this.Name); + } + } } } diff --git a/ACadSharp/Objects/NonGraphicalObject.cs b/ACadSharp/Objects/NonGraphicalObject.cs index 8cebe551..d07a7b97 100644 --- a/ACadSharp/Objects/NonGraphicalObject.cs +++ b/ACadSharp/Objects/NonGraphicalObject.cs @@ -12,6 +12,10 @@ public abstract class NonGraphicalObject : CadObject, INamedCadObject public event EventHandler OnNameChanged; /// + /// + /// The name of a will be used as the name of the entry when the owner is a + /// otherwise the name may not be saved if there is no dxf code assigned to the . + /// public virtual string Name { get { return this._name; } diff --git a/ACadSharp/Tables/BlockRecord.cs b/ACadSharp/Tables/BlockRecord.cs index 42216fb7..3fffa4a0 100644 --- a/ACadSharp/Tables/BlockRecord.cs +++ b/ACadSharp/Tables/BlockRecord.cs @@ -5,7 +5,6 @@ using ACadSharp.Entities; using System.Linq; using System.Collections.Generic; -using ACadSharp.IO.Templates; namespace ACadSharp.Tables { @@ -30,9 +29,45 @@ public class BlockRecord : TableEntry /// public const string PaperSpaceName = "*Paper_Space"; - public static BlockRecord ModelSpace { get { return new BlockRecord(ModelSpaceName); } } + /// + /// Create an instance of the *Model_Space block. + /// + /// + /// It only can be one Model in each document. + /// + public static BlockRecord ModelSpace + { + get + { + BlockRecord record = new BlockRecord(ModelSpaceName); + + Layout layout = new Layout(); + layout.Name = Layout.ModelLayoutName; + layout.AssociatedBlock = record; + + return record; + } + } + + /// + /// Create an instance of the *Paper_Space block. + /// + /// + /// This is the default paper space in the document. + /// + public static BlockRecord PaperSpace + { + get + { + BlockRecord record = new BlockRecord(PaperSpaceName); - public static BlockRecord PaperSpace { get { return new BlockRecord(PaperSpaceName); } } + Layout layout = new Layout(); + layout.Name = Layout.PaperLayoutName; + layout.AssociatedBlock = record; + + return record; + } + } /// public override ObjectType ObjectType => ObjectType.BLOCK_HEADER; @@ -80,14 +115,9 @@ public class BlockRecord : TableEntry public Layout Layout { get { return this._layout; } - set + internal set { this._layout = value; - - if (value == null) - return; - - this._layout.AssociatedBlock = this; } } @@ -125,19 +155,16 @@ public IEnumerable Viewports } /// - /// Entities owned by this block + /// Entities owned by this block. /// /// - /// Entities with an owner cannot be added to another block + /// Entities with an owner cannot be added to another block. /// public CadObjectCollection Entities { get; private set; } /// /// Sort entities table for this block record. /// - /// - /// - /// public SortEntitiesTable SortEntitiesTable { get @@ -232,7 +259,11 @@ public override CadObject Clone() { BlockRecord clone = (BlockRecord)base.Clone(); - clone.Layout = (Layout)(this.Layout?.Clone()); + Layout layout = (Layout)(this.Layout?.Clone()); + if (layout is not null) + { + layout.AssociatedBlock = this; + } clone.Entities = new CadObjectCollection(clone); foreach (var item in this.Entities) diff --git a/ACadSharp/Tables/LineType.cs b/ACadSharp/Tables/LineType.cs index 778160f6..a5404d26 100644 --- a/ACadSharp/Tables/LineType.cs +++ b/ACadSharp/Tables/LineType.cs @@ -78,7 +78,7 @@ public double PatternLen private List _segments = new List(); - public LineType() : base() { } + internal LineType() : base() { } public LineType(string name) : base(name) { } diff --git a/ACadSharp/Tables/LineTypeSegment.cs b/ACadSharp/Tables/LineTypeSegment.cs index ad5edfed..bed4f889 100644 --- a/ACadSharp/Tables/LineTypeSegment.cs +++ b/ACadSharp/Tables/LineTypeSegment.cs @@ -8,43 +8,43 @@ public partial class LineType public class Segment { /// - /// Dash, dot or space length + /// Dash, dot or space length. /// [DxfCodeValue(49)] public double Length { get; set; } /// - /// Complex linetype element type + /// Complex linetype element type. /// [DxfCodeValue(74)] public LinetypeShapeFlags Shapeflag { get; set; } /// - /// Shape number + /// Shape number. /// [DxfCodeValue(75)] public short ShapeNumber { get; set; } /// - /// Offset + /// Offset. /// [DxfCodeValue(44, 45)] public XY Offset { get; set; } /// - /// Rotation value in radians of embedded shape or text + /// Rotation value in radians of embedded shape or text. /// [DxfCodeValue(DxfReferenceType.IsAngle, 50)] public double Rotation { get; set; } /// - /// Scale value + /// Scale value. /// [DxfCodeValue(46)] - public double Scale { get; set; } + public double Scale { get; set; } = 1.0d; /// - /// Text string + /// Text string. /// /// /// Only present if is present diff --git a/ACadSharp/Transparency.cs b/ACadSharp/Transparency.cs index 9c0a912a..a4e0d7e4 100644 --- a/ACadSharp/Transparency.cs +++ b/ACadSharp/Transparency.cs @@ -1,21 +1,25 @@ -#region copyright -//Copyright 2021, Albert Domenech. -//All rights reserved. -//This source code is licensed under the MIT license. -//See LICENSE file in the project root for full license information. -#endregion -using System; -using System.Collections.Generic; -using System.Text; +using System; namespace ACadSharp { + /// + /// Represents the transparency for the graphical objects. + /// public struct Transparency { + /// + /// Gets the ByLayer transparency. + /// public static Transparency ByLayer { get { return new Transparency(-1); } } - + + /// + /// Gets the ByBlock transparency. + /// public static Transparency ByBlock { get { return new Transparency(100); } } + /// + /// Gets the Opaque transparency. + /// public static Transparency Opaque { get { return new Transparency(0); } } /// @@ -25,7 +29,7 @@ public bool IsByLayer { get { return _value == -1; } } - + /// /// Defines if the transparency is defined by block. /// @@ -38,7 +42,7 @@ public bool IsByBlock /// Gets or sets the transparency value. /// /// - /// Transparency values must be in range from 0 to 90, the reserved values -1 and 100 represents ByLayer and ByBlock. + /// Transparency values must be in range from 0 (opaque) to 90 (transparent), the reserved values -1 and 100 represents ByLayer and ByBlock. /// public short Value { @@ -63,8 +67,16 @@ public short Value _value = value; } } + private short _value; + /// + /// Initializes a new instance of the Transparency struct. + /// + /// Alpha value range from 0 to 90. + /// + /// Transparency values must be in range from 0 (opaque) to 90 (transparent), the reserved values -1 and 100 represents ByLayer and ByBlock. + /// public Transparency(short value) { _value = -1; @@ -72,11 +84,23 @@ public Transparency(short value) } /// - /// Gets the transparency value within range of a valid value + /// Gets the alpha value of a transperency. + /// + /// + /// + public static int ToAlphaValue(Transparency transparency) + { + byte alpha = (byte)(255 * (100 - transparency.Value) / 100.0); + byte[] bytes = transparency.IsByBlock ? new byte[] { 0, 0, 0, 1 } : new byte[] { alpha, 0, 0, 2 }; + return BitConverter.ToInt32(bytes, 0); + } + + /// + /// Gets the transparency from a transparency value /// /// A transparency value /// A - public static Transparency FromValue(int value) + public static Transparency FromAlphaValue(int value) { byte[] bytes = BitConverter.GetBytes(value); short alpha = (short)(100 - (bytes[0] / 255.0) * 100); diff --git a/CSUtilities b/CSUtilities index 95e916a6..eca6f7eb 160000 --- a/CSUtilities +++ b/CSUtilities @@ -1 +1 @@ -Subproject commit 95e916a62f0ddf59cd165e0606a74ba044919056 +Subproject commit eca6f7ebe91058bcc89fb818fb14aae050a91152 diff --git a/wiki b/wiki deleted file mode 160000 index 2a7a8cd0..00000000 --- a/wiki +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 2a7a8cd06791be0d39a696dbf6f154e496a53aef