ACadSharp icon indicating copy to clipboard operation
ACadSharp copied to clipboard

Implement DWG Writer for MultiLeader etc.

Open mme1950 opened this issue 1 year ago • 14 comments

The DWG writer methods for MultiLeader, MultiLeaderStyle etc. are not yet implemented. The DXF write methods should be added.

We will implement it and open a PR.

mme1950 avatar Mar 05 '24 07:03 mme1950

Hi @DomCR,

we need some Help.

We implemented the methods writeMultiLeader and writeMultiLeaderStyle. We read a document with a multileader and write the document without modification. When we read the saved document the list of entities is empty.

Is there anything we have to take care of?

We created a PR: #300

regards Matthias

mme1950 avatar Mar 06 '24 12:03 mme1950

Hi @DomCR,

it seems that ALL "UNLISTED" entities do not appear in the documents _cadObjects.

mme1950 avatar Mar 07 '24 07:03 mme1950

Here is the problem: https://github.com/DomCR/ACadSharp/blob/1d3203b2c38bba9a2340e6258d5e8a1d78c1389a/ACadSharp/IO/DWG/DwgStreamWriters/DwgObjectWriter.Common.cs#L109

By now all UNLISTED are ignored because they have to be related to a DxfClass and is currently not impmlemented.

Here is how the DwgReader handles this objects:

https://github.com/DomCR/ACadSharp/blob/1d3203b2c38bba9a2340e6258d5e8a1d78c1389a/ACadSharp/IO/DWG/DwgStreamReaders/DwgObjectReader.cs#L953

A provisional solution could be to check the type of the CadObject in writeCommonData and if is a MultiLeader or MultiLeaderStyle find the related class in the CadDocument and write the type using the classNumber instead of the ObjectType. That way you will be able to bypass the switch and avoid any breaking changes for any other UNLISTED object that the file may contain.

I'll open a branch to take a look for a generic implementation.

DomCR avatar Mar 07 '24 10:03 DomCR

Thanks, it works.

mme1950 avatar Mar 09 '24 07:03 mme1950

Hi @DomCR , we are trying to understand the concepts of writing DXF.

  • What is the DxfClassMap exactly required for?
  • Is it possible to use a generic DXF-writer method based on reflection and the DxfCodeValue-attributes?
  • Oviously there is a reason to implement dedicated writer methods.
  • An XYZ can be written using the first group code, e. g. using +0 for x, +10 for y, +20 for z, right?
  • It does not work for an XYZ having the group codes 48, 49, 140 as assigned to MultiLeaderStyle.BlockContentScale, but it is possible to write x, y, z separately.
  • Handles have to be written with writeHandle.
  • It would be convenient to have a method to write Color properties.

mme1950 avatar Mar 20 '24 10:03 mme1950

Hi @DomCR,

thanks for merging #292, we will continue with the writers. #311 should enable writing unlisted types without work-around, right?

mme1950 avatar Mar 20 '24 10:03 mme1950

What is the DxfClassMap exactly required for?

They are needed to specify the type of CadObject, you can check the readUnlistedType(short classNumber) I'm not sure about the actual use, I guess that these are dynamic types or objects, but the DxfClass is needed to specify them in the file.

Is it possible to use a generic DXF-writer method based on reflection and the DxfCodeValue-attributes?

I've tried to do it using reflection in the writer but it ends with corrupted files, some of the codes are meant to be in a certain order, with reflection is really hard to specify these kind of things so I decided to use a more "traditional" approach.

An XYZ can be written using the first group code, e. g. using +0 for x, +10 for y, +20 for z, right?

Yes, the writer has a method that handles that, IDxfStreamWriter.Write(int code, IVector value, DxfClassMap map = null)

It does not work for an XYZ having the group codes 48, 49, 140 as assigned to MultiLeaderStyle.BlockContentScale, but it is possible to write x, y, z separately.

That's the reason why I asked you to separate those properties, you can store them using a XYZ structure but they are not one, during the implementation make sure that you write each component separated.

Handles have to be written with writeHandle.

There are 2 different ways for dxf to reference another object in a file, by name or by handle, you can use each corresponding method to do so:

IDxfStreamWriter

void WriteHandle(int code, IHandledCadObject value, DxfClassMap map = null);

void WriteName(int code, INamedCadObject value, DxfClassMap map = null);

It would be convenient to have a method to write Color properties.

Yes, it would be good but before that I have to make sure that all the objects accept true color, not sure if there are some cases where the color is restricted.

thanks for merging #292, we will continue with the writers. #311 should enable writing unlisted types without work-around, right?

yes, the https://github.com/DomCR/ACadSharp/pull/311 should fix the unlisted types.

DomCR avatar Mar 20 '24 14:03 DomCR

@DomCR, thanks.

mme1950 avatar Mar 20 '24 17:03 mme1950

Hi @DomCR,

DxfStreamWriterBase:

  • WriteHandle should write the handle of a IHandledCadObject if it is not null, right? It writes a zero. I have never seen a handle of zero in a DXF file.
  • In General: Some properties having a null value are missing in the original DXF. Should they be marked as optional to suppress them on writing DXF?

mme1950 avatar Mar 22 '24 07:03 mme1950

Hi @DomCR,

we are trying to find out how to write colours to DXF. Essentially it should be the same as in DWG. There is one implementation in DwgStreamWriterAC18, i.e. for AutoCAD version AC18+. For older versions the implementation in DwgStreamWriterBase is relevant: only colour indices are written.

Looking at the DWG readers I find the following: We have an implementation of ReadCmColor in DwgStreamReaderAC18 that can read colour indices and true colour. The implementation in DwgStreamReaderBase is for older versions. This seems reasonable to me.

But: In DwgMergedReader.ReadCmColor the base implementation is called if (!(this._mainReader is DwgStreamReaderAC18)). Otherwise, the same code as the implementation of ReadCmColor in DwgStreamReaderAC18 follows. If I did not miss anything the implementation in DwgMergedReader can be reduced to.

	public Color ReadCmColor()
	{
		return this._mainReader.ReadCmColor();
	}

mme1950 avatar Mar 22 '24 10:03 mme1950

It would be convenient to have a method to write Color properties.

Yes, it would be good but before that I have to make sure that all the objects accept true color, not sure if there are some cases where the color is restricted.

The DXF Write method taking a Color cannot distinguish whether it is a CM color or a EN color. So we need separate methods.

A WriteCmColor method accepts a Color and writes a color index or a true color. If an object does not accept true color the Color object should not contain a true color. To avoid problems if someone has set some true color into a Color property and tries to write it as DXF the respective DXF writers should explicitly call some another color-write method that ensures that only a color index is written.

BTW: We have the same problem with writing DWG.

mme1950 avatar Mar 25 '24 07:03 mme1950

Good morning @DomCR , I added a WriteCmColor method to IDxfStreamWriter and implemented DxfStreamWriterBase. Please review these changes in #323 and let me know what you think about this approach.

mme1950 avatar Mar 27 '24 07:03 mme1950

Hi @DomCR,

I do not see how how versions-dependent properties should be handled on writing DXF.

mme1950 avatar Mar 30 '24 12:03 mme1950

Good morning @DomCR , I added a WriteCmColor method to IDxfStreamWriter and implemented DxfStreamWriterBase. Please review these changes in #323 and let me know what you think about this approach.

I've added some comments in the PR, about the WriteCmColor I will open a PR to fix this issue, by now you can use the method GetApproxIndex to write the colors, it won't allow to write the true color but is a temporary workaround, this is an implementation needed also for the DimensionStyles.

I do not see how how versions-dependent properties should be handled on writing DXF.

I just check the version, this example is taken from writeMText.

if (this.Version >= ACadVersion.AC1021)
{
    this._writer.Write(46, mtext.RectangleHeight, map);
}

DomCR avatar Apr 01 '24 20:04 DomCR