Draft: move functions to draftgeoutils.sort_edges
This commit is contained in:
@@ -33,6 +33,7 @@ SET (Draft_geoutils
|
||||
draftgeoutils/general.py
|
||||
draftgeoutils/edges.py
|
||||
draftgeoutils/intersections.py
|
||||
draftgeoutils/sort_edges.py
|
||||
)
|
||||
|
||||
SET(Draft_tests
|
||||
|
||||
@@ -281,172 +281,10 @@ def getBoundary(shape):
|
||||
from draftgeoutils.edges import isLine
|
||||
|
||||
|
||||
def sortEdges(edges):
|
||||
"""Deprecated. Use Part.__sortEdges__ instead."""
|
||||
raise DeprecationWarning("Deprecated. Use Part.__sortEdges__ instead")
|
||||
|
||||
# Build a dictionary of edges according to their end points.
|
||||
# Each entry is a set of edges that starts, or ends, at the
|
||||
# given vertex hash.
|
||||
if len(edges) < 2:
|
||||
return edges
|
||||
sdict = dict()
|
||||
edict = dict()
|
||||
nedges = []
|
||||
for e in edges:
|
||||
if hasattr(e,"Length"):
|
||||
if e.Length != 0:
|
||||
sdict.setdefault( e.Vertexes[0].hashCode(), [] ).append(e)
|
||||
edict.setdefault( e.Vertexes[-1].hashCode(),[] ).append(e)
|
||||
nedges.append(e)
|
||||
if not nedges:
|
||||
print("DraftGeomUtils.sortEdges: zero-length edges")
|
||||
return edges
|
||||
# Find the start of the path. The start is the vertex that appears
|
||||
# in the sdict dictionary but not in the edict dictionary, and has
|
||||
# only one edge ending there.
|
||||
startedge = None
|
||||
for v, se in sdict.items():
|
||||
if v not in edict and len(se) == 1:
|
||||
startedge = se
|
||||
break
|
||||
# The above may not find a start vertex; if the start edge is reversed,
|
||||
# the start vertex will appear in edict (and not sdict).
|
||||
if not startedge:
|
||||
for v, se in edict.items():
|
||||
if v not in sdict and len(se) == 1:
|
||||
startedge = se
|
||||
break
|
||||
# If we still have no start vertex, it was a closed path. If so, start
|
||||
# with the first edge in the supplied list
|
||||
if not startedge:
|
||||
startedge = nedges[0]
|
||||
v = startedge.Vertexes[0].hashCode()
|
||||
# Now build the return list by walking the edges starting at the start
|
||||
# vertex we found. We're done when we've visited each edge, so the
|
||||
# end check is simply the count of input elements (that works for closed
|
||||
# as well as open paths).
|
||||
ret = list()
|
||||
# store the hash code of the last edge, to avoid picking the same edge back
|
||||
eh = None
|
||||
for i in range(len(nedges)):
|
||||
try:
|
||||
eset = sdict[v]
|
||||
e = eset.pop()
|
||||
if not eset:
|
||||
del sdict[v]
|
||||
if e.hashCode() == eh:
|
||||
raise KeyError
|
||||
v = e.Vertexes[-1].hashCode()
|
||||
eh = e.hashCode()
|
||||
except KeyError:
|
||||
try:
|
||||
eset = edict[v]
|
||||
e = eset.pop()
|
||||
if not eset:
|
||||
del edict[v]
|
||||
if e.hashCode() == eh:
|
||||
raise KeyError
|
||||
v = e.Vertexes[0].hashCode()
|
||||
eh = e.hashCode()
|
||||
e = invert(e)
|
||||
except KeyError:
|
||||
print("DraftGeomUtils.sortEdges failed - running old version")
|
||||
return sortEdgesOld(edges)
|
||||
ret.append(e)
|
||||
# All done.
|
||||
return ret
|
||||
from draftgeoutils.sort_edges import sortEdges
|
||||
|
||||
|
||||
def sortEdgesOld(lEdges, aVertex=None):
|
||||
"""Deprecated. Use Part.__sortEdges__ instead."""
|
||||
raise DeprecationWarning("Deprecated. Use Part.__sortEdges__ instead")
|
||||
|
||||
#There is no reason to limit this to lines only because every non-closed edge always
|
||||
#has exactly two vertices (wmayer)
|
||||
#for e in lEdges:
|
||||
# if not isinstance(e.Curve,Part.LineSegment):
|
||||
# print("Warning: sortedges cannot treat wired containing curves yet.")
|
||||
# return lEdges
|
||||
|
||||
def lookfor(aVertex, inEdges):
|
||||
"""Look for (aVertex, inEdges) returns count, the position of the instance
|
||||
the position in the instance and the instance of the Edge"""
|
||||
count = 0
|
||||
linstances = [] #lists the instances of aVertex
|
||||
for i in range(len(inEdges)) :
|
||||
for j in range(2) :
|
||||
if aVertex.Point == inEdges[i].Vertexes[j-1].Point:
|
||||
instance = inEdges[i]
|
||||
count += 1
|
||||
linstances += [i,j-1,instance]
|
||||
return [count]+linstances
|
||||
|
||||
if (len(lEdges) < 2):
|
||||
if aVertex is None:
|
||||
return lEdges
|
||||
else:
|
||||
result = lookfor(aVertex,lEdges)
|
||||
if result[0] != 0:
|
||||
if aVertex.Point == result[3].Vertexes[0].Point:
|
||||
return lEdges
|
||||
else:
|
||||
if geomType(result[3]) == "Line":
|
||||
return [Part.LineSegment(aVertex.Point,result[3].Vertexes[0].Point).toShape()]
|
||||
elif geomType(result[3]) == "Circle":
|
||||
mp = findMidpoint(result[3])
|
||||
return [Part.Arc(aVertex.Point,mp,result[3].Vertexes[0].Point).toShape()]
|
||||
elif geomType(result[3]) == "BSplineCurve" or\
|
||||
geomType(result[3]) == "BezierCurve":
|
||||
if isLine(result[3].Curve):
|
||||
return [Part.LineSegment(aVertex.Point,result[3].Vertexes[0].Point).toShape()]
|
||||
else:
|
||||
return lEdges
|
||||
else:
|
||||
return lEdges
|
||||
|
||||
olEdges = [] # ol stands for ordered list
|
||||
if aVertex is None:
|
||||
for i in range(len(lEdges)*2) :
|
||||
if len(lEdges[i/2].Vertexes) > 1:
|
||||
result = lookfor(lEdges[i/2].Vertexes[i%2],lEdges)
|
||||
if result[0] == 1 : # Have we found an end ?
|
||||
olEdges = sortEdgesOld(lEdges, result[3].Vertexes[result[2]])
|
||||
return olEdges
|
||||
# if the wire is closed there is no end so choose 1st Vertex
|
||||
# print("closed wire, starting from ",lEdges[0].Vertexes[0].Point)
|
||||
return sortEdgesOld(lEdges, lEdges[0].Vertexes[0])
|
||||
else :
|
||||
#print("looking ",aVertex.Point)
|
||||
result = lookfor(aVertex,lEdges)
|
||||
if result[0] != 0 :
|
||||
del lEdges[result[1]]
|
||||
next = sortEdgesOld(lEdges, result[3].Vertexes[-((-result[2])^1)])
|
||||
#print("result ",result[3].Vertexes[0].Point," ",result[3].Vertexes[1].Point, " compared to ",aVertex.Point)
|
||||
if aVertex.Point == result[3].Vertexes[0].Point:
|
||||
#print("keeping")
|
||||
olEdges += [result[3]] + next
|
||||
else:
|
||||
#print("inverting", result[3].Curve)
|
||||
if geomType(result[3]) == "Line":
|
||||
newedge = Part.LineSegment(aVertex.Point,result[3].Vertexes[0].Point).toShape()
|
||||
olEdges += [newedge] + next
|
||||
elif geomType(result[3]) == "Circle":
|
||||
mp = findMidpoint(result[3])
|
||||
newedge = Part.Arc(aVertex.Point,mp,result[3].Vertexes[0].Point).toShape()
|
||||
olEdges += [newedge] + next
|
||||
elif geomType(result[3]) == "BSplineCurve" or \
|
||||
geomType(result[3]) == "BezierCurve":
|
||||
if isLine(result[3].Curve):
|
||||
newedge = Part.LineSegment(aVertex.Point,result[3].Vertexes[0].Point).toShape()
|
||||
olEdges += [newedge] + next
|
||||
else:
|
||||
olEdges += [result[3]] + next
|
||||
else:
|
||||
olEdges += [result[3]] + next
|
||||
return olEdges
|
||||
else :
|
||||
return []
|
||||
from draftgeoutils.sort_edges import sortEdgesOld
|
||||
|
||||
|
||||
from draftgeoutils.edges import invert
|
||||
|
||||
223
src/Mod/Draft/draftgeoutils/sort_edges.py
Normal file
223
src/Mod/Draft/draftgeoutils/sort_edges.py
Normal file
@@ -0,0 +1,223 @@
|
||||
# ***************************************************************************
|
||||
# * 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 sorting edges."""
|
||||
## @package sort_edges
|
||||
# \ingroup DRAFTGEOUTILS
|
||||
# \brief Provides various functions for sorting edges.
|
||||
|
||||
import lazy_loader.lazy_loader as lz
|
||||
|
||||
from draftgeoutils.general import geomType
|
||||
from draftgeoutils.edges import findMidpoint, isLine, invert
|
||||
|
||||
# Delay import of module until first use because it is heavy
|
||||
Part = lz.LazyLoader("Part", globals(), "Part")
|
||||
|
||||
|
||||
def sortEdges(edges):
|
||||
"""Sort edges. Deprecated. Use Part.__sortEdges__ instead."""
|
||||
raise DeprecationWarning("Deprecated. Use Part.__sortEdges__ instead")
|
||||
|
||||
if len(edges) < 2:
|
||||
return edges
|
||||
|
||||
# Build a dictionary of edges according to their end points.
|
||||
# Each entry is a set of edges that starts, or ends, at the
|
||||
# given vertex hash.
|
||||
sdict = dict()
|
||||
edict = dict()
|
||||
nedges = []
|
||||
for e in edges:
|
||||
if hasattr(e, "Length"):
|
||||
if e.Length != 0:
|
||||
sdict.setdefault(e.Vertexes[0].hashCode(), []).append(e)
|
||||
edict.setdefault(e.Vertexes[-1].hashCode(), []).append(e)
|
||||
nedges.append(e)
|
||||
|
||||
if not nedges:
|
||||
print("DraftGeomUtils.sortEdges: zero-length edges")
|
||||
return edges
|
||||
|
||||
# Find the start of the path. The start is the vertex that appears
|
||||
# in the sdict dictionary but not in the edict dictionary, and has
|
||||
# only one edge ending there.
|
||||
startedge = None
|
||||
for v, se in sdict.items():
|
||||
if v not in edict and len(se) == 1:
|
||||
startedge = se
|
||||
break
|
||||
|
||||
# The above may not find a start vertex; if the start edge is reversed,
|
||||
# the start vertex will appear in edict (and not sdict).
|
||||
if not startedge:
|
||||
for v, se in edict.items():
|
||||
if v not in sdict and len(se) == 1:
|
||||
startedge = se
|
||||
break
|
||||
|
||||
# If we still have no start vertex, it was a closed path. If so, start
|
||||
# with the first edge in the supplied list
|
||||
if not startedge:
|
||||
startedge = nedges[0]
|
||||
v = startedge.Vertexes[0].hashCode()
|
||||
|
||||
# Now build the return list by walking the edges starting at the start
|
||||
# vertex we found. We're done when we've visited each edge, so the
|
||||
# end check is simply the count of input elements (that works for closed
|
||||
# as well as open paths).
|
||||
ret = list()
|
||||
# store the hash code of the last edge, to avoid picking the same edge back
|
||||
eh = None
|
||||
for i in range(len(nedges)):
|
||||
try:
|
||||
eset = sdict[v]
|
||||
e = eset.pop()
|
||||
if not eset:
|
||||
del sdict[v]
|
||||
if e.hashCode() == eh:
|
||||
raise KeyError
|
||||
v = e.Vertexes[-1].hashCode()
|
||||
eh = e.hashCode()
|
||||
except KeyError:
|
||||
try:
|
||||
eset = edict[v]
|
||||
e = eset.pop()
|
||||
if not eset:
|
||||
del edict[v]
|
||||
if e.hashCode() == eh:
|
||||
raise KeyError
|
||||
v = e.Vertexes[0].hashCode()
|
||||
eh = e.hashCode()
|
||||
e = invert(e)
|
||||
except KeyError:
|
||||
print("DraftGeomUtils.sortEdges failed - running old version")
|
||||
return sortEdgesOld(edges)
|
||||
ret.append(e)
|
||||
|
||||
return ret
|
||||
|
||||
|
||||
def sortEdgesOld(lEdges, aVertex=None):
|
||||
"""Sort edges. Deprecated. Use Part.__sortEdges__ instead."""
|
||||
raise DeprecationWarning("Deprecated. Use Part.__sortEdges__ instead")
|
||||
|
||||
# There is no reason to limit this to lines only because
|
||||
# every non-closed edge always has exactly two vertices (wmayer)
|
||||
# for e in lEdges:
|
||||
# if not isinstance(e.Curve,Part.LineSegment):
|
||||
# print("Sortedges cannot treat wired containing curves yet.")
|
||||
# return lEdges
|
||||
|
||||
def lookfor(aVertex, inEdges):
|
||||
"""Look for a vertex in the list of edges.
|
||||
|
||||
Returns count, the position of the instance
|
||||
the position in the instance and the instance of the Edge.
|
||||
"""
|
||||
count = 0
|
||||
linstances = [] # lists the instances of aVertex
|
||||
for i in range(len(inEdges)):
|
||||
for j in range(2):
|
||||
if aVertex.Point == inEdges[i].Vertexes[j-1].Point:
|
||||
instance = inEdges[i]
|
||||
count += 1
|
||||
linstances += [i, j-1, instance]
|
||||
return [count] + linstances
|
||||
|
||||
if len(lEdges) < 2:
|
||||
if aVertex is None:
|
||||
return lEdges
|
||||
else:
|
||||
result = lookfor(aVertex, lEdges)
|
||||
if result[0] != 0:
|
||||
if aVertex.Point == result[3].Vertexes[0].Point:
|
||||
return lEdges
|
||||
else:
|
||||
if geomType(result[3]) == "Line":
|
||||
return [Part.LineSegment(aVertex.Point,
|
||||
result[3].Vertexes[0].Point).toShape()]
|
||||
elif geomType(result[3]) == "Circle":
|
||||
mp = findMidpoint(result[3])
|
||||
return [Part.Arc(aVertex.Point,
|
||||
mp,
|
||||
result[3].Vertexes[0].Point).toShape()]
|
||||
elif (geomType(result[3]) == "BSplineCurve"
|
||||
or geomType(result[3]) == "BezierCurve"):
|
||||
if isLine(result[3].Curve):
|
||||
return [Part.LineSegment(aVertex.Point,
|
||||
result[3].Vertexes[0].Point).toShape()]
|
||||
else:
|
||||
return lEdges
|
||||
else:
|
||||
return lEdges
|
||||
|
||||
olEdges = [] # ol stands for ordered list
|
||||
if aVertex is None:
|
||||
for i in range(len(lEdges)*2):
|
||||
if len(lEdges[i/2].Vertexes) > 1:
|
||||
result = lookfor(lEdges[i/2].Vertexes[i % 2], lEdges)
|
||||
if result[0] == 1: # Have we found an end ?
|
||||
olEdges = sortEdgesOld(lEdges,
|
||||
result[3].Vertexes[result[2]])
|
||||
return olEdges
|
||||
# if the wire is closed there is no end so choose 1st Vertex
|
||||
# print("closed wire, starting from ",lEdges[0].Vertexes[0].Point)
|
||||
return sortEdgesOld(lEdges, lEdges[0].Vertexes[0])
|
||||
else:
|
||||
# print("looking ",aVertex.Point)
|
||||
result = lookfor(aVertex, lEdges)
|
||||
if result[0] != 0:
|
||||
del lEdges[result[1]]
|
||||
_next = sortEdgesOld(lEdges,
|
||||
result[3].Vertexes[-((-result[2])^1)])
|
||||
# print("result ", result[3].Vertexes[0].Point, " ",
|
||||
# result[3].Vertexes[1].Point, " compared to ",aVertex.Point)
|
||||
if aVertex.Point == result[3].Vertexes[0].Point:
|
||||
# print("keeping")
|
||||
olEdges += [result[3]] + _next
|
||||
else:
|
||||
# print("inverting", result[3].Curve)
|
||||
if geomType(result[3]) == "Line":
|
||||
newedge = Part.LineSegment(aVertex.Point,
|
||||
result[3].Vertexes[0].Point).toShape()
|
||||
olEdges += [newedge] + _next
|
||||
elif geomType(result[3]) == "Circle":
|
||||
mp = findMidpoint(result[3])
|
||||
newedge = Part.Arc(aVertex.Point,
|
||||
mp,
|
||||
result[3].Vertexes[0].Point).toShape()
|
||||
olEdges += [newedge] + _next
|
||||
elif (geomType(result[3]) == "BSplineCurve"
|
||||
or geomType(result[3]) == "BezierCurve"):
|
||||
if isLine(result[3].Curve):
|
||||
newedge = Part.LineSegment(aVertex.Point,
|
||||
result[3].Vertexes[0].Point).toShape()
|
||||
olEdges += [newedge] + _next
|
||||
else:
|
||||
olEdges += [result[3]] + _next
|
||||
else:
|
||||
olEdges += [result[3]] + _next
|
||||
return olEdges
|
||||
else:
|
||||
return []
|
||||
Reference in New Issue
Block a user