haplokuon / netDxf

.net dxf Reader-Writer
MIT License
1.01k stars 411 forks source link

How to position entities on an exported image #265

Closed srudin closed 1 year ago

srudin commented 3 years ago

KNOWLEDGE: Experienced programmer but almost no experience with CAD functionality or DXF model.

GOAL: I have some DXF files and need to convert them to an image and display that image on a website. Using html/javascript I then need to add some interactive polygons (e.g. they can be clicked, change colors etc.) over the image. The polygons refer to entities ("inserts" I think?) that are defined in the DXF files already.

PROBLEM 1: I cannot export/convert the DXF files to images. I saw that there are other libraries who can do that - is it correct that netDxf does not support that?

PROBLEM 2: As I was not able to export/convert I used a free online converter and got a jpg image from there. I now tried to paint the polygons on the image but don't understand how to transform the values from the DXF coordinates to the image coordinates. Are there any helper classes or what is the formula to do that?

CODE: For better understanding here is some of the trial code I have created so far (I know the logic around the new points is totally wrong):

DxfDocument dxfDocument = DxfDocument.Load(modelFile);

using (var image = Image.FromFile(imageFile))
{
    using (var graphics = Graphics.FromImage(image))
    {
        foreach (Insert entity in dxfDocument.Layouts[dxfDocument.ActiveLayout].AssociatedBlock.Entities.OfType<Insert>().Where(e => e.Attributes.Any(a => a.Tag == "AP_NR")))
        {
            Console.WriteLine(entity.Block.Name);
            Console.WriteLine(string.Join(", ", entity.Attributes.Where(a => !string.IsNullOrEmpty(a.Value as string)).Select(a => a.Tag + ": " + a.Value)));
            Console.WriteLine("------------------------");

            IList<Point> points = new List<Point>();
            foreach (Line line in entity.Block.Entities.OfType<Line>())
            {
                // I used 38 because that's what I get dividing the test image width in pixel through the plotsettings papersize of the layout
                points.Add(new Point((int)((entity.Position.X * 38) + (line.StartPoint.X * 38)), (int)((entity.Position.Y * 38) + (line.StartPoint.Y * 38))));
                points.Add(new Point((int)((entity.Position.X * 38) + (line.EndPoint.X * 38)), (int)((entity.Position.Y * 38) + (line.EndPoint.Y * 38))));
            }

            if (points.Count > 0)
            {
                graphics.DrawPolygon(new Pen(Color.DeepPink, 3), points.ToArray());
            }
        }

        image.Save(testFile, ImageFormat.Jpeg);
    }
}
haplokuon commented 3 years ago

Only the information from the image is not enough. Like with any other transformation three things are required a scale, a rotation, and a translation. You need to know how the image was created:

  1. The relative scale between the size of the image and the size of the area of the drawing that was converted as an image.
  2. The rotation of the image in relation with the original drawing, if applicable.
  3. The relative origin of the image with the origin of the drawing.

Then you can build a transformation matrix to convert from one coordinate system to another. The only additional thing to take care is that the drawing space is continuous while an image space is discreet (a pixel is the smallest unit), but that can be easily be handled using the resolution of the image (dpi).

srudin commented 1 year ago

Ok, I will try, thx!