Script to slice a cylinder.

Need help, or want to share a macro? Post here!
Forum rules
Be nice to others! Respect the FreeCAD code of conduct!
keithsloan52
Veteran
Posts: 2764
Joined: Mon Feb 27, 2012 5:31 pm

Script to slice a cylinder.

Post by keithsloan52 »

Okay I can create a cylinder with Part.makeCylinder although when I try with cyl = Part.makeCylinder(radius,height,[pnt,dir,angle]) it does not like the third parameter, complains it is not a list and wants a Vector.

That aside I would like to slice the cylinder in two. i.e. create a plane = Part.makePlane(length,width,[pnt,dir]) and use it to slice the cylinder and access one of the shapes. Does not seem to like cyl.cut(plane)

Again parameters of Plane do not seem to match https://wiki.freecadweb.org/Part_API

Code: Select all

tube1 = Part.makeCylinder(fp.rmax, fp.z)
tube2 = Part.makeCylinder(fp.rmin, fp.z)
tube = tube1.cut(tube2)
topPlane = Part.makePlane(100,100, \
                FreeCAD.Vector(fp.highX,fp.highY,fp.highZ))
                #[pntC,FreeCAD.Vector(fp.highX,fp.highY,fp.highZ)])
comp = tube.cut(topPlane)
botPlane = Part.makePlane(100,100, \
                FreeCAD.Vector(fp.lowX,fp.lowY,fp.lowZ))
                #[pntC,FreeCAD.Vector(fp.lowX,fp.lowY,fp.lowZ)])
        #botTube = topTube.cut(botPlane)
fp.Shape = comp


User avatar
Chris_G
Veteran
Posts: 2596
Joined: Tue Dec 31, 2013 4:10 pm
Location: France
Contact:

Re: Script to slice a cylinder.

Post by Chris_G »

keithsloan52 wrote: Sat Apr 04, 2020 4:45 am Okay I can create a cylinder with Part.makeCylinder although when I try with cyl = Part.makeCylinder(radius,height,[pnt,dir,angle]) it does not like the third parameter, complains it is not a list and wants a Vector.
The brackets don't stand for a python list, but mean that these parameters are optional.
keithsloan52
Veteran
Posts: 2764
Joined: Mon Feb 27, 2012 5:31 pm

Re: Script to slice a cylinder.

Post by keithsloan52 »

Thanks. Any idea about making a slice/cut?
User avatar
Chris_G
Veteran
Posts: 2596
Joined: Tue Dec 31, 2013 4:10 pm
Location: France
Contact:

Re: Script to slice a cylinder.

Post by Chris_G »

Code: Select all

def cut_cylinder_with_plane(cyl, plane):
    "Cut a cylinder with a plane"
    f = plane.toShape()
    so = f.extrude(plane.Axis*1e10)
    cut = cyl.cut(so)
    common = cyl.common(so)
    return cut, common
User avatar
onekk
Veteran
Posts: 6199
Joined: Sat Jan 17, 2015 7:48 am
Contact:

Re: Script to slice a cylinder.

Post by onekk »

Code: Select all

"""testfig.py

   Author: Carlo Dormeletti
   Copyright: 2020
   Licence: CC BY-NC-SA 4.0 IT 
"""

import os

import FreeCAD
from FreeCAD import Base, Rotation, Vector
import Part
import Draft
from math import pi, sin, cos, acos
import Draft

DOC = FreeCAD.activeDocument()
DOC_NAME = "Pippo"

def clear_doc():
    """
    Clear the active document deleting all the objects
    """
    for obj in DOC.Objects:
        DOC.removeObject(obj.Name)

def setview():
    """Rearrange View"""

    FreeCAD.Gui.activeDocument().activeView().viewAxometric()
    FreeCAD.Gui.activeDocument().activeView().setAxisCross(True)
    DOC.recompute()
    FreeCAD.Gui.SendMsgToActiveView("ViewFit")

if DOC is None:
    FreeCAD.newDocument(DOC_NAME)
    FreeCAD.setActiveDocument(DOC_NAME)
    DOC = FreeCAD.activeDocument()

else:

    clear_doc()


# EPS= tolerance to uset to cut the parts
EPS = 0.10
EPS_C = EPS * -0.5

obj = DOC.addObject("Part::Cylinder", "cylinder_name")
obj.Angle = 360
obj.Radius = 30
obj.Height = 50
obj.Placement = FreeCAD.Placement(Vector(0, 0, 0), Rotation())
DOC.recompute()

obj1 = DOC.addObject("Part::Plane", "Plane_name")
obj1.Length = 100
obj1.Width = 100
obj1.Placement = FreeCAD.Placement(Vector(-50, -50, 15), Rotation(0,0,45))

DOC.recompute()

obj2 = DOC.addObject("Part::Feature", "Plane_cut")
obj2.Shape = obj1.Shape.extrude(Vector(0,0, 0.1))

DOC.recompute()

obj3 = DOC.addObject("Part::Cut", "cut_name")
obj3.Base = obj
obj3.Tool = obj2
obj3.Refine = True

DOC.recompute()

setview()

Maybe is not wat you want, the cur operation, is not done (at least with this code) if a plane is a "Part::Plane", the trick is to transform it in a solid with a minimal height, and the cut is done.

But a cut maybe is not what you want, for see a section, you could use another

Code: Select all

"""testfig2.py

   Author: Carlo Dormeletti
   Copyright: 2020
   Licence: CC BY-NC-SA 4.0 IT 
"""

import os

import FreeCAD
from FreeCAD import Base, Rotation, Vector
import Part
import Draft
from math import pi, sin, cos, acos
import Draft

DOC = FreeCAD.activeDocument()
DOC_NAME = "Pippo"

def clear_doc():
    """
    Clear the active document deleting all the objects
    """
    for obj in DOC.Objects:
        DOC.removeObject(obj.Name)

def setview():
    """Rearrange View"""

    FreeCAD.Gui.activeDocument().activeView().viewAxometric()
    FreeCAD.Gui.activeDocument().activeView().setAxisCross(True)
    DOC.recompute()
    FreeCAD.Gui.SendMsgToActiveView("ViewFit")

if DOC is None:
    FreeCAD.newDocument(DOC_NAME)
    FreeCAD.setActiveDocument(DOC_NAME)
    DOC = FreeCAD.activeDocument()

else:

    clear_doc()


# EPS= tolerance to uset to cut the parts
EPS = 0.10
EPS_C = EPS * -0.5

thick = 2
tube_e_rad = 30
tube_i_rad = tube_e_rad - thick 
tube_h = 50
tube_a = 180

obj = DOC.addObject("Part::Cylinder", "cylinder_ext")
obj.Angle = tube_a
obj.Radius = tube_e_rad
obj.Height = tube_h
obj.Placement = FreeCAD.Placement(Vector(0, 0, 0), Rotation())

obj1 = DOC.addObject("Part::Cylinder", "cylinder_int")
obj1.Angle = tube_a
obj1.Radius = tube_i_rad
obj1.Height = tube_h + EPS
obj1.Placement = FreeCAD.Placement(Vector(0, 0, EPS_C), Rotation())


tube = DOC.addObject("Part::Cut", "cut_name")
tube.Base = obj
tube.Tool = obj1
tube.Refine = True

DOC.recompute()

box_l = 100
box_w = 100
box_h = 60

pos_z = 25 # cut height 

obj2 = DOC.addObject("Part::Box", "box_name")
obj2.Length = box_l
obj2.Width = box_w
obj2.Height = box_h

centre = FreeCAD.Vector(box_l * 0.5, box_w * 0.5, box_h * 0.5)  # central point of box 
pos = Vector(box_l * -0.5, box_w * -0.5, pos_z)    
rot = Rotation(0,0,30) # rotation with euler angle see https://wiki.freecadweb.org/Placement
newplace = FreeCAD.Placement(pos,rot,centre)       # make a new Placement object
obj2.Placement = newplace     


DOC.recompute()

obj3 = DOC.addObject("Part::Cut", "cut_name")
obj3.Base = tube
obj3.Tool = obj2
obj3.Refine = True

DOC.recompute()

Hope it helps.

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/
keithsloan52
Veteran
Posts: 2764
Joined: Mon Feb 27, 2012 5:31 pm

Re: Script to slice a cylinder.

Post by keithsloan52 »

Chris_G wrote: Sat Apr 04, 2020 9:32 am

Code: Select all

def cut_cylinder_with_plane(cyl, plane):
    "Cut a cylinder with a plane"
    f = plane.toShape()
    so = f.extrude(plane.Axis*1e10)
    cut = cyl.cut(so)
    common = cyl.common(so)
    return cut, common
When I create a Plane with topPlane = Part.makePlane(100, 100, FreeCAD.Vector(0,0,5),FreeCAD.Vector(1,0,1))
and call I get error

f = plane.toShape()
<class 'AttributeError'>: 'Part.Face' object has no attribute 'toShape'

Does not need to be a Plane, but I just need to create a Shape which is a cylinder cut with the same parameters as a Plane,
i.e. Point and a direction

There is also https://forum.freecadweb.org/viewtopic.php?f=3&t=679

But I have yet to get the desired result
User avatar
Chris_G
Veteran
Posts: 2596
Joined: Tue Dec 31, 2013 4:10 pm
Location: France
Contact:

Re: Script to slice a cylinder.

Post by Chris_G »

keithsloan52 wrote: Sat Apr 04, 2020 12:26 pm When I create a Plane with topPlane = Part.makePlane(100, 100, FreeCAD.Vector(0,0,5),FreeCAD.Vector(1,0,1))
and call I get error

f = plane.toShape()
<class 'AttributeError'>: 'Part.Face' object has no attribute 'toShape'
My example code was suppose to work with a geometry plane.
The Part.makeSomething functions create topology shapes.
So you can't call toShape() on them, since they are already shapes.

Code: Select all

def cut_cylinder_with_plane(cyl, plane):
    "Cut a cylinder with a plane"
    if not isinstance(plane, Part.Shape):
        f = plane.toShape()
    else:
        f = plane
    so = f.extrude(plane.Axis*1e10)
    cut = cyl.cut(so)
    common = cyl.common(so)
    return cut, common
keithsloan52
Veteran
Posts: 2764
Joined: Mon Feb 27, 2012 5:31 pm

Re: Script to slice a cylinder.

Post by keithsloan52 »

Chris_G wrote: Sat Apr 04, 2020 1:31 pm
keithsloan52 wrote: Sat Apr 04, 2020 12:26 pm When I create a Plane with topPlane = Part.makePlane(100, 100, FreeCAD.Vector(0,0,5),FreeCAD.Vector(1,0,1))
and call I get error

f = plane.toShape()
<class 'AttributeError'>: 'Part.Face' object has no attribute 'toShape'
My example code was suppose to work with a geometry plane.
The Part.makeSomething functions create topology shapes.
So you can't call toShape() on them, since they are already shapes.

Code: Select all

def cut_cylinder_with_plane(cyl, plane):
    "Cut a cylinder with a plane"
    if not isinstance(plane, Part.Shape):
        f = plane.toShape()
    else:
        f = plane
    so = f.extrude(plane.Axis*1e10)
    cut = cyl.cut(so)
    common = cyl.common(so)
    return cut, common
Ah makes more sense, penny is slowly dropping that Part makes Shapes.

Does not like plane.Axis*1e10.

I assume the purpose is to extrude at the plane's normal.
User avatar
Chris_G
Veteran
Posts: 2596
Joined: Tue Dec 31, 2013 4:10 pm
Location: France
Contact:

Re: Script to slice a cylinder.

Post by Chris_G »

keithsloan52 wrote: Sat Apr 04, 2020 2:51 pm Ah makes more sense, penny is slowly dropping that Part makes Shapes.
Just to be clear :
- Part.Plane() create a geometry / Part.makePlane() create a shape
- Part.Cylinder() create a geometry / Part.makeCylinder() create a shape
... and so on
keithsloan52 wrote: Sat Apr 04, 2020 2:51 pm Does not like plane.Axis*1e10.
Ooops, sorry, I didn't test the code.
This should be better :

Code: Select all

def cut_cylinder_with_plane(cyl, plane):
    "Cut a cylinder with a plane"
    if not isinstance(plane, Part.Shape):
        f = plane.toShape()
    else:
        f = plane
    so = f.extrude(f.Surface.Axis*1e10)
    cut = cyl.cut(so)
    common = cyl.common(so)
    return cut, common
keithsloan52
Veteran
Posts: 2764
Joined: Mon Feb 27, 2012 5:31 pm

Re: Script to slice a cylinder.

Post by keithsloan52 »

No probs

I changed the code to the following, don't really understand the (1,1) but

Code: Select all

def cutShapeWithPlane(self, shape, plane):
        "Cut a shape with a plane"
        #so = plane.extrude(plane.Axis*1e10)
        so = plane.extrude(plane.normalAt(1,1))
        cut = shape.cut(so)
        #common = shape.common(so)
        return cut
Which does cut my cylinder in two, but what I am after is just the bottom half.
cutcyl.png
cutcyl.png (18.7 KiB) Viewed 918 times
How would I do that?
Post Reply