I'd like to make it as easy to use the router from a 2D input shape (often in DXF form, sometimes SVG) as it is to use a laser cutter. This capability would get a lot of immediate use where I work, and would allow me to shut down a different project that did a similar thing in javascript in the browser: https://bitbucket.org/goatchurch/laserplacer/
The very basic Path workbench features has all the necessary cutting of shapes, tabs dressup, etc.
So, I'm looking at the DXF importing feature, because that's how a lot of the shapes are supplied.
The problems I've found with the current implementation are:
(1) The colour property is lost from all the geometry. You don't get to assign certain colour to be of construction type in the sketcher.
(2) The geometry is individually listed in the model tree as well as in the sketch.
(3) None of the points are joined by constraints (eg at the endpoints) so it is impossible to pad the sketch into a solid shape in the Part Design workbench.
The issue of the C++ and the "legacy" python DXF importer is discussed here: https://forum.freecadweb.org/viewtopic.php?f=3&t=32493
(And it seems the C++ importer doesn't have the import into a sketch feature.)
The code that is doing the importing is here:
https://github.com/FreeCAD/FreeCAD/blob ... portDXF.py
What seems to happen is that line 1059 calls dxfReader.readDXF(filename), which parses the contents of the dxf file into a list of objects, and then we iterate through this list (by type) and call a series of FC functions to inject the geometry into the document.
Now, I think the base DXF parsing could be replaced with https://github.com/mozman/ezdxf because that library is getting a great deal of development, has the right license, and is being done by a single-minded developer who has no other distractions from making it perfect. (He comprehensively stomped my bug reports in the past, like this one https://github.com/mozman/dxfgrabber/issues/12 .)
So, the main thing to look at is how the importer then injects the geometry I need into FC.
Take the example of importing a square (four lines) into FC with the Sketch option.
My reading of the code suggests that the following is implemented:
Code: Select all
# You can try this in the Python console
import FreeCAD, Draft
doc = FreeCAD.getDocument("Unnamed")
l1 = Draft.makeWire([(10,10,0), (10,30,0)])
sh1 = Draft.makeSketch(l1, autoconstraints=True)
sketch = sh1
l2 = Draft.makeWire([(10,30,0), (30,30,0)])
sh2 = Draft.makeSketch(l2, autoconstraints=True, addTo=sketch)
l3 = Draft.makeWire([(30,30,0), (30,10,0)])
sh3 = Draft.makeSketch(l3, autoconstraints=True, addTo=sketch)
l4 = Draft.makeWire([(30,10,0), (10,10,0)])
sh4 = Draft.makeSketch(l4, autoconstraints=True, addTo=sketch)
We could avoid leaving the model list clutted by including:
Code: Select all
doc.removeObject(l1.Name)
doc.removeObject(l2.Name)
doc.removeObject(l3.Name)
doc.removeObject(l4.Name)
Luckily the Python console when running the Sketcher gives a lot of feedback, so it appears you can do it like so:
Code: Select all
from FreeCAD import Vector
sketch = Draft.makeSketch([])
sketch.addGeometry(Part.LineSegment(Vector(10,10,0), Vector(10,30,0)))
sketch.addGeometry(Part.LineSegment(Vector(10,30,0), Vector(30,30,0)))
sketch.addGeometry(Part.LineSegment(Vector(30,30,0), Vector(30,10,0)))
sketch.addGeometry(Part.LineSegment(Vector(30,10,0), Vector(10,10,0)))
Code: Select all
sketch.toggleConstruction(2)
As for (3), maybe there is a feature outside of the importer that can apply to any sketch called "infer constraints" which will nail down any coincident nodes, and perhaps any tangencies in the way the arcs join.
It would be useful to be able to drag the shapes around the screen into position on the stock without them distorting or falling apart. This could be done by generating one point in the middle with a set of relative constructive rays coming out from it with fixed length and angle that nails down all the end points.
I guess this is the equivalent of wanting to import in a "dumb solid" from a different 3D CAD package, when you can't have all the constructive operations. This is my idea of a "dumb contour" that holds its shape, but isn't very editable. Can it exist in the Sketcher, or does it need hacking in (like putting a constructive ray to each point)?
In the meantime, it seems that the joining constraints can go in like:
Code: Select all
sketch.addConstraint(Sketcher.Constraint('Coincident',0,1,3,2))
sketch.addConstraint(Sketcher.Constraint('Coincident',0,2,1,1))
sketch.addConstraint(Sketcher.Constraint('Coincident',1,2,2,1))
sketch.addConstraint(Sketcher.Constraint('Coincident',2,2,3,1))
doc.recompute()
Am I on the right track here?
I hope to implement it in a fairly clean macro to achieve my requirements (that is joining all the contours and islands into connected objects and separating the etching lines from the cutting lines). How does FC handle a dependency on an outside Python library, like ezdxf?