Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implementation of MULTILEADER and MULTILEADERSTYLE #169

Merged
merged 30 commits into from
Nov 3, 2023

Conversation

mme1950
Copy link
Contributor

@mme1950 mme1950 commented Sep 15, 2023

No description provided.

@mme1950 mme1950 marked this pull request as ready for review September 25, 2023 00:10
@DomCR
Copy link
Owner

DomCR commented Sep 28, 2023

Please check the conflicts with master

@DomCR DomCR added the feature New feature added label Sep 28, 2023
@DomCR DomCR self-requested a review September 28, 2023 16:02
@@ -153,10 +153,6 @@ public void SetValue<TCadObject>(int code, TCadObject obj, object value)
{
this._property.SetValue(obj, Enum.ToObject(this._property.PropertyType, value));
}
else if (this._property.PropertyType.IsEquivalentTo(typeof(ushort)))
Copy link
Owner

Choose a reason for hiding this comment

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

Why is this if statement being removed?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I am afraid, we did something wrong. We did not change this file. We have to check how this happened.



/// <summary>
/// TODO Do we need this class to represent a list of arrow heads
Copy link
Owner

Choose a reason for hiding this comment

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

Please don't add a TODO comment in the summary, this should only describe the element and not give development notes.

I've encountered multiple instances of this error, please apply the same solution for all of them.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I pulled the TODO out of the summary.
I think we do not need the ArrowheadAssociation class.
The Arrowheads property should have the type IList (or whatever type an arrowhead is)

/// <summary>
/// Text attachment direction for MText contents
/// 0 = Horizontal
/// 1 = Vertical
Copy link
Owner

Choose a reason for hiding this comment

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

Values shouldn't be specified in the summary.

I've encountered multiple instances of this error, please apply the same solution for all of them.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It is copied from the documentation, just to be sure that the created enum types are correct.
I moved itnto the value tag, OK?

Copy link
Owner

Choose a reason for hiding this comment

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

Value tag should only be used to add a commentary about the value restriction, if is an enumeration you don't need to specify the values, you can remove the tag.


public override CadObject Clone()
{
MultiLeader clone = (MultiLeader)base.Clone();
Copy link
Owner

Choose a reason for hiding this comment

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

There are elements in this object that need to be cloned separately, for an example you can check how the type Entity handles the cloning method.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

OK

@@ -1573,7 +1573,7 @@ public XYZ ModelSpaceYAxis
/// </remarks>
[CadSystemVariable("$TIMEZONE", 70)]
public int TimeZone { get; set; }

Copy link
Owner

Choose a reason for hiding this comment

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

Not a big deal but to make the review easier avoid this Indentation changes.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

There should not be any changes in this class.

{
last.CurveTangent = this._reader.ValueAsDouble;
}
return true;
Copy link
Owner

Choose a reason for hiding this comment

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

Why has this been removed?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

As before. We did not make any changes to this class.

@@ -10,11 +9,8 @@ internal class DxfHeaderSectionWriter : DxfSectionWriterBase

public CadHeader Header { get { return this._document.Header; } }

public DxfWriterOptions Options { get; }

public DxfHeaderSectionWriter(IDxfStreamWriter writer, CadDocument document, CadObjectHolder holder, DxfWriterOptions options) : base(writer, document, holder)
Copy link
Owner

Choose a reason for hiding this comment

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

Options should not be removed from this class.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

As before. We did not make any changes to this class.

@@ -23,9 +19,6 @@ protected override void writeSection()

foreach (KeyValuePair<string, CadSystemVariable> item in map)
{
if (!this.Options.WriteAllHeaderVariables && !this.Options.HeaderVariables.Contains(item.Key))
Copy link
Owner

Choose a reason for hiding this comment

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

This if is needed to avoid errors in the writer, please revert the changes.

@@ -37,7 +37,7 @@ protected void writeObject<T>(T co)
this.writeMappedObject<DictionaryVariable>(dictvar);
break;
case SortEntitiesTable sortensTable:
//this.writeSortentsTable(sortensTable);
this.writeSortentsTable(sortensTable);
Copy link
Owner

Choose a reason for hiding this comment

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

Same as the reader writeSortentsTable(sortensTable) has some errors, please do not uncomment this line.

insert.Block = block;
}
else if (!string.IsNullOrEmpty(this.BlockName) && builder.TryGetTableEntry(this.BlockName, out block))
if (builder.TryGetCadObject(this.BlockHeaderHandle, out BlockRecord block))
Copy link
Owner

Choose a reason for hiding this comment

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

This is an old if, please revert to the new one.

@DomCR
Copy link
Owner

DomCR commented Sep 28, 2023

First of all, great work!! this looks great!! to continue with the development I would like to add a few notes:

  • Add test to check that the MLEADER and MLEADERSTYLE are read without errors, the current test files only contain MLEADERSTYLE, you should add a file in each version (if possible) containing MLEADER in it.
  • The DxfReader and DxfWriter haven't been updated, do you plan to do it in this PR or keep it separately?
  • When updating the branch be careful for which are the last changes in master, some of my comments were related to this issue.

Overall looks good, I will continue to review the PR while you work on it and continue to give feedback to you.

Thanks for the contribution.

@mme1950
Copy link
Contributor Author

mme1950 commented Sep 28, 2023

I am afraid, we did something wrong. Some of the changes you mentioned above have not been made by us. We have to check how this happened.

Maybe we have to redo the fork, create a branch and enter a PR.
I will return to it tomorrow.

@mme1950
Copy link
Contributor Author

mme1950 commented Sep 29, 2023

  • Add test to check that the MLEADER and MLEADERSTYLE are read without errors, the current test files only contain MLEADERSTYLE, you should add a file in each version (if possible) containing MLEADER in it.

OK, we must view the test project.

  • The DxfReader and DxfWriter haven't been updated, do you plan to do it in this PR or keep it separately?

We then also must add writeMultiLeader and writeMultiLeaderStyle to DwgObjectWriter, right?
I would prefer do do it separately.

  • When updating the branch be careful for which are the last changes in master, some of my comments were related to this issue.

OK

@DomCR
Copy link
Owner

DomCR commented Oct 1, 2023

I've been reviewing the PR, for some reason your PR is pointing to an old version of master and registering a lot of changes that should not be there... I don't know why is this way, I'll try to find out more about this issue.

In the meantime keep an eye to the test, I've approved the build but is failing, check what is happening, it may be caused due this unnecessary changes.

@mme1950
Copy link
Contributor Author

mme1950 commented Oct 2, 2023

For a full test we have to create a DWG files with "all" variants of Mutileader also for older AutoCAD versions, right?
To make the test run a subset may be sufficient.
For all variants we have to learn about block content, arrow heads and some other things we did not try yet.

@DomCR
Copy link
Owner

DomCR commented Oct 4, 2023

For a full test we have to create a DWG files with "all" variants of Mutileader also for older AutoCAD versions, right? To make the test run a subset may be sufficient. For all variants we have to learn about block content, arrow heads and some other things we did not try yet.

If you want to just test in a single version you have to make sure that the reader will ignore the entities for all other versions to avoid issues or bugs.

Copy link
Owner

Choose a reason for hiding this comment

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

This document shouldn't have changes.

@@ -320,10 +320,6 @@ public override CadObject Clone()
{
MultiLeader clone = (MultiLeader)base.Clone();

clone.Style = (MultiLeaderStyle)this.Style?.Clone();
clone.LineType = (LineType)this.LineType?.Clone();
clone.TextStyle = (TextStyle)this.TextStyle?.Clone();
Copy link
Owner

Choose a reason for hiding this comment

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

This should be cloned, otherwise the styles won't be detached form the document.

Copy link
Owner

Choose a reason for hiding this comment

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

This document should not be changed, I imagine that you added some MLeader entities in a file and override the existing one.

Instead of overriding the file, create a new one, you can use a name like sample_MLeader_{version}.dwg

/// Common AcDbAnnotScaleObjectContextData data (see paragraph 20.4.71).
/// 300 DXF: “CONTEXT_DATA{“
/// </summary>
public partial class MultiLeaderAnnotContext : CadObject
Copy link
Owner

Choose a reason for hiding this comment

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

The documentation for this class should be revised, I see that is copied from the PDF.

/// Common AcDbAnnotScaleObjectContextData data (see paragraph 20.4.71).
/// 300 DXF: “CONTEXT_DATA{“
/// </summary>
public partial class MultiLeaderAnnotContext : CadObject
Copy link
Owner

Choose a reason for hiding this comment

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

The documentation for this class should be revised, I see that is copied from the PDF.

/// <value>
/// 0 = Horizontal
/// 1 = Vertical
/// </value>
Copy link
Owner

Choose a reason for hiding this comment

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

The value tag for the documentation should be only used to add value restrictions like a range of values, enumeration types don't need to be specified.

@mme1950
Copy link
Contributor Author

mme1950 commented Oct 30, 2023

It seems that some tests are failing, one of them is the DwgReaderTest the test is making a comparison with a json file that does not belong to the new sample, the best way to go it will be to move the sample to another folder and create an specific test for it.

Also I see that the Clone() test is failing too for the MultiLeader it goes in some kind of loop.

Let me know if you need any help with that.

Hi @DomCR,

I am sorry, I did not have time to work on this project the last two weeks.
I return today to analyse these problems with Nihad.

Then we should try to finish.
I would like to solve the problems regarding the version compliance by simply not supporting mutileaders form AutoCAD versions older than R2010.
I think the object model is OK now.

@DomCR
Copy link
Owner

DomCR commented Oct 30, 2023

It seems that some tests are failing, one of them is the DwgReaderTest the test is making a comparison with a json file that does not belong to the new sample, the best way to go it will be to move the sample to another folder and create an specific test for it.
Also I see that the Clone() test is failing too for the MultiLeader it goes in some kind of loop.
Let me know if you need any help with that.

Hi @DomCR,

I am sorry, I did not have time to work on this project the last two weeks. I return today to analyse these problems with Nihad.

Then we should try to finish. I would like to solve the problems regarding the version compliance by simply not supporting mutileaders form AutoCAD versions older than R2010. I think the object model is OK now.

The PR and the implementation looks good, and if you want to focus on one feature at a time that's ok, even if you want to split the PR that would be OK for me too.

Just as a general note, check the documentation comments and avoid to use the /// tag for enums and keep in mind to delete the development methods.

@mme1950
Copy link
Contributor Author

mme1950 commented Oct 30, 2023

Hi @DomCR,

is it OK for you, to restrict ths support of multileader entities to version R2010 Plus?
Then I will change the implementation accordingly.

Here are some remarks to our implementation:

Object Model

According to the PDF (OpenDesign_Specification_for_.dwg_files) and online documentation the MultiLeader entity embeds an object that provides a subset ob the properties of a MLeaderAnnotContext object. The MLeaderAnnotContext includes a list of embedded LEADER objects. LEADER objects contain a list of LEDER_LINE objects.

In the DXF file with a MULTILEADER entity we also found a complete MLeaderAnnotContext object with the common properties and properties identical to the object embedded into the MULTILEADER.

This structure is reproduced in the object model:

  • The MultiLeader class has a Style property referencing a MultiLeaderStyle object.
  • A MultiLeaderAnnotContext class is defined holding the subset of properties from the MLeaderAnnotContext. Each MultiLeader references exactly one MultiLeaderAnnotContext.
  • The MultiLeaderAnnotContext has a list of LeaderRoot objects.
  • A LederRoot has a list of LeaderLine objects.

Several properties of the MultiLeader class also exist in the MultiLeaderAnnotContext class. Values may be redundant or conflicting.

Remarks

In AutoCAD a MultiLeader can have one or more leaders evolving to leader lines (LEADER_LINE). It seems there is no way to add more than one leader (LEADER), having one or more leader lines each.

Thus: There can be only one LEADER. More than one LEADER would require an individual Contents. But the MultiLeader can have has one "Contents", either a Text contents or a contents block.

The MultiLeader class has a LineType property enherited from Entity referencing a LineType object. A second property of type LineType (LeaderLineType) is defined in the MultiLeader class. The referenced LineType objects are different.

Open Issues

Version Compliance

Due to lack of documentation and because we cannot create and test DWG-files with old AutoCAD versions we can support multileaders only for R2010 Plus.

List of Arrowheads

In the PDF (OpenDesign_Specification_for_.dwg_files) documentation and also in the various DXF documentations a list of arrowheads is mentioned. This data are obviously not present in the DWG. We assume that the documentation is wrong.

Two Unknown Bytes in MultiLeader

Between 291 Enable Dogleg and 41 Dogleg Length we must call Advance(2).

@mme1950
Copy link
Contributor Author

mme1950 commented Oct 30, 2023

Hi @DomCR,

final changes (hopefully):

  • removed all enum values from /// comments, except where only a subset is mentioned in the documentation.
  • fixed formatting (opening brace on new line).
  • removed analyse methods.
  • readMultiLeader and readMultiLeaderStyle return null when version is older than R2010.

regards
Matthias

@mme1950
Copy link
Contributor Author

mme1950 commented Nov 2, 2023

Hi @DomCR,

please commit this PR if the code is OK for you now.

regards
Matthias

Copy link
Owner

Choose a reason for hiding this comment

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

I think this file should not be modified, please revert the changes.


/// <summary>
/// Text Left Attachment Type
/// TODO Property Name
Copy link
Owner

Choose a reason for hiding this comment

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

Please remove this line

[DxfCodeValue(173)]
public TextAttachmentType TextLeftAttachment { get; set; }

// TODO Property Name
Copy link
Owner

Choose a reason for hiding this comment

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

Please remove this line

#region Block Content Properties

/// <summary>
/// Block Content ID (optional) Type = BlockRecord
Copy link
Owner

Choose a reason for hiding this comment

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

Is not needed to specify the type as Type = BlockRecord and the optional flag you can add the DxfReferenceType as a parameter in the DxfCodeValue attribute

}

public void Advance(int offset)
{
throw new InvalidOperationException();
_mainReader.Advance(offset);
Copy link
Owner

Choose a reason for hiding this comment

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

I think that this is the only line that should be modified in this file

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I agree, we did not change anything else in this file.

@@ -1206,12 +1212,27 @@ private void readCommonAttData(AttributeBase att)

switch (att.AttributeType)
{
case AttributeType.SingleLine:
Copy link
Owner

Choose a reason for hiding this comment

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

the method readCommonAttData(AttributeBase att) should not change

//numentries handles in the file (soft owner)
//Handle refs H NULL(soft pointer)
//xdicobjhandle(hard owner)
//the apps(soft owner)
Copy link
Owner

Choose a reason for hiding this comment

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

readDocumentTable<T> should not change

@@ -1393,7 +1408,7 @@ private void readInsertCommonData(CadInsertTemplate template)
template.OwnedObjectsCount = 0;

//R2004+:
if (this.R2004Plus && template.HasAtts)
if (this.R2004Plus & template.HasAtts)
Copy link
Owner

Choose a reason for hiding this comment

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

readInsertCommonData(CadInsertTemplate template) should not change

@@ -1562,15 +1577,12 @@ private CadTemplate readPolyline3D()
this.readCommonEntityData(template);

//Flags RC 70 NOT DIRECTLY THE 75. Bit-coded (76543210):
byte flags = this._objectReader.ReadByte();

byte num1 = this._objectReader.ReadByte();
Copy link
Owner

Choose a reason for hiding this comment

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

readPolyline3D() should not change

Copy link
Owner

Choose a reason for hiding this comment

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

There are a lot of changes in methods outside the scope for this file, I think is due some merge conflicts.

Please check the changes, this file should only be changes for the MULTILEADER and MULTILEADERSTYLE implementation methods

@DomCR
Copy link
Owner

DomCR commented Nov 3, 2023

Great Job with this one!! looks really good!!

I've reviewed the PR, most of the comments are related to the documentation or fix some merging errors that you may have had during the development, I'll try to block any PRs that mess with you files until this is merge into master.

@DomCR
Copy link
Owner

DomCR commented Nov 3, 2023

There are some test failing:

  • Failed ACadSharp.Tests.ColorTests: this are due the merging errors, once you restore those classes you will be good.
  • Failed ACadSharp.Tests.IO.IOTests: this test is using the DwgWriter and DxfWriter for testing, the ACadSharp.IO.DXF.DxfSectionWriterBase.writeEntity and DwgObjectWriter.Entities are throwing an exception for your new entities, please add them into the ignore list so this exception is avoided.

@DomCR
Copy link
Owner

DomCR commented Nov 3, 2023

If you need a hand resolving this issues, please let me know and I'll commit the changes directly to this PR.

@mme1950
Copy link
Contributor Author

mme1950 commented Nov 3, 2023

Hi @DomCR,

we hopefully fixed the merge conflicts and changed the comments as you requested.
However the comments are in general very poor. I will improve them later when we learnt how properties specified in AutoCAD arrive in the data.

regards
Matthias

Copy link
Owner

@DomCR DomCR left a comment

Choose a reason for hiding this comment

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

The PR looks good but there is still a problem with the clone for ACadSharp.Entities.MultiLeader I'll take a look and see if I can help

@DomCR
Copy link
Owner

DomCR commented Nov 3, 2023

Here is a fix for the ACadSharp.Entities.MultiLeader.Clone() error:

		public override CadObject Clone()
		{
			MultiLeader clone = (MultiLeader)base.Clone();

			clone.ContextData = (MultiLeaderAnnotContext)this.ContextData?.Clone();

			foreach (var att in BlockAttributes)
			{
				clone.BlockAttributes.Add(att);
			}

			return clone;
		}

@mme1950
Copy link
Contributor Author

mme1950 commented Nov 3, 2023

Oh.

@DomCR
Copy link
Owner

DomCR commented Nov 3, 2023

Oh.

Sorry I wanted to try if I was able to push directly here and make the merge if the test passed.

@DomCR
Copy link
Owner

DomCR commented Nov 3, 2023

Great job!!

@DomCR DomCR merged commit f0504fa into DomCR:master Nov 3, 2023
2 checks passed
@mme1950
Copy link
Contributor Author

mme1950 commented Nov 3, 2023

Hi @DomCR

So you made the change yourself and merged everythng, Thank you wery much.
We will now concentrate on our DWG-to-SVG converter and so intensively test the multileder reader.
Then we shall implement the DXF-reader and the writers.

Again thank you very much for your help and the review. It is great to contribute to such an active project.
Greetings from Berlin to Barcelona.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
feature New feature added
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Help needed: How to read substructures (e. g. CONTEXT_DATA in MULTILEADERSTYLE)
3 participants