Draft: move functions to draftgeoutils.circles, part 1

This commit is contained in:
vocx-fc
2020-05-31 19:30:48 -05:00
committed by Yorik van Havre
parent 7eee6ae4f6
commit 6ec6fb2ca1
3 changed files with 184 additions and 94 deletions

View File

@@ -42,6 +42,7 @@ SET (Draft_geoutils
draftgeoutils/offsets.py
draftgeoutils/linear_algebra.py
draftgeoutils/cuboids.py
draftgeoutils/circles.py
)
SET(Draft_tests

View File

@@ -194,15 +194,7 @@ from draftgeoutils.geometry import findDistance
from draftgeoutils.intersections import angleBisection
def findClosestCircle(point, circles):
"""Return the circle with closest center."""
dist = 1000000
closest = None
for c in circles:
if c.Center.sub(point).Length < dist:
dist = c.Center.sub(point).Length
closest = c
return closest
from draftgeoutils.circles import findClosestCircle
from draftgeoutils.faces import isCoplanar
@@ -241,34 +233,7 @@ from draftgeoutils.fillets import fillet
from draftgeoutils.fillets import filletWire
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
from draftgeoutils.circles import getCircleFromSpline
from draftgeoutils.wires import curvetowire
@@ -397,67 +362,13 @@ def circleFrom3tan(tan1, tan2, tan3):
return circleFrom2Circle1Lines(tan1, tan2, tan3)
def circlefrom2Lines1Point(edge1, edge2, point):
"""circlefrom2Lines1Point(edge, edge, Vector)"""
bis = angleBisection(edge1, edge2)
if not bis: return None
mirrPoint = mirror(point, bis)
return circlefrom1Line2Points(edge1, point, mirrPoint)
from draftgeoutils.circles import circlefrom2Lines1Point
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
from draftgeoutils.circles import circlefrom1Line2Points
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
from draftgeoutils.circles import circleFrom2LinesRadius
def circleFrom3LineTangents(edge1, edge2, edge3):

View File

@@ -0,0 +1,178 @@
# ***************************************************************************
# * 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 for circle operations."""
## @package circles
# \ingroup DRAFTGEOUTILS
# \brief Provides various functions for circle operations.
import math
import lazy_loader.lazy_loader as lz
import FreeCAD as App
import DraftVecUtils
from draftgeoutils.general import geomType, edg, vec, NORM
from draftgeoutils.geometry import mirror
from draftgeoutils.edges import findMidpoint
from draftgeoutils.intersections import findIntersection, angleBisection
# Delay import of module until first use because it is heavy
Part = lz.LazyLoader("Part", globals(), "Part")
def findClosestCircle(point, circles):
"""Return the circle with closest center to a given point."""
dist = 1000000
closest = None
for c in circles:
if c.Center.sub(point).Length < dist:
dist = c.Center.sub(point).Length
closest = c
return closest
def getCircleFromSpline(edge):
"""Return a circle-based edge from a bspline-based edge.
Return None if the edge is not a BSplineCurve.
"""
if geomType(edge) != "BSplineCurve" or 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 circlefrom1Line2Points(edge, p1, p2):
"""Return a list of circles created from an edge and two points.
It calculates up to 2 possible centers.
"""
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 = App.Vector.add(s, App.Vector(edgeDir).multiply(projectedDist))
projectedCen2 = App.Vector.add(s, App.Vector(edgeDir).multiply(-projectedDist))
perpEdgeDir = edgeDir.cross(App.Vector(0, 0, 1))
perpCen1 = App.Vector.add(projectedCen1, perpEdgeDir)
perpCen2 = App.Vector.add(projectedCen2, perpEdgeDir)
mid = findMidpoint(p1_p2)
x = DraftVecUtils.crossproduct(vec(p1_p2))
x.normalize()
perp_mid = App.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 circlefrom2Lines1Point(edge1, edge2, point):
"""Return a list of circles from two edges and one point."""
bis = angleBisection(edge1, edge2)
if not bis:
return None
mirrPoint = mirror(point, bis)
return circlefrom1Line2Points(edge1, point, mirrPoint)
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