Path.Area: Welcome, to the new era!

Here's the place for discussion related to CAM/CNC and the development of the Path module.
Forum rules
Be nice to others! Respect the FreeCAD code of conduct!
User avatar
sliptonic
Veteran
Posts: 3457
Joined: Tue Oct 25, 2011 10:46 pm
Location: Columbia, Missouri
Contact:

Re: Path.Area: Welcome, to the new era!

Post by sliptonic »

realthunder wrote: I thought you've called that method before?
I probably have but I've slept since then and probably forgot. Sorry if I'm making you repeat yourself. Must be getting old. :oops:
And in case you've missed my previous post. Please also try calling makeSections(project=True ...) to see if it can replace TechDraw.findShapeOutline. It is a complex operation, and I am expecting some problems here.
I've been playing with 'project=True' for a couple days and haven't hit any problem shapes yet. However, it doesn't seem to be as fast as the TechDraw method.

my benchmark script might be flawed so I'm including it below. With this script I'm getting results where the TechDraw method is from .3x to 5x faster depending on the shape.:

Code: Select all

import TechDraw
import Part
import Path
import timeit

sel = Gui.Selection.getSelectionEx()[0]
obj = sel.Object
shape = obj.Shape

def areaway():
    z = Path.Area(Offset=0,SectionCount=1, Project=True)
    z.add(shape)
    x = z.getShape()
    # Part.show(x)

def techdrawway():
    x = TechDraw.findShapeOutline(shape, 1, FreeCAD.Vector(0,0,1))
    # Part.show(x)

print (timeit.timeit(areaway, number=100))
print (timeit.timeit(techdrawway, number=100))
#areaway()
#techdrawway()
realthunder
Veteran
Posts: 2190
Joined: Tue Jan 03, 2017 10:55 am

Re: Path.Area: Welcome, to the new era!

Post by realthunder »

sliptonic wrote:I probably have but I've slept since then and probably forgot. Sorry if I'm making you repeat yourself. Must be getting old. :oops:
Well, I am not exactly young here either :D

quote="sliptonic"]my benchmark script might be flawed so I'm including it below. With this script I'm getting results where the TechDraw method is from .3x to 5x faster depending on the shape.:[/quote]Hmm...could you please post those models that Area is much slower? I'll take a look.
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
User avatar
sliptonic
Veteran
Posts: 3457
Joined: Tue Oct 25, 2011 10:46 pm
Location: Columbia, Missouri
Contact:

Re: Path.Area: Welcome, to the new era!

Post by sliptonic »

With the attached file I'm seeing this after 100 iterations.

Area: 44.4123110771
TechDraw 5.21004390717
Attachments
planing.fcstd
(95.55 KiB) Downloaded 29 times
realthunder
Veteran
Posts: 2190
Joined: Tue Jan 03, 2017 10:55 am

Re: Path.Area: Welcome, to the new era!

Post by realthunder »

sliptonic wrote:With the attached file I'm seeing this after 100 iterations.

Area: 44.4123110771
TechDraw 5.21004390717
A quick run on my computer, there is definitely some bottleneck somewhere in Path.Area, but it is not the projection code. It might be somewhere very unexpected. First, you can turn on Path.Area timing code using Path.Area.setDefaultParams(LogLevel=4). And look for log message 'projection total' time, or 'makeSection total' time. On my computer it is averaged at 0.02s per run. The following test code gives a better result, suggesting the bottleneck may be in Path.Area destruction code. Just a hint. Need more time to dig deeper

Code: Select all

import FreeCADGui
import FreeCAD
import TechDraw
import Part
import Path
import timeit

sel = FreeCADGui.Selection.getSelectionEx()[0]
obj = sel.Object
shape = obj.Shape

# Fill=0: return wires instead of making face
# Coplanar=0: no coplanar checking, because projection only returns planar wire
# The above two setting only gives marginal improvements, though. 
# The big difference is to take Path.Area out of the loop instead of creating/destroying a new one on each loop
area = Path.Area(Fill=0, Coplanar=0).add(shape)

def areaway():
    x = area.makeSections(heights=[1.0],project=True)[0].getShape()
    # Part.show(x)

def techdrawway():
    x = TechDraw.findShapeOutline(shape, 1, FreeCAD.Vector(0,0,1))
    # Part.show(x)

print (timeit.timeit(areaway, number=10))
print (timeit.timeit(techdrawway, number=10))
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
User avatar
sliptonic
Veteran
Posts: 3457
Joined: Tue Oct 25, 2011 10:46 pm
Location: Columbia, Missouri
Contact:

Re: Path.Area: Welcome, to the new era!

Post by sliptonic »

Now that I'm starting to get the hang of this, I'm really excited. Rearranging my contour code made a big difference in speed and I still haven't been able to stump the projection algorithm with a shape yet. :D

After re-arranging, CW/CCW is still reversed but the bug I mentioned where one step-down was going in the opposite direction has disappeared. I think that was a red-herring in my operation.

The clearance/safe height issue remains and this might help you whenever you get to it. In this image, the cutter would perform a rapid move all the way from clearance to the first section height. That would be a crash because it's cutting through material from safe-height to start-depth. It correctly performs a feed move between section layers but not to the first section. Setting the start depth to the top of the material doesn't work because then the first entire profile is done without cutting anything.
snapshot-1.png
snapshot-1.png (139.23 KiB) Viewed 1957 times
User avatar
sliptonic
Veteran
Posts: 3457
Joined: Tue Oct 25, 2011 10:46 pm
Location: Columbia, Missouri
Contact:

Re: Path.Area: Welcome, to the new era!

Post by sliptonic »

Working more with Projection and sections I hit some weirdness.

I want to create a solid that represents the outside perimeter without the inside holes. Then I can subtract the original part from it to find the material to be removed without worrying about the perimeter profile. I call this part the 'envelope' and I wrote a macro to create it.

Code: Select all

import Path
from PathScripts import PathUtils as PU

obj = Gui.Selection.getSelectionEx()[0].Object

def getEnvelope(shape):
    area = Path.Area(Fill=1, Coplanar=0).add(shape)
    area.setPlane(Part.makeCircle(10))
    sec = area.makeSections(heights=[1.0], project=True)[0].getShape(rebuild=True)
    return sec.extrude(FreeCAD.Vector(0, 0, shape.BoundBox.ZMax))

Part.show(getEnvelope(obj.Shape))
But when I repeatedly run the macro with the same original part, I get different results for the envelope. Image below shows the original part at left, and envelopes created from four runs. The first and third are correct but the other two are wrong in different ways. I assume Area is caching the added shapes but I'm not sure how to clear it.
snapshot-1-2.png
snapshot-1-2.png (23.04 KiB) Viewed 1922 times
Attachments
drilling.fcstd
(232 KiB) Downloaded 28 times
realthunder
Veteran
Posts: 2190
Joined: Tue Jan 03, 2017 10:55 am

Re: Path.Area: Welcome, to the new era!

Post by realthunder »

sliptonic wrote:Working more with Projection and sections I hit some weirdness.
I can confirm this a bug in Area. I'll try to fix it soon.
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: Path.Area: Welcome, to the new era!

Post by realthunder »

sliptonic wrote:Working more with Projection and sections I hit some weirdness.
This probably has something to do with the loop orientation bug you've found early, and the problem is a complex one. I'll propose a compromised change, and I want your opinion first. The change is to limit the orientation as 0=None, and 1=Reversed. The reason is that the CW and CCW notion actually depends on whether the wire is for outline or inner hole. Profiling operation contain both type of wires, while pocket (if the pattern are closed wires) are all inner wires. For inner wires, the material is in fact at the opposite side comparing to the outer wire. So for climb milling you'll want CW for outer wire, and CCW for inner wire.

OCC, when making face, use CCW for outer wire and CW for inner wire. However, the problem is complicated by the fact that CW and CCW depends on the direction of the surface normal, or in layman's term, depends on which direction you are looking at. To make things manageable, Area will make an assumption that the face normal shall be pointing towards (0,0,1) direction. WorkPlane is used to let user control how to transform the actual wire plane into this direction. In another word, Area will internally transform the wire so that the work plane's normal align with (0,0,1) before any further processing. Before orientation adjustment, Area shall normalize all wires orientation, so that the outer wire is CCW, and inner wires is CW with regarding (0,0,1) direction. So now, you can see why it makes sense to just having two options for orientation. 'None' means keep the original orientation, which corresponds to conventional milling, and 'Reversed' for climb milling.

Path.fromShapes() will not have enough information to determine which wire is supposed to be outer and which is inner. So it just assumes the orientation of the input wires are already normalized, and simply reverse it if orientation='Reversed'. Any suggestion?
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
User avatar
sliptonic
Veteran
Posts: 3457
Joined: Tue Oct 25, 2011 10:46 pm
Location: Columbia, Missouri
Contact:

Re: Path.Area: Welcome, to the new era!

Post by sliptonic »

I'm pretty sure the compromised change is fine. If anyone else see's a problem, please weigh in.

Does this have anything to do with why the ZigZag pattern stopped working? I can get pocket paths out of offset but not zigzag.
realthunder
Veteran
Posts: 2190
Joined: Tue Jan 03, 2017 10:55 am

Re: Path.Area: Welcome, to the new era!

Post by realthunder »

sliptonic wrote:Does this have anything to do with why the ZigZag pattern stopped working? I can get pocket paths out of offset but not zigzag.
Not likely. Most likely due to the new patterns added. I'll look into that shortly.
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
Post Reply