The SVG to DXF conversion breaks the scaling of the shapes

Hello,

So our app has been using the SVG to DXF conversion for some months now, with success.
Despite the conversion working, the customers came out to us complaining about the scaling of the DXF files.

There is indeed a scaling problem in the resulting DXF. The distances are not the same as is the PDF. We tried to play with the zoom/viewBox but the scaling of the result DXF file seems very inconsistent. Even deleting an element to simplify the SVG gave me some different scaling.

Here is a picture of the input SVG, which only contains a 400x300mm green rectangle:
image.png (79.6 KB)

Here is the output DXF from your service, and you can see the measure shows wrong results (quite a big difference for this occurrence):
image.png (112.7 KB)

Just for the extra information, here is the exact same SVG file but without the “width” and “height” in the SVG tag, and the DXF output still show a different measure:
image.png (111.8 KB)

Our app is a very precise construction dimensioning. As it is currently in production, we can’t afford to provide that kind of DXF export. We need either a quick workaround or a quick fix, or we’ll need to consider converting the DXF ourselves :'(.

Hopefully we can find a solution together. Good luck with this one.

@Ancotech

Can you please provide the code or method you are using for the SVG to DXF conversion? Additionally, what version of the Aspose.CAD library are you using?

Our production app is using aspose-cad-cloud v24.5.2 for Java, but the results are equally inconsistent with your online tool.

@Ancotech,
Hi.
Preserving physical dimensions during conversions is tricky because of differences between formats. If we are not mistaken, the default units for SVG are pixels, we don’t see mm units after brief looking at your file, so it seems for this example we are talking about 400x300 pixels. Let us check if we can do such conversion and come back with more information. It could be helpful for us if you can attach the DXF options you are using on your side for conversion.

@Ancotech,
Hello,
we need your further clarifications on the problem.

  1. SVG has pixels units by default, but separate units could be set for specific paths there.
  2. DXF R12 which is the result of export has no units by specification (but inches are often assumed as from practice).
  3. As we can guess now you understand the SVG values in mm and measure the result DXF in millimeters also, expecting to see the value 400 as is the initial SVG, is that right?

Could you please attach the initial SVG file and the desired DXF file for it, so we can see exactly what is the required solution for you (the current DXF result could be helpful as well).

Hi,

Thank you for your quick answer as always. I am indeed not familiar with SVG units, and am currently trying to catch up.

You guess right, we generate our SVG with the default unit but it’s supposed to represent millimeters.

Here are some samples for you to work with:
SVG-to-DXF-examples.zip (281.4 KB)

So here you will have 3 cases:

  • the most simple version of the generated SVG from our app
  • an overly simplified version of the same SVG
  • the latter, but with “mm” unit specified in the “width” and “height” of the svg tag (which shows that I indeed don’t get how this works)

Each case have the SVG input, the DXF output, and a screenshot of the measurement.

The expected output would be to have a measure of 400mm for the longer side of the green rectangle. I can’t provide that since it’s what I’m trying to achieve.

I will be investigating SVG unit while waiting for your answer and will post something here if I find a solution. Besides that, any kind of workaround would help a lot.

Thank you.

@Ancotech,
could you please test on your side if the attached files have the desired sizes.
DXF.zip (89.4 KB)

Hello again!

So the DXF fils you provided are not showing the right measure BUT they are showing the same measure for the same distance between the files:

outputs.zip (181.8 KB)

It already really good news to have some kind of consistency. If this reflects a solution you have, that could allow my team to work with some kind of ratio.

What did you change to get thoses ?

@Ancotech,
let us get the desired result, could you please evaluate the next attempt :slight_smile:
DXF2.zip (78.7 KB)

We are trying to set up such export options that will avoid scaling and preserve the required units.

1 Like

Those all look great! It’s exactly what we expect. How did you proceed? Do we wait for an update of the service?

@Ancotech,
So, the idea is to preserve size and units. The DXF R12 has no units and the viewer assumes they are inches.

To make conversion without scaling it is required to set up PageHeight and PageWidth export options to be the same as the initial size of SVG file. So firstly we do the request to get start sizes, e.g., via:

PostDrawingPropertiesRequest getProperties = new PostDrawingPropertiesRequest();
getProperties.DrawingData = System.IO.File.OpenRead(fileName);

CadResponse responseStreamProperties = api.PostDrawingProperties(getProperties);

double initialHeight = (double)responseStreamProperties.Height;
double initialWidth = (double)responseStreamProperties.Width;

During testing we found some internal losing of precision (not exactly losing, but likely some settings to preserve gaps around the result of export) during processing that could be important for you. We were able to calculate the correction, so you need to multiply old sizes by this factor to get more precise results. Feel free skip it if results are OK without this.

double ratio = 1 / 0.9923130037;
double newWidth = (initialWidth * ratio);
double newHeight = (initialHeight * ratio);

Finally, you need to perform export request passing desired sizes and millimeter as units, for instance, like this:

PutDrawingDXFRequest request = new PutDrawingDXFRequest();
request.DrawingData = System.IO.File.OpenRead(fileName);
request.ExportOptions = @"{""VectorRasterizationOptions"": { ""PageHeight"":"
+ newHeight.ToString(System.Globalization.CultureInfo.InvariantCulture) + @",""PageWidth"":" + newWidth.ToString(System.Globalization.CultureInfo.InvariantCulture) + @", ""UnitType"": ""Millimeter"" }}";

var responseStream = api.PutDrawingDXF(request);

The last one note is about files with mm in sizes. Unfortunately, you need to know this in advance - the sizes of SVG drawing are recalculated to pixels at loading and the initial measurement units are not available. For this case it is required to take into account the scaling also:

// 1 mm = 3.7795275591 pixel(X)

double mmToPixels = 3.7795275591;

double ratio = 1 / 0.9923130037;
double newWidth = (initialWidth * ratio / mmToPixels);
double newHeight = (initialHeight * ratio / mmToPixels);

Please try if this is useful in your side.

First, the file with the mm in sizes was just here for testing purposes. I actually put the “mm” inside by hand just to see if it was easier for you to handle. It’s not needed to work with that.

Long story short, your solution seems to work just fine.

Just one thing: I said I was working with Java and you provided a solution in C#. Luckily I happen to have experience in both, but it took me some time not notice what was wrong. Be carefull to warn next time ^^.

This is the Java code snippet, for those who might be interested:

  public String convert(String fileContent) throws Exception {

      String APP_KEY = System.getenv("ASPOSE_APP_ID");
      String APP_SECRET = System.getenv("ASPOSE_APP_SECRET");

      CadApi cadApi = new CadApi(APP_SECRET, APP_KEY);

      byte[] localInputImage = fileContent.getBytes();

      PostDrawingPropertiesRequest properties = new PostDrawingPropertiesRequest(localInputImage);
      CadResponse responseStreamProperties = cadApi.postDrawingProperties(properties);

      Double ratio = 1 / 0.9923130037; // ASPOSE ratio to removes the margin
      Double actualHeight = (double)responseStreamProperties.getHeight() * ratio;
      Double actualWidth = (double)responseStreamProperties.getWidth() * ratio;

      String exportOptions = String.format(
          """
          { "VectorRasterizationOptions": {
              "PageHeight": "%f",
              "PageWidth": "%f",
              "UnitType": "Millimeter"
          }}
          """, actualHeight, actualWidth);
      PutDrawingDXFRequest request = new PutDrawingDXFRequest(
          localInputImage,
          null,
          exportOptions,
          null);

      return new String(cadApi.putDrawingDXF(request));
  }

Anyway, elegant solution, thank you very much on behalf of the whole team!

Hi again!

After some tests, we noticed that strange behavior that remains:
image.png (83.6 KB)

The measure are obviously similar yet the numbers are very different. Any idea what might cause that?

@Ancotech,
please accept my apologies for the confusion with the programming language, searching for solution went too beyond the language :slight_smile:

I tested few files (without any conversion and from different sources) and found such behavior for all of them. Looks like measuring of empty space goes using some other measurement units or scale. Did not find any pattern or possible explanation at first glance.