def circlefrom1Line2Points(edge, p1, p2): """circlefrom1Line2Points(edge, Vector, Vector)""" p1_p2 = edg(p1, p2) s = findIntersection(edge, p1_p2, True, True) if not s: return None s = s[0] v1 = p1.sub(s) v2 = p2.sub(s) projectedDist = math.sqrt(abs(v1.dot(v2))) edgeDir = vec(edge) edgeDir.normalize() projectedCen1 = Vector.add(s, Vector(edgeDir).multiply(projectedDist)) projectedCen2 = Vector.add(s, Vector(edgeDir).multiply(-projectedDist)) perpEdgeDir = edgeDir.cross(Vector(0, 0, 1)) perpCen1 = Vector.add(projectedCen1, perpEdgeDir) perpCen2 = Vector.add(projectedCen2, perpEdgeDir) mid = findMidpoint(p1_p2) x = DraftVecUtils.crossproduct(vec(p1_p2)) x.normalize() perp_mid = Vector.add(mid, x) cen1 = findIntersection(edg(projectedCen1, perpCen1), edg(mid, perp_mid), True, True) cen2 = findIntersection(edg(projectedCen2, perpCen2), edg(mid, perp_mid), True, True) circles = [] if cen1: radius = DraftVecUtils.dist(projectedCen1, cen1[0]) circles.append(Part.Circle(cen1[0], NORM, radius)) if cen2: radius = DraftVecUtils.dist(projectedCen2, cen2[0]) circles.append(Part.Circle(cen2[0], NORM, radius)) if circles: return circles else: return None
def circleFrom3CircleTangents(circle1, circle2, circle3): """Return the circle that is tangent to three other circles. This problem is called the 'Problem of Appollonius'. A special case is that of 'Soddy circles'. To Do ----- Currently not all possible solutions are found, only the Soddy circles. * Calc all 6 homothetic centers. * Create 3 lines from the inner and 4 from the outer h. center. * Calc. the 4 inversion poles of these lines for each circle. * Calc. the radical center of the 3 circles. * Calc. the intersection points (max. 8) of 4 lines (through each inversion pole and the radical center) with the circle. * This gives us all the tangent points. """ if (geomType(circle1) != "Circle" and geomType(circle2) != "Circle" and geomType(circle3) == "Circle"): print("debug: circleFrom3CircleTangents bad input! Must be circles") return None int12 = findIntersection(circle1, circle2, True, True) int23 = findIntersection(circle2, circle3, True, True) int31 = findIntersection(circle3, circle1, True, True) if int12 and int23 and int31: if len(int12) == 1 and len(int23) == 1 and len(int31) == 1: # If only one intersection with each circle, Soddy circle # r1 = circle1.Curve.Radius # r2 = circle2.Curve.Radius # r3 = circle3.Curve.Radius outerSoddy = outerSoddyCircle(circle1, circle2, circle3) # print(str(outerSoddy)) # Debug innerSoddy = innerSoddyCircle(circle1, circle2, circle3) # print(str(innerSoddy)) # Debug circles = [] if outerSoddy: circles.append(outerSoddy) if innerSoddy: circles.append(innerSoddy) return circles # Here the rest of the circles should be calculated # ... else: # Some circles are inside each other or an error has occurred. return None
def circleFrom3CircleTangents(circle1, circle2, circle3): """ http://en.wikipedia.org/wiki/Problem_of_Apollonius#Inversive_methods http://mathworld.wolfram.com/ApolloniusCircle.html http://mathworld.wolfram.com/ApolloniusProblem.html """ if (geomType(circle1) == "Circle") and (geomType(circle2) == "Circle") \ and (geomType(circle3) == "Circle"): int12 = findIntersection(circle1, circle2, True, True) int23 = findIntersection(circle2, circle3, True, True) int31 = findIntersection(circle3, circle1, True, True) if int12 and int23 and int31: if len(int12) == 1 and len(int23) == 1 and len(int31) == 1: # Only one intersection with each circle. # => "Soddy Circle" - 2 solutions. # http://en.wikipedia.org/wiki/Problem_of_Apollonius#Mutually_tangent_given_circles:_Soddy.27s_circles_and_Descartes.27_theorem # http://mathworld.wolfram.com/SoddyCircles.html # http://mathworld.wolfram.com/InnerSoddyCenter.html # http://mathworld.wolfram.com/OuterSoddyCenter.html r1 = circle1.Curve.Radius r2 = circle2.Curve.Radius r3 = circle3.Curve.Radius outerSoddy = outerSoddyCircle(circle1, circle2, circle3) # print(str(outerSoddy) + "\n") # Debug innerSoddy = innerSoddyCircle(circle1, circle2, circle3) # print(str(innerSoddy) + "\n") # Debug circles = [] if outerSoddy: circles.append(outerSoddy) if innerSoddy: circles.append(innerSoddy) return circles # @todo Calc all 6 homothetic centers. # @todo Create 3 lines from the inner and 4 from the outer h. center. # @todo Calc. the 4 inversion poles of these lines for each circle. # @todo Calc. the radical center of the 3 circles. # @todo Calc. the intersection points (max. 8) of 4 lines (through each inversion pole and the radical center) with the circle. # This gives us all the tangent points. else: # Some circles are inside each other or an error has occurred. return None else: print("debug: circleFrom3CircleTangents bad parameters!\n") # FreeCAD.Console.PrintMessage("debug: circleFrom3CircleTangents bad parameters!\n") return None
def getCircleFromSpline(edge): """Return a circle-based edge from a bspline-based edge.""" if geomType(edge) != "BSplineCurve": return None if len(edge.Vertexes) != 1: return None # get 2 points p1 = edge.Curve.value(0) p2 = edge.Curve.value(math.pi / 2) # get 2 tangents t1 = edge.Curve.tangent(0)[0] t2 = edge.Curve.tangent(math.pi / 2)[0] # get normal n = p1.cross(p2) if DraftVecUtils.isNull(n): return None # get rays r1 = DraftVecUtils.rotate(t1, math.pi / 2, n) r2 = DraftVecUtils.rotate(t2, math.pi / 2, n) # get center (intersection of rays) i = findIntersection(p1, p1.add(r1), p2, p2.add(r2), True, True) if not i: return None c = i[0] r = (p1.sub(c)).Length circle = Part.makeCircle(r, c, n) #print(circle.Curve) return circle
def findRadicalCenter(circle1, circle2, circle3): """ findRadicalCenter(circle1, circle2, circle3): Calculates the radical center (also called the power center) of three circles. It is the intersection point of the three radical axes of the pairs of circles. http://en.wikipedia.org/wiki/Power_center_(geometry) http://mathworld.wolfram.com/RadicalCenter.html @sa findRadicalAxis """ if (geomType(circle1) == "Circle") and (geomType(circle2) == "Circle"): radicalAxis12 = findRadicalAxis(circle1, circle2) radicalAxis23 = findRadicalAxis(circle1, circle2) if not radicalAxis12 or not radicalAxis23: # No radical center could be calculated. return None int = findIntersection(radicalAxis12, radicalAxis23, True, True) if int: return int else: # No radical center could be calculated. return None else: FreeCAD.Console.PrintMessage( "debug: findRadicalCenter bad parameters!\n") return None
def findRadicalCenter(circle1, circle2, circle3): """Calculate the radical center of three circles. It is also called the power center. It is the intersection point of the three radical axes of the pairs of circles. http://en.wikipedia.org/wiki/Power_center_(geometry) http://mathworld.wolfram.com/RadicalCenter.html See Also -------- findRadicalAxis """ if (geomType(circle1) != "Circle" or geomType(circle2) != "Circle" or geomType(circle3) != "Circle"): print("debug: findRadicalCenter bad parameters! Must be circles.") return None radicalAxis12 = findRadicalAxis(circle1, circle2) radicalAxis23 = findRadicalAxis(circle2, circle3) if not radicalAxis12 or not radicalAxis23: # No radical center could be calculated. return None intersect = findIntersection(radicalAxis12, radicalAxis23, True, True) if intersect: return intersect else: # No radical center could be calculated. return None
def circleFrom2LinesRadius(edge1, edge2, radius): """Retun a list of circles from two edges and one radius. It calculates 4 centers. """ intsec = findIntersection(edge1, edge2, True, True) if not intsec: return None intsec = intsec[0] bis12 = angleBisection(edge1, edge2) bis21 = Part.LineSegment(bis12.Vertexes[0].Point, DraftVecUtils.rotate(vec(bis12), math.pi/2.0)) ang12 = abs(DraftVecUtils.angle(vec(edge1), vec(edge2))) ang21 = math.pi - ang12 dist12 = radius / math.sin(ang12 * 0.5) dist21 = radius / math.sin(ang21 * 0.5) circles = [] cen = App.Vector.add(intsec, vec(bis12).multiply(dist12)) circles.append(Part.Circle(cen, NORM, radius)) cen = App.Vector.add(intsec, vec(bis12).multiply(-dist12)) circles.append(Part.Circle(cen, NORM, radius)) cen = App.Vector.add(intsec, vec(bis21).multiply(dist21)) circles.append(Part.Circle(cen, NORM, radius)) cen = App.Vector.add(intsec, vec(bis21).multiply(-dist21)) circles.append(Part.Circle(cen, NORM, radius)) return circles
def circleFrom3LineTangents(edge1, edge2, edge3): """Return a list of circles from three edges. It calculates up to 6 possible centers. """ def rot(ed): geo = Part.LineSegment(v1(ed), v1(ed).add(DraftVecUtils.rotate(vec(ed), math.pi/2))) return geo.toShape() bis12 = angleBisection(edge1, edge2) bis23 = angleBisection(edge2, edge3) bis31 = angleBisection(edge3, edge1) intersections = [] intsec = findIntersection(bis12, bis23, True, True) if intsec: radius = findDistance(intsec[0], edge1).Length intersections.append(Part.Circle(intsec[0], NORM, radius)) intsec = findIntersection(bis23, bis31, True, True) if intsec: radius = findDistance(intsec[0], edge1).Length intersections.append(Part.Circle(intsec[0], NORM, radius)) intsec = findIntersection(bis31, bis12, True, True) if intsec: radius = findDistance(intsec[0], edge1).Length intersections.append(Part.Circle(intsec[0], NORM, radius)) intsec = findIntersection(rot(bis12), rot(bis23), True, True) if intsec: radius = findDistance(intsec[0], edge1).Length intersections.append(Part.Circle(intsec[0], NORM, radius)) intsec = findIntersection(rot(bis23), rot(bis31), True, True) if intsec: radius = findDistance(intsec[0], edge1).Length intersections.append(Part.Circle(intsec[0], NORM, radius)) intsec = findIntersection(rot(bis31), rot(bis12), True, True) if intsec: radius = findDistance(intsec[0], edge1).Length intersections.append(Part.Circle(intsec[0], NORM, radius)) circles = [] for intsec in intersections: exists = False for cir in circles: if DraftVecUtils.equals(cir.Center, intsec.Center): exists = True break if not exists: circles.append(intsec) if circles: return circles else: return None
def circleFrom3LineTangents(edge1, edge2, edge3): """circleFrom3LineTangents(edge,edge,edge)""" def rot(ed): return Part.LineSegment( v1(ed), v1(ed).add(DraftVecUtils.rotate(vec(ed), math.pi / 2))).toShape() bis12 = angleBisection(edge1, edge2) bis23 = angleBisection(edge2, edge3) bis31 = angleBisection(edge3, edge1) intersections = [] int = findIntersection(bis12, bis23, True, True) if int: radius = findDistance(int[0], edge1).Length intersections.append(Part.Circle(int[0], NORM, radius)) int = findIntersection(bis23, bis31, True, True) if int: radius = findDistance(int[0], edge1).Length intersections.append(Part.Circle(int[0], NORM, radius)) int = findIntersection(bis31, bis12, True, True) if int: radius = findDistance(int[0], edge1).Length intersections.append(Part.Circle(int[0], NORM, radius)) int = findIntersection(rot(bis12), rot(bis23), True, True) if int: radius = findDistance(int[0], edge1).Length intersections.append(Part.Circle(int[0], NORM, radius)) int = findIntersection(rot(bis23), rot(bis31), True, True) if int: radius = findDistance(int[0], edge1).Length intersections.append(Part.Circle(int[0], NORM, radius)) int = findIntersection(rot(bis31), rot(bis12), True, True) if int: radius = findDistance(int[0], edge1).Length intersections.append(Part.Circle(int[0], NORM, radius)) circles = [] for int in intersections: exists = False for cir in circles: if DraftVecUtils.equals(cir.Center, int.Center): exists = True break if not exists: circles.append(int) if circles: return circles else: return None
def circleFrom2LinesRadius(edge1, edge2, radius): """circleFrom2LinesRadius(edge,edge,radius)""" int = findIntersection(edge1, edge2, True, True) if not int: return None int = int[0] bis12 = angleBisection(edge1, edge2) bis21 = Part.LineSegment(bis12.Vertexes[0].Point, DraftVecUtils.rotate(vec(bis12), math.pi / 2.0)) ang12 = abs(DraftVecUtils.angle(vec(edge1), vec(edge2))) ang21 = math.pi - ang12 dist12 = radius / math.sin(ang12 * 0.5) dist21 = radius / math.sin(ang21 * 0.5) circles = [] cen = Vector.add(int, vec(bis12).multiply(dist12)) circles.append(Part.Circle(cen, NORM, radius)) cen = Vector.add(int, vec(bis12).multiply(-dist12)) circles.append(Part.Circle(cen, NORM, radius)) cen = Vector.add(int, vec(bis21).multiply(dist21)) circles.append(Part.Circle(cen, NORM, radius)) cen = Vector.add(int, vec(bis21).multiply(-dist21)) circles.append(Part.Circle(cen, NORM, radius)) return circles
def angleBisection(edge1, edge2): """angleBisection(edge,edge) - Returns an edge that bisects the angle between the 2 edges.""" if (geomType(edge1) == "Line") and (geomType(edge2) == "Line"): p1 = edge1.Vertexes[0].Point p2 = edge1.Vertexes[-1].Point p3 = edge2.Vertexes[0].Point p4 = edge2.Vertexes[-1].Point int = findIntersection(edge1, edge2, True, True) if int: line1Dir = p2.sub(p1) angleDiff = DraftVecUtils.angle(line1Dir, p4.sub(p3)) ang = angleDiff * 0.5 origin = int[0] line1Dir.normalize() dir = DraftVecUtils.rotate(line1Dir, ang) return Part.LineSegment(origin, origin.add(dir)).toShape() else: diff = p3.sub(p1) origin = p1.add(diff.multiply(0.5)) dir = p2.sub(p1) dir.normalize() return Part.LineSegment(origin, origin.add(dir)).toShape() else: return None