Download src/Mod/PartDesign/Scripts/FilletArc.py from AbdulElahGwaith/FreeCAD: direct link, hf CLI and curl.
- Browser
- Download file 3.36 kB
-
https://huggingface.co/AbdulElahGwaith/FreeCAD/resolve/main/src/Mod/PartDesign/Scripts/FilletArc.py
- Command line
-
hf download hf://AbdulElahGwaith/FreeCAD/src/Mod/PartDesign/Scripts/FilletArc.py
-
curl -L -o FilletArc.py https://huggingface.co/AbdulElahGwaith/FreeCAD/resolve/main/src/Mod/PartDesign/Scripts/FilletArc.py
3.36 kB
| #! python | |
| # (c) 2010 Werner Mayer LGPL | |
| __author__ = "Werner Mayer <wmayer[at]users.sourceforge.net>" | |
| # 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 calculate 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()) | |