Request for help from newbie regarding converting polyhedron to wireframe

Post here for help on using FreeCAD's graphical user interface (GUI).
Forum rules
and Helpful information
IMPORTANT: Please click here and read this first, before asking for help

Also, be nice to others! Read the FreeCAD code of conduct!
bonomo
Posts: 22
Joined: Wed Jul 06, 2022 8:29 pm

Re: Request for help from newbie regarding converting polyhedron to wireframe

Post by bonomo »

Dear Ed,

Is there any reason that the macro would work with a whole sphere, but not half a sphere?

The macro attached is a slightly modified version of the one you wrote: the center of the shell is specified as the origin, and I specify the radial distance and the thickness.

It works perfectly with a full hex-pent sphere, but with a half-sphere, it does not produce the radial webbing, even though it reports no errors. I, of course, have been examining the macro, but I am still at the beginning stages of using and understanding the language.

Are you able to look at this macro yet again?

Thanks! You have been *extremely* helpful!
Attachments
Goldberg8inchfacesTOP.step
upper half, hex-pent sphere
(460.09 KiB) Downloaded 11 times
WilliamsHALF.FCMacro
Slightly modified version of your macro
(2.52 KiB) Downloaded 10 times
Goldberg8inchfaces.step
complete hex-pent sphere
(903.47 KiB) Downloaded 12 times
edwilliams16
Veteran
Posts: 3192
Joined: Thu Sep 24, 2020 10:31 pm
Location: Hawaii
Contact:

Re: Request for help from newbie regarding converting polyhedron to wireframe

Post by edwilliams16 »

The problem is that I assume the input is a solid. Your half version is an open shell. I actually only use the solid to cut away the tiny ears where the struts overlap at the corners. So the following skips that part if it's a shell input.

Code: Select all

#script to make edge structure of HALF a regular polyhedron, presuming the "whole" polyhedron would be centered at the origin
#select the polyhedron in the tree view and run the macro
#Ed williams 7/9/22 modified by Richard Bonomo 8/2/2022 to accomodate half-polyhedrons
#Added code that takes common with an expanded polyhedron. This trims the struts at the corners. 7/11/22 
# EW 8/2/22 added output when input is a shell - but without the trim functionality

import Part
from math import degrees
DEBUG = False

if DEBUG:
	import ptvsd
	print("Waiting for debugger attach")
	ptvsd.enable_attach(address=('localhost', 5678))
	ptvsd.wait_for_attach()

def radialExtrudeEdge(edge, radialDist, thick, center = App.Vector(0, 0, 0)):
    v1, v2 = [v.Point for v in edge.Vertexes]
    v1p = (1 + radialDist/(v1 - center).Length)*(v1 - center) + center
    v2p = (1 + radialDist/(v2 - center).Length)*(v2 - center) + center
    poly = Part.makePolygon([v1, v1p, v2p, v2, v1])
    shp = Part.Face(poly)
    axis = v2 -v1
    midpoint = (v1 + v2)/2
    halfangle = degrees((thick/(midpoint - center).Length) * 0.5)
    revp = shp.revolve(center, axis, halfangle)
    revm = shp.revolve(center, axis, - halfangle)
    return revp.fuse(revm)


doc = App.ActiveDocument
sel, = Gui.Selection.getSelection()
edges = sel.Shape.Edges
vertices = sel.Shape.Vertexes
#fuse = True #fusing is slow and sometimes fails
#center = sel.Shape.CenterOfGravity  # regular solid so expand around center
center = App.Vector(0.0,0.0,0.0)
radius = (vertices[0].Point - center).Length
#radialDist = radius/10 # input - or specify distance
radialDist = 12.7
# thick = radius/20 # input - or specify distance
thick = 1.14
scale = 1.0 # >1 to try to avoid coplanar issues =1 if you will use uncut shape
fuse = True  #can be slow (this is the active fuse status -- uncomment to fuse
shps = []
for edge in edges:
    shp = radialExtrudeEdge(edge, radialDist * scale, thick, center)
    shps.append(shp)

#fusedshp = shps[0].fuse(shps[1:])
#Part.show(fusedshp, sel.Name + "bumpy_frame")
uncutcmpd = Part.makeCompound(shps)
uncutcmpddoc = Part.show(uncutcmpd, sel.Name + "_uncut_struts")
uncutcmpddoc.ViewObject.Visibility = False
if fuse:
    fusion = doc.addObject("Part::MultiFuse",sel.Name + '_uncut_frame')
    fusion.Shapes = uncutcmpddoc
    fusion.Refine = True

if sel.Shape.ShapeType =='Shell':
    App.Console.PrintMessage('Need solid input not shell to cut\n')
else:
    lnk = doc.addObject('App::Link',sel.Name)
    lnk.setLink(sel)
    lnk.Label = sel.Name
    lnk.Scale = 1 + radialDist/radius # try to avoid coplanar issues
    lnk.Placement.Base = -(radialDist/radius)*center #compensate for scaling moving center
    lnk.ViewObject.Visibility = False

    shpscut = []
    for s in shps:
        shpscut.append(lnk.Shape.common(s))
    cmpd = Part.makeCompound(shpscut)
    cmpddoc = Part.show(cmpd, sel.Name + "_struts")
    cmpddoc.ViewObject.Visibility = False

    if fuse:
        fusion = doc.addObject("Part::MultiFuse",sel.Name + '_frame')
        fusion.Shapes = cmpddoc
        fusion.Refine = True

doc.recompute()
junk = 0 #provides end breakpoint for debugger
To get back the clipping functionality, eithert you need to provide a solid STEP input, or I have to create a function to turn your half- shell into one.
Screen Shot 2022-08-02 at 2.08.09 PM.png
Screen Shot 2022-08-02 at 2.08.09 PM.png (36.9 KiB) Viewed 461 times
bonomo
Posts: 22
Joined: Wed Jul 06, 2022 8:29 pm

Re: Request for help from newbie regarding converting polyhedron to wireframe

Post by bonomo »

Dear William,

Thank you, again!

When I made the shell, all I had done is take a Goldberg polyhedron STEP file, use the "Defeature" workbench to remove the faces I did not want, and re-exported the result to a new STEP file. Apparently this process makes it no longer a solid?

You are being so generous with your help, I find myself thinking that I should at least send you a Pizza (or something) coupon, if Forum rules allow that!

RB
edwilliams16
Veteran
Posts: 3192
Joined: Thu Sep 24, 2020 10:31 pm
Location: Hawaii
Contact:

Re: Request for help from newbie regarding converting polyhedron to wireframe

Post by edwilliams16 »

bonomo wrote: Wed Aug 03, 2022 12:30 am Dear William,

Thank you, again!

When I made the shell, all I had done is take a Goldberg polyhedron STEP file, use the "Defeature" workbench to remove the faces I did not want, and re-exported the result to a new STEP file. Apparently this process makes it no longer a solid?

You are being so generous with your help, I find myself thinking that I should at least send you a Pizza (or something) coupon, if Forum rules allow that!

RB
I'm not that familiar with Defeature - but I can understand that if you wanted to get the cutaway shell closed, the code wouldn't know how you wanted it done.

I do this to learn python and FreeCAD and to entertain myself - but you are welcome to donate to FreeCAD, if you think that appropriate.

https://wiki.freecadweb.org/Donate
edwilliams16
Veteran
Posts: 3192
Joined: Thu Sep 24, 2020 10:31 pm
Location: Hawaii
Contact:

Re: Request for help from newbie regarding converting polyhedron to wireframe

Post by edwilliams16 »

It finally occurred to me that we don't need to reconstruct a solid to trim the struts as we already have it in hand. Import both Goldberg files and ctrl-select them both, then run the following macro. It was just a few lines of code to refer the solid to the second selection.

Code: Select all

#script to make edge structure of a regular polyhedron
#select the polyhedron in the tree view and run the macro
#Ed williams 7/9/22
#Added code that takes common with an expanded polyhedron. This trims the struts at the corners. 7/11/22 
#Ed Williams 8/2/22 for a shell input multi-select both the shell and the corresponding full solid and run 

import Part
from math import degrees

DEBUG = False

if DEBUG:
    import sys
    freecadpython = sys.executable.replace('freecad', 'python')
    App.Console.PrintMessage('Using ' + freecadpython +'\n')
    try:
        import debugpy
    except ModuleNotFoundError:
        App.Console.PrintMessage('Install debugpy by: ' + freecadpython + ' -m pip install --upgrade debugpy\n')
    #see https://github.com/microsoft/debugpy/issues/262
       
    debugpy.configure(python=freecadpython)
    if not debugpy.is_client_connected():
        debugpy.listen(5678)

    App.Console.PrintMessage("Waiting for debugger attach\n")
    debugpy.wait_for_client()
    debugpy.breakpoint()

def radialExtrudeEdge(edge, radialDist, thick, center = App.Vector(0, 0, 0)):
    v1, v2 = [v.Point for v in edge.Vertexes]
    v1p = (1 + radialDist/(v1 - center).Length)*(v1 - center) + center
    v2p = (1 + radialDist/(v2 - center).Length)*(v2 - center) + center
    poly = Part.makePolygon([v1, v1p, v2p, v2, v1])
    shp = Part.Face(poly)
    axis = v2 -v1
    midpoint = (v1 + v2)/2
    halfangle = degrees((thick/(midpoint - center).Length) * 0.5)
    revp = shp.revolve(center, axis, halfangle)
    revm = shp.revolve(center, axis, - halfangle)
    return revp.fuse(revm)


doc = App.ActiveDocument
sels = Gui.Selection.getSelection()
if len(sels) == 1:  #select solid
    sel =sels[0]
    selsolid = sel
elif len(sels) == 2:
    if sels[0].Shape.ShapeType == 'Shell': #select shell and solid
        sel = sels[0]
        selsolid = sels[1]
    else:
        sel = sels[1]
        selsolid = sels[0]

edges = sel.Shape.Edges
vertices = sel.Shape.Vertexes
#fuse = True #fusing is slow and sometimes fails
#center = sel.Shape.CenterOfGravity  # regular solid so expand around center
center = App.Vector(0.0, 0.0, 0.0)
radius = (vertices[0].Point - center).Length
#radialDist = radius/5 # input - or specify distance
radialDist = 12.7
#thick = radius/160 # input - or specify distance
thick = 1.14
scale = 1.1 # >1 to try to avoid coplanar issues
fuse = True  #can be slow
shps = []
for edge in edges:
    shp = radialExtrudeEdge(edge, radialDist * scale, thick, center)
    shps.append(shp)

#fusedshp = shps[0].fuse(shps[1:])
#Part.show(fusedshp, sel.Name + "_frame")

lnk = doc.addObject('App::Link',selsolid.Name)
lnk.setLink(selsolid)
lnk.Label = selsolid.Name
lnk.Scale = 1 + radialDist/radius # try to avoid coplanar issues
lnk.Placement.Base = -(radialDist/radius)*center #compensate for scaling moving center
lnk.ViewObject.Visibility = False

shpscut = []
for s in shps:
    shpscut.append(lnk.Shape.common(s))

cmpd = Part.makeCompound(shpscut)
cmpddoc = Part.show(cmpd, sel.Name + "_struts")
cmpddoc.ViewObject.Visibility = False

if fuse:
    fusion = doc.addObject("Part::MultiFuse",sel.Name + '_frame')
    fusion.Shapes = cmpddoc
    fusion.Refine = True

doc.recompute()
junk = 0 #provides end breakpoint for debugger



Screen Shot 2022-08-02 at 10.08.59 PM.png
Screen Shot 2022-08-02 at 10.08.59 PM.png (45.13 KiB) Viewed 344 times
Post Reply