8000 MultiLeader Block update · Issue #632 · DomCR/ACadSharp · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

MultiLeader Block update #632

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

Open
DomCR opened this issue Apr 25, 2025 · 24 comments
Open

MultiLeader Block update #632

DomCR opened this issue Apr 25, 2025 · 24 comments

Comments

@DomCR
Copy link
Owner
DomCR commented Apr 25, 2025

Is your feature request related to a problem? Please describe.
MultiLeader are not shown when are allocated in blocks.

Describe the solution you'd like
Create the MultiLeader block in a similar manner than dimensions so they are updated when they are allocated inside blocks.

Additional context
Add any other context or screenshots about the feature request here.

@mme1950
Copy link
Contributor
mme1950 commented Apr 25, 2025

Hi @DomCR,
actually the a MultiLeader does not show up also when it is not in a block.
The attached files contain the following steps

  • MultiLeader created in AutoCAD
  • Read and Saved by ACadSharp
  • Repaired in AutoCAD (Style colors reset to ByLayer, Style changed and reset.)

m-ACadSharp-AutoCAD.zip

@mme1950
Copy link
Contributor
mme1950 commented Apr 25, 2025

When I compare documents stored as DXF I see some differences:

  • Colours are changed: bit 02000000 is added.
    C0000000 --> C2000000
    C1000000 --> C3000000
    It seems we have to learn what the 02000000 bit means.
    But I do not think that the changed colours are relevant.
  • The color of the leader line (BL 92) was null but is set to C3000000
    This is wrong, but should not be relevant.

@mme1950
Copy link
Contributor
mme1950 commented Apr 25, 2025

In the original DXF The extended data of the multiLeader contain the following record:
1001 S AcDbBlockRepETag
1070 BS 1
1071 BL 298
1005 S 2F4

1005 2F4 is the Handle of the MultiLeaderItself.

In the data written by ACadSharp these data contain:
1001 S AcDbBlockRepETag
1070 BS 1
1071 BL 298 12A
1005 S F402000000000000

byte order reversed.

This, however, it is not changed back in the repaired dock. So this is not relevant either

@mme1950
Copy link
Contributor
mme1950 commented Apr 30, 2025

Hi @DomCR,
as far I remember, you did not have additional information about CmColor bit 0x02000000,
ReadCmColor does not take this bit into account.
In AutoCAD the color is ByLayer, but is written as 0xC0000000. Since bit 0x01000000 is not set, this is read as true color black.
This is consequently written as 0xC300000.
Normally I expect that ByLayer is to be represented as index color 256.
To preserve the value of 0xC0000000 this has to be handled as a special case.
I try to find out if it makes any difference.

@mme1950
Copy link
Contributor
mme1950 commented May 3, 2025

Hi @DomCR,
comparing the DXFs containing a MultiLeader written by AutoCAD and by ACadSharp a relevant difference becomes visible:
The file written by AutoCAD contains an ACDB_MLEADEROBJECTCONTEXTDATA_CLASS object, containing exactly the same data as the embedded ContextData structure in the MultiLeader. It seems thate this redundant data are important for AutoCAD.

@mme1950
Copy link
Contributor
mme1950 commented May 4, 2025

Hi @DomCR,
it seems we have to implement ACDB_MLEADEROBJECTCONTEXTDATA_CLASS derived from NonGraphicalObject and the reader and writer methods.
DXF:

0	S	ACDB_MLEADEROBJECTCONTEXTDATA_CLASS	
5	H	351	
102	S	{ACAD_REACTORS	
	330	H	2F7	
102	S	}	
330	H	2F7	
100	S	AcDbObjectContextData	
70	BS	4	
290	B	1	
100	S	AcDbAnnotScaleObjectContextData	
340	H	10D	

The following properties are identical to the ContextData sub-object in the MultiLeader.

The ACDB_MLEADEROBJECTCONTEXTDATA_CLASS object is linked to the MultiLeader object as follows:

  • MultiLeader.XDictionary ponts to dictionray with an entry AcDbContextDataManager.
  • AcDbContextDataManager is a dictionary with an entry ACDB_ANNOTATIONSCALES
  • ACDB_ANNOTATIONSCALES is a dictionary with an entry pointing to the ACDB_MLEADEROBJECTCONTEXTDATA_CLASS object.

The dictionaries are properly read except that the ACDB_ANNOTATIONSCALES has no entry because the ACDB_MLEADEROBJECTCONTEXTDATA_CLASS object cannot be resolved.

I expect that implementing this class and the respective reader and writer ensures that a MultiLeader is fully described so that it becomes visible in AutoCAD. The clone mechanism for MultiLeader has to be extended to the ACDB_MLEADEROBJECTCONTEXTDATA_CLASS object that is linked via the dictionary.

Please let me know if you have remarks or suggestions.

@mme1950
Copy link
Contributor
mme1950 commented May 6, 2025

Hi @DomCR,
I now succeeded to write a DWG with a MultiLeader with ACadSharp, and the MultiLeader is visible in AutoCAD.

  • I completed the implementation for ACDB_MLEADEROBJECTCONTEXTDATA_CLASS:
    NonGraphicalObject
       ObjectContextData
           AnnotScaleObjectContextData
               MultiLeaderAnnotContext
    
    Properties of these classes are as documented in ODS.
  • I added this entry to the classes list:
       0	S	CLASS	
       1	S	ACDB_MLEADEROBJECTCONTEXTDATA_CLASS	
       2	S	AcDbMLeaderObjectContextData	
       3	S	ObjectDBX Classes	
       90	BL	1153	481
       91	BL	1	1
       280	BS	0	
       281	BS	0
    
  • ObjectName and SubclassMarker of MultiLeaderAnnotContext had to be changed:
    ObjectName: ACDB_MLEADEROBJECTCONTEXTDATA_CLASS
    SubclassMarker: AcDbMLeaderObjectContextData
    
  • The class name MultiLeaderAnnotContext (as documented in ODS) should be changed accordingly:
    MultiLeaderObjectContextData

There are some open tasks/questions:

  • We have sample DWGs with a MultiLeader with and without an ACDB_MLEADEROBJECTCONTEXTDATA_CLASS object.
    When does AutoCAD require this object?
  • It seems that the "ebedded" data structure CONTEXT_DATA in the MultiLeader data is identical to the content of the ACDB_MLEADEROBJECTCONTEXTDATA_CLASS object.
    The CONTEXT_DATA must be read to advance in stream.
    If a ACDB_MLEADEROBJECTCONTEXTDATA_CLASS object exists, the MultiLeader.ContextData property should return this object instead of the object created from the "embedded" data.
  • The ACDB_MLEADEROBJECTCONTEXTDATA_CLASS object must be cloned with the MultiLeader.
    Up to now we do not clone dictionary entries.

@DomCR
Copy link
Owner Author
DomCR commented May 7, 2025

Hi @mme1950,

I've done some investigation here:

Can you provide the code to write a DWG with a MultiLeader? I'm trying to make it work but it always requires to recover the file and erases the MultiLeader.

For what you say the DxfClass is not fully necessary, but I don't understand why, also It doesn't make sense that the MultiLeaderAnnotContext is a NonGraphicalObject but it doesn't have a handle or name assign, is not even stored in the dictionary. 😵

One test that succeeded at drawing a MultiLeader has been to just clone one form another document, which I thought is because some value is incorrect, in Autocad I get an error saying "var out of range" and deletes the entity when is created manually using ACadSharp.

@mme1950
Copy link
Contributor
mme1950 commented May 7, 2025

Hi @DomCR,
I am just creating a CR.

It sems that it is important that the ACDB_MLEADEROBJECTCONTEXTDATA_CLASS object is contained in the DWG as compleate object with common an superclass properties and a handle. This object contains data identical to the CONTEXT_DATA substructure.

I think it should be derived from NonGraphicalObject.

@DomCR
Copy link
Owner Author
DomCR commented May 7, 2025

But where is stored? the MultiLeader entities usually don't have any dictionary.

@mme1950
Copy link
Contributor
mme1950 commented May 7, 2025

The MultiLeader has an XDictionary property.

@mme1950
Copy link
Contributor
mme1950 commented May 7, 2025

Here you can see how to find the attached object:

		private bool tryGetContextdata(out MultiLeaderObjectContextData contextData)
		{
			if (this.XDictionary.TryGetEntry("AcDbContextDataManager", out CadDictionary contextDataManager) &&
				contextDataManager.TryGetEntry("ACDB_ANNOTATIONSCALES", out CadDictionary annotScales) &&
				annotScales.TryGetEntry("*A1", out MultiLeaderObjectContextData a1))
			{
				contextData = a1;
				return true;
			}
			contextData = null;
			return false;
		}

@DomCR
Copy link
Owner Author
DomCR commented May 7, 2025

Which version is the file that you are reading?

@mme1950
Copy link
Contributor
mme1950 commented May 7, 2025

NOTE: I renamed the MultiLeaderAnnotContext class to MultiLeaderObjectContextData.

@mme1950
Copy link
Contributor
mme1950 commented May 7, 2025

Which version is the file that you are reading?

This is the DWG originally created by AutoCAD:
m.zip

This DWG was written by ACadSharp with my latest changes.
m+.zip

@mme1950
Copy link
Contributor
mme1950 commented May 7, 2025
  1. Step (completed)
    • Implementation of class MultiLeaderObjectContextData and superclasses derived from NonGraphicalObject.
    • CadTemplate classes Reader and writer: Some unknown bits have to be skipped.

    Saved MultiLeader can be opened in AutoCAD, and the MultiLeader is visible.

  2. Step (done)
    • Renaming
  3. Step (draft implementation not yet tested)
    • Clone mechanism
  4. Use reference to standalone MultiLeaderObjectContextData instead of CONTEXT_DATA subobject. (To be done)

@DomCR
Copy link
Owner Author
DomCR commented May 7, 2025

Can you try to add this assert to the MultiLeaderTests?

Assert.NotNull(multiLeader.XDictionary);

For me it always fails.

@DomCR
Copy link
Owner Author
DomCR commented May 7, 2025

Which version is the file that you are reading?

This is the DWG originally created by AutoCAD: m.zip

This DWG was written by ACadSharp with my latest changes. m+.zip

If you are re-writing the file, this works seem to work fine, the issue is when you create a new one using ACadSharp.

@mme1950
Copy link
Contributor
mme1950 commented May 7, 2025

When I create the file in AutoCAD write it with current version of ACadSharp, AutoCAD can open the file, but the MultiLeader is invisible. When I write the MultiLeaderObjectContextData as CadObject with handle, the MultiLeader becomes visible.

I did not try yet to ceate a MultiLeader from scratch.

When cloning a MultiLeader (with an XDictionary) and the attached MultiLeaderObjectContextData it must be ensured that the dictionaries are "cloned" too. I have to test this process now.

I will let you know.

@mme1950
Copy link
Contributor
mme1950 commented May 7, 2025

The MultiLeader has been cloned and the text modified with ACadSharp. This DWG can be opened with AutoCAD and both MultiLeaders are visible. The leader line has been modified in AutoCAD.
m+CMod.zip

I am glad.

Next:

  • Write Blocks with MultiLeaders
  • Clone Blocks with MultiLeaders

@mme1950
Copy link
Contributor
mme1950 commented May 7, 2025

Can you try to add this assert to the MultiLeaderTests?

Assert.NotNull(multiLeader.XDictionary);

For me it always fails.

I do not understand when AutoCAD creates an additional MultiLeaderObjectContextData object and links it via XDictionary... to the MultiLeader. May be the sample files used do not contain an XDictionary.

In the m.zip MultiLeader.XDictionary is not null.

8000

@mme1950
Copy link
Contributor
mme1950 commented May 8, 2025
  • Write Blocks with MultiLeaders
  • Clone Blocks with MultiLeaders

This seems to work.

@mme1950
Copy link
Contributor
mme1950 commented May 8, 2025

Hi @DomCR,

I want to infer one more change:

  • If the MultiLeader refers to a MultiLeaderObjectContextData object via XDictionary etc. the MultiLeaderObjectContextData` object that was created from the embedded CONTEXT_DATA structure should be discarded,
  • and the MultiLeader.ContextData property should return the real MultiLeaderObjectContextData object.
  • This ensures that when the MultiLeader lines and content is modified that the MultiLeaderObjectContextData object is kept synchronized.
  • The writeMultiLeader method should work as before.

Please let me know, what you think about this approach.

@mme1950
Copy link
Contributor
mme1950 commented May 9, 2025

Which version is the file that you are reading?

Do you think it depends on the AutoCAD version wether or not a MultiLeaderObjectContextData object is required?

The m.dwg has AC1032.

This file has AC1032 too, but does not contain a MultiLeaderObjectContextData object.
20240213_multileader_2_arrows.zip

If I write this file without cange still no MultiLeaderObjectContextData object is added.
If I change the MultiLeader.Style the MultiLeaderObjectContextData object is added.

20240213_multileader_2_arrows-A.zip

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

No branches or pull requests

2 participants
0