Pattern-Projector / pattern-projector

https://www.patternprojector.com/
MIT License
88 stars 19 forks source link

DXF support #58

Closed j-huff closed 8 months ago

j-huff commented 9 months ago

It might be nice add DXF support. Possibly using this npm package: https://github.com/vagran/dxf-viewer

courtneypattison commented 9 months ago

I've never heard of DXF before, lol. What would we want it for?

j-huff commented 9 months ago

I've never heard of DXF before, lol. What would we want it for?

"DXF is short for Drawing Exchange Format or Drawing Interchange Format and is a type of vector file. Engineers, designers and architects often use the DXF format for 2D and 3D drawings during product design."

Basically it's really easy to export DXF files from CAD programs, and very difficult to export PDF files, especially when the drawing is larger than standard letter paper. I'm most comfortable creating technical drawings using CAD (Fusion 360 specifically).

This is obviously a moonshot sort of feature request, as I'm sure it's not the easiest thing to implement. Do you have any suggestions for pattern design software that makes it easy to export large format PDFs?

hluedeke commented 9 months ago

Do you have any suggestions for pattern design software that makes it easy to export large format PDFs?

Is DXF the only file format your design software supports? Can you export to svg?

I think Inkscape might be able to open dxf files, though I’ve never tried it. Maybe give that a shot?

j-huff commented 9 months ago

I found a workaround by converting it using DWG TrueView.

Rather than fully integrating DXF support, you could add a sort of automatic conversion. This would be easiest done server-side. When the user selects a file in a format other than a PDF, it gets uploaded to the server, converted to PDF, and sent back to application to render. This would allow for easy integration of a variety of file formats.

For now, I just wrote a simple python script for converting DXF files to PDF:

import argparse
import ezdxf
from ezdxf.addons.drawing import Frontend, RenderContext, pymupdf, layout, config

def inches_to_mm(inches):
    return inches * 25.4

def dxf_to_pdf(input_name, output_name, margin_inches=1, lineweight_scaling=5.0):

    doc = ezdxf.readfile(input_name)
    # Recommended: audit & repair DXF document before rendering
    auditor = doc.audit()
    # The auditor.errors attribute stores severe errors,
    # which *may* raise exceptions when rendering.
    if len(auditor.errors) != 0:
        raise exception("The DXF document is damaged and can't be converted!")

    msp = doc.modelspace()
    # 1. create the render context
    context = RenderContext(doc)
    # 2. create the backend
    backend = pymupdf.PyMuPdfBackend()
    # 3. create the frontend
    cfg = config.Configuration(background_policy=config.BackgroundPolicy.WHITE, lineweight_scaling=lineweight_scaling)
    frontend = Frontend(context, backend, config=cfg)
    # 4. draw the modelspace
    frontend.draw_layout(msp)
    ## 5. Auto-detect layout size with margin
    margin = inches_to_mm(margin_inches)
    page = layout.Page(0, 0, layout.Units.mm, margins=layout.Margins.all(margin))

    # 6. get the PDF rendering as bytes
    pdf_bytes = backend.get_pdf_bytes(page)
    with open(output_name, "wb") as fp:
        fp.write(pdf_bytes)

def main():
    # Set up argument parser
    parser = argparse.ArgumentParser(description='Convert DXF files to PDF.',
            formatter_class=argparse.ArgumentDefaultsHelpFormatter)
    parser.add_argument('input_filename', type=str, help='The input DXF file')
    parser.add_argument('output_filename', type=str, help='The output PDF file')
    parser.add_argument('-m','--margin', type=float, help='The margin to add (inches)', default=1)
    parser.add_argument('-l','--line-weight', type=float, help='Scaling factor for line weight', default=5)
    args = parser.parse_args()

    # Convert the DXF file to a PDF
    dxf_to_pdf(args.input_filename, args.output_filename, args.margin, args.line_weight)

if __name__ == '__main__':
    main()
hluedeke commented 9 months ago

I’m glad you were able to find a workaround.

When the user selects a file in a format other than a PDF, it gets uploaded to the server

Believe it or not, this application doesn’t have an API - your file upload stays 100% on the client.

hluedeke commented 9 months ago

That being said, I think the client-only processing is intentional, particularly because this app is a progressive web app that allows the user to download it and use it offline if they want. This isn’t well documented (yet) but we plan to have a “download as an app” button here in the near future.

I’d be interested to see what the demand for other file formats is. So far you’re the first to request anything other than pdf.

PS. Thanks for sharing your code! You certainly didn’t have to!

roel-v commented 9 months ago

CAD software (I'm thinking AutoCAD here specifically, where DXF originated, but also all other CAD software I've ever worked with) has great PDF export support. In fact the main use case for AutoCAD in architectural firms is to create A0 PDFs that can be send off to a print shop (some larger firms may still have their own large size plotters like in ye olde days, but I haven't seen one myself in many years). In AutoCAD you create a 'layout' into which you put viewports into your model, and the software will take care of sizing. You'll want to set the sizing to 100% for sewing patterns of course.

Apart from that, you can use open source software like Inkscape to convert from DXF to PDF, or in a pinch even GIS software like QGIS. They all have explicit 'sizing in real world units' support which is the most tricky issue when converting between digital formats (like are margins included in your size settings etc). No need for custom programming.

courtneypattison commented 9 months ago

If we plan on adding editing to PP in the future, I think looking into using DXF or another CAD format would be a great idea.

j-huff commented 9 months ago

...but also all other CAD software I've ever worked with) has great PDF export support.

Not the free version of Fusion 360. Furthermore, for some patterns, A0 might not be large enough for 1:1 scale.

The point of the DXF to PDF script was not that it is actually required to get the result I want, but rather that it's easier and more consistent. Exporting to DXF files directly from sketches is very simple.

j-huff commented 9 months ago

Believe it or not, this application doesn’t have an API - your file upload stays 100% on the client.

Oh yeah I'm completely aware that the app is client side. In fact I almost mentioned that it might be an optional thing to enable so that the demo wouldn't have to support it.

edit: I understand now though that it's probably not worth changing the entire design philosophy of your app just to meet the whims of a handful of people.

courtneypattison commented 9 months ago

...but also all other CAD software I've ever worked with) has great PDF export support.

Not the free version of Fusion 360. Furthermore, for some patterns, A0 might not be large enough for 1:1 scale.

Ah, that sucks. I don't know much about PDFs, but I don't think they're limited to A0 sizing. They can be much larger than that. Not that I like PDFs, gosh I'm so frustrated with them right now.

I understand now though that it's not worth changing the entire design philosophy of your app just to meet the whims of a handful of people.

I would like to keep this site completely client side. For offline support and really just to keep things simple and maintainable. That doesn't mean that we can't have DXF support. As you mentioned earlier, there's a client side DXF viewer we could pop in the replace pdfjs for DXF files. Maybe lazily load it in so it doesn't affect the majority of people who just use PDF. That being said, getting PDFs working well has been difficult and I'm overwhelmed with other priorities. Would you be interested in making a PR to support DXF? Or even forking the project for a DXF version of PP. I'd love to see it!

j-huff commented 9 months ago

Ah, that sucks. I don't know much about PDFs, but I don't think they're limited to A0 sizing.

This was less a comment about limitations of PDF as a format and more about the limitations of the CAD software that I've used. I'm sure there are ways to get CAD software to output larger formats, but when I tried (in AutoCAD) it wasn't obvious how to do so. Maybe with enough tinkering there's a way. But this is the exact reason why I'm annoyed at the CAD software's PDF export functionality. It shouldn't be frustrating but it is (at least more me, maybe I'm just impatient).

Would you be interested in making a PR to support DXF? Or even forking the project for a DXF version of PP. I'd love to see it!

I'll think about it. I don't really have a good development environment at home right now and haven't done front-end development in many years. I feel like I'd be more drawn to forking it and adding server-side functionality for stuff like storing and managing patterns. The format converter would be a nice bonus here. I feel like it would be much less maintainable for the front-end to be capable of displaying a bunch of different formats. I'm much more comfortable with writing APIs than doing front-end stuff, so if anyone is interested in going down that route with me I'd be happy to collaborate.

courtneypattison commented 9 months ago

AutoCAD sounds frustrating! I think you're right that adding multi format support would less maintainable and server side functionality is out of scope for this project. If you do decide to fork and work on your proposal, that would be awesome. I'm already swamped with this project right now though so I wouldn't be able to help.