Draft: move functions to draftgeoutils.intersections
This commit is contained in:
@@ -32,6 +32,7 @@ SET (Draft_geoutils
|
||||
draftgeoutils/__init__.py
|
||||
draftgeoutils/general.py
|
||||
draftgeoutils/edges.py
|
||||
draftgeoutils/intersections.py
|
||||
)
|
||||
|
||||
SET(Draft_tests
|
||||
|
||||
@@ -101,253 +101,11 @@ from draftgeoutils.general import isValidPath
|
||||
from draftgeoutils.edges import findEdge
|
||||
|
||||
|
||||
def findIntersection(edge1, edge2,
|
||||
infinite1=False, infinite2=False,
|
||||
ex1=False, ex2=False,
|
||||
dts=True, findAll=False):
|
||||
"""findIntersection(edge1,edge2,infinite1=False,infinite2=False,dts=True):
|
||||
returns a list containing the intersection point(s) of 2 edges.
|
||||
You can also feed 4 points instead of edge1 and edge2. If dts is used,
|
||||
Shape.distToShape() is used, which can be buggy"""
|
||||
|
||||
def getLineIntersections(pt1, pt2, pt3, pt4, infinite1, infinite2):
|
||||
if pt1:
|
||||
# first check if we don't already have coincident endpoints
|
||||
if (pt1 in [pt3,pt4]):
|
||||
return [pt1]
|
||||
elif (pt2 in [pt3,pt4]):
|
||||
return [pt2]
|
||||
norm1 = pt2.sub(pt1).cross(pt3.sub(pt1))
|
||||
norm2 = pt2.sub(pt4).cross(pt3.sub(pt4))
|
||||
if not DraftVecUtils.isNull(norm1):
|
||||
try:
|
||||
norm1.normalize()
|
||||
except:
|
||||
return []
|
||||
if not DraftVecUtils.isNull(norm2):
|
||||
try:
|
||||
norm2.normalize()
|
||||
except:
|
||||
return []
|
||||
if DraftVecUtils.isNull(norm1.cross(norm2)):
|
||||
vec1 = pt2.sub(pt1)
|
||||
vec2 = pt4.sub(pt3)
|
||||
if DraftVecUtils.isNull(vec1) or DraftVecUtils.isNull(vec2):
|
||||
return [] # One of the line has zero-length
|
||||
try:
|
||||
vec1.normalize()
|
||||
vec2.normalize()
|
||||
except:
|
||||
return []
|
||||
norm3 = vec1.cross(vec2)
|
||||
if not DraftVecUtils.isNull(norm3) and (norm3.x+norm3.y+norm3.z != 0):
|
||||
k = ((pt3.z-pt1.z)*(vec2.x-vec2.y)+(pt3.y-pt1.y)*(vec2.z-vec2.x)+ \
|
||||
(pt3.x-pt1.x)*(vec2.y-vec2.z))/(norm3.x+norm3.y+norm3.z)
|
||||
vec1.scale(k,k,k)
|
||||
intp = pt1.add(vec1)
|
||||
|
||||
if infinite1 == False and not isPtOnEdge(intp,edge1) :
|
||||
return []
|
||||
|
||||
if infinite2 == False and not isPtOnEdge(intp,edge2) :
|
||||
return []
|
||||
|
||||
return [intp]
|
||||
else :
|
||||
return [] # Lines have same direction
|
||||
else :
|
||||
return [] # Lines aren't on same plane
|
||||
|
||||
# First, check bound boxes
|
||||
if isinstance(edge1,Part.Edge) and isinstance(edge2,Part.Edge) \
|
||||
and (not infinite1) and (not infinite2):
|
||||
if not edge1.BoundBox.intersect(edge2.BoundBox):
|
||||
return [] # bound boxes don't intersect
|
||||
|
||||
# First, try to use distToShape if possible
|
||||
if dts and isinstance(edge1,Part.Edge) and isinstance(edge2,Part.Edge) \
|
||||
and (not infinite1) and (not infinite2):
|
||||
dist, pts, geom = edge1.distToShape(edge2)
|
||||
sol = []
|
||||
if round(dist,precision()) == 0:
|
||||
for p in pts:
|
||||
if not p in sol:
|
||||
sol.append(p[0])
|
||||
return sol
|
||||
|
||||
pt1 = None
|
||||
|
||||
if isinstance(edge1,FreeCAD.Vector) and isinstance(edge2,FreeCAD.Vector):
|
||||
# we got points directly
|
||||
pt1 = edge1
|
||||
pt2 = edge2
|
||||
pt3 = infinite1
|
||||
pt4 = infinite2
|
||||
infinite1 = ex1
|
||||
infinite2 = ex2
|
||||
return getLineIntersections(pt1,pt2,pt3,pt4,infinite1,infinite2)
|
||||
|
||||
elif (geomType(edge1) == "Line") and (geomType(edge2) == "Line") :
|
||||
# we have 2 straight lines
|
||||
pt1, pt2, pt3, pt4 = [edge1.Vertexes[0].Point,
|
||||
edge1.Vertexes[1].Point,
|
||||
edge2.Vertexes[0].Point,
|
||||
edge2.Vertexes[1].Point]
|
||||
return getLineIntersections(pt1,pt2,pt3,pt4,infinite1,infinite2)
|
||||
|
||||
elif (geomType(edge1) == "Circle") and (geomType(edge2) == "Line") \
|
||||
or (geomType(edge1) == "Line") and (geomType(edge2) == "Circle") :
|
||||
|
||||
# deals with an arc or circle and a line
|
||||
|
||||
edges = [edge1,edge2]
|
||||
for edge in edges :
|
||||
if geomType(edge) == "Line":
|
||||
line = edge
|
||||
else :
|
||||
arc = edge
|
||||
|
||||
dirVec = vec(line) ; dirVec.normalize()
|
||||
pt1 = line.Vertexes[0].Point
|
||||
pt2 = line.Vertexes[1].Point
|
||||
pt3 = arc.Vertexes[0].Point
|
||||
pt4 = arc.Vertexes[-1].Point
|
||||
center = arc.Curve.Center
|
||||
|
||||
int = []
|
||||
# first check for coincident endpoints
|
||||
if DraftVecUtils.equals(pt1,pt3) or DraftVecUtils.equals(pt1,pt4):
|
||||
if findAll:
|
||||
int.append(pt1)
|
||||
else:
|
||||
return [pt1]
|
||||
elif (pt2 in [pt3,pt4]):
|
||||
if findAll:
|
||||
int.append(pt2)
|
||||
else:
|
||||
return [pt2]
|
||||
|
||||
if DraftVecUtils.isNull(pt1.sub(center).cross(pt2.sub(center)).cross(arc.Curve.Axis)) :
|
||||
# Line and Arc are on same plane
|
||||
|
||||
dOnLine = center.sub(pt1).dot(dirVec)
|
||||
onLine = Vector(dirVec)
|
||||
onLine.scale(dOnLine,dOnLine,dOnLine)
|
||||
toLine = pt1.sub(center).add(onLine)
|
||||
|
||||
if toLine.Length < arc.Curve.Radius :
|
||||
dOnLine = (arc.Curve.Radius**2 - toLine.Length**2)**(0.5)
|
||||
onLine = Vector(dirVec)
|
||||
onLine.scale(dOnLine,dOnLine,dOnLine)
|
||||
int += [center.add(toLine).add(onLine)]
|
||||
onLine = Vector(dirVec)
|
||||
onLine.scale(-dOnLine,-dOnLine,-dOnLine)
|
||||
int += [center.add(toLine).add(onLine)]
|
||||
elif round(toLine.Length-arc.Curve.Radius,precision()) == 0 :
|
||||
int = [center.add(toLine)]
|
||||
else :
|
||||
return []
|
||||
|
||||
else :
|
||||
# Line isn't on Arc's plane
|
||||
if dirVec.dot(arc.Curve.Axis) != 0 :
|
||||
toPlane = Vector(arc.Curve.Axis) ; toPlane.normalize()
|
||||
d = pt1.dot(toPlane)
|
||||
if not d:
|
||||
return []
|
||||
dToPlane = center.sub(pt1).dot(toPlane)
|
||||
toPlane = Vector(pt1)
|
||||
toPlane.scale(dToPlane/d,dToPlane/d,dToPlane/d)
|
||||
ptOnPlane = toPlane.add(pt1)
|
||||
if round(ptOnPlane.sub(center).Length - arc.Curve.Radius,precision()) == 0 :
|
||||
int = [ptOnPlane]
|
||||
else :
|
||||
return []
|
||||
else :
|
||||
return []
|
||||
|
||||
if infinite1 == False :
|
||||
for i in range(len(int)-1,-1,-1) :
|
||||
if not isPtOnEdge(int[i],edge1) :
|
||||
del int[i]
|
||||
if infinite2 == False :
|
||||
for i in range(len(int)-1,-1,-1) :
|
||||
if not isPtOnEdge(int[i],edge2) :
|
||||
del int[i]
|
||||
return int
|
||||
|
||||
elif (geomType(edge1) == "Circle") and (geomType(edge2) == "Circle") :
|
||||
# deals with 2 arcs or circles
|
||||
cent1, cent2 = edge1.Curve.Center, edge2.Curve.Center
|
||||
rad1 , rad2 = edge1.Curve.Radius, edge2.Curve.Radius
|
||||
axis1, axis2 = edge1.Curve.Axis , edge2.Curve.Axis
|
||||
c2c = cent2.sub(cent1)
|
||||
|
||||
if cent1.sub(cent2).Length == 0:
|
||||
# circles are concentric
|
||||
return []
|
||||
|
||||
if DraftVecUtils.isNull(axis1.cross(axis2)) :
|
||||
if round(c2c.dot(axis1),precision()) == 0 :
|
||||
# circles are on same plane
|
||||
dc2c = c2c.Length ;
|
||||
if not DraftVecUtils.isNull(c2c): c2c.normalize()
|
||||
if round(rad1+rad2-dc2c,precision()) < 0 \
|
||||
or round(rad1-dc2c-rad2,precision()) > 0 or round(rad2-dc2c-rad1,precision()) > 0 :
|
||||
return []
|
||||
else :
|
||||
norm = c2c.cross(axis1)
|
||||
if not DraftVecUtils.isNull(norm): norm.normalize()
|
||||
if DraftVecUtils.isNull(norm): x = 0
|
||||
else: x = (dc2c**2 + rad1**2 - rad2**2)/(2*dc2c)
|
||||
y = abs(rad1**2 - x**2)**(0.5)
|
||||
c2c.scale(x,x,x)
|
||||
if round(y,precision()) != 0 :
|
||||
norm.scale(y,y,y)
|
||||
int = [cent1.add(c2c).add(norm)]
|
||||
int += [cent1.add(c2c).sub(norm)]
|
||||
else :
|
||||
int = [cent1.add(c2c)]
|
||||
else :
|
||||
return [] # circles are on parallel planes
|
||||
else :
|
||||
# circles aren't on same plane
|
||||
axis1.normalize() ; axis2.normalize()
|
||||
U = axis1.cross(axis2)
|
||||
V = axis1.cross(U)
|
||||
dToPlane = c2c.dot(axis2)
|
||||
d = V.add(cent1).dot(axis2)
|
||||
V.scale(dToPlane/d,dToPlane/d,dToPlane/d)
|
||||
PtOn2Planes = V.add(cent1)
|
||||
planeIntersectionVector = U.add(PtOn2Planes)
|
||||
intTemp = findIntersection(planeIntersectionVector,edge1,True,True)
|
||||
int = []
|
||||
for pt in intTemp :
|
||||
if round(pt.sub(cent2).Length-rad2,precision()) == 0 :
|
||||
int += [pt]
|
||||
|
||||
if infinite1 == False :
|
||||
for i in range(len(int)-1,-1,-1) :
|
||||
if not isPtOnEdge(int[i],edge1) :
|
||||
del int[i]
|
||||
if infinite2 == False :
|
||||
for i in range(len(int)-1,-1,-1) :
|
||||
if not isPtOnEdge(int[i],edge2) :
|
||||
del int[i]
|
||||
|
||||
return int
|
||||
else:
|
||||
print("DraftGeomUtils: Unsupported curve type: (" + str(edge1.Curve) + ", " + str(edge2.Curve) + ")")
|
||||
return []
|
||||
from draftgeoutils.intersections import findIntersection
|
||||
|
||||
|
||||
def wiresIntersect(wire1, wire2):
|
||||
"""wiresIntersect(wire1,wire2): returns True if some of the edges of the wires are intersecting otherwise False"""
|
||||
for e1 in wire1.Edges:
|
||||
for e2 in wire2.Edges:
|
||||
if findIntersection(e1,e2,dts=False):
|
||||
return True
|
||||
return False
|
||||
from draftgeoutils.intersections import wiresIntersect
|
||||
|
||||
|
||||
|
||||
def pocket2d(shape, offset):
|
||||
@@ -1251,71 +1009,9 @@ def offsetWire(wire, dvec, bind=False, occ=False,
|
||||
else:
|
||||
return nedges
|
||||
|
||||
def connect(edges, closed=False):
|
||||
"""Connect the edges in the given list by their intersections."""
|
||||
nedges = []
|
||||
v2 = None
|
||||
|
||||
for i in range(len(edges)):
|
||||
curr = edges[i]
|
||||
#print("debug: DraftGeomUtils.connect edge ",i," : ",curr.Vertexes[0].Point,curr.Vertexes[-1].Point)
|
||||
if i > 0:
|
||||
prev = edges[i-1]
|
||||
else:
|
||||
if closed:
|
||||
prev = edges[-1]
|
||||
else:
|
||||
prev = None
|
||||
if i < (len(edges)-1):
|
||||
next = edges[i+1]
|
||||
else:
|
||||
if closed: next = edges[0]
|
||||
else:
|
||||
next = None
|
||||
if prev:
|
||||
#print("debug: DraftGeomUtils.connect prev : ",prev.Vertexes[0].Point,prev.Vertexes[-1].Point)
|
||||
from draftgeoutils.intersections import connect
|
||||
|
||||
# If the edge pairs has intersection
|
||||
# ... and if there is prev v2 (prev v2 was calculated intersection), do not calculate again, just use it as current v1 - avoid chance of slight difference in result
|
||||
# And, if edge pairs has no intersection (parallel edges, line - arc do no intersect, etc.), so just just current edge endpoints as v1
|
||||
# ... and connect these 2 non-intersecting edges
|
||||
|
||||
# seem have chance that 2 parallel edges offset same width, result in 2 colinear edges - Wall / DraftGeomUtils seem make them 1 edge and thus 1 vertical plane
|
||||
i = findIntersection(curr,prev,True,True)
|
||||
if i:
|
||||
if v2:
|
||||
v1 = v2
|
||||
else:
|
||||
v1 = i[DraftVecUtils.closest(curr.Vertexes[0].Point,i)]
|
||||
else:
|
||||
v1 = curr.Vertexes[0].Point
|
||||
|
||||
nedges.append(Part.LineSegment(v2,v1).toShape())
|
||||
|
||||
else:
|
||||
v1 = curr.Vertexes[0].Point
|
||||
if next:
|
||||
#print("debug: DraftGeomUtils.connect next : ",next.Vertexes[0].Point,next.Vertexes[-1].Point)
|
||||
i = findIntersection(curr,next,True,True)
|
||||
if i:
|
||||
v2 = i[DraftVecUtils.closest(curr.Vertexes[-1].Point,i)]
|
||||
else:
|
||||
v2 = curr.Vertexes[-1].Point
|
||||
else:
|
||||
v2 = curr.Vertexes[-1].Point
|
||||
if geomType(curr) == "Line":
|
||||
if v1 != v2:
|
||||
nedges.append(Part.LineSegment(v1,v2).toShape())
|
||||
elif geomType(curr) == "Circle":
|
||||
if v1 != v2:
|
||||
nedges.append(Part.Arc(v1,findMidpoint(curr),v2).toShape())
|
||||
try:
|
||||
return Part.Wire(nedges)
|
||||
except:
|
||||
print("DraftGeomUtils.connect: unable to connect edges")
|
||||
for e in nedges:
|
||||
print(e.Curve, " ",e.Vertexes[0].Point, " ", e.Vertexes[-1].Point)
|
||||
return None
|
||||
|
||||
def findDistance(point, edge, strict=False):
|
||||
"""
|
||||
|
||||
386
src/Mod/Draft/draftgeoutils/intersections.py
Normal file
386
src/Mod/Draft/draftgeoutils/intersections.py
Normal file
@@ -0,0 +1,386 @@
|
||||
# ***************************************************************************
|
||||
# * 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 basic functions for calculating intersections of shapes."""
|
||||
## @package intersections
|
||||
# \ingroup DRAFTGEOUTILS
|
||||
# \brief Provides basic functions for calculating intersections of shapes.
|
||||
|
||||
import lazy_loader.lazy_loader as lz
|
||||
|
||||
import FreeCAD
|
||||
import DraftVecUtils
|
||||
|
||||
from draftgeoutils.general import precision, vec, geomType, isPtOnEdge
|
||||
from draftgeoutils.edges import findMidpoint
|
||||
|
||||
# Delay import of module until first use because it is heavy
|
||||
Part = lz.LazyLoader("Part", globals(), "Part")
|
||||
|
||||
|
||||
def findIntersection(edge1, edge2,
|
||||
infinite1=False, infinite2=False,
|
||||
ex1=False, ex2=False,
|
||||
dts=True, findAll=False):
|
||||
"""Return a list containing the intersection points of 2 edges.
|
||||
|
||||
You can also feed 4 points instead of `edge1` and `edge2`.
|
||||
If `dts` is used, `Shape.distToShape()` is used, which can be buggy.
|
||||
"""
|
||||
|
||||
def getLineIntersections(pt1, pt2, pt3, pt4, infinite1, infinite2):
|
||||
if pt1:
|
||||
# first check if we don't already have coincident endpoints
|
||||
if pt1 in [pt3, pt4]:
|
||||
return [pt1]
|
||||
elif (pt2 in [pt3, pt4]):
|
||||
return [pt2]
|
||||
norm1 = pt2.sub(pt1).cross(pt3.sub(pt1))
|
||||
norm2 = pt2.sub(pt4).cross(pt3.sub(pt4))
|
||||
|
||||
if not DraftVecUtils.isNull(norm1):
|
||||
try:
|
||||
norm1.normalize()
|
||||
except Part.OCCError:
|
||||
return []
|
||||
|
||||
if not DraftVecUtils.isNull(norm2):
|
||||
try:
|
||||
norm2.normalize()
|
||||
except Part.OCCError:
|
||||
return []
|
||||
|
||||
if DraftVecUtils.isNull(norm1.cross(norm2)):
|
||||
vec1 = pt2.sub(pt1)
|
||||
vec2 = pt4.sub(pt3)
|
||||
if DraftVecUtils.isNull(vec1) or DraftVecUtils.isNull(vec2):
|
||||
return [] # One of the lines has zero-length
|
||||
try:
|
||||
vec1.normalize()
|
||||
vec2.normalize()
|
||||
except Part.OCCError:
|
||||
return []
|
||||
norm3 = vec1.cross(vec2)
|
||||
denom = norm3.x + norm3.y + norm3.z
|
||||
if not DraftVecUtils.isNull(norm3) and denom != 0:
|
||||
k = ((pt3.z - pt1.z) * (vec2.x - vec2.y)
|
||||
+ (pt3.y - pt1.y) * (vec2.z - vec2.x)
|
||||
+ (pt3.x - pt1.x) * (vec2.y - vec2.z))/denom
|
||||
vec1.scale(k, k, k)
|
||||
intp = pt1.add(vec1)
|
||||
|
||||
if infinite1 is False and not isPtOnEdge(intp, edge1):
|
||||
return []
|
||||
|
||||
if infinite2 is False and not isPtOnEdge(intp, edge2):
|
||||
return []
|
||||
|
||||
return [intp]
|
||||
else:
|
||||
return [] # Lines have same direction
|
||||
else:
|
||||
return [] # Lines aren't on same plane
|
||||
|
||||
# First, check bound boxes
|
||||
if (isinstance(edge1, Part.Edge) and isinstance(edge2, Part.Edge)
|
||||
and (not infinite1) and (not infinite2)):
|
||||
if not edge1.BoundBox.intersect(edge2.BoundBox):
|
||||
return [] # bound boxes don't intersect
|
||||
|
||||
# First, try to use distToShape if possible
|
||||
if (dts and isinstance(edge1, Part.Edge) and isinstance(edge2, Part.Edge)
|
||||
and (not infinite1) and (not infinite2)):
|
||||
dist, pts, geom = edge1.distToShape(edge2)
|
||||
sol = []
|
||||
if round(dist, precision()) == 0:
|
||||
for p in pts:
|
||||
if p not in sol:
|
||||
sol.append(p[0])
|
||||
return sol
|
||||
|
||||
pt1 = None
|
||||
|
||||
if isinstance(edge1, FreeCAD.Vector) and isinstance(edge2, FreeCAD.Vector):
|
||||
# we got points directly
|
||||
pt1 = edge1
|
||||
pt2 = edge2
|
||||
pt3 = infinite1
|
||||
pt4 = infinite2
|
||||
infinite1 = ex1
|
||||
infinite2 = ex2
|
||||
return getLineIntersections(pt1, pt2, pt3, pt4, infinite1, infinite2)
|
||||
|
||||
elif (geomType(edge1) == "Line") and (geomType(edge2) == "Line"):
|
||||
# we have 2 straight lines
|
||||
pt1, pt2, pt3, pt4 = [edge1.Vertexes[0].Point,
|
||||
edge1.Vertexes[1].Point,
|
||||
edge2.Vertexes[0].Point,
|
||||
edge2.Vertexes[1].Point]
|
||||
return getLineIntersections(pt1, pt2, pt3, pt4, infinite1, infinite2)
|
||||
|
||||
elif ((geomType(edge1) == "Circle") and (geomType(edge2) == "Line")
|
||||
or (geomType(edge1) == "Line") and (geomType(edge2) == "Circle")):
|
||||
|
||||
# deals with an arc or circle and a line
|
||||
edges = [edge1, edge2]
|
||||
for edge in edges:
|
||||
if geomType(edge) == "Line":
|
||||
line = edge
|
||||
else:
|
||||
arc = edge
|
||||
|
||||
dirVec = vec(line)
|
||||
dirVec.normalize()
|
||||
pt1 = line.Vertexes[0].Point
|
||||
pt2 = line.Vertexes[1].Point
|
||||
pt3 = arc.Vertexes[0].Point
|
||||
pt4 = arc.Vertexes[-1].Point
|
||||
center = arc.Curve.Center
|
||||
|
||||
int = []
|
||||
# first check for coincident endpoints
|
||||
if DraftVecUtils.equals(pt1, pt3) or DraftVecUtils.equals(pt1, pt4):
|
||||
if findAll:
|
||||
int.append(pt1)
|
||||
else:
|
||||
return [pt1]
|
||||
elif pt2 in [pt3, pt4]:
|
||||
if findAll:
|
||||
int.append(pt2)
|
||||
else:
|
||||
return [pt2]
|
||||
|
||||
if DraftVecUtils.isNull(pt1.sub(center).cross(pt2.sub(center)).cross(arc.Curve.Axis)):
|
||||
# Line and Arc are on same plane
|
||||
|
||||
dOnLine = center.sub(pt1).dot(dirVec)
|
||||
onLine = FreeCAD.Vector(dirVec)
|
||||
onLine.scale(dOnLine, dOnLine, dOnLine)
|
||||
toLine = pt1.sub(center).add(onLine)
|
||||
|
||||
if toLine.Length < arc.Curve.Radius:
|
||||
dOnLine = (arc.Curve.Radius**2 - toLine.Length**2)**(0.5)
|
||||
onLine = FreeCAD.Vector(dirVec)
|
||||
onLine.scale(dOnLine, dOnLine, dOnLine)
|
||||
int += [center.add(toLine).add(onLine)]
|
||||
onLine = FreeCAD.Vector(dirVec)
|
||||
onLine.scale(-dOnLine, -dOnLine, -dOnLine)
|
||||
int += [center.add(toLine).add(onLine)]
|
||||
elif round(toLine.Length - arc.Curve.Radius, precision()) == 0:
|
||||
int = [center.add(toLine)]
|
||||
else:
|
||||
return []
|
||||
|
||||
else:
|
||||
# Line isn't on Arc's plane
|
||||
if dirVec.dot(arc.Curve.Axis) != 0:
|
||||
toPlane = FreeCAD.Vector(arc.Curve.Axis)
|
||||
toPlane.normalize()
|
||||
d = pt1.dot(toPlane)
|
||||
if not d:
|
||||
return []
|
||||
dToPlane = center.sub(pt1).dot(toPlane)
|
||||
toPlane = FreeCAD.Vector(pt1)
|
||||
toPlane.scale(dToPlane/d, dToPlane/d, dToPlane/d)
|
||||
ptOnPlane = toPlane.add(pt1)
|
||||
if round(ptOnPlane.sub(center).Length - arc.Curve.Radius,
|
||||
precision()) == 0:
|
||||
int = [ptOnPlane]
|
||||
else:
|
||||
return []
|
||||
else:
|
||||
return []
|
||||
|
||||
if infinite1 is False:
|
||||
for i in range(len(int) - 1, -1, -1):
|
||||
if not isPtOnEdge(int[i], edge1):
|
||||
del int[i]
|
||||
if infinite2 is False:
|
||||
for i in range(len(int) - 1, -1, -1):
|
||||
if not isPtOnEdge(int[i], edge2):
|
||||
del int[i]
|
||||
return int
|
||||
|
||||
elif (geomType(edge1) == "Circle") and (geomType(edge2) == "Circle"):
|
||||
# deals with 2 arcs or circles
|
||||
cent1, cent2 = edge1.Curve.Center, edge2.Curve.Center
|
||||
rad1, rad2 = edge1.Curve.Radius, edge2.Curve.Radius
|
||||
axis1, axis2 = edge1.Curve.Axis, edge2.Curve.Axis
|
||||
c2c = cent2.sub(cent1)
|
||||
|
||||
if cent1.sub(cent2).Length == 0:
|
||||
# circles are concentric
|
||||
return []
|
||||
|
||||
if DraftVecUtils.isNull(axis1.cross(axis2)):
|
||||
if round(c2c.dot(axis1), precision()) == 0:
|
||||
# circles are on same plane
|
||||
dc2c = c2c.Length
|
||||
if not DraftVecUtils.isNull(c2c):
|
||||
c2c.normalize()
|
||||
if (round(rad1 + rad2 - dc2c, precision()) < 0
|
||||
or round(rad1 - dc2c - rad2, precision()) > 0
|
||||
or round(rad2 - dc2c - rad1, precision()) > 0):
|
||||
return []
|
||||
else:
|
||||
norm = c2c.cross(axis1)
|
||||
if not DraftVecUtils.isNull(norm):
|
||||
norm.normalize()
|
||||
if DraftVecUtils.isNull(norm):
|
||||
x = 0
|
||||
else:
|
||||
x = (dc2c**2 + rad1**2 - rad2**2) / (2*dc2c)
|
||||
y = abs(rad1**2 - x**2)**(0.5)
|
||||
c2c.scale(x, x, x)
|
||||
if round(y, precision()) != 0:
|
||||
norm.scale(y, y, y)
|
||||
int = [cent1.add(c2c).add(norm)]
|
||||
int += [cent1.add(c2c).sub(norm)]
|
||||
else:
|
||||
int = [cent1.add(c2c)]
|
||||
else:
|
||||
return [] # circles are on parallel planes
|
||||
else:
|
||||
# circles aren't on same plane
|
||||
axis1.normalize()
|
||||
axis2.normalize()
|
||||
U = axis1.cross(axis2)
|
||||
V = axis1.cross(U)
|
||||
dToPlane = c2c.dot(axis2)
|
||||
d = V.add(cent1).dot(axis2)
|
||||
V.scale(dToPlane/d, dToPlane/d, dToPlane/d)
|
||||
PtOn2Planes = V.add(cent1)
|
||||
planeIntersectionVector = U.add(PtOn2Planes)
|
||||
intTemp = findIntersection(planeIntersectionVector,
|
||||
edge1, True, True)
|
||||
int = []
|
||||
for pt in intTemp:
|
||||
if round(pt.sub(cent2).Length-rad2, precision()) == 0:
|
||||
int += [pt]
|
||||
|
||||
if infinite1 is False:
|
||||
for i in range(len(int) - 1, -1, -1):
|
||||
if not isPtOnEdge(int[i], edge1):
|
||||
del int[i]
|
||||
if infinite2 is False:
|
||||
for i in range(len(int) - 1, -1, -1):
|
||||
if not isPtOnEdge(int[i], edge2):
|
||||
del int[i]
|
||||
|
||||
return int
|
||||
else:
|
||||
print("DraftGeomUtils: Unsupported curve type: "
|
||||
"(" + str(edge1.Curve) + ", " + str(edge2.Curve) + ")")
|
||||
return []
|
||||
|
||||
|
||||
def wiresIntersect(wire1, wire2):
|
||||
"""Return True if some of the edges of the wires are intersecting.
|
||||
|
||||
Otherwise return `False`.
|
||||
"""
|
||||
for e1 in wire1.Edges:
|
||||
for e2 in wire2.Edges:
|
||||
if findIntersection(e1, e2, dts=False):
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
def connect(edges, closed=False):
|
||||
"""Connect the edges in the given list by their intersections."""
|
||||
nedges = []
|
||||
v2 = None
|
||||
|
||||
for i in range(len(edges)):
|
||||
curr = edges[i]
|
||||
# print("debug: DraftGeomUtils.connect edge ", i, " : ",
|
||||
# curr.Vertexes[0].Point, curr.Vertexes[-1].Point)
|
||||
if i > 0:
|
||||
prev = edges[i-1]
|
||||
else:
|
||||
if closed:
|
||||
prev = edges[-1]
|
||||
else:
|
||||
prev = None
|
||||
if i < (len(edges)-1):
|
||||
_next = edges[i+1]
|
||||
else:
|
||||
if closed:
|
||||
_next = edges[0]
|
||||
else:
|
||||
_next = None
|
||||
if prev:
|
||||
# print("debug: DraftGeomUtils.connect prev : ",
|
||||
# prev.Vertexes[0].Point, prev.Vertexes[-1].Point)
|
||||
|
||||
# If the edge pairs has intersection and if there is prev v2
|
||||
# (prev v2 was calculated intersection), do not calculate
|
||||
# again, just use it as current v1 - avoid chance of slight
|
||||
# difference in result. And, if edge pairs
|
||||
# has no intersection (parallel edges, line
|
||||
# - arc do no intersect, etc.), so just just current
|
||||
# edge endpoints as v1 and connect these 2 non-intersecting
|
||||
# edges
|
||||
|
||||
# Seem have chance that 2 parallel edges offset same width,
|
||||
# result in 2 colinear edges - Wall / DraftGeomUtils
|
||||
# seem make them 1 edge and thus 1 vertical plane
|
||||
i = findIntersection(curr, prev, True, True)
|
||||
if i:
|
||||
if v2:
|
||||
v1 = v2
|
||||
else:
|
||||
v1 = i[DraftVecUtils.closest(curr.Vertexes[0].Point, i)]
|
||||
else:
|
||||
v1 = curr.Vertexes[0].Point
|
||||
nedges.append(Part.LineSegment(v2, v1).toShape())
|
||||
else:
|
||||
v1 = curr.Vertexes[0].Point
|
||||
|
||||
if _next:
|
||||
# print("debug: DraftGeomUtils.connect _next : ",
|
||||
# _next.Vertexes[0].Point, _next.Vertexes[-1].Point)
|
||||
i = findIntersection(curr, _next, True, True)
|
||||
if i:
|
||||
v2 = i[DraftVecUtils.closest(curr.Vertexes[-1].Point, i)]
|
||||
else:
|
||||
v2 = curr.Vertexes[-1].Point
|
||||
else:
|
||||
v2 = curr.Vertexes[-1].Point
|
||||
if geomType(curr) == "Line":
|
||||
if v1 != v2:
|
||||
nedges.append(Part.LineSegment(v1, v2).toShape())
|
||||
elif geomType(curr) == "Circle":
|
||||
if v1 != v2:
|
||||
nedges.append(Part.Arc(v1,
|
||||
findMidpoint(curr),
|
||||
v2).toShape())
|
||||
try:
|
||||
return Part.Wire(nedges)
|
||||
except:
|
||||
print("DraftGeomUtils.connect: unable to connect edges")
|
||||
for e in nedges:
|
||||
print(e.Curve, " ",
|
||||
e.Vertexes[0].Point, " ",
|
||||
e.Vertexes[-1].Point)
|
||||
return None
|
||||
Reference in New Issue
Block a user