Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement DXF Importing #17

Closed
dcowden opened this issue Dec 6, 2018 · 39 comments
Closed

Implement DXF Importing #17

dcowden opened this issue Dec 6, 2018 · 39 comments

Comments

@dcowden
Copy link
Member

dcowden commented Dec 6, 2018

Issue by dcowden
Sunday Dec 11, 2016 at 22:02 GMT
Originally opened as dcowden/cadquery#173


Created from issue #155

@dcowden
Copy link
Member Author

dcowden commented Dec 6, 2018

Comment by dcowden
Friday Nov 24, 2017 at 20:57 GMT


Added a starting point. I have a whole zip file of all of the american steel shapes, and all of the 8020 shapes once we get this going!

@dcowden
Copy link
Member Author

dcowden commented Dec 6, 2018

Comment by RustyVermeer
Tuesday Nov 28, 2017 at 18:21 GMT


I have started poking around with the code in the DXF branch.

The following is a rough start at this only, of course.

import read_dxf as rd
from pointmap import *
import cadquery as cq
from cadquery import *

dwg = rd.import_drawing('tests/1515-ULS.dxf')

base = cq.Workplane('XY')

#add edges
for loop in dwg.get_loops()[0]:
    for e in loop:
        start = dwg.coordinates(e[0])
        startPoint = base.plane.toWorldCoords((start[0], start[1]))
        end = dwg.coordinates(e[1])
        endPoint = base.plane.toWorldCoords((end[0], end[1]))
        edgeData = dwg.edgeData(e)

        if edgeData == {}:
            line = Edge.makeLine(startPoint, endPoint)
            base._addPendingEdge(line)
        else:
            mid = edgeData['arc']
            midPoint = base.plane.toWorldCoords((mid[0], mid[1]))
            arc = Edge.makeThreePointArc(startPoint, midPoint, endPoint)
            base._addPendingEdge(arc)
    base.wire()

base.moveTo(0, 0).center(0, 0)

sorted_wires = sortWiresByBuildOrder(list(base.ctx.pendingWires), base.plane,[])
sorted_wires.reverse()

base2 = cq.Workplane('XY')

for wirelist in (sorted_wires):
    for wire in wirelist:
        print wire
        base2._addPendingWire(wire)

base2.consolidateWires()
base2.extrude(30.0).findSolid().exportStep('dxf_out.step')

What I've done in the above code is:

  • read the dxf in using the import_drawing function
  • set up an empty cq workplane
  • for each loop, add either a line or arc according to the edgeData
  • turn each loop into a wire
  • create a new base workplane with reverse sorted list of wires. This is to (hopefully) guarantee that the largest loop is first in the list. I based this off of the fact that cq.Workplane('XY').circle(10).circle(20).extrude(10) results in 2 cylinders, but cq.Workplane('XY').circle(20).circle(10).extrude(10) results in a tube (what I think most users would expect)

I'm running into a problem with the 1515-ULS.dxf test file though.

image

That is the resulting step file opened in SolidWorks. It's missing the 2 end faces.

Without the center hole, things work as expected:

image

I am unsure how to solve this issue. Does FreeCAD or CQ have a notion of wire orientation?

Or perhaps I am just misusing available functions in CQ? Has this problem been addressed somehow in the extrude functions?

@dcowden
Copy link
Member Author

dcowden commented Dec 6, 2018

Comment by dcowden
Tuesday Nov 28, 2017 at 22:29 GMT


that's a great start. I think your approach is good. sortWiresByBuildOrder should return the outerwire first, but for extrusion i dont think it matters.

I think i see the problem. in the example, the inner contour doesnt look like its closed. The upper-right of the 'star' appears to be missing:

capture

That could be an issue where the last contour is not being closed or whatever?

@dcowden
Copy link
Member Author

dcowden commented Dec 6, 2018

Comment by RustyVermeer
Wednesday Nov 29, 2017 at 01:38 GMT


Sort order does matter, actually. At least, it does for this particular case.

Leaving sort with outer wire later in the list produces (the 'default' output of that function):

image
Every loop was extruded as its own solid, so there are 5 separate solids in that image.

And reversing the sort (with the center 'star' thing filtered out just for this example):

image

As for your suggestion about a missing contour:
Unfortunately, that missing contour is just a graphical error. Here's the same part with a view exactly normal to that face:

image

There is no contour error there. I doubly confirmed that it's not open by extruding ONLY that star center, and it worked correctly:

image

Not sure how to tackle this particular issue. Any insights or ideas of where to look next?

Despite this, it's possible to make a workplane() function that imports DXF and creates wires on the stack, so I'll go forward with that, anyway.

@dcowden
Copy link
Member Author

dcowden commented Dec 6, 2018

Comment by jmwright
Wednesday Nov 29, 2017 at 01:55 GMT


This problem could be related to #83

I'm pretty sure that in some cases there's a glitch in how FreeCAD or OCC sort/order wires and edges. I've never had the time to dig into the FreeCAD internals to see where it comes from though.

@dcowden
Copy link
Member Author

dcowden commented Dec 6, 2018

Comment by dcowden
Wednesday Nov 29, 2017 at 03:06 GMT


Ah i see ok. Well, this is a really really great first try. I'm
disappointed to be running into a glitch, though i guess its a good thing
we started with a complex enough example to bring it to the surface.

I'm pretty sure it doesnt have anything to do with your code-- the solution
is probably inside or around the wire sorting code (sortWiresByBuildOrder).

It appears that when i wrote this, i may have even known this is an issue--
I can't remember writing this, but inside of sortWiresByBuildOrder, i say:

Assume:
The wires make up one or more faces, which could have 'holes'
Outer wires are listed ahead of inner wires
there are no wires inside wires inside wires
( IE, islands -- we can deal with that later on )
none of the wires are construction wires

FreeCAD should be smart enough to nest wires inside each other and figure
things out, but it clearly isnt. My hunch is that FreeCAD is expecting
the order of the edges to be in a particular order, and that it assumes the
normal direction based on that order. The theory would be that the order
of the edges in the 'star' wire are somehow backwards, causing FreeCAD to
think the material direction is in the wrong direction. My comments in
extudeLinear
https://github.com/dcowden/cadquery/blob/master/cadquery/freecad_impl/shapes.py#L846
imply
that I ran into this during development.

To test this theory, I would recommend reversing the order of the edges in
the 'star'. To do this, you can use Wire.assembleEdges() to control the
order of the edges by hand, and see if it magically fixes it. If it does,
that means that to get this to work, we'll have to do the work we expect
FreeCAD to be doing, and manually order the edges and the wires correctly.
That really stinks.

On Tue, Nov 28, 2017 at 8:55 PM, Jeremy Wright notifications@github.com
wrote:

This problem could be related to #83
dcowden/cadquery#83

I'm pretty sure that in some cases there's a glitch in how FreeCAD or OCC
sort/order wires and edges. I've never had the time to dig into the FreeCAD
internals to see where it comes from though.


You are receiving this because you were assigned.
Reply to this email directly, view it on GitHub
dcowden/cadquery#173 (comment),
or mute the thread
https://github.com/notifications/unsubscribe-auth/ABPOA5x7j_wz_cvn-gjLuXaU3M1so6tpks5s7LmMgaJpZM4LKDOf
.

@dcowden
Copy link
Member Author

dcowden commented Dec 6, 2018

Comment by easyw
Wednesday Nov 29, 2017 at 10:36 GMT


Hi @dcowden @jmwright @RustyVermeer
in kicad StepUp to manage this I use the OpenSCAD2Dgeom function 'edgestofaces
face = OpenSCAD2Dgeom.edgestofaces(edges)
here a macro that uses this approach
https://www.freecadweb.org/wiki/Macro_DXF_to_Face_and_Sketch

@dcowden
Copy link
Member Author

dcowden commented Dec 6, 2018

Comment by dcowden
Wednesday Nov 29, 2017 at 11:43 GMT


@easyw thanks a bunch for this! That looks like just what we need.

@dcowden
Copy link
Member Author

dcowden commented Dec 6, 2018

Comment by dcowden
Wednesday Nov 29, 2017 at 11:48 GMT


...oh except I'd rather not import openscad code to solve it... Perhaps we can use the same approach but realized using the embedded occ code.

I think occ has a function that organizes edges as well

@dcowden
Copy link
Member Author

dcowden commented Dec 6, 2018

Comment by easyw
Wednesday Nov 29, 2017 at 12:01 GMT


@dcowden

I think occ has a function that organizes edges as well

please let me know which is in case you find it 😄

@dcowden
Copy link
Member Author

dcowden commented Dec 6, 2018

Comment by dcowden
Wednesday Nov 29, 2017 at 12:19 GMT


@easyw @RustyVermeer

ShapeAnalysisWire and ShapeAnalysisWireOrder are the ones I had in mind:

https://www.opencascade.com/doc/occt-7.0.0/refman/html/class_shape_analysis___wire.html
https://www.opencascade.com/doc/occt-7.0.0/refman/html/class_shape_analysis___wire_order.html

These would fix the problem if it is related to edge ordering. I am not sure they would fix the issue if they are related to wire nesting issues, however.

One other strategy might be to look at the FreeCAD code and see what they do when you extrude a drawing. I suspect that this case would work fine if the objects were imported into a sketch and then the sketch was extrude, so they solve it somehow....

@dcowden
Copy link
Member Author

dcowden commented Dec 6, 2018

Comment by dcowden
Wednesday Nov 29, 2017 at 12:26 GMT


Here is a starting point to get into what's going on in OCC land:

https://github.com/FreeCAD/FreeCAD/blob/master/src/Mod/Part/App/FeatureExtrusion.cpp

In this code you can begin to see the limitations of using OCC. Note on this line how FreeCAD folks have applied a work around to use a copy to work around a problem extruding circles:

https://github.com/FreeCAD/FreeCAD/blob/master/src/Mod/Part/App/FeatureExtrusion.cpp#L260

It looks like they have a dedicated class to make an extrudable face out of wires:

https://github.com/FreeCAD/FreeCAD/blob/master/src/Mod/Part/App/FeatureExtrusion.cpp#L304

https://github.com/FreeCAD/FreeCAD/blob/master/src/Mod/Part/App/FaceMaker.cpp

@dcowden
Copy link
Member Author

dcowden commented Dec 6, 2018

Comment by RustyVermeer
Wednesday Nov 29, 2017 at 14:28 GMT


Hmm... looks like quite the rabbit hole :)

I learned something else, recently while trying your suggestion to change the order of edges.

If I reverse the edge list order, nothing changes and the issue still occurs.
But, if for the troublesome wire I swap the START and END vertices as I build the edge list for that wire, I can successfully create the part.

image

What is still strange to me, though, is that the other 4 internal wires (at the corners) worked without switching start/end vertices. And I checked if the start of one edge aligns with the end of the other. They all do, by default. So, I cannot simply compare one edge's start to the next edge's end, as that doesn't necessarily indicate that 'flipping' the edge is necessary.

@dcowden
Copy link
Member Author

dcowden commented Dec 6, 2018

Comment by adam-urbanczyk
Wednesday Nov 29, 2017 at 17:31 GMT


@dcowden @RustyVermeer @easyw here is an example of sorting wires using OCC:

https://github.com/adam-urbanczyk/cadquery/blob/6d5630c77b80d08b27dea5d722f68c14de0a0895/cadquery/occ_impl/shapes.py#L1384

Maybe you could give it a try?

@RustyVermeer can you export this model as a BREP file? It sounds like there is something wrong with the edges orientation

@dcowden
Copy link
Member Author

dcowden commented Dec 6, 2018

Comment by RustyVermeer
Monday Dec 04, 2017 at 18:15 GMT


@adam-urbanczyk I'm not sure exactly what you'd like? Is there a brep export directly in CQ, or do you want me to save the STEP files from Solidworks out to their wireframe modes?

I recently pushed some changes to the dxf_branch. I appear to have broken some things, unfortunately (still new to most of this stuff).

After cloning to my VPS and fiddling a bit, I was able to get the current dxf function to work as expected.

Essentially I do a check for clockwise or counter clockwise orientations of the edges, and then force all to be CCW. This has so far proven to work for all of the dxf files I've tried. There's still a good chance this isn't perfect, though.

@dcowden
Copy link
Member Author

dcowden commented Dec 6, 2018

Comment by dcowden
Monday Dec 04, 2017 at 18:25 GMT


@adam-urbanczyk do you want a bunch more DXFs to try? And, what are your thoughts about how we can bundle common profiles with CQ?

I have this huge library of standard ANSI sections ( steel tubes, i beams, etc). Seems a shame not to bundle them all into CQ with a cool function that will generate those sections automatically by name

But then again maybe that's best done as a separate module ( plugin )

@dcowden
Copy link
Member Author

dcowden commented Dec 6, 2018

Comment by RustyVermeer
Monday Dec 04, 2017 at 18:36 GMT


I know you asked the other Adam... but I hope I can still answer too :)

I think the dxf import makes sense as part of the CQ core functionality.
Adding all of those dxf files really seems like a plugin type thing to me.

Regardless of that, it might be useful to have them all for testing purposes on my end. Could you help me out with that, @dcowden ?

@dcowden
Copy link
Member Author

dcowden commented Dec 6, 2018

Comment by dcowden
Monday Dec 04, 2017 at 19:00 GMT


Sorry about that-- I meant you but input from all Adams is great.

Tonight i'll make a big zipfile of them all and post them somewhere for you.

@dcowden
Copy link
Member Author

dcowden commented Dec 6, 2018

Comment by easyw
Monday Dec 04, 2017 at 20:53 GMT


may I have those too? 😄
I would like to play with them too

@dcowden
Copy link
Member Author

dcowden commented Dec 6, 2018

Comment by dcowden
Monday Dec 04, 2017 at 21:15 GMT


@easyw sure thing!

@dcowden
Copy link
Member Author

dcowden commented Dec 6, 2018

Comment by dcowden
Monday Dec 04, 2017 at 21:16 GMT


@easyw @adam-urbanczyk @RustyVermeer @jmwright
i think it would be really cool if we can couple the new dxf stuff with robust ( and user-contributable) repo of standard DXFs.

@dcowden
Copy link
Member Author

dcowden commented Dec 6, 2018

Comment by RustyVermeer
Tuesday Dec 05, 2017 at 01:12 GMT


Would your idea be as simple as creating a github repo full of dxf files and calling it a day?
Or would there be additional 'machinery' you'd like built around it?

@dcowden
Copy link
Member Author

dcowden commented Dec 6, 2018

Comment by dcowden
Tuesday Dec 05, 2017 at 02:06 GMT


@RustyVermeer @easyw @adam-urbanczyk @jmwright
Ok guys made a quick repo with all my DXFs-- enjoy!

https://github.com/dcowden/dxf

@dcowden
Copy link
Member Author

dcowden commented Dec 6, 2018

Comment by adam-urbanczyk
Wednesday Dec 06, 2017 at 20:57 GMT


@RustyVermeer You can import/export a .brep file using CQ (both in FreeCAD and OCC backends), which is an OCC-specific lossless format. That is what I meant.

@dcowden Yeah would be nice to have those bundled with CQ. BTW: do you know https://github.com/jreinhardt/BOLTS ?

@adam-urbanczyk
Copy link
Member

@RustyVermeer what is the status of the DXF branch? IS it worth trying to integrate it into CQ2.0?

@dumblob
Copy link

dumblob commented Nov 28, 2019

@RustyVermeer I'd be also interested in the status - can I/someone be of any help?

@jmwright
Copy link
Member

@dumblob I haven't seen @RustyVermeer on GitHub for a long time, and his activity graph doesn't show anything for over a year. All the DXF import work was done only on the CQ 1.0 (FreeCAD based) repo. I think it's probably safe if you wanted to start working on this issue on your own.

Here's the relevant branch and a relevant directory from CQ 1.0, but since it was written to run on top of FreeCAD, I'm not sure how much of it you'd be able to re-use. The readme in the directory gives some background on what Rusty was doing.

@adam-james-v
Copy link

adam-james-v commented Nov 28, 2019

I'll apologize up front for my silence and inactivity.

To get directly to it: This is not something I have maintained, nor is it something I have the ability to work on. @jmwright is correct to point out that things have advanced quite a bit beyond my work, and I can't say how well this will mesh with the latest work.

A bit of honesty:
I bit off more than I could chew with this, and got intimidated and scared. Instead of admitting this up front, I 'ghosted' the issue and have avoided things for some time. I must admit I'm ashamed of this choice. I consider it a big mistake, and I do apologize.

Stewardship of open source work is (as I'm learning) critically important, and I've failed on that front.
@dumblob I'm very sorry to disappoint. At this point, the help people can give is to approach it themselves.

Edit: didn't finish a sentence...

@adam-urbanczyk
Copy link
Member

@RustyVermeer take it easy. Even if unfinished, your work is greatly appreciated!

@jmwright
Copy link
Member

@RustyVermeer Thanks for all your contributions. Don't beat yourself up about it.

@dumblob
Copy link

dumblob commented Nov 29, 2019

@RustyVermeer no disappointment on my side. It's totally normal and an inevitable part of open source work to approach it rather "dynamically" when it comes to personal life and priorities 😉. Cheer up and don't be ashamed. Great work you've done.

@adam-james-v
Copy link

Thanks for the support everyone. I am glad to know that there's value in the work :)

I do hope that CadQuery can continue to grow and gain interest, it's certainly a great project!

@greyltc
Copy link
Contributor

greyltc commented Apr 28, 2020

I wonder if something like this https://github.com/mozman/ezdxf could be integrated

@jmwright
Copy link
Member

@greyltc Wow, that's a really interesting option. Thanks for posting it.

@adam-urbanczyk
Copy link
Member

BTW this is what @RustyVermeer was trying to integrate. If you want to pick this up @greyltc we'll definitely merge it.

@greyltc
Copy link
Contributor

greyltc commented Apr 28, 2020

Oh! Woops! I didn't realize his work was ezdxf based.

@adam-urbanczyk
Copy link
Member

If anyone is interested I added some preliminary dxf importing capabilities to the OCD-dxf branch (https://github.com/CadQuery/cadquery/tree/OCP-dxf). Feedback is welcome!
obraz

@dcowden
Copy link
Member Author

dcowden commented May 10, 2020 via email

@adam-urbanczyk
Copy link
Member

Solved by #372

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

6 participants