File size: 5,790 Bytes
985c397 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 | # SPDX-License-Identifier: LGPL-2.1-or-later
# ***************************************************************************
# * Copyright (c) 2009, 2010 Yorik van Havre <yorik@uncreated.net> *
# * Copyright (c) 2009, 2010 Ken Cline <cline@frii.com> *
# * *
# * This file is part of the FreeCAD CAx development system. *
# * *
# * This program is free software; you can redistribute it and/or modify *
# * it under the terms of the GNU Lesser General Public License (LGPL) *
# * as published by the Free Software Foundation; either version 2 of *
# * the License, or (at your option) any later version. *
# * for detail see the LICENCE text file. *
# * *
# * FreeCAD is distributed in the hope that it will be useful, *
# * but WITHOUT ANY WARRANTY; without even the implied warranty of *
# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
# * GNU Library General Public License for more details. *
# * *
# * You should have received a copy of the GNU Library General Public *
# * License along with FreeCAD; if not, write to the Free Software *
# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
# * USA *
# * *
# ***************************************************************************
"""Provides various functions to work with arcs."""
## @package arcs
# \ingroup draftgeoutils
# \brief 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
# Delay import of module until first use because it is heavy
Part = lz.LazyLoader("Part", globals(), "Part")
## \addtogroup draftgeoutils
# @{
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
# we take an arbitrary other point on the edge that has little chances
# to be aligned with the first one
v2 = edge.Curve.tangent(edge.ParameterRange[0] + 0.01)[0]
n = edge.Curve.Axis
# if that axis points "the wrong way" from the reference, we invert it
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
# (PREC = 4 = same as Part Module), Is it possible?
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:
# 2-point arc
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:
# circle
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
## @}
|