Skip to content
This repository was archived by the owner on Feb 3, 2023. It is now read-only.

Commit 560a7e3

Browse files
algrssashaverma
authored andcommitted
Speed up mesh xsection (#5)
* Speed up mesh xsection * Lint * Remove unused import * Bump to v 1.2.1
1 parent de49d87 commit 560a7e3

File tree

2 files changed

+39
-22
lines changed

2 files changed

+39
-22
lines changed

blmath/__init__.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
__version__ = '1.1.1'
1+
__version__ = '1.2.1'

blmath/geometry/primitives/plane.py

+38-21
Original file line numberDiff line numberDiff line change
@@ -263,7 +263,6 @@ def mesh_xsections(self, m, neighborhood=None):
263263
Returns a list of Polylines.
264264
'''
265265
import operator
266-
import scipy.sparse as sp
267266
from blmath.geometry import Polyline
268267

269268
# 1: Select those faces that intersect the plane, fs
@@ -294,54 +293,72 @@ def edge_from_face(f):
294293
verts = verts[list(np.sqrt(np.sum(np.diff(verts, axis=0) ** 2, axis=1)) > eps) + [True]]
295294
# the True at the end there is because np.diff returns pairwise differences; one less element than the original array
296295

297-
# 4: Build the edge adjacency matrix
298-
E = sp.dok_matrix((verts.shape[0], verts.shape[0]), dtype=np.bool)
296+
class Graph(object):
297+
# A little utility class to build a symmetric graph
298+
def __init__(self, size):
299+
self.size = size
300+
self.d = {}
301+
def __len__(self):
302+
return len(self.d)
303+
def add_edge(self, ii, jj):
304+
assert ii >= 0 and ii < self.size
305+
assert jj >= 0 and jj < self.size
306+
if ii not in self.d:
307+
self.d[ii] = set()
308+
if jj not in self.d:
309+
self.d[jj] = set()
310+
self.d[ii].add(jj)
311+
self.d[jj].add(ii)
312+
313+
# 4: Build the edge adjacency graph
314+
G = Graph(verts.shape[0])
299315
def indexof(v, in_this):
300316
return np.nonzero(np.all(np.abs(in_this - v) < eps, axis=1))[0]
301317
for ii, v in enumerate(verts):
302318
for other_v in list(v2s[indexof(v, v1s)]) + list(v1s[indexof(v, v2s)]):
303319
neighbors = indexof(other_v, verts)
304-
E[ii, neighbors] = True
305-
E[neighbors, ii] = True
320+
for jj in neighbors:
321+
G.add_edge(ii, jj)
306322

307-
def eulerPath(E):
323+
def euler_path(graph):
308324
# Based on code from Przemek Drochomirecki, Krakow, 5 Nov 2006
309325
# http://code.activestate.com/recipes/498243-finding-eulerian-path-in-undirected-graph/
310326
# Under PSF License
311327
# NB: MUTATES graph
312-
if len(E.nonzero()[0]) == 0:
313-
return None
328+
314329
# counting the number of vertices with odd degree
315-
odd = list(np.nonzero(np.bitwise_and(np.sum(E, axis=0), 1))[1])
316-
odd.append(np.nonzero(E)[0][0])
330+
odd = [x for x in graph.keys() if len(graph[x])&1]
331+
odd.append(graph.keys()[0])
317332
# This check is appropriate if there is a single connected component.
318333
# Since we're willing to take away one connected component per call,
319334
# we skip this check.
320-
# if len(odd) > 3:
335+
# if len(odd)>3:
321336
# return None
322337
stack = [odd[0]]
323338
path = []
324339
# main algorithm
325340
while stack:
326341
v = stack[-1]
327-
nonzero = np.nonzero(E)
328-
nbrs = nonzero[1][nonzero[0] == v]
329-
if len(nbrs) > 0:
330-
u = nbrs[0]
342+
if v in graph:
343+
u = graph[v].pop()
331344
stack.append(u)
332-
# deleting edge u-v
333-
E[u, v] = False
334-
E[v, u] = False
345+
# deleting edge u-v (v-u already removed by pop)
346+
graph[u].remove(v)
347+
# graph[v].remove(u)
348+
if len(graph[v]) == 0:
349+
del graph[v]
350+
if len(graph[u]) == 0:
351+
del graph[u]
335352
else:
336353
path.append(stack.pop())
337354
return path
338355

339356
# 5: Find the paths for each component
340357
components = []
341358
components_closed = []
342-
while len(E.nonzero()[0]) > 0:
343-
# This works because eulerPath mutates the graph as it goes
344-
path = eulerPath(E)
359+
while len(G) > 0:
360+
# This works because euler_path mutates the graph as it goes
361+
path = euler_path(G.d)
345362
if path is None:
346363
raise ValueError("mesh slice has too many odd degree edges; can't find a path along the edge")
347364
component_verts = verts[path]

0 commit comments

Comments
 (0)