Vcarve SVG prep work

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!
Post Reply
User avatar
WayofWood
Posts: 62
Joined: Mon Nov 26, 2018 4:59 pm

Vcarve SVG prep work

Post by WayofWood »

I wrote a small (and very inefficient) Python script to automate the prep work in order to V-carve a SVG graphic (as described here: https://wiki.freecadweb.org/Path_Vcarve).

As said it's very inefficient and will take forever for more complex shapes but for simple shapes it's definitely faster than running the operation by hand.

Maybe some of you find that script helpful:

Code: Select all

import FreeCAD as App
import Draft

# First convert all wires to faces
objects = App.ActiveDocument.Objects

for object in objects:
	print("Name:{}\t Label: {}\t ".format(object.Name,object.Label ) )
	print("  => Faces:{}".format(len(object.Shape.Faces)))
	faces = len(object.Shape.Faces)
	if (faces == 0):
		oldname = object.Name
		add_list, delete_list = Draft.upgrade(object, delete=True)
		add_list[0].Label = oldname
	else:
		oldname = object.Name
		add_list, delete_list = Draft.downgrade(object, delete=True)
		add_list1, delete_list1 = Draft.upgrade(add_list[0], delete=True)
		add_list1[0].Label = oldname

App.ActiveDocument.recompute()

# Put objects with the same name in a group
objects = App.ActiveDocument.Objects
basenames = {}

for object in objects:
	print("Name:{}\t Label: {}\t ".format(object.Name,object.Label ) )
	name = object.Label
	basenames[name] = [ object ]

	if (len(object.Shape.Faces) > 0):
		face = object.Shape.Faces[0]
		for subobject in objects:
			thisname = subobject.Label
			if (thisname.startswith(name) and thisname != name):
				print ("Candidate for adding: {} to list {}".format(thisname, name))
				isinside=True
				for vertex in subobject.Shape.Vertexes:
					if (face.isInside(vertex.Point, 0.000001, True) == False):
						isinside = False
				if (isinside):		
					basenames[name].append( subobject )
					print (" ==> Added")
				# Test reverse (shorter name contained in longer name)
				else:
					isinside = True
					if (len(subobject.Shape.Faces) > 0):
						face = subobject.Shape.Faces[0]
						for vertex in object.Shape.Vertexes:
							if (face.isInside(vertex.Point, 0.000001, True) == False):
								isinside = False
						if (isinside):		
							basenames[name].append( subobject )
							print (" ==> Added")
					
print (basenames)

# Cut away the smaller parts from the larger ones
for group in basenames:
	list= sorted(basenames[group], key=lambda x: x.Shape.Faces[0].Area, reverse=True)
	if (len(list) > 1):
		Draft.downgrade(list, False)
		for o in list:
			o.Visibility = False

App.ActiveDocument.recompute()
User avatar
onekk
Veteran
Posts: 6146
Joined: Sat Jan 17, 2015 7:48 am
Contact:

Re: Vcarve SVG prep work

Post by onekk »

First consideration.

Very good work.

Some other considerations, to make your work more "incisive", don't take it as criticis, only a way to do it better.

I could guess the way it is working, but it lacks of some basilar infos.

Code: Select all

objects = App.ActiveDocument.Objects
It will use all the objects in the Active Document?

An it will traverse them to obtain things to fed to a Path.VCarve?

Adding some instructions will make easy for an user to guess "what the code is doing", I could guess that is doing the "massage" suggested from the wiki page you linked.

And from other posts I know what you are trying to do, maybe putting a link also to the "discussion" page, will make things to be more clear.

Some consideration, as you have some faces, and you want to obtain some faces, dividing them in outline and "other elements to be carved differently" (holes?), maybe there are better ways of doing things, especially if you use scripting.

The way you are using is the mimick of the gui, that is "almost everything" the worst way to proceed.

I could guess that you want to obtain faces from wires, it is more easy to iedntify the wire and use:

Code: Select all

face = Part.Face(wire)
Part.show(face, "face1")
And usually more fast than "invoking a Gui command" like you are doing.

In FreeCAD script could be "programming in python using FreeCAD methods" and also "using a Macro language that mimic actions in GUI".

The first approach is generally more fast as you have not to invoke the "overwork" of invoking and executing "Gui commands".

But this is a different "point of view", sadly many users came her from programs that don't have this "way of working", or maybe "way of thinking".

Problem could be to identify wires to be transformed in faces, and other thing, but it is not impossible, as from the other forum post you have found a way to identify what wire is "internal" to other wires.

Tanks for Sharing and Best Regards

Carlo D.
GitHub page: https://github.com/onekk/freecad-doc.
- In deep articles on FreeCAD.
- Learning how to model with scripting.
- Various other stuffs.

Blog: https://okkmkblog.wordpress.com/
User avatar
WayofWood
Posts: 62
Joined: Mon Nov 26, 2018 4:59 pm

Re: Vcarve SVG prep work

Post by WayofWood »

onekk wrote: Wed Jan 12, 2022 10:44 am Some other considerations, to make your work more "incisive", don't take it as criticis, only a way to do it better.
Thanks. Very valid points. I added a bit of documentation to make it easier to understand what I am trying to do:

https://github.com/wayofwood/FreeCADScr ... ortcleanup
User avatar
onekk
Veteran
Posts: 6146
Joined: Sat Jan 17, 2015 7:48 am
Contact:

Re: Vcarve SVG prep work

Post by onekk »

Very well done.

Thanks for sharing the code.

Regards

Carlo D.
GitHub page: https://github.com/onekk/freecad-doc.
- In deep articles on FreeCAD.
- Learning how to model with scripting.
- Various other stuffs.

Blog: https://okkmkblog.wordpress.com/
Post Reply