This script is used to generate a pocket hole in a model.


1) Open a part model to which you would like to apply the pocket hole.

2) Click on the Script tab of the ribbon, and then click on Launch.

3) Paste the below script into the New Script Window, click on Save As in the script tab of the ribbon and save the file to a folder.

4) Place the attached PocketHoleCreatorIcon.png into the same folder from step (3) above.

5) Click Run from the Script section of the ribbon and the Pocket Hole Creator dialog will appear.

6) Click on an Edge of the model to populate the Edge field of the dialog.  Click on the Face field of the dialog, and then click on a Face of the model to populate it.

7) Input the rest of your desired parameters into the dialog, and click Create Pocket Hole to complete the operation.


# Pocket Hole Creator
# (c) Alibre, LLC 2019, All Rights Reserved
# Version 1.00

from __future__ import division
from math import *

# compares two points [X1, Y1, Z1] and [X2, Y2, Z2]
# returns true if they are the same
def PointsAreEqual(P1, P2):
  if (round(P1[0], 6) == round(P2[0], 6) and
      round(P1[1], 6) == round(P2[1], 6) and
      round(P1[2], 6) == round(P2[2], 6)):
    return True
  else:
    return False

# gets part faces that use an edge
# returns a list of faces
def GetFacesFromEdge(Prt, Ege):
  Faces = []
  PartEdge = [[Ege.Vertices[0].X, Ege.Vertices[0].Y, Ege.Vertices[0].Z], [Ege.Vertices[1].X, Ege.Vertices[1].Y, Ege.Vertices[1].Z]]
  for Fce in Prt.Faces:
    for Edg in Fce.GetEdges():
      EdgeVertices = Edg.GetVertices()
      V1 = [EdgeVertices[0].X, EdgeVertices[0].Y, EdgeVertices[0].Z]
      V2 = [EdgeVertices[1].X, EdgeVertices[1].Y, EdgeVertices[1].Z]
      if ((PointsAreEqual(V1, PartEdge[0]) and PointsAreEqual(V2, PartEdge[1])) or
          (PointsAreEqual(V2, PartEdge[0]) and PointsAreEqual(V1, PartEdge[1]))):
         Faces.append(Fce)
  return Faces

# given a part, face and edge of the face this returns the other face
# that shares the same edge
def GetOtherFace(Prt, Edg, TopFace):
  Fces = GetFacesFromEdge(Prt, Edg)
  for EgeFace in Fces:
    if EgeFace.Name != TopFace.Name:
      return EgeFace
  return None

# creates a pocket hole
def CreatePocketHole(Values):
  # TargetEdge = edge that the pocket hole is on
  # Fce = face where the pocket is inserted
  # DistanceFromEdge = distance from the edge of the face for the packet
  # Depth = distance from pocket to drill hole
  # Diameter = diameter of packet
  # DrillDiameter = diameter of drill hole
  # Angle = angle of pocket
  TargetEdge       = Values[1]
  Fce              = Values[2]
  DistanceFromEdge = Values[3]
  Depth            = Values[4]
  Diameter         = Values[5]
  DrillDiameter    = Values[6]
  Angle            = Values[7]

  Prt = Fce.GetPart()

  # get face that has exit hole
  ExitFace = GetOtherFace(Prt, TargetEdge, Fce)

  # get thickness of part (height of face with exit hole)
  ExitFaceEdges = ExitFace.GetEdges()
   
  Thickness = 0
  for ExEdg in ExitFaceEdges:
    if ExEdg.Length > 0:
      if ExEdg.Length != TargetEdge.Length:
        Thickness = ExEdg.Length
  if Thickness == 0:
    print "Unable to get thickness of part"
    sys.exit()

  # get location of center of exit hole
  ExitHoleCenterX = TargetEdge.Length - DistanceFromEdge
  ExitHoleCenterY = Thickness / 2.0

  # get location of exit hole center in 3D coordinates
  ExitSk = Prt.AddSketch('Exit Sk', ExitFace)
  ExitSk.StartFaceMapping(TargetEdge.Vertices[0], TargetEdge.Vertices[1])
  ExitPt = ExitSk.AddPoint(ExitHoleCenterX, ExitHoleCenterY, False)
  ExitSk.StopFaceMapping()
  ExitPtGlobal = ExitSk.PointtoGlobal(ExitSk.Figures[0].X, ExitSk.Figures[0].Y)

  Prt.RemoveSketch(ExitSk)

  # create exit point
  ExitPoint = Prt.AddPoint('Exit', ExitPtGlobal[0], ExitPtGlobal[1], ExitPtGlobal[2])

  # get location of entry hole in 2D
  EntryHoleCenterX = DistanceFromEdge
  EntryHoleCenterY = (Thickness / 2.0) / tan(radians(Angle))

  # get location of entry hole center in 3D coordinates
  EntrySk = Prt.AddSketch('Entry Sk', Fce)
  EntrySk.StartFaceMapping(TargetEdge.Vertices[0], TargetEdge.Vertices[1])
  EntryPt = EntrySk.AddPoint(EntryHoleCenterX, EntryHoleCenterY, False)
  EntrySk.StopFaceMapping()
  EntryPtGlobal = EntrySk.PointtoGlobal(EntrySk.Figures[0].X, EntrySk.Figures[0].Y)
  Prt.RemoveSketch(EntrySk)

  # create entry point
  EntryPoint = Prt.AddPoint('Entry', EntryPtGlobal[0], EntryPtGlobal[1], EntryPtGlobal[2])

  # create axis from entry to exit point
  PocketAxis = Prt.AddAxis('Pocket Axis', EntryPoint.GetCoordinates(), ExitPoint.GetCoordinates())

  # create plane perpendicular to axis on the start point
  nx = ExitPtGlobal[0] - EntryPtGlobal[0]
  ny = ExitPtGlobal[1] - EntryPtGlobal[1]
  nz = ExitPtGlobal[2] - EntryPtGlobal[2]
  EntryPlane = Prt.AddPlane('Entry Plane', [nx, ny, nz], EntryPoint.GetCoordinates())

  # get drill distances
  EntrytoExitDistance = (Thickness / 2.0) / sin(radians(Angle))
  Drill1Distance = EntrytoExitDistance - Depth

  # first drill
  Drill1Sk = Prt.AddSketch('Drill 1', EntryPlane)
  DrillCenter = Drill1Sk.GlobaltoPoint(EntryPtGlobal[0], EntryPtGlobal[1], EntryPtGlobal[2])
  Drill1Sk.AddCircle(DrillCenter[0], DrillCenter[1], Diameter, False)
  Prt.AddExtrudeCut('Drill 1', Drill1Sk, Drill1Distance * 2, False, Part.EndCondition.MidPlane, None, 0, Part.DirectionType.Normal, None, 0, 0)

  # second drill
  Drill2Sk = Prt.AddSketch('Drill 2', EntryPlane)
  DrillCenter = Drill2Sk.GlobaltoPoint(EntryPtGlobal[0], EntryPtGlobal[1], EntryPtGlobal[2])
  Drill2Sk.AddCircle(DrillCenter[0], DrillCenter[1], DrillDiameter, False)
  Prt.AddExtrudeCut('Drill 2', Drill2Sk, 0, False, Part.EndCondition.ThroughAll, None, 0, Part.DirectionType.Normal, None, 0, 0)

  # clean up
  EntryPoint.Hide()
  ExitPoint.Hide()
  PocketAxis.Hide()
  EntryPlane.Hide()

###########################################################################################

# check minimum requirements
if AlibreScriptVersion < 1110:
  sys.exit('Please upgrade your copy of Alibre Design to use this script')

ScriptName = 'Pocket Hole Creator'

Win = Windows()

# define options to show in dialog window
Options = []
Options.append([None, WindowsInputTypes.Image, 'PocketHoleCreatorIcon.png', 200])
Options.append(['Edge', WindowsInputTypes.Edge, None])
Options.append(['Face', WindowsInputTypes.Face, None])
Options.append(['Distance From Edge', WindowsInputTypes.Real, 20.0])
Options.append(['Depth', WindowsInputTypes.Real, 10.0])
Options.append(['Diameter', WindowsInputTypes.Real, 10.0])
Options.append(['Drill Diameter', WindowsInputTypes.Real, 4.0])
Options.append(['Angle', WindowsInputTypes.Real, 15.0])

# show utility window
Win.UtilityDialog(ScriptName, 'Create Pocket Hole', CreatePocketHole, None, Options, 200)