Cleanup for version 8.

This commit is contained in:
Juan Pablo Caram 2015-01-02 12:59:06 -05:00
parent 04d028ecc0
commit fe61447887
2 changed files with 203 additions and 203 deletions

View File

@ -14,7 +14,7 @@ from shapely.geometry.base import BaseGeometry
from numpy import arctan2, Inf, array, sqrt, pi, ceil, sin, cos, sign, dot from numpy import arctan2, Inf, array, sqrt, pi, ceil, sin, cos, sign, dot
from numpy.linalg import solve from numpy.linalg import solve
from mpl_toolkits.axes_grid.anchored_artists import AnchoredDrawingArea #from mpl_toolkits.axes_grid.anchored_artists import AnchoredDrawingArea
from rtree import index as rtindex from rtree import index as rtindex

404
camlib.py
View File

@ -17,8 +17,8 @@ import re
import collections import collections
import numpy as np import numpy as np
import matplotlib import matplotlib
import matplotlib.pyplot as plt #import matplotlib.pyplot as plt
from scipy.spatial import Delaunay, KDTree #from scipy.spatial import Delaunay, KDTree
from rtree import index as rtindex from rtree import index as rtindex
@ -2982,206 +2982,206 @@ def parse_gerber_number(strnumber, frac_digits):
return int(strnumber)*(10**(-frac_digits)) return int(strnumber)*(10**(-frac_digits))
def voronoi(P): # def voronoi(P):
""" # """
Returns a list of all edges of the voronoi diagram for the given input points. # Returns a list of all edges of the voronoi diagram for the given input points.
""" # """
delauny = Delaunay(P) # delauny = Delaunay(P)
triangles = delauny.points[delauny.vertices] # triangles = delauny.points[delauny.vertices]
#
circum_centers = np.array([triangle_csc(tri) for tri in triangles]) # circum_centers = np.array([triangle_csc(tri) for tri in triangles])
long_lines_endpoints = [] # long_lines_endpoints = []
#
lineIndices = [] # lineIndices = []
for i, triangle in enumerate(triangles): # for i, triangle in enumerate(triangles):
circum_center = circum_centers[i] # circum_center = circum_centers[i]
for j, neighbor in enumerate(delauny.neighbors[i]): # for j, neighbor in enumerate(delauny.neighbors[i]):
if neighbor != -1: # if neighbor != -1:
lineIndices.append((i, neighbor)) # lineIndices.append((i, neighbor))
else: # else:
ps = triangle[(j+1)%3] - triangle[(j-1)%3] # ps = triangle[(j+1)%3] - triangle[(j-1)%3]
ps = np.array((ps[1], -ps[0])) # ps = np.array((ps[1], -ps[0]))
#
middle = (triangle[(j+1)%3] + triangle[(j-1)%3]) * 0.5 # middle = (triangle[(j+1)%3] + triangle[(j-1)%3]) * 0.5
di = middle - triangle[j] # di = middle - triangle[j]
#
ps /= np.linalg.norm(ps) # ps /= np.linalg.norm(ps)
di /= np.linalg.norm(di) # di /= np.linalg.norm(di)
#
if np.dot(di, ps) < 0.0: # if np.dot(di, ps) < 0.0:
ps *= -1000.0 # ps *= -1000.0
else: # else:
ps *= 1000.0 # ps *= 1000.0
#
long_lines_endpoints.append(circum_center + ps) # long_lines_endpoints.append(circum_center + ps)
lineIndices.append((i, len(circum_centers) + len(long_lines_endpoints)-1)) # lineIndices.append((i, len(circum_centers) + len(long_lines_endpoints)-1))
#
vertices = np.vstack((circum_centers, long_lines_endpoints)) # vertices = np.vstack((circum_centers, long_lines_endpoints))
#
# filter out any duplicate lines # # filter out any duplicate lines
lineIndicesSorted = np.sort(lineIndices) # make (1,2) and (2,1) both (1,2) # lineIndicesSorted = np.sort(lineIndices) # make (1,2) and (2,1) both (1,2)
lineIndicesTupled = [tuple(row) for row in lineIndicesSorted] # lineIndicesTupled = [tuple(row) for row in lineIndicesSorted]
lineIndicesUnique = np.unique(lineIndicesTupled) # lineIndicesUnique = np.unique(lineIndicesTupled)
#
return vertices, lineIndicesUnique # return vertices, lineIndicesUnique
#
#
def triangle_csc(pts): # def triangle_csc(pts):
rows, cols = pts.shape # rows, cols = pts.shape
#
A = np.bmat([[2 * np.dot(pts, pts.T), np.ones((rows, 1))], # A = np.bmat([[2 * np.dot(pts, pts.T), np.ones((rows, 1))],
[np.ones((1, rows)), np.zeros((1, 1))]]) # [np.ones((1, rows)), np.zeros((1, 1))]])
#
b = np.hstack((np.sum(pts * pts, axis=1), np.ones((1)))) # b = np.hstack((np.sum(pts * pts, axis=1), np.ones((1))))
x = np.linalg.solve(A,b) # x = np.linalg.solve(A,b)
bary_coords = x[:-1] # bary_coords = x[:-1]
return np.sum(pts * np.tile(bary_coords.reshape((pts.shape[0], 1)), (1, pts.shape[1])), axis=0) # return np.sum(pts * np.tile(bary_coords.reshape((pts.shape[0], 1)), (1, pts.shape[1])), axis=0)
#
#
def voronoi_cell_lines(points, vertices, lineIndices): # def voronoi_cell_lines(points, vertices, lineIndices):
""" # """
Returns a mapping from a voronoi cell to its edges. # Returns a mapping from a voronoi cell to its edges.
#
:param points: shape (m,2) # :param points: shape (m,2)
:param vertices: shape (n,2) # :param vertices: shape (n,2)
:param lineIndices: shape (o,2) # :param lineIndices: shape (o,2)
:rtype: dict point index -> list of shape (n,2) with vertex indices # :rtype: dict point index -> list of shape (n,2) with vertex indices
""" # """
kd = KDTree(points) # kd = KDTree(points)
#
cells = collections.defaultdict(list) # cells = collections.defaultdict(list)
for i1, i2 in lineIndices: # for i1, i2 in lineIndices:
v1, v2 = vertices[i1], vertices[i2] # v1, v2 = vertices[i1], vertices[i2]
mid = (v1+v2)/2 # mid = (v1+v2)/2
_, (p1Idx, p2Idx) = kd.query(mid, 2) # _, (p1Idx, p2Idx) = kd.query(mid, 2)
cells[p1Idx].append((i1, i2)) # cells[p1Idx].append((i1, i2))
cells[p2Idx].append((i1, i2)) # cells[p2Idx].append((i1, i2))
#
return cells # return cells
#
#
def voronoi_edges2polygons(cells): # def voronoi_edges2polygons(cells):
""" # """
Transforms cell edges into polygons. # Transforms cell edges into polygons.
#
:param cells: as returned from voronoi_cell_lines # :param cells: as returned from voronoi_cell_lines
:rtype: dict point index -> list of vertex indices which form a polygon # :rtype: dict point index -> list of vertex indices which form a polygon
""" # """
#
# first, close the outer cells # # first, close the outer cells
for pIdx, lineIndices_ in cells.items(): # for pIdx, lineIndices_ in cells.items():
dangling_lines = [] # dangling_lines = []
for i1, i2 in lineIndices_: # for i1, i2 in lineIndices_:
connections = filter(lambda (i1_, i2_): (i1, i2) != (i1_, i2_) and (i1 == i1_ or i1 == i2_ or i2 == i1_ or i2 == i2_), lineIndices_) # connections = filter(lambda (i1_, i2_): (i1, i2) != (i1_, i2_) and (i1 == i1_ or i1 == i2_ or i2 == i1_ or i2 == i2_), lineIndices_)
assert 1 <= len(connections) <= 2 # assert 1 <= len(connections) <= 2
if len(connections) == 1: # if len(connections) == 1:
dangling_lines.append((i1, i2)) # dangling_lines.append((i1, i2))
assert len(dangling_lines) in [0, 2] # assert len(dangling_lines) in [0, 2]
if len(dangling_lines) == 2: # if len(dangling_lines) == 2:
(i11, i12), (i21, i22) = dangling_lines # (i11, i12), (i21, i22) = dangling_lines
#
# determine which line ends are unconnected # # determine which line ends are unconnected
connected = filter(lambda (i1,i2): (i1,i2) != (i11,i12) and (i1 == i11 or i2 == i11), lineIndices_) # connected = filter(lambda (i1,i2): (i1,i2) != (i11,i12) and (i1 == i11 or i2 == i11), lineIndices_)
i11Unconnected = len(connected) == 0 # i11Unconnected = len(connected) == 0
#
connected = filter(lambda (i1,i2): (i1,i2) != (i21,i22) and (i1 == i21 or i2 == i21), lineIndices_) # connected = filter(lambda (i1,i2): (i1,i2) != (i21,i22) and (i1 == i21 or i2 == i21), lineIndices_)
i21Unconnected = len(connected) == 0 # i21Unconnected = len(connected) == 0
#
startIdx = i11 if i11Unconnected else i12 # startIdx = i11 if i11Unconnected else i12
endIdx = i21 if i21Unconnected else i22 # endIdx = i21 if i21Unconnected else i22
#
cells[pIdx].append((startIdx, endIdx)) # cells[pIdx].append((startIdx, endIdx))
#
# then, form polygons by storing vertex indices in (counter-)clockwise order # # then, form polygons by storing vertex indices in (counter-)clockwise order
polys = dict() # polys = dict()
for pIdx, lineIndices_ in cells.items(): # for pIdx, lineIndices_ in cells.items():
# get a directed graph which contains both directions and arbitrarily follow one of both # # get a directed graph which contains both directions and arbitrarily follow one of both
directedGraph = lineIndices_ + [(i2, i1) for (i1, i2) in lineIndices_] # directedGraph = lineIndices_ + [(i2, i1) for (i1, i2) in lineIndices_]
directedGraphMap = collections.defaultdict(list) # directedGraphMap = collections.defaultdict(list)
for (i1, i2) in directedGraph: # for (i1, i2) in directedGraph:
directedGraphMap[i1].append(i2) # directedGraphMap[i1].append(i2)
orderedEdges = [] # orderedEdges = []
currentEdge = directedGraph[0] # currentEdge = directedGraph[0]
while len(orderedEdges) < len(lineIndices_): # while len(orderedEdges) < len(lineIndices_):
i1 = currentEdge[1] # i1 = currentEdge[1]
i2 = directedGraphMap[i1][0] if directedGraphMap[i1][0] != currentEdge[0] else directedGraphMap[i1][1] # i2 = directedGraphMap[i1][0] if directedGraphMap[i1][0] != currentEdge[0] else directedGraphMap[i1][1]
nextEdge = (i1, i2) # nextEdge = (i1, i2)
orderedEdges.append(nextEdge) # orderedEdges.append(nextEdge)
currentEdge = nextEdge # currentEdge = nextEdge
#
polys[pIdx] = [i1 for (i1, i2) in orderedEdges] # polys[pIdx] = [i1 for (i1, i2) in orderedEdges]
#
return polys # return polys
#
#
def voronoi_polygons(points): # def voronoi_polygons(points):
""" # """
Returns the voronoi polygon for each input point. # Returns the voronoi polygon for each input point.
#
:param points: shape (n,2) # :param points: shape (n,2)
:rtype: list of n polygons where each polygon is an array of vertices # :rtype: list of n polygons where each polygon is an array of vertices
""" # """
vertices, lineIndices = voronoi(points) # vertices, lineIndices = voronoi(points)
cells = voronoi_cell_lines(points, vertices, lineIndices) # cells = voronoi_cell_lines(points, vertices, lineIndices)
polys = voronoi_edges2polygons(cells) # polys = voronoi_edges2polygons(cells)
polylist = [] # polylist = []
for i in xrange(len(points)): # for i in xrange(len(points)):
poly = vertices[np.asarray(polys[i])] # poly = vertices[np.asarray(polys[i])]
polylist.append(poly) # polylist.append(poly)
return polylist # return polylist
#
#
class Zprofile: # class Zprofile:
def __init__(self): # def __init__(self):
#
# data contains lists of [x, y, z] # # data contains lists of [x, y, z]
self.data = [] # self.data = []
#
# Computed voronoi polygons (shapely) # # Computed voronoi polygons (shapely)
self.polygons = [] # self.polygons = []
pass # pass
#
def plot_polygons(self): # def plot_polygons(self):
axes = plt.subplot(1, 1, 1) # axes = plt.subplot(1, 1, 1)
#
plt.axis([-0.05, 1.05, -0.05, 1.05]) # plt.axis([-0.05, 1.05, -0.05, 1.05])
#
for poly in self.polygons: # for poly in self.polygons:
p = PolygonPatch(poly, facecolor=np.random.rand(3, 1), alpha=0.3) # p = PolygonPatch(poly, facecolor=np.random.rand(3, 1), alpha=0.3)
axes.add_patch(p) # axes.add_patch(p)
#
def init_from_csv(self, filename): # def init_from_csv(self, filename):
pass # pass
#
def init_from_string(self, zpstring): # def init_from_string(self, zpstring):
pass # pass
#
def init_from_list(self, zplist): # def init_from_list(self, zplist):
self.data = zplist # self.data = zplist
#
def generate_polygons(self): # def generate_polygons(self):
self.polygons = [Polygon(p) for p in voronoi_polygons(array([[x[0], x[1]] for x in self.data]))] # self.polygons = [Polygon(p) for p in voronoi_polygons(array([[x[0], x[1]] for x in self.data]))]
#
def normalize(self, origin): # def normalize(self, origin):
pass # pass
#
def paste(self, path): # def paste(self, path):
""" # """
Return a list of dictionaries containing the parts of the original # Return a list of dictionaries containing the parts of the original
path and their z-axis offset. # path and their z-axis offset.
""" # """
#
# At most one region/polygon will contain the path # # At most one region/polygon will contain the path
containing = [i for i in range(len(self.polygons)) if self.polygons[i].contains(path)] # containing = [i for i in range(len(self.polygons)) if self.polygons[i].contains(path)]
#
if len(containing) > 0: # if len(containing) > 0:
return [{"path": path, "z": self.data[containing[0]][2]}] # return [{"path": path, "z": self.data[containing[0]][2]}]
#
# All region indexes that intersect with the path # # All region indexes that intersect with the path
crossing = [i for i in range(len(self.polygons)) if self.polygons[i].intersects(path)] # crossing = [i for i in range(len(self.polygons)) if self.polygons[i].intersects(path)]
#
return [{"path": path.intersection(self.polygons[i]), # return [{"path": path.intersection(self.polygons[i]),
"z": self.data[i][2]} for i in crossing] # "z": self.data[i][2]} for i in crossing]
def autolist(obj): def autolist(obj):