Skip to content
11 changes: 11 additions & 0 deletions src/ACadSharp/Entities/Entity.cs
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,17 @@ public virtual LineType LineType
[DxfCodeValue(370)]
public LineWeightType LineWeight { get; set; } = LineWeightType.ByLayer;

/// <summary>
/// Plot style source of the entity (named plot style drawings), as stored in DWG: 0 = by layer,
/// 1 = by block, 3 = the style in <see cref="PlotStyleHandle"/>.
/// </summary>
public byte PlotStyleFlags { get; set; }

/// <summary>
/// Handle of the entity's plot style name (an entry of the ACAD_PLOTSTYLENAME dictionary) when <see cref="PlotStyleFlags"/> is 3.
/// </summary>
public ulong PlotStyleHandle { get; set; }

/// <inheritdoc/>
[DxfCodeValue(DxfReferenceType.Handle, 347)]
public Material Material
Expand Down
26 changes: 26 additions & 0 deletions src/ACadSharp/Entities/UnknownEntity.cs
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,32 @@ public override string SubclassMarker
}
}

/// <summary>
/// Remote text (Express Tools RTEXT) data, when this unknown entity is one and could be read.
/// </summary>
public RemoteText RText { get; set; }

/// <summary>
/// Data of an Express Tools RTEXT object: text from a file or from a DIESEL expression.
/// </summary>
public class RemoteText
{
/// <summary>Insertion point.</summary>
public XYZ InsertPoint { get; set; }
/// <summary>Extrusion direction.</summary>
public XYZ Normal { get; set; } = XYZ.AxisZ;
/// <summary>Rotation, radians.</summary>
public double Rotation { get; set; }
/// <summary>Text height.</summary>
public double Height { get; set; }
/// <summary>Flags: 1 = contents is a DIESEL expression, otherwise a file name.</summary>
public short Flags { get; set; }
/// <summary>DIESEL expression or file name.</summary>
public string Contents { get; set; }
/// <summary>Handle of the text style.</summary>
public ulong StyleHandle { get; set; }
}

/// <summary>
/// Dxf class linked to this entity.
/// </summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,15 @@ private void readAnnotScaleObjectContextData(CadAnnotScaleObjectContextDataTempl
template.ScaleHandle = this.handleReference();
}

private CadTemplate readDimensionObjectContextData()
{
var template = new CadDimensionObjectContextDataTemplate(new DimensionObjectContextData());
this.readAnnotScaleObjectContextData(template);
//H 2 dimension block for this scale; the data fields are not read
template.BlockHandle = this.handleReference();
return template;
}

private CadTemplate readBlkRefObjectContextData()
{
BlockReferenceObjectContextData contextData = new BlockReferenceObjectContextData();
Expand Down
42 changes: 33 additions & 9 deletions src/ACadSharp/IO/DWG/DwgStreamReaders/DwgObjectReader.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2000,10 +2000,11 @@ private void readEntityMode(CadEntityTemplate template)

//R2000 +:
//Plotstyle flags BB 00 = bylayer, 01 = byblock, 11 = plotstyle handle present at end of object
if (this._objectReader.Read2Bits() == 3)
template.CadObject.PlotStyleFlags = this._objectReader.Read2Bits();
if (template.CadObject.PlotStyleFlags == 3)
{
//PLOTSTYLE (hard pointer) present if plotstyle flags were 11
long plotstyleFlags = (long)this.handleReference();
template.CadObject.PlotStyleHandle = this.handleReference();
}

//R2007 +:
Expand Down Expand Up @@ -2714,12 +2715,10 @@ private CadTemplate readLayer()
var color = this._mergedReaders.ReadCmColor();
layer.Color = color.IsByBlock || color.IsByLayer ? Color.Default : color;

//TODO: This is not the Layer control handle
template.LayerControlHandle = this.handleReference();
//Handle refs H Layer control (soft pointer)
//[Reactors(soft pointer)]
//xdicobjhandle(hard owner)
//External reference block handle(hard pointer)
//Handle refs H Layer control (soft pointer), [Reactors (soft pointer)] and xdicobjhandle
//(hard owner) are read with the common data; this one is the
//External reference block handle (hard pointer): the xref a dependent layer comes from
layer.XrefBlockHandle = this.handleReference();

//R2000+:
if (this.R2000Plus)
Expand Down Expand Up @@ -5091,7 +5090,7 @@ private void readPlotSettings(PlotSettings plot)
plot.ShadePlotDPI = this._objectReader.ReadBitShort();

//6 plot view handle(hard pointer)
ulong plotViewHandle = this.handleReference();
plot.PlotViewHandle = this.handleReference();
}

//R2007 +:
Expand Down Expand Up @@ -6182,6 +6181,11 @@ private CadTemplate readUnlistedType(short classNumber)
break;
}

if (template == null && c.DxfName.EndsWith("DIMOBJECTCONTEXTDATA_CLASS"))

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be in the switch in readUnlistedType following the same pattern.

You can use "ACDB_DIMOBJECTCONTEXTDATA_CLASS".

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Moved into the readUnlistedType switch. A single ACDB_DIMOBJECTCONTEXTDATA_CLASS case would never match, though: DWG/DXF files store one class per dimension type, and no file declares the base name (that is why I had used EndsWith). I checked this against a drawing made in AutoCAD.

So there is now one class and one DxfFileToken constant per type, all derived from an abstract DimensionObjectContextData (AcDbDimensionObjectContextData):

  • ACDB_ALDIMOBJECTCONTEXTDATA_CLASS → AlignedDimensionObjectContextData (aligned and linear)
  • ACDB_ANGDIMOBJECTCONTEXTDATA_CLASS → AngularDimensionObjectContextData (angular and arc length)
  • ACDB_DMDIMOBJECTCONTEXTDATA_CLASS → DiametricDimensionObjectContextData
  • ACDB_ORDDIMOBJECTCONTEXTDATA_CLASS → OrdinateDimensionObjectContextData
  • ACDB_RADIMOBJECTCONTEXTDATA_CLASS → RadialDimensionObjectContextData
  • ACDB_RADIMLRGOBJECTCONTEXTDATA_CLASS → RadialDimensionLargeObjectContextData (extends the radial one)

The data fields are now read as well, from both DWG and DXF: text location and rotation, the per-scale overrides (DIMTOFL, DIMSOXD, DIMTIX and the override flags), arrow flips, and each type's points. I decoded the DWG bit layout from that AutoCAD drawing and checked it against its DXF export. One finding: DWG stores DIMATFIT and DIMTMOVE only as "overridden" bits, so their values are read from DXF only.

The drawing is in samples/annotative/, and DimensionObjectContextDataTests compares the DWG and DXF reads. Known gaps: LARGE_RADIAL_DIMENSION entities are not read yet, so the large radial context data is not covered by the tests (its layout was only checked by hand against the DXF), and the writers still skip these objects.

{
template = this.readDimensionObjectContextData();
}

if (template == null && c.IsAnEntity)
{
template = this.readUnknownEntity(c);
Expand Down Expand Up @@ -7290,6 +7294,26 @@ private CadTemplate readUnknownEntity(DxfClass dxfClass)

this.readCommonEntityData(template);

if (dxfClass?.DxfName == "RTEXT")

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be in the switch in readUnlistedType following the same pattern.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done: moved to case DxfFileToken.EntityRText in the readUnlistedType switch, which calls a new readRText(c). RTEXT has no class of its own in the library, so it still produces an UnknownEntity with RText filled in.

{
try
{
var rt = new UnknownEntity.RemoteText();
rt.InsertPoint = this._objectReader.Read3BitDouble();
rt.Normal = this._objectReader.Read3BitDouble();
rt.Rotation = this._objectReader.ReadBitDouble();
rt.Height = this._objectReader.ReadBitDouble();
rt.Flags = this._objectReader.ReadBitShort();
rt.Contents = this._textReader.ReadVariableText();
rt.StyleHandle = this.handleReference();
entity.RText = rt;
}
catch (System.Exception ex)
{
this._builder.Notify($"RTEXT could not be read: {ex.Message}", NotificationType.Warning);
}
}

return template;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ private bool skipEntry(NonGraphicalObject entry, out bool notify)
case AecCleanupGroup:
case AecBinRecord:
case DimensionAssociation:
case DimensionObjectContextData:
case UnknownNonGraphicalObject:
case VisualStyle:
case ProxyObject:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -741,6 +741,7 @@ private bool isObjectSupported(CadObject co)
case AecCleanupGroup:
case AecBinRecord:
case DimensionAssociation:
case DimensionObjectContextData:
case Material:
case MultiLeaderObjectContextData:
case VisualStyle:
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
using ACadSharp.Objects;
using ACadSharp.Tables;

namespace ACadSharp.IO.Templates;

internal class CadDimensionObjectContextDataTemplate : CadAnnotScaleObjectContextDataTemplate
{
public ulong? BlockHandle { get; set; }

public CadDimensionObjectContextDataTemplate(DimensionObjectContextData cadObject) : base(cadObject) { }

protected override void build(CadDocumentBuilder builder)
{
base.build(builder);

if (builder.TryGetCadObject(this.BlockHandle, out BlockRecord block))
{
((DimensionObjectContextData)this.CadObject).Block = block;
}
}
}
8 changes: 5 additions & 3 deletions src/ACadSharp/IO/Templates/CadLayerTemplate.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,6 @@ namespace ACadSharp.IO.Templates
{
internal class CadLayerTemplate : CadTableEntryTemplate<Layer>
{
public ulong LayerControlHandle { get; set; }

public ulong PlotStyleHandle { get; set; }

public ulong MaterialHandle { get; set; }
Expand All @@ -28,7 +26,11 @@ protected override void build(CadDocumentBuilder builder)

base.build(builder);

//this.CadObject.PlotStyleName = builder.GetCadObject(PlotStyleHandle);
// DWG keeps the layer's plot style (ACAD_PLOTSTYLENAME entry) as a handle; the DXF reader sets it directly.
if (this.PlotStyleHandle != 0)
{
this.CadObject.PlotStyleName = this.PlotStyleHandle;
}

if (builder.TryGetCadObject(this.MaterialHandle, out Material material))
{
Expand Down
16 changes: 16 additions & 0 deletions src/ACadSharp/Objects/DimensionObjectContextData.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
using ACadSharp.Tables;

namespace ACadSharp.Objects;

/// <summary>
/// Annotation scale representation of a dimension (ACDB_*DIMOBJECTCONTEXTDATA_CLASS): the dimension's
/// geometry block for one annotation scale. Only the block is read.
/// </summary>
public class DimensionObjectContextData : AnnotScaleObjectContextData
{
/// <summary>Anonymous block holding the dimension's graphics at <see cref="AnnotScaleObjectContextData.Scale"/>.</summary>
public BlockRecord Block { get; set; }

/// <inheritdoc/>
public override string ObjectName => "ACDB_DIMOBJECTCONTEXTDATA_CLASS";
}
6 changes: 6 additions & 0 deletions src/ACadSharp/Objects/PlotSettings.cs
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,12 @@ public double NumeratorScale
[DxfCodeValue(6)]
public string PlotViewName { get; set; }

/// <summary>
/// Handle of the named view plotted when the plot type is View (DWG R2004+ store the view this way
/// instead of by <see cref="PlotViewName"/>); 0 when none.
/// </summary>
public ulong PlotViewHandle { get; set; }

/// <summary>
/// Gets the scale factor.
/// </summary>
Expand Down
6 changes: 6 additions & 0 deletions src/ACadSharp/Tables/Layer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,12 @@ public bool PlotFlag
[DxfCodeValue(DxfReferenceType.Unprocess, 390)]
public ulong PlotStyleName { get; internal set; } = 0;

/// <summary>
/// Handle of the xref block record an xref-dependent layer comes from (0 when not dependent).
/// The layer's "XREF|" name prefix can be stale after the xref is renamed; this link is not.
/// </summary>
public ulong XrefBlockHandle { get; set; }

/// <inheritdoc/>
public override string SubclassMarker => DxfSubclassMarker.Layer;

Expand Down
Loading