(C#)Can I read only one block's contents(text,line,circle and so on) and draw the graph into windows form application?

pic_20230804163700.png (19.4 KB)
Here is the example, the graph and MText are in the same block,(there may many blocks here,but I only want to read one of them, not all),Can I use C#(windows form application) to draw the graph and use textbox to show the MText? Thanks

@autopay,
Hello.
The entire content of the file is read during file loading. You need to identify the block somehow and analyze its content. Here is the example how to get content of the block:

using (CadImage cadImage = (CadImage)Image.Load(fileName))
{
    foreach (CadBaseEntity entity in cadImage.Entities)
    {
        if (entity.TypeName == CadEntityTypeName.INSERT)
        {
            CadInsertObject insert = (CadInsertObject)entity;

            CadBlockEntity block = cadImage.BlockEntities[insert.Name];

            foreach (CadBaseEntity blockEntity in block.Entities)
            {
                if (blockEntity.TypeName == CadEntityTypeName.MTEXT)
                {
                    CadMText mtext = (CadMText)blockEntity;
                    System.Console.WriteLine(mtext.Text);
                }
                ...
                if (blockEntity.TypeName == CadEntityTypeName.ATTRIB)
                {...}

                if (blockEntity.TypeName == CadEntityTypeName.ATTDEF)
                {...}

                if (blockEntity.TypeName == CadEntityTypeName.TEXT)
                {...}
            }
        }
    }
}

Thanks for the reply, how can I draw the graph after reading these data. By the way, I want to use winform to draw the graph,does the ASPOSE have the method to draw the graph automatically or I need to read each object(line,circle,eclipse…) and draw it by myself

@autopay,
we don’t provide the ability to draw directly, just export to some file or stream. So, it appears you need to iterate over objects and process them as you need (draw or analyze, for instance).

Thank you,could you please provide an example of exporting one eneity or one block’s content to stream?

@autopay,
here is the example how to write only insert entities to the file:

using (CadImage cadImage = (CadImage)Image.Load(fileName))
{
    foreach (CadBaseEntity entity in cadImage.Entities)
    {
        CadBaseEntity[] entities = cadImage.Entities;
        List<CadBaseEntity> filteredEntities = new List<CadBaseEntity>();

        foreach (CadBaseEntity baseEntity in entities)
        {
            if (baseEntity.TypeName == CadEntityTypeName.INSERT)
            {
                filteredEntities.Add(baseEntity);
            }
        }

        cadImage.Entities = filteredEntities.ToArray();
        cadImage.Save("output.pdf", new PdfOptions());
    }
}

You can filter other entities by your criteria in a similar way.

Thank you so much, I’ll try it now

Based on your code,I can read some entities, but when I try to read the entity on the block ,I can not export them to a stream or a file, can you help me to check where is the issue?

using (CadImage cadImage = (CadImage)Aspose.CAD.Image.Load (fileName))
{
CadBlockDictionary entities = cadImage.BlockEntities;
List filteredEntities = new List();
foreach (DictionaryEntry block in entities)
{
if (block.Key.ToString().Contains(“part”))
{
CadBlockEntity entity = (CadBlockEntity)block.Value;
foreach (var item in entity.Entities)
{
if (item.TypeName == CadEntityTypeName.CIRCLE)
{
CadCircle circle = (CadCircle)item;
filteredEntities.Add(circle);
}
if (item.TypeName == CadEntityTypeName.MTEXT)
{
CadMText mtext = (CadMText)item;
filteredEntities.Add(mtext);
}
if (item.TypeName == CadEntityTypeName.MLINE)
{
CadMultiLine mline = (CadMultiLine)item;
filteredEntities.Add(mline);
}
}
}
}
cadImage.Entities = filteredEntities.ToArray();
cadImage.Save(“output.pdf”, new PdfOptions());
}

@autopay,
you should iterate over cadImage.Entities collection, because it contains parts of the drawing. CadImage.BlockEntities contains additional information also that can be not used in the drawing at all but stored inside the file. Please note also that Insert entity can have some options like rotation, scaling and so on.

Please provide the file you are trying to process and specify the block you need so we can assist you better.

thanks for you help, there is my dwg file data sample.zip (117.0 KB)
I want to read block <part 1>'s graph’s part ,block <part 2>'s graph’s part and the table on the right, thanks again for your help, I really appreciate it

@autopay,
Let’s consider all options to export content of the block.

This example is preferrable. It removes all other entities in the drawing except of the required blocks (containing “part” for this example). After the export of cadImage to PDF you can see blocks like they are looking in AutoCAD.

// loading of the drawing
...
foreach (CadBaseEntity entity in cadImage.Entities)
{
	CadBaseEntity[] entities = cadImage.Entities;
	List<CadBaseEntity> filteredEntities = new List<CadBaseEntity>();

	foreach (CadBaseEntity baseEntity in entities)
	{
		if (baseEntity.TypeName == CadEntityTypeName.INSERT)
		{
			CadInsertObject insert = (CadInsertObject)baseEntity;

			if (insert.OriginalBlockName.Contains("part"))
			{
				filteredEntities.Add(baseEntity);
			}
		}
	}

	cadImage.Entities = filteredEntities.ToArray();
}

// saving of the drawing
...

This example allows to get access to separate items inside the block. You can process them as you need, e.g., print properties, change them, create your own custom objects using these values and process them etc. It is worth noting that separate objects inside CadInsert do not include information from block they are located inside: rotation, scales are stored inside the CadInsert object itself.

// loading of the drawing
...
foreach (CadBaseEntity entity in cadImage.Entities)
{
	CadBaseEntity[] entities = cadImage.Entities;

	foreach (CadBaseEntity baseEntity in entities)
	{
		if (baseEntity.TypeName == CadEntityTypeName.INSERT)
		{
			CadInsertObject insert = (CadInsertObject)baseEntity;

			if (insert.OriginalBlockName.Contains("part"))
			{
				CadBlockEntity block = cadImage.BlockEntities[insert.Name];

				foreach (CadBaseEntity blockEntity in block.Entities)
				{
					if (blockEntity.TypeName == CadEntityTypeName.MTEXT)
					{
						CadMText mtext = (CadMText)blockEntity;
						System.Console.WriteLine(mtext.Text);
					}

					if (blockEntity.TypeName == CadEntityTypeName.ATTRIB)
					{ ... }

					if (blockEntity.TypeName == CadEntityTypeName.ATTDEF)
					{ ... }

					if (blockEntity.TypeName == CadEntityTypeName.TEXT)
					{ ... }

					...
				}
			}
		}
	}
}
// saving of the drawing
...

The last example shows how to replace blocks in the drawing with sets of entities they contain. Again, this example destroys the link between CadInsert and entities inside it, you need to care about possible transformations like cadInsert.RotationAngle, cadInsert.ScaleX, etc. separately.

// loading of the drawing
...
string modelHandle = cadImage.Layouts["Model"].BlockTableRecordHandle;

List<CadBaseEntity> filteredEntities = new List<CadBaseEntity>();
foreach (CadBaseEntity baseEntity in cadImage.Entities)
{
	if (baseEntity.TypeName == CadEntityTypeName.INSERT)
	{
		CadInsertObject insert = (CadInsertObject)baseEntity;

		if (insert.OriginalBlockName.Contains("part"))
		{
			System.Console.WriteLine(insert.OriginalBlockName);
			CadBlockEntity block = cadImage.BlockEntities[insert.Name];

			foreach (CadBaseEntity blockEntity in block.Entities)
			{
				blockEntity.SoftOwner = modelHandle;
				filteredEntities.Add(blockEntity);
			}
		}
	}
}

cadImage.Entities = filteredEntities.ToArray();

cadImage.UpdateSize();
// saving of the drawing
...

In my humble opinion the first option is the best to export some block with our embedded support of all transformations inside it. Two other examples are better when you need to analyse block content and process it entity by entity.

Thanks for your thoughtful reply and the three examples, they inspire me a lot. Now, I can use them to export an block to other files. Here,I have another question, actually, I want to develop an program which can read each block’s graph and save them as a separate file(one block one file), so that I can use this exported file as the attachment to some spcific production parts. By using the first example, I can export an block to a file.but seemingly, I exported the entire dwg file and made the other objects invisible. can I just export object of concern(the block I mentioned above) instead of exporting entire graph?
export 2.png (59.5 KB)
export1.png (12.6 KB)

The export 1 is which I want, thanks again for your help.

@autopay,
please try to call

cadImage.UpdateSize();

after the update of Entities collection.

That’s perfect, thank you for your help. I really appreciate it.

1 Like

Sorry for bothering again,how can I read the table data right of the graph?I can only read their ID one bye one, but I can not read the actual data in the table.Is there any convenient way to read the whole table data ? If possible, you can still use the data sample.zip which I upload above.thanks .

@autopay,
Despite that table looks like a table it is still a block reference consisting of lines and attributes. So the common approach is similar including some specific for attributes:

foreach (CadBaseEntity baseEntity in cadImage.Entities)
{
	if (baseEntity.TypeName == CadEntityTypeName.INSERT)
	{
		CadInsertObject insert = (CadInsertObject)baseEntity;

		if (insert.OriginalBlockName == "I$CF8F9B5D9")
		{
			CadBlockEntity block = cadImage.BlockEntities[insert.Name];

			foreach (CadBaseEntity blockEntity in block.Entities)
			{
				if (blockEntity.TypeName == CadEntityTypeName.ATTDEF)
				{
					CadAttDef attdef = (CadAttDef)blockEntity;

					foreach (CadBaseEntity att in insert.ChildObjects)
					{
						if (att.TypeName == CadEntityTypeName.ATTRIB)
						{
							CadAttrib attrib = (CadAttrib)att;

							if (attrib.DefinitionTagString == attdef.Id)
							{
								System.Console.WriteLine("{0}, {1}", attdef.Id, attrib.DefaultText);
								break;
							}
						}
					}
				}

				if (blockEntity.TypeName == CadEntityTypeName.LINE)
				{ ... }
			}
		}
	}
}

I got it, thanks

1 Like