Here some code to demostrate the proof of concept of my the approach
Code: Select all
import FreeCAD
from FreeCAD import Base, Rotation, Vector
import Part
import Path
import Draft
import DraftVecUtils
import draftgeoutils.arcs as dgu
import math as mt
import numpy as np
DOC_NAME = "Pippo"
DOC = FreeCAD.activeDocument()
def clear_doc():
"""
Clear the active document deleting all the objects
"""
for obj in DOC.Objects:
DOC.removeObject(obj.Name)
if DOC is None:
FreeCAD.newDocument(DOC_NAME)
FreeCAD.setActiveDocument(DOC_NAME)
DOC = FreeCAD.activeDocument()
VIEW = FreeCAD.Gui.ActiveDocument.ActiveView
else:
clear_doc()
VIEW = FreeCAD.Gui.ActiveDocument.ActiveView
def setview():
"""Rearrange View"""
DOC.recompute()
VIEW.viewAxometric()
VIEW.setAxisCross(True)
VIEW.fitAll()
def a2P(a, b):
"""calculate the angle between two vectors
angle is returned in radians
"""
deltaY = b.y - a.y
deltaX = b.x - a.x
# atan2 return a value in radians
angle = mt.atan2(deltaY, deltaX)
return angle
def dest_pt(pt, angle, length):
"""calculate destination point
Parameters:
pt = starting point
angle = rad
length = units
"""
dpx = pt.x + mt.cos(angle) * length
dpy = pt.y + mt.sin(angle) * length
return Vector(dpx, dpy, pt.z)
def get_arc_center(firstPt, lastPt, center):
radius1 = firstPt.sub(center).Length
radius2 = lastPt.sub(center).Length
thirdPt = Vector(firstPt.sub(center).add(lastPt).sub(center))
thirdPt.normalize()
thirdPt.scale(radius1, radius1, radius1)
thirdPt = thirdPt.add(center)
return thirdPt
EPS = 0.10
EPS_C = EPS * -0.5
VZOR = Vector(0,0,0)
RZO = Rotation(0, 0, 0)
obj1 = Part.makeCylinder(30, 10, Vector(0,0,0), Vector(0,0,1), 70)
obj1.Placement = FreeCAD.Placement(Vector(0,0,0), Rotation(32,0,0))
#Part.show(obj1)
segment = obj1.Edges[0]
print(dgu.isClockwise(segment))
anobj = segment.Curve
rad = anobj.Radius
print("Original segment perimeter = {}".format(2*rad*mt.pi))
print("Original segment Length = {}".format(segment.Length))
center = anobj.Center
p1 = segment.Vertexes[0].Point
p2 = segment.Vertexes[-1].Point
midarcpt = get_arc_center(p1, p2, center)
line1 = Part.makeLine(center, p1)
line2 = Part.makeLine(center, p2)
line3 = Part.makeLine(center, midarcpt)
Part.show(segment)
Part.show(line1)
Part.show(line2)
Part.show(line3)
offset = - 10
red_f = 2
a1 = a2P(center, p1)
a2 = a2P(center, p2)
a3 = a2P(center, midarcpt)
spt1 = dest_pt(center, a1, (line1.Length + offset) )
spt2 = dest_pt(center, a2, (line2.Length + offset) )
spt3 = dest_pt(center, a3, (line3.Length + offset) )
newarc = Part.Edge(Part.Arc(spt2, spt3, spt1))
#Part.show(newarc)
v1 = spt1.sub(center)
v2 = spt2.sub(center)
if newarc.Curve.Axis.z > 0:
# clockwise
ang1 = -DraftVecUtils.angle(v1)
ang2 = -DraftVecUtils.angle(v2)
else:
# counterclockwise
ang2 = -DraftVecUtils.angle(v1)
ang1 = -DraftVecUtils.angle(v2)
print(mt.degrees(ang1))
print(mt.degrees(ang2))
gen_circ = newarc.Curve.Radius * 2 * mt.pi
nalen = newarc.Length
na_sect = mt.degrees(ang1 - ang2)
ang_adv = gen_circ / 360
red_f = red_f / ang_adv # ang_adv in degree
e_ang = mt.radians(mt.degrees(ang2) + red_f)
s_ang = mt.radians(mt.degrees(ang1) - red_f)
print("New Arc Length = {} gen circumf = {}".format(nalen, gen_circ))
print("New Arc sector width {} ang adv = {}".format(na_sect, ang_adv))
slot = Part.Circle()
slot.Center = center
slot.Radius = newarc.Curve.Radius
slot_sh = slot.toShape(e_ang, s_ang)
Part.show(slot_sh)
setview()
Code is pretty self.explanatory.
I have to cope with several problem, as many calculations are not in FreeCAD, or deal with some complex assumptions.
My basic assumptio is that the esdge lay on XY plane, and Z is costant, some calculations are done with this assumption.
I scavenged some code from Draft.ImportDXF and draftgeoutils, to make the calculus, as the entire methods are not useful.
I have generated a section of cylinder, and rotate it to make some difficult calculations, and extrated the "upper external" edge of the solid (not shown)
Based on this edge you have to supply two parameters
an offset that is negative as it is based on the radius of the generating arc of the circular edge
a reduction factor red_f in mm for the edge of the generated arc.
The line are cosmetic but are used in some calculations, to get the two extrema of the arc
The reduction factor is calculated from the length of the arc using the angular advanced that correspond to 1 degree and then added or subtracted to the start and end angles of the generated segment.
using the same techinque and determining the points it could be easily traced the profile for the pocket to obtain a pocket to use if the tool diameter is smaller than the pocket width.
Hope it helps
Carlo D.