Skip to content
This repository has been archived by the owner on Feb 9, 2021. It is now read-only.

Implement DXF Importing #173

Closed
dcowden opened this issue Dec 11, 2016 · 25 comments
Closed

Implement DXF Importing #173

dcowden opened this issue Dec 11, 2016 · 25 comments

Comments

@dcowden
Copy link
Owner

dcowden commented Dec 11, 2016

Created from issue #155

dcowden added a commit that referenced this issue Nov 24, 2017
@dcowden
Copy link
Owner Author

dcowden commented Nov 24, 2017

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 dcowden assigned dcowden and unassigned dcowden Nov 24, 2017
@adam-james-v
Copy link
Collaborator

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
Owner Author

dcowden commented Nov 28, 2017

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?

@adam-james-v
Copy link
Collaborator

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.

@jmwright
Copy link
Collaborator

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
Owner Author

dcowden commented Nov 29, 2017 via email

@easyw
Copy link

easyw commented Nov 29, 2017

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
Owner Author

dcowden commented Nov 29, 2017

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

@dcowden
Copy link
Owner Author

dcowden commented Nov 29, 2017

...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

@easyw
Copy link

easyw commented Nov 29, 2017

@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
Owner Author

dcowden commented Nov 29, 2017

@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
Owner Author

dcowden commented Nov 29, 2017

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

@adam-james-v
Copy link
Collaborator

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.

@adam-urbanczyk
Copy link
Contributor

@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

@adam-james-v
Copy link
Collaborator

@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
Owner Author

dcowden commented Dec 4, 2017

@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 )

@adam-james-v
Copy link
Collaborator

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
Owner Author

dcowden commented Dec 4, 2017

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.

@easyw
Copy link

easyw commented Dec 4, 2017

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

@dcowden
Copy link
Owner Author

dcowden commented Dec 4, 2017

@easyw sure thing!

@dcowden
Copy link
Owner Author

dcowden commented Dec 4, 2017

@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.

@adam-james-v
Copy link
Collaborator

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
Owner Author

dcowden commented Dec 5, 2017

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

https://github.com/dcowden/dxf

@adam-urbanczyk
Copy link
Contributor

@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 ?

@dcowden
Copy link
Owner Author

dcowden commented Dec 6, 2018

This has been closed in favor of the CQ 2.0 implemention at https://github.com/cadquery/cadquery

@dcowden dcowden closed this as completed Dec 6, 2018
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

5 participants