#! python # -*- coding: utf-8 -*- # (c) 2010 Werner Mayer LGPL __author__ = "Werner Mayer " # Formulas: # M2 = P + b*r2 + t*u # S1 = (r2*M1 + r1*M2)/(r1+r2) # S2 = M2-b*r2 import math # 3d vector class class Vector: def __init__(self,x,y,z): self.x=x self.y=y self.z=z def add(self,vec): return Vector(self.x+vec.x,self.y+vec.y,self.z+vec.z) def sub(self,vec): return Vector(self.x-vec.x,self.y-vec.y,self.z-vec.z) def dot(self,vec): return self.x*vec.x+self.y*vec.y+self.z*vec.z def mult(self,s): return Vector(self.x*s,self.y*s,self.z*s) def cross(self,vec): return Vector( self.y * vec.z - self.z * vec.y, self.z * vec.x - self.x * vec.z, self.x * vec.y - self.y * vec.x) def length(self): return math.sqrt(self.x*self.x+self.y*self.y+self.z*self.z) def norm(self): l = self.length() if l > 0: self.x /= l self.y /= l self.z /= l def __repr__(self): return "(%f,%f,%f)" % (self.x,self.y,self.z) # A signum function def sgn(val): if val > 0: return 1 elif val < 0: return -1 else: return 0 # M1 ... is the center of the arc # P ... is the end point of the arc and start point of the line # Q .. is a second point on the line # N ... is the normal of the plane where the arc and the line lie on, usually N=(0,0,1) # r2 ... the fillet radius # ccw ... counter-clockwise means which part of the arc is given. ccw must be either True or False def makeFilletArc(M1,P,Q,N,r2,ccw): u = Q.sub(P) v = P.sub(M1) if ccw: b = u.cross(N) else: b = N.cross(u) b.norm() uu = u.dot(u) uv = u.dot(v) r1 = v.length() # distinguish between internal and external fillets r2 *= sgn(uv); cc = 2.0 * r2 * (b.dot(v)-r1) dd = uv * uv - uu * cc if dd < 0: raise RuntimeError("Unable to caluclate intersection points") t1 = (-uv + math.sqrt(dd)) / uu t2 = (-uv - math.sqrt(dd)) / uu if (abs(t1) < abs(t2)): t = t1 else: t = t2 br2 = b.mult(r2) print(br2) ut = u.mult(t) print(ut) M2 = P.add(ut).add(br2) S1 = M1.mult(r2/(r1+r2)).add(M2.mult(r1/(r1+r2))) S2 = M2.sub(br2) return (S1,S2,M2) def test(): from FreeCAD import Base import Part P1=Base.Vector(1,-5,0) P2=Base.Vector(-5,2,0) P3=Base.Vector(1,5,0) #Q=Base.Vector(5,10,0) #Q=Base.Vector(5,11,0) Q=Base.Vector(5,0,0) r2=3.0 axis=Base.Vector(0,0,1) ccw=False arc=Part.ArcOfCircle(P1,P2,P3) C=arc.Center Part.show(Part.makeLine(P3,Q)) Part.show(arc.toShape()) (S1,S2,M2) = makeArc(Vector(C.x,C.y,C.z),Vector(P3.x,P3.y,P3.z),Vector(Q.x,Q.y,Q.z),Vector(axis.x,axis.y,axis.z),r2,ccw) circle=Part.Circle(Base.Vector(M2.x,M2.y,M2.z), Base.Vector(0,0,1), math.fabs(r2)) Part.show(circle.toShape())