diff --git a/src/ACadSharp.Tests/IO/LocalSampleTests.cs b/src/ACadSharp.Tests/IO/LocalSampleTests.cs
index 5ef18e32..21a9522e 100644
--- a/src/ACadSharp.Tests/IO/LocalSampleTests.cs
+++ b/src/ACadSharp.Tests/IO/LocalSampleTests.cs
@@ -34,14 +34,6 @@ public void ReadUserDwg(FileModel test)
return;
CadDocument doc = DwgReader.Read(test.Path, this._dwgConfiguration, this.onNotification);
-
- CadDocument newDoc = new CadDocument();
-
- foreach (var entity in doc.Entities)
- {
- doc.Entities.Remove(entity);
- newDoc.Entities.Add(entity);
- }
}
[Theory]
diff --git a/src/ACadSharp.Tests/IO/MultiLeaderTests.cs b/src/ACadSharp.Tests/IO/MultiLeaderTests.cs
index 5c251833..5786a681 100644
--- a/src/ACadSharp.Tests/IO/MultiLeaderTests.cs
+++ b/src/ACadSharp.Tests/IO/MultiLeaderTests.cs
@@ -2,7 +2,6 @@
using ACadSharp.IO;
using ACadSharp.Tests.TestModels;
using System.Collections.Generic;
-using System.IO;
using Xunit;
using Xunit.Abstractions;
diff --git a/src/ACadSharp.Tests/IO/ViewportTests.cs b/src/ACadSharp.Tests/IO/ViewportTests.cs
new file mode 100644
index 00000000..339ad0f2
--- /dev/null
+++ b/src/ACadSharp.Tests/IO/ViewportTests.cs
@@ -0,0 +1,38 @@
+using ACadSharp.Entities;
+using ACadSharp.IO;
+using ACadSharp.Tests.TestModels;
+using System.IO;
+using Xunit;
+using Xunit.Abstractions;
+
+namespace ACadSharp.Tests.IO
+{
+ public class ViewportTests : IOTestsBase
+ {
+ public ViewportTests(ITestOutputHelper output) : base(output)
+ {
+ }
+
+ [Theory]
+ [MemberData(nameof(DwgFilePaths))]
+ [MemberData(nameof(DxfAsciiFiles))]
+ public void ScaleInViewport(FileModel test)
+ {
+ CadDocument doc;
+ if (Path.GetExtension(test.FileName).Equals(".dxf"))
+ {
+ doc = DxfReader.Read(test.Path);
+ }
+ else
+ {
+ doc = DwgReader.Read(test.Path);
+ }
+
+ ACadSharp.Tables.BlockRecord paper = doc.PaperSpace;
+ foreach (Viewport v in paper.Viewports)
+ {
+ Assert.NotNull(v.Scale);
+ }
+ }
+ }
+}
diff --git a/src/ACadSharp.Tests/IO/WriterSingleObjectTests.cs b/src/ACadSharp.Tests/IO/WriterSingleObjectTests.cs
index e0614709..722321ac 100644
--- a/src/ACadSharp.Tests/IO/WriterSingleObjectTests.cs
+++ b/src/ACadSharp.Tests/IO/WriterSingleObjectTests.cs
@@ -404,6 +404,11 @@ public void ChangedEncoding()
this.Document.Layers.Add(new Layer("我的自定义层"));
}
+ public void AddCustomScale()
+ {
+ this.Document.Scales.Add(new Scale("Hello"));
+ }
+
public void AddBlockWithAttributes()
{
BlockRecord record = new("my_block");
@@ -491,6 +496,7 @@ static WriterSingleObjectTests()
Data.Add(new(nameof(SingleCaseGenerator.CreateCircleHatch)));
Data.Add(new(nameof(SingleCaseGenerator.ChangedEncoding)));
Data.Add(new(nameof(SingleCaseGenerator.AddBlockWithAttributes)));
+ Data.Add(new(nameof(SingleCaseGenerator.AddCustomScale)));
}
protected string getPath(string name, string ext, ACadVersion version)
diff --git a/src/ACadSharp/Entities/Viewport.cs b/src/ACadSharp/Entities/Viewport.cs
index 118b0641..5cdd6466 100644
--- a/src/ACadSharp/Entities/Viewport.cs
+++ b/src/ACadSharp/Entities/Viewport.cs
@@ -4,6 +4,7 @@
using CSMath;
using System;
using System.Collections.Generic;
+using System.Linq;
namespace ACadSharp.Entities
{
@@ -23,6 +24,8 @@ public class Viewport : Entity
///
public const int PaperViewId = 1;
+ public const string ASDK_XREC_ANNOTATION_SCALE_INFO = "ASDK_XREC_ANNOTATION_SCALE_INFO";
+
///
public override ObjectType ObjectType => ObjectType.VIEWPORT;
@@ -322,6 +325,31 @@ public double ViewWidth
//Soft pointer reference to viewport object (for layer VP property override)
+ ///
+ ///
+ ///
+ public Scale Scale
+ {
+ get
+ {
+ return this._scale;
+ }
+ set
+ {
+ if (this.Document != null)
+ {
+ this._scale = this.updateCollection(value, this.Document.Scales);
+ this.updateScaleXRecord();
+ }
+ else
+ {
+ this._scale = value;
+ }
+ }
+ }
+
+ private Scale _scale;
+
///
public override CadObject Clone()
{
@@ -372,5 +400,57 @@ public List SelectEntities(bool includePartial = true)
return entities;
}
+
+ internal override void AssignDocument(CadDocument doc)
+ {
+ base.AssignDocument(doc);
+
+ this._scale = this.updateCollection(this.Scale, doc.Scales);
+
+ this.Document.Scales.OnRemove += this.scalesOnRemove;
+ }
+
+ internal override void UnassignDocument()
+ {
+ this.Document.Scales.OnRemove -= this.scalesOnRemove;
+
+ base.UnassignDocument();
+
+ this._scale = (Scale)this.Scale.Clone();
+ }
+
+ private void scalesOnRemove(object sender, CollectionChangedEventArgs e)
+ {
+ if (e.Item.Equals(this.Scale))
+ {
+ this.Scale = this.Document.Scales.FirstOrDefault();
+ }
+ }
+
+ private void updateScaleXRecord()
+ {
+ if (this.Document == null)
+ {
+ return;
+ }
+
+ if (this.XDictionary.TryGetEntry(ASDK_XREC_ANNOTATION_SCALE_INFO, out XRecord record))
+ {
+ foreach (XRecord.Entry item in record.Entries)
+ {
+ if (item.Code == 340)
+ {
+ item.Value = this._scale.Handle;
+ }
+ }
+ }
+ else
+ {
+ record = new XRecord(ASDK_XREC_ANNOTATION_SCALE_INFO);
+ this.XDictionary.Add(record);
+
+ record.CreateEntry(340, _scale.Handle);
+ }
+ }
}
}
diff --git a/src/ACadSharp/IO/DWG/DwgStreamReaders/DwgObjectReader.cs b/src/ACadSharp/IO/DWG/DwgStreamReaders/DwgObjectReader.cs
index 7d98092a..437f252e 100644
--- a/src/ACadSharp/IO/DWG/DwgStreamReaders/DwgObjectReader.cs
+++ b/src/ACadSharp/IO/DWG/DwgStreamReaders/DwgObjectReader.cs
@@ -1777,7 +1777,7 @@ private CadTemplate readDimOrdinate()
//14 - pt 3BD 14 See DXF documentation.
dimension.LeaderEndpoint = this._objectReader.Read3BitDouble();
- byte flags = (this._objectReader.ReadByte());
+ byte flags = this._objectReader.ReadByte();
dimension.IsOrdinateTypeX = (flags & 0b01) != 0;
this.readCommonDimensionHandles(template);
@@ -1936,7 +1936,7 @@ private void readCommonDimensionData(CadDimensionTemplate template)
//The actual 70 - group value comes from 3 things:
//6 for being an ordinate DIMENSION, plus whatever bits "Flags 1" and "Flags 2" specify.
- byte flags = (this._objectReader.ReadByte());
+ byte flags = this._objectReader.ReadByte();
dimension.IsTextUserDefinedLocation = (flags & 0b01) == 0;
//User text TV 1
@@ -5297,50 +5297,50 @@ private CadTemplate readXRecord()
{
case GroupCodeValueType.String:
case GroupCodeValueType.ExtendedDataString:
- xRecord.Entries.Add(new XRecord.Entry(code, this._objectReader.ReadTextUnicode()));
+ xRecord.CreateEntry(code, this._objectReader.ReadTextUnicode());
break;
case GroupCodeValueType.Point3D:
- xRecord.Entries.Add(new XRecord.Entry(code,
+ xRecord.CreateEntry(code,
new XYZ(
this._objectReader.ReadDouble(),
this._objectReader.ReadDouble(),
this._objectReader.ReadDouble()
- )));
+ ));
break;
case GroupCodeValueType.Double:
case GroupCodeValueType.ExtendedDataDouble:
- xRecord.Entries.Add(new XRecord.Entry(code, this._objectReader.ReadDouble()));
+ xRecord.CreateEntry(code, this._objectReader.ReadDouble());
break;
case GroupCodeValueType.Byte:
- xRecord.Entries.Add(new XRecord.Entry(code, this._objectReader.ReadByte()));
+ xRecord.CreateEntry(code, this._objectReader.ReadByte());
break;
case GroupCodeValueType.Int16:
case GroupCodeValueType.ExtendedDataInt16:
- xRecord.Entries.Add(new XRecord.Entry(code, this._objectReader.ReadShort()));
+ xRecord.CreateEntry(code, this._objectReader.ReadShort());
break;
case GroupCodeValueType.Int32:
case GroupCodeValueType.ExtendedDataInt32:
- xRecord.Entries.Add(new XRecord.Entry(code, this._objectReader.ReadRawLong()));
+ xRecord.CreateEntry(code, this._objectReader.ReadRawLong());
break;
case GroupCodeValueType.Int64:
- xRecord.Entries.Add(new XRecord.Entry(code, this._objectReader.ReadRawULong()));
+ xRecord.CreateEntry(code, this._objectReader.ReadRawULong());
break;
case GroupCodeValueType.Handle:
- xRecord.Entries.Add(new XRecord.Entry(code, this._objectReader.ReadTextUnicode()));
+ xRecord.CreateEntry(code, this._objectReader.ReadTextUnicode());
break;
case GroupCodeValueType.Bool:
- xRecord.Entries.Add(new XRecord.Entry(code, this._objectReader.ReadByte() > 0));
+ xRecord.CreateEntry(code, this._objectReader.ReadByte() > 0);
break;
case GroupCodeValueType.Chunk:
case GroupCodeValueType.ExtendedDataChunk:
- xRecord.Entries.Add(new XRecord.Entry(code, this._objectReader.ReadBytes(this._objectReader.ReadByte())));
+ xRecord.CreateEntry(code, this._objectReader.ReadBytes(this._objectReader.ReadByte()));
break;
case GroupCodeValueType.ObjectId:
case GroupCodeValueType.ExtendedDataHandle:
- xRecord.Entries.Add(new XRecord.Entry(code, this._objectReader.ReadRawULong()));
+ xRecord.CreateEntry(code, this._objectReader.ReadRawULong());
break;
default:
- this.notify($"Unedintified GroupCodeValueType {code} for XRecord [{xRecord.Handle}]", NotificationType.Warning);
+ this.notify($"Unidentified GroupCodeValueType {code} for XRecord [{xRecord.Handle}]", NotificationType.Warning);
break;
}
}
@@ -5349,7 +5349,7 @@ private CadTemplate readXRecord()
if (this.R2000Plus)
{
//Cloning flag BS 280
- xRecord.ClonningFlags = (DictionaryCloningFlags)this._objectReader.ReadBitShort();
+ xRecord.CloningFlags = (DictionaryCloningFlags)this._objectReader.ReadBitShort();
}
long size = this._objectInitialPos + (long)(this._size * 8U) - 7L;
diff --git a/src/ACadSharp/IO/DWG/DwgStreamWriters/DwgObjectWriter.Objects.cs b/src/ACadSharp/IO/DWG/DwgStreamWriters/DwgObjectWriter.Objects.cs
index c36ac818..31e81664 100644
--- a/src/ACadSharp/IO/DWG/DwgStreamWriters/DwgObjectWriter.Objects.cs
+++ b/src/ACadSharp/IO/DWG/DwgStreamWriters/DwgObjectWriter.Objects.cs
@@ -680,7 +680,7 @@ private void writeXRecord(XRecord xrecord)
if (this.R2000Plus)
{
//Cloning flag BS 280
- this._writer.WriteBitShort((short)xrecord.ClonningFlags);
+ this._writer.WriteBitShort((short)xrecord.CloningFlags);
}
}
diff --git a/src/ACadSharp/IO/DXF/DxfStreamReader/DxfObjectsSectionReader.cs b/src/ACadSharp/IO/DXF/DxfStreamReader/DxfObjectsSectionReader.cs
index f261d9c2..56c1842f 100644
--- a/src/ACadSharp/IO/DXF/DxfStreamReader/DxfObjectsSectionReader.cs
+++ b/src/ACadSharp/IO/DXF/DxfStreamReader/DxfObjectsSectionReader.cs
@@ -194,8 +194,6 @@ private bool readXRecord(CadTemplate template, DxfMap map)
{
CadXRecordTemplate tmp = template as CadXRecordTemplate;
- //TODO: Finsih cadXrecordtemplate
-
switch (this._reader.Code)
{
case 100 when this._reader.ValueAsString == DxfSubclassMarker.XRecord:
@@ -212,7 +210,7 @@ private void readXRecordEntries(XRecord recrod)
while (this._reader.DxfCode != DxfCode.Start)
{
- recrod.Entries.Add(new XRecord.Entry(this._reader.Code, this._reader.Value));
+ recrod.CreateEntry(this._reader.Code, this._reader.Value);
this._reader.ReadNext();
}
diff --git a/src/ACadSharp/IO/Templates/CadDictionaryTemplate.cs b/src/ACadSharp/IO/Templates/CadDictionaryTemplate.cs
index 3aef681a..6700113c 100644
--- a/src/ACadSharp/IO/Templates/CadDictionaryTemplate.cs
+++ b/src/ACadSharp/IO/Templates/CadDictionaryTemplate.cs
@@ -35,6 +35,10 @@ public override void Build(CadDocumentBuilder builder)
{
if (builder.TryGetCadObject(item.Value, out NonGraphicalObject entry))
{
+ //This section basically sets the key and name to the same value to make sure that the
+ //different collections and dictionaries work properly.
+ //For some collections like Scales there are some cases where the key doesn't match the name
+ //but regarding changing the key doesn't seem to take an effect on it.
if (string.IsNullOrEmpty(entry.Name))
{
entry.Name = item.Key;
@@ -42,7 +46,7 @@ public override void Build(CadDocumentBuilder builder)
try
{
- this.CadObject.Add(item.Key, entry);
+ this.CadObject.Add(entry.Name, entry);
}
catch (System.Exception ex)
{
diff --git a/src/ACadSharp/IO/Templates/CadViewportTemplate.cs b/src/ACadSharp/IO/Templates/CadViewportTemplate.cs
index af13ce1a..b6404c12 100644
--- a/src/ACadSharp/IO/Templates/CadViewportTemplate.cs
+++ b/src/ACadSharp/IO/Templates/CadViewportTemplate.cs
@@ -1,10 +1,11 @@
using ACadSharp.Entities;
+using ACadSharp.Objects;
using ACadSharp.Tables;
using System.Collections.Generic;
namespace ACadSharp.IO.Templates
{
- internal class CadViewportTemplate : CadEntityTemplate
+ internal class CadViewportTemplate : CadEntityTemplate
{
public ulong? ViewportHeaderHandle { get; set; }
@@ -39,7 +40,7 @@ public override void Build(CadDocumentBuilder builder)
{
viewport.Boundary = entity;
}
- else if(this.BoundaryHandle.HasValue && this.BoundaryHandle > 0)
+ else if (this.BoundaryHandle.HasValue && this.BoundaryHandle > 0)
{
builder.Notify($"Boundary {this.BoundaryHandle} not found for viewport {this.CadObject.Handle}", NotificationType.Warning);
}
@@ -54,6 +55,21 @@ public override void Build(CadDocumentBuilder builder)
builder.Notify($"Base ucs not implemented for Viewport, handle {this.BaseUcsHandle}");
}
+ if (this.CadObject.XDictionary != null &&
+ this.CadObject.XDictionary.TryGetEntry(Viewport.ASDK_XREC_ANNOTATION_SCALE_INFO, out XRecord record))
+ {
+ foreach (XRecord.Entry item in record.Entries)
+ {
+ if (item.Code == 340)
+ {
+ if (builder.TryGetCadObject((ulong?)item.Value, out Scale scale))
+ {
+ this.CadObject.Scale = scale;
+ }
+ }
+ }
+ }
+
foreach (var handle in this.FrozenLayerHandles)
{
if (builder.TryGetCadObject(handle, out Layer layer))
diff --git a/src/ACadSharp/Objects/Collections/ObjectDictionaryCollection.cs b/src/ACadSharp/Objects/Collections/ObjectDictionaryCollection.cs
index 6c9dc9d1..0fab922c 100644
--- a/src/ACadSharp/Objects/Collections/ObjectDictionaryCollection.cs
+++ b/src/ACadSharp/Objects/Collections/ObjectDictionaryCollection.cs
@@ -31,7 +31,7 @@ protected ObjectDictionaryCollection(CadDictionary dictionary)
/// Add an entry to the collection
///
///
- public void Add(T entry)
+ public virtual void Add(T entry)
{
this._dictionary.Add(entry);
}
diff --git a/src/ACadSharp/Objects/Collections/ScaleCollection.cs b/src/ACadSharp/Objects/Collections/ScaleCollection.cs
index f0af6f46..94ba7a07 100644
--- a/src/ACadSharp/Objects/Collections/ScaleCollection.cs
+++ b/src/ACadSharp/Objects/Collections/ScaleCollection.cs
@@ -1,10 +1,28 @@
-namespace ACadSharp.Objects.Collections
+using System.Collections.Generic;
+
+namespace ACadSharp.Objects.Collections
{
public class ScaleCollection : ObjectDictionaryCollection
{
+ private readonly Dictionary _scales = new Dictionary();
+
public ScaleCollection(CadDictionary dictionary) : base(dictionary)
{
this._dictionary = dictionary;
+
+ foreach (Scale item in this._dictionary)
+ {
+ this._scales.Add(item.Name, item);
+ }
+ }
+
+ ///
+ ///
+ ///
+ ///
+ public override void Add(Scale entry)
+ {
+ base.Add(entry);
}
}
}
diff --git a/src/ACadSharp/Objects/XRecord.Entry.cs b/src/ACadSharp/Objects/XRecord.Entry.cs
new file mode 100644
index 00000000..c3080849
--- /dev/null
+++ b/src/ACadSharp/Objects/XRecord.Entry.cs
@@ -0,0 +1,45 @@
+namespace ACadSharp.Objects
+{
+ public partial class XRecord
+ {
+ public class Entry
+ {
+ public int Code { get; }
+
+ public object Value { get; set; }
+
+ public GroupCodeValueType GroupCode
+ {
+ get
+ {
+ return GroupCodeValue.TransformValue(this.Code);
+ }
+ }
+
+ public bool HasLinkedObject
+ {
+ get
+ {
+ switch (this.GroupCode)
+ {
+ case GroupCodeValueType.Handle:
+ case GroupCodeValueType.ObjectId:
+ case GroupCodeValueType.ExtendedDataHandle:
+ return true;
+ default:
+ return false;
+ }
+ }
+ }
+
+ public XRecord Owner { get; set; }
+
+ internal Entry(int code, object value, XRecord owner)
+ {
+ this.Code = code;
+ this.Value = value;
+ this.Owner = owner;
+ }
+ }
+ }
+}
diff --git a/src/ACadSharp/Objects/XRecrod.cs b/src/ACadSharp/Objects/XRecrod.cs
index 7bee708b..0cbbf28e 100644
--- a/src/ACadSharp/Objects/XRecrod.cs
+++ b/src/ACadSharp/Objects/XRecrod.cs
@@ -4,15 +4,18 @@
namespace ACadSharp.Objects
{
///
- /// Represents a object
+ /// Represents a object.
///
///
/// Object name
/// Dxf class name
+ ///
+ ///
+ /// Is not recommended to modify, add or remove entries to an XRecord unless you know what consequences will cause in the document.
///
[DxfName(DxfFileToken.ObjectXRecord)]
[DxfSubClass(DxfSubclassMarker.XRecord)]
- public class XRecord : NonGraphicalObject
+ public partial class XRecord : NonGraphicalObject
{
///
public override ObjectType ObjectType => ObjectType.XRECORD;
@@ -27,22 +30,20 @@ public class XRecord : NonGraphicalObject
/// Duplicate record cloning flag (determines how to merge duplicate entries)
///
[DxfCodeValue(280)]
- public DictionaryCloningFlags ClonningFlags { get; set; }
+ public DictionaryCloningFlags CloningFlags { get; set; }
//1-369 (except 5 and 105) These values can be used by an application in any way
- public List Entries { get; set; } = new List();
+ public IEnumerable Entries { get { return this._entries; } }
- public class Entry
- {
- public int Code { get; }
+ private readonly List _entries = new List();
+
+ public XRecord() : base() { }
- public object Value { get; }
+ public XRecord(string name) : base(name) { }
- public Entry(int code, object value)
- {
- this.Code = code;
- this.Value = value;
- }
+ public void CreateEntry(int code, object value)
+ {
+ this._entries.Add(new Entry(code, value, this));
}
}
}
diff --git a/src/CSUtilities b/src/CSUtilities
index 2e0fbe7f..03f926cb 160000
--- a/src/CSUtilities
+++ b/src/CSUtilities
@@ -1 +1 @@
-Subproject commit 2e0fbe7f2305037ec10e358891e80ffd7fdfdc2d
+Subproject commit 03f926cb78953c7f49f79a799828f1f1f2ad4ea5