| | |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | """Provides various functions to work with arcs.""" |
| | |
| | |
| | |
| |
|
| | import math |
| | import lazy_loader.lazy_loader as lz |
| |
|
| | import FreeCAD as App |
| | import DraftVecUtils |
| |
|
| | from draftgeoutils.general import geomType |
| | from draftgeoutils.edges import findMidpoint |
| |
|
| | |
| | Part = lz.LazyLoader("Part", globals(), "Part") |
| |
|
| | |
| | |
| |
|
| |
|
| | def isClockwise(edge, ref=None): |
| | """Return True if a circle-based edge has a clockwise direction. |
| | |
| | Parameters |
| | ---------- |
| | edge : |
| | The edge to be analyzed. |
| | |
| | ref : Vector, optional |
| | The normal around which the direction of the edge is to be determined. |
| | Defaults to the Z normal vector. |
| | |
| | Returns |
| | ------- |
| | bool |
| | Returns True if the edge is clockwise oriented around the ref Vector |
| | or not. |
| | """ |
| | if not geomType(edge) == "Circle": |
| | return True |
| |
|
| | v1 = edge.Curve.tangent(edge.ParameterRange[0])[0] |
| | if DraftVecUtils.isNull(v1): |
| | return True |
| |
|
| | |
| | |
| | v2 = edge.Curve.tangent(edge.ParameterRange[0] + 0.01)[0] |
| | n = edge.Curve.Axis |
| | |
| | if not ref: |
| | ref = App.Vector(0, 0, 1) |
| | if n.getAngle(ref) > math.pi / 2: |
| | n = n.negative() |
| |
|
| | if DraftVecUtils.angle(v1, v2, n) < 0: |
| | return False |
| |
|
| | if n.z < 0: |
| | return False |
| |
|
| | return True |
| |
|
| |
|
| | def isWideAngle(edge): |
| | """Return True if the given edge is an arc with angle > 180 degrees.""" |
| | if geomType(edge) != "Circle": |
| | return False |
| |
|
| | r = edge.Curve.Radius |
| | total = 2 * r * math.pi |
| |
|
| | if edge.Length > total / 2: |
| | return True |
| |
|
| | return False |
| |
|
| |
|
| | def arcFrom2Pts(firstPt, lastPt, center, axis=None): |
| | """Build an arc with center and 2 points, can be oriented with axis.""" |
| | radius1 = firstPt.sub(center).Length |
| | radius2 = lastPt.sub(center).Length |
| |
|
| | |
| | if round(radius1 - radius2, 4) != 0: |
| | return None |
| |
|
| | thirdPt = App.Vector(firstPt.sub(center).add(lastPt).sub(center)) |
| | thirdPt.normalize() |
| | thirdPt.scale(radius1, radius1, radius1) |
| | thirdPt = thirdPt.add(center) |
| | newArc = Part.Edge(Part.Arc(firstPt, thirdPt, lastPt)) |
| |
|
| | if axis and newArc.Curve.Axis.dot(axis) < 0: |
| | thirdPt = thirdPt.sub(center) |
| | thirdPt.scale(-1, -1, -1) |
| | thirdPt = thirdPt.add(center) |
| | newArc = Part.Edge(Part.Arc(firstPt, thirdPt, lastPt)) |
| |
|
| | return newArc |
| |
|
| |
|
| | def arcFromSpline(edge): |
| | """Turn given edge into a circular arc from three points. |
| | |
| | Takes its first point, midpoint and endpoint. It works best with bspline |
| | segments such as those from imported svg files. Use this only |
| | if you are sure your edge is really an arc. |
| | |
| | It returns None if there is a problem, including passing straight edges. |
| | """ |
| | if geomType(edge) == "Line": |
| | print("This edge is straight, cannot build an arc on it") |
| | return None |
| |
|
| | if len(edge.Vertexes) > 1: |
| | |
| | p1 = edge.Vertexes[0].Point |
| | p2 = edge.Vertexes[-1].Point |
| | ml = edge.Length / 2 |
| | p3 = edge.valueAt(ml) |
| | try: |
| | return Part.Arc(p1, p3, p2).toShape() |
| | except Part.OCCError: |
| | print("Couldn't make an arc out of this edge") |
| | return None |
| | else: |
| | |
| | p1 = edge.Vertexes[0].Point |
| | p2 = findMidpoint(edge) |
| | ray = p2.sub(p1) |
| | ray.scale(0.5, 0.5, 0.5) |
| | center = p1.add(ray) |
| | radius = ray.Length |
| | try: |
| | return Part.makeCircle(radius, center) |
| | except Part.OCCError: |
| | print("couldn't make a circle out of this edge") |
| | return None |
| |
|
| |
|
| | |
| |
|