DomCR / ACadSharp

C# library to read/write cad files like dxf/dwg.
MIT License
386 stars 111 forks source link

Implement DWG Writer for MultiLeader etc. #297

Open mme1950 opened 6 months ago

mme1950 commented 6 months ago

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 commented 6 months ago

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 commented 6 months ago

Hi @DomCR,

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

DomCR commented 6 months ago

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.

mme1950 commented 6 months ago

Thanks, it works.

mme1950 commented 5 months ago

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

mme1950 commented 5 months ago

Hi @DomCR,

thanks for merging #292, we will continue with the writers.

311 should enable writing unlisted types without work-around, right?

DomCR commented 5 months ago

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.

mme1950 commented 5 months ago

@DomCR, thanks.

mme1950 commented 5 months ago

Hi @DomCR,

DxfStreamWriterBase:

mme1950 commented 5 months ago

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 commented 5 months ago

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 commented 5 months ago

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 commented 5 months ago

Hi @DomCR,

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

DomCR commented 5 months ago

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);
}