Add alternative algorithms for Part.makeOffset2D

Merged, abandoned or rejected pull requests are moved here to clear the main Pull Requests forum.
realthunder
Veteran
Posts: 2190
Joined: Tue Jan 03, 2017 10:55 am

Add alternative algorithms for Part.makeOffset2D

Post by realthunder »

Pull request link: https://github.com/FreeCAD/FreeCAD/pull/414

OCC BRepOffsetAPI_MakeOffset seems to be able to deal with 3D wire offset on non-planar faces. However, its algorithm is not well documented, overly complicated, and buggy. Part.makeOffset2D only deals with co-planar 2D objects, which requires a much more simplified algorithm. This commit adds two alternative algorithms provided by libarea (currently part of Path Mod) to do the 2D offset. libarea, from HeeksCNC, in turn, uses the execllent and well documented ClipperLib to do the actual work.

An extra parameter, algo, is added to Part.makeOffset2D to select the algorithm,
  • 0 = OCC BRepOffsetAPI_MakeOffset
  • 1 = libarea's own MakeLoop for offset, and ClipperLib::Clipper to clean the edge
  • 2 = Same as above, but without final Arc fitting (mostly for debugging purpose)
  • 3 = use libarea's wrapping of ClipperLib::ClipperOffset
  • 4 = Same as above, but without final Arc fitting (mostly for debugging purpose)
Other changes to Part.makeOffset2D,
  • Allow FaceMaker to fail, and return a wire compound for debugging purpose.
  • Unify all faces created by FaceMakerBullsEye and return a single face shape if the use pass in a single input face.
If this patch works well, I'd recommend to make libarea the default handler for makeOffset2D. In fact, I'd suggest to move libarea to Part Mod, since Path Mod only use libarea python bindings, not C++. And let Part Mod use libarea to handle all 2D (faces, wires) only operations, like fuse, cut, etc, which FreeCAD can't handle right now.

Here are some pictures showing OCC's problem, and what libarea/ClipperLib is capable of. I currently goal is investigate the possibility of doing PCB milling using FreeCAD. The test file is in the attachment. The test FACE is extracted from a PCB, partly shown below,
2.png
2.png (14.52 KiB) Viewed 4004 times
First, to make it clear, this is not a compound, but a single FACE. If it were a compound, makeOffset2D will offset each face individually, and won't fuse the result afterwards. FreeCAD can't do FACE fusing at the moment AFAIK.

When doing an offset of 0.1, BRepOffsetAPI_MakeOffset failed to construct a proper face, showing only individual vertexes, as shown below,
8.png
8.png (7.35 KiB) Viewed 4004 times
After investigating, it seems that BRepOffsetAPI_MakeOffset somehow has flipped certain edges. After adjusting those edges, it was able to construct the face. If that's all the problem, I won't go further. However, BRepOffsetAPI_MakeOffset crashes for offset beyond 0.1. It seems BRepOffsetAPI_MakeOffset can't handle faces with inner faces. So I removed those inner faces. And it now produces result with intersected edges. To fix that problem, one might as well wrote a 2D offset algorithm from scratch, which at its core is to determine and eliminate intersected offset edges. This is when I decide to abandon BRepOffsetAPI_MakeOffset.
7.png
7.png (13.93 KiB) Viewed 4004 times
Now, libarea is able to do 0.1, 0.2, and 0.3 without any problem. Here is three offset result super imposed together. Note that each offset result is also a single FACE, not compound, which makes it trivial to convert to Path for milling. Path Mod is already using libarea for pocketing, but still uses makeOffset2D to do profiling. My patch shall greatly simplify isolation routing using FreeCAD.
6.png
6.png (16.14 KiB) Viewed 4004 times
Attachments
makeOffset2D.fcstd
(325.61 KiB) Downloaded 79 times
Try Assembly3 with my custom build of FreeCAD at here.
And if you'd like to show your support, you can donate through patreon, liberapay, or paypal
ickby
Veteran
Posts: 3116
Joined: Wed Oct 05, 2011 7:36 am

Re: Add alternative algorithms for Part.makeOffset2D

Post by ickby »

I don't have much insight into libarea/clipper, but I always thought that they work on polygonial data? And if not, if they work with curves, do they support all 2d geometrie FreeCAD supports, like elipses, splines, parabols and all kind of conics?
And let Part Mod use libarea to handle all 2D (faces, wires) only operations, like fuse, cut, etc, which FreeCAD can't handle right now. FreeCAD can't do FACE fusing at the moment AFAIK.
It can. There is a warning popping up when done from gui, but it works, and in latest occ versions rather well.
wmayer
Founder
Posts: 20319
Joined: Thu Feb 19, 2009 10:32 am
Contact:

Re: Add alternative algorithms for Part.makeOffset2D

Post by wmayer »

Using libarea in Part is problematic because it depends on boost-python. Now on Windows it's a major pita to get the debug version of boost-python working correctly.

Therefore it would be good to avoid to directly link libarea from the Part module but rather access it via its Python interface. Of course this wouldn't solve the actual problem but at least it avoids the instant crash when loading the Part module and the crash will only happen when using the libarea based offset algorithm.
User avatar
DeepSOIC
Veteran
Posts: 7896
Joined: Fri Aug 29, 2014 12:45 am
Location: used to be Saint-Petersburg, Russia

Re: Add alternative algorithms for Part.makeOffset2D

Post by DeepSOIC »

realthunder wrote:First, to make it clear, this is not a compound, but a single FACE.
How on earth is that possible? Is such "face" valid?

EDIT: noticed the attached project. So I opened it, and the face failed geometry check ("invalid imbrication of wires", whatever that means :roll: ).
multi-island face is invalid.png
multi-island face is invalid.png (56.36 KiB) Viewed 3935 times
realthunder
Veteran
Posts: 2190
Joined: Tue Jan 03, 2017 10:55 am

Re: Add alternative algorithms for Part.makeOffset2D

Post by realthunder »

ickby wrote:I don't have much insight into libarea/clipper, but I always thought that they work on polygonial data? And if not, if they work with curves, do they support all 2d geometrie FreeCAD supports, like elipses, splines, parabols and all kind of conics?
Clipper works with polygon and poly line only. libarea is able to discretize arcs, feed to clipper and then fit back arcs. I added code to discretized other type of curves, but no way to fit them back, although libarea will still try to fit them back with arcs if possible. I think arc alone is already usable. When OCC does boolean operation, it also breaks curves with all sorts of fitting. In fact, if OCC happens to fit a broken curve with something other than arc, that curve is not usable by sketch as external geometry.
ickby wrote: It can. There is a warning popping up when done from gui, but it works, and in latest occ versions rather well.
Well, FreeCAD can fuse a bunch of faces, and it produces more faces as a result, which is really of no use here. The one operation I am really looking for is removeSplitter, to actually merge a bunch of faces into one. I know there are ways to do it indirectly, by extruding the faces, fuse, removeSplitter, and then extract the base face. This is how I get the PCB single face in the project file. I haven't used other boolean operations on face, so can't comment. But for face fuse here. Doing solid multiFuse using OCC and then removeSplitter is more than 100 times slower than doing it using Clipper, not to mention that Clipper is much more robust than OCC in this regard.
Last edited by realthunder on Wed Jan 04, 2017 3:01 am, edited 1 time in total.
Try Assembly3 with my custom build of FreeCAD at here.
And if you'd like to show your support, you can donate through patreon, liberapay, or paypal
realthunder
Veteran
Posts: 2190
Joined: Tue Jan 03, 2017 10:55 am

Re: Add alternative algorithms for Part.makeOffset2D

Post by realthunder »

wmayer wrote:Using libarea in Part is problematic because it depends on boost-python. Now on Windows it's a major pita to get the debug version of boost-python working correctly.

Therefore it would be good to avoid to directly link libarea from the Part module but rather access it via its Python interface. Of course this wouldn't solve the actual problem but at least it avoids the instant crash when loading the Part module and the crash will only happen when using the libarea based offset algorithm.
There are only two files in libarea that provides the binding using boost-python, a rather simple binding. Removing these two files is straight forward, or just split the two files and make a libarea-python library. All other part are C++ only. The way I see it, it will be better if we can provide our own binding, such that other part of FreeCAD can operate directly on FreeCAD 2D objects with a more robust algorithm. And I think Part TopoShape is the place to provide such function implicitly rather than requiring user to explicitly choose a whole different module. Path related operation can exposed through Path Mod of course.
Try Assembly3 with my custom build of FreeCAD at here.
And if you'd like to show your support, you can donate through patreon, liberapay, or paypal
realthunder
Veteran
Posts: 2190
Joined: Tue Jan 03, 2017 10:55 am

Re: Add alternative algorithms for Part.makeOffset2D

Post by realthunder »

DeepSOIC wrote:How on earth is that possible? Is such "face" valid?
Well, it can extrude and everything :) The reason I made it this way is to avoid changing makeOffset2D's current logic too much. makeOffset2D will do offset separately on combo faces, and FreeCAD has no easy way to merge multiple faces, so the result is not really useful. In clipper, it can offset non intersecting faces collectively, and the result is automatically merged into non intersecting faces as well. Intersecting faces will need to be offset separately , and the result can be easily merged into non intersecting faces with clipper. So a better change is to let makeOffset2D use clipper to merge the final output before return. A even better one IMO, is to add face merging using clipper directly into TopoShape. I am seeking comments here to see what direction to go.
Try Assembly3 with my custom build of FreeCAD at here.
And if you'd like to show your support, you can donate through patreon, liberapay, or paypal
ickby
Veteran
Posts: 3116
Joined: Wed Oct 05, 2011 7:36 am

Re: Add alternative algorithms for Part.makeOffset2D

Post by ickby »

libarea is able to discretize arcs, feed to clipper and then fit back arcs. I added code to discretized other type of curves, but no way to fit them back
Ok, this is a major drawback. so the algorithm may be used as alternative, but definitely not as default. That breaks the whole BRep concept.
wmayer
Founder
Posts: 20319
Joined: Thu Feb 19, 2009 10:32 am
Contact:

Re: Add alternative algorithms for Part.makeOffset2D

Post by wmayer »

How on earth is that possible? Is such "face" valid?
In OCC there is a check to mark such a face as invalid. See here: http://git.dev.opencascade.org/gitweb/? ... =HEAD#l285

The method checks the wires of a face and there must be only one wire that is allowed to contain some data, all other wires must mark holes. So, if there is any other wire that contains data then the face is considered as invalid with (BRepCheck_InvalidImbricationOfWires).
User avatar
DeepSOIC
Veteran
Posts: 7896
Joined: Fri Aug 29, 2014 12:45 am
Location: used to be Saint-Petersburg, Russia

Re: Add alternative algorithms for Part.makeOffset2D

Post by DeepSOIC »

realthunder wrote:
DeepSOIC wrote:How on earth is that possible? Is such "face" valid?
Well, it can extrude and everything :)
Indeed it can extrude, the result pretends to be a single solid. However if I try to cut a hole in this solid, it fails. So that solid isn't useful for anything, I'm afraid.
pcb-cant-cut.png
pcb-cant-cut.png (166.92 KiB) Viewed 3879 times
Post Reply