macro for finding holes

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!
danielfalck
Posts: 395
Joined: Fri Oct 07, 2011 8:58 pm
Location: Beaverton,Oregon, USA
Contact:

macro for finding holes

Post by danielfalck »

Here's a small macro that I set up to find info on holes in a model, for drilling. This might be handy for others, so I am posting it here.

Code: Select all

#***************************************************************************
#*                                                                         
#*   Copyright (c) 2013 Daniel Falck  <ddfalck@gmail.com>                  
#*                                                                        
#*   This program is free software; you can redistribute it and/or modify  
#*   it under the terms of the GNU Lesser General Public License (LGPL)    
#*   as published by the Free Software Foundation; either version 2 of     
#*   the License, or (at your option) any later version.                   
#*   for detail see the LICENCE text file.                                 
#*                                                                         
#*   This program is distributed in the hope that it will be useful,      
#*   but WITHOUT ANY WARRANTY; without even the implied warranty of       
#*   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         
#*   GNU Library General Public License for more details.                 
#*                                                                         
#*   You should have received a copy of the GNU Library General Public    
#*   License along with this program; if not, write to the Free Software   
#*   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  
#*   USA                                                                   
#*                                                                         
#***************************************************************************
from FreeCAD import Part
from PyQt4 import QtGui,QtCore
'''
this macro makes a list of holes for drilling  from a solid
select the solid and run the macro
it will place on the clipboard a list of holes like such:
[[5.0, (80.0, -20.0), 0.0, -5.0], [2.5, (20.0, -20.0), 0.0, -5.0])
the first element of the first item is the radius of the hole, the second it's XY coords
the third is the ZMax of the hole, the fourth ZMin
manipulate the line that starts with  'holelist.append' to make the list fit your own needs
'''
def findholes(obj):
    facelist = []
    holelist = []
    for f in obj.Faces:
        if  f.ParameterRange[1]> 6.28318 and f.ParameterRange[1]< 6.283186 : #eliminate flat faces
            facelist.append(f)

    for h in facelist:
        curvelist=[]
        for w in h.Wires:
            for c in w.Edges:
                if ( isinstance(c.Curve,Part.Circle) ):
                        curvelist.append((c.Curve.Radius,c.Curve.Center.x,c.Curve.Center.y))
            coords = list(set(curvelist[:]))
        holelist.append(list((coords[0][0], (coords[0][1],coords[0][2]),h.BoundBox.ZMax,h.BoundBox.ZMin)))
    clipboard = QtGui.QApplication.clipboard()
    clipboard.setText(str(holelist))

sel=Gui.Selection.getSelection()
obj = sel[0].Shape
findholes(obj)
aj5robinson
Posts: 40
Joined: Sat Apr 28, 2012 10:41 am
Location: Melbourne, Australia

Re: macro for finding holes

Post by aj5robinson »

Nice macro Dan,

While I am at it, here are a bunch of macros I published. Some are related to CAM, others were used to quickly knock out a complex model.

https://github.com/andrewjrobinson/FreeCAD-Macro-Suite (anyone is welcome to contribute to this collection)


Cheers
Andrew
nahshon
Posts: 225
Joined: Wed Jul 24, 2013 8:06 pm

Re: macro for finding holes

Post by nahshon »

Dan,
I see some problems:
1. The macro will find any cylinder object. It does not distinguish a hole from a pad or an extrusion.
2. The test on f.ParameterRange[1] (cylinder ends at 2*PI?) is not sufficient. Must also check that it's starting at 0.
3. The macro ignores the orientation of a hole. Holes that are not parallel to the Z axis get weird results.
4. There's a problem if a hole does not end on a planar surface that is orthogonal to its axis.

-- Itai
findholes-test1.fcstd
Test case that failed
(26.05 KiB) Downloaded 149 times
danielfalck
Posts: 395
Joined: Fri Oct 07, 2011 8:58 pm
Location: Beaverton,Oregon, USA
Contact:

Re: macro for finding holes

Post by danielfalck »

nahshon wrote:Dan,
I see some problems:
1. The macro will find any cylinder object. It does not distinguish a hole from a pad or an extrusion.
2. The test on f.ParameterRange[1] (cylinder ends at 2*PI?) is not sufficient. Must also check that it's starting at 0.
3. The macro ignores the orientation of a hole. Holes that are not parallel to the Z axis get weird results.
4. There's a problem if a hole does not end on a planar surface that is orthogonal to its axis.

-- Itai
findholes-test1.fcstd

Yes, you are right. I am reworking this now.
1. This is going to be tricky. I might change the macro to have the user select the inside face of holes- but this might be tedious.
2. Thanks- I have added this (will paste in later, when I'm done with macro)
3. I am putting in a test for the hole being only in the Vector(0,0,1) orientation, since my current machine isn't 5 axis
4. Using Drawing.projectEx() and the BoundBox.ZMax and BoundBox.ZMin, this can be worked out.

Thanks for your comments.
danielfalck
Posts: 395
Joined: Fri Oct 07, 2011 8:58 pm
Location: Beaverton,Oregon, USA
Contact:

Re: macro for finding holes

Post by danielfalck »

Ok, here is another version of it. I used the BoundBox of the curved faces for nearly everything this time. I used the BoundBox.XLength to get the diameter of the holes, as well as the BoundBox.Center to get centers. I hope that doesn't seem like cheating too much ;) . Thanks for the constructive comments- they really helped me push it further.
Edit (-feels like going back in time )- I borrowed 'h.Surface.Axis.z==1.0' from nahshon's script and was able to eliminate a few more lines of code.

Code: Select all

#***************************************************************************
#*                                                                         *
#*   Copyright (c) 2013 Daniel Falck  <ddfalck@gmail.com>                  *  
#*                                                                         *
#*   This program is free software; you can redistribute it and/or modify  *
#*   it under the terms of the GNU Lesser General Public License (LGPL)    *
#*   as published by the Free Software Foundation; either version 2 of     *
#*   the License, or (at your option) any later version.                   *
#*   for detail see the LICENCE text file.                                 *
#*                                                                         *
#*   This program is distributed in the hope that it will be useful,       *
#*   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
#*   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
#*   GNU Library General Public License for more details.                  *
#*                                                                         *
#*   You should have received a copy of the GNU Library General Public     *
#*   License along with this program; if not, write to the Free Software   *
#*   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  *
#*   USA                                                                   *
#*                                                                         *
#***************************************************************************
from FreeCAD import Part,Base
from PyQt4 import QtGui,QtCore
import Draft
from math import pi
'''
This macro makes a list of holes for drilling  from a solid 
1. Select a solid object that has holes in it and run the macro
2. It only collects info on holes that are parallel to the Z axis- I don't have a 4 or 5 axis mill at the moment
3. It pulls the center of the hole bounding box and the XLength for it's diameter
4. It will place a list of the holes on the clipboard
5. Uncomment the line that starts with '#Draft.makeLine' and manipulate it, if you want to see lines down the center of each hole.
6. Manipulate the line that starts with  'holelist.append' to make the list fit your own needs- I've put the ZMax at the ZMax of the solid's bounding box
because I want to make sure that my drill tip doesn't collide with anything on the top of the part. YMMV.
'''
def findholes(obj):
    facelist = []
    holelist =[]

    for f in obj.Faces:
        if ( round(f.ParameterRange[0], 8)==0.0 ) and ( round(f.ParameterRange[1],8) == round(pi*2, 8)  ) : #eliminate flat faces
            facelist.append(f)

    for h in facelist:
        for w in h.Wires:
            for c in w.Edges:
                if ( isinstance(c.Curve,Part.Line)):
                    v0=Base.Vector(c.Vertexes[0].X, c.Vertexes[0].Y, c.Vertexes[0].Z); v1=Base.Vector(c.Vertexes[1].X,c.Vertexes[1].Y, c.Vertexes[1].Z)
                    if (v1.sub(v0).x == 0) and (v1.sub(v0).y == 0) and (h.Surface.Axis.z==1.0):
                        lsp = Base.Vector(h.BoundBox.Center.x,h.BoundBox.Center.y,h.BoundBox.ZMax)
                        lep = Base.Vector(h.BoundBox.Center.x,h.BoundBox.Center.y,h.BoundBox.ZMin)
                        if obj.isInside(lsp, 0,False) or obj.isInside(lep, 0,False):
                            pass
                        else:
                            Draft.makeLine((h.BoundBox.Center.x,h.BoundBox.Center.y,obj.BoundBox.ZMax ),(h.BoundBox.Center.x,h.BoundBox.Center.y,h.BoundBox.ZMin  ))
                            x =h.BoundBox.Center.x;y=h.BoundBox.Center.y;zmax=obj.BoundBox.ZMax;zmin=h.BoundBox.ZMin;diameter=h.BoundBox.XLength
                            holelist.append((diameter, x,y,zmax,zmin))
    clipboard = QtGui.QApplication.clipboard()
    clipboard.setText(str(holelist))

sel=Gui.Selection.getSelection()
obj = sel[0].Shape
findholes(obj)

nahshon
Posts: 225
Joined: Wed Jul 24, 2013 8:06 pm

Re: macro for finding holes

Post by nahshon »

Dan,
I made some changes based on your code, before seeing your latest post.
I check that face.Surface is an instance of a Cylinder and then I can use the Axis, Center and Radius from it. I do not use the edges, so the drill do not have to end with a circle (meaning - the drilled area do not need to be a flat surface!)

I check curvature to know if it's a hole or a pad. it worked with my test cases but I'm not sure this is always correct. There must be a better way!
(The test for obj.isInside is not correct. Try a cylinder with a square hole along its axis).

Need to add code to analyze through holes vs blind holes.
3-axis process cannot handle blind holes on the bottom side of the part! Just like holes that are not vertical.

I would really prefer to be able to find holes in all the possible orientations (meaning: change of output format) and then move the orientation filtering to a post-processor.

-- Itai

Code: Select all

#***************************************************************************
#*                                                                         
#*   Copyright (c) 2013 Daniel Falck  <ddfalck@gmail.com>                 
#*                                                                       
#*   This program is free software; you can redistribute it and/or modify 
#*   it under the terms of the GNU Lesser General Public License (LGPL)   
#*   as published by the Free Software Foundation; either version 2 of     
#*   the License, or (at your option) any later version.                   
#*   for detail see the LICENCE text file.                                 
#*                                                                         
#*   This program is distributed in the hope that it will be useful,     
#*   but WITHOUT ANY WARRANTY; without even the implied warranty of       
#*   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         
#*   GNU Library General Public License for more details.                 
#*                                                                         
#*   You should have received a copy of the GNU Library General Public   
#*   License along with this program; if not, write to the Free Software   
#*   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 
#*   USA                                                                   
#*                                                                         
#***************************************************************************
from FreeCAD import Part, Gui
from PyQt4 import QtGui, QtCore
import math
'''
this macro makes a list of holes for drilling  from a solid
select the solid and run the macro
it will place on the clipboard a list of holes like such:
[[5.0, (80.0, -20.0), 0.0, -5.0], [2.5, (20.0, -20.0), 0.0, -5.0])
the first element of the first item is the radius of the hole, the second it's XY coords
the third is the ZMax of the hole, the fourth ZMin
manipulate the line that starts with  'holelist.append' to make the list fit your own needs
'''
def findholes(obj):
    pi2 = 2.0 * math.pi
    eps = 0.000001
    holelist = []
    for f in obj.Faces:
        if not(isinstance(f.Surface, Part.Cylinder)) or math.fabs(f.ParameterRange[0]) > eps or math.fabs(f.ParameterRange[1]-pi2) > eps:
            continue

        s = f.Surface
        if math.fabs(s.Axis.x) > eps or math.fabs(s.Axis.y) > eps:
            continue

        c = f.curvatureAt(0,0)
        if c[0] > 0 or c[1] > 0:
            continue

        holelist.append(list((s.Radius, (s.Center.x, s.Center.y), f.BoundBox.ZMax,f.BoundBox.ZMin)))

    clipboard = QtGui.QApplication.clipboard()
    clipboard.setText(str(holelist))

sel=Gui.Selection.getSelection()
obj = sel[0].Shape
findholes(obj)
User avatar
NormandC
Veteran
Posts: 18587
Joined: Sat Feb 06, 2010 9:52 pm
Location: Québec, Canada

Re: macro for finding holes

Post by NormandC »

I think this would be great to have in the Macro recipes in the wiki.

It's a pity we cannot create a "shortcut" for a topic linking to a different sub-forum. This topic would also have its place in the "Python scripting and macros" sub-forum.
danielfalck
Posts: 395
Joined: Fri Oct 07, 2011 8:58 pm
Location: Beaverton,Oregon, USA
Contact:

Re: macro for finding holes

Post by danielfalck »

Here is a screenshot of the type of model I've been able to parse successfully:

Image

I guess, that if a boss has a hole in it, it would fail. Maybe creating a line from one corner of the face BoundBox.Diagonal to another (and trim the line so that it lies within the circle) and use obj.isInside would catch that one.

Edit- Blind holes in the bottom of the part are a problem....
nahshon
Posts: 225
Joined: Wed Jul 24, 2013 8:06 pm

Re: macro for finding holes

Post by nahshon »

Maybe the experts could help.
  1. What's the best way to find if a cylinder face is representing a hole?
    I used:

    Code: Select all

    c = f.curvatureAt(0,0)
    if c[0] > 0 or c[1] > 0:   # not a hole
        continue
    I believe there are better ways.
  2. I want to check possible drilling direction by using the intersection (cut) between the body and a cylinder.
    I only need to know if the intersection is empty or not (simple collision testing). What's the correct way?
    (finding the actual cut is possible but it's too expensive).
Thanks,
-- Itai
wmayer
Founder
Posts: 20243
Joined: Thu Feb 19, 2009 10:32 am
Contact:

Re: macro for finding holes

Post by wmayer »

Use the cylinder axis and check if it hits the model somewhere. If not you can be sure it's a hole but if it hits it doesn't necessarily mean it's not a hole. And is it intended that you only consider cylindrical holes? What about conical holes or polygonal holes? What if the hole is not straight?
Post Reply