Adds the voronoi module and demo
This commit is contained in:
parent
e8fdfbfa04
commit
ca985518b0
3 changed files with 144 additions and 18 deletions
41
run_all.py
41
run_all.py
|
|
@ -159,23 +159,26 @@ else:
|
||||||
hull_edges = list(utils.tour(hull))
|
hull_edges = list(utils.tour(hull))
|
||||||
LOGN( "\t\tHull of",len(hull_edges),"edges" )
|
LOGN( "\t\tHull of",len(hull_edges),"edges" )
|
||||||
|
|
||||||
LOGN( "\tRemove triangles that have at least one edge in common with the convex hull" )
|
LOGN( "\tRemove triangles that are not sub-parts of the Penrose tiling" )
|
||||||
def adjoin_hull(triangle):
|
# def adjoin_hull(triangle):
|
||||||
"""Return True if the given triangle has at least one edge that is in the set hull_edges."""
|
# """Return True if the given triangle has at least one edge that is in the set hull_edges."""
|
||||||
for (p,q) in utils.tour(list(triangle)):
|
# for (p,q) in utils.tour(list(triangle)):
|
||||||
if (p,q) in hull_edges or (q,p) in hull_edges:
|
# if (p,q) in hull_edges or (q,p) in hull_edges:
|
||||||
return True
|
# return True
|
||||||
return False
|
# return False
|
||||||
|
|
||||||
def acute_triangle(triangle):
|
def acute_triangle(triangle):
|
||||||
"""Return True if the center of the circumcircle of the given triangle lies inside the triangle.
|
"""Return True if the center of the circumcircle of the given triangle lies inside the triangle.
|
||||||
That is if the triangle is acute."""
|
That is if the triangle is acute."""
|
||||||
return triangulation.in_triangle( triangulation.circumcircle(triangle)[0], triangle )
|
return triangulation.in_triangle( triangulation.circumcircle(triangle)[0], triangle )
|
||||||
|
|
||||||
|
# FIXME at depth 3, some triangles have an edge in the convex hull...
|
||||||
# Filter out edges that are in hull_edges
|
# Filter out edges that are in hull_edges
|
||||||
tri_nohull = list(filter_if_not( adjoin_hull, triangles ))
|
# tri_nohull = list(filter_if_not( adjoin_hull, triangles ))
|
||||||
# Filter out triangles that are obtuse
|
# Filter out triangles that are obtuse
|
||||||
triangulated = list(filter_if_not( acute_triangle, tri_nohull ))
|
# triangulated = list(filter_if_not( acute_triangle, tri_nohull ))
|
||||||
|
|
||||||
|
triangulated = list(filter_if_not( acute_triangle, triangles ))
|
||||||
LOGN( "\t\tRemoved", len(triangles)-len(triangulated), "triangles" )
|
LOGN( "\t\tRemoved", len(triangles)-len(triangulated), "triangles" )
|
||||||
|
|
||||||
triangulation_edges = triangulation.edges_of( triangulated )
|
triangulation_edges = triangulation.edges_of( triangulated )
|
||||||
|
|
@ -189,15 +192,18 @@ else:
|
||||||
########################################################################
|
########################################################################
|
||||||
|
|
||||||
if args.voronoi:
|
if args.voronoi:
|
||||||
voronoi_centers = utils.load_points(args.voronoi)
|
# voronoi_centers = utils.load_points(args.voronoi)
|
||||||
|
pass
|
||||||
|
|
||||||
else:
|
else:
|
||||||
LOGN( "Compute the nodes of the Voronoï diagram" )
|
# LOGN( "Compute the nodes of the Voronoï diagram" )
|
||||||
voronoi_centers = voronoi.centers(triangulated)
|
voronoi_graph = voronoi.dual( triangulated )
|
||||||
|
voronoi_edges = voronoi.edges_of( voronoi_graph )
|
||||||
|
voronoi_centers = voronoi_graph.keys()
|
||||||
|
|
||||||
with open("d%i_voronoi_centers.points" % depth, "w") as fd:
|
# with open("d%i_voronoi_centers.points" % depth, "w") as fd:
|
||||||
for p in voronoi_centers:
|
# for p in voronoi_centers:
|
||||||
fd.write( "%f %f\n" % (p[0],p[1]) )
|
# fd.write( "%f %f\n" % (p[0],p[1]) )
|
||||||
|
|
||||||
|
|
||||||
########################################################################
|
########################################################################
|
||||||
|
|
@ -238,8 +244,9 @@ uberplot.scatter_segments( ax, penrose_segments, edgecolor=tcol, alpha=0.9, line
|
||||||
# triangulation
|
# triangulation
|
||||||
uberplot.plot_segments( ax, triangulation_edges, edgecolor="green", alpha=0.2, linewidth=1 )
|
uberplot.plot_segments( ax, triangulation_edges, edgecolor="green", alpha=0.2, linewidth=1 )
|
||||||
|
|
||||||
# Voronoï centers
|
# Voronoï
|
||||||
uberplot.scatter_points( ax, voronoi_centers, edgecolor="none", facecolor="green", linewidth=0 )
|
uberplot.scatter_points( ax, voronoi_centers, edgecolor="magenta", facecolor="white", s=200, alpha=0.5 )
|
||||||
|
uberplot.plot_segments( ax, voronoi_edges, edgecolor="magenta", alpha=0.2, linewidth=1 )
|
||||||
|
|
||||||
ax.set_aspect('equal')
|
ax.set_aspect('equal')
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -39,7 +39,8 @@ def scatter_segments( ax, segments, **kwargs ):
|
||||||
def scatter_points( ax, points, **kwargs ):
|
def scatter_points( ax, points, **kwargs ):
|
||||||
x = [i[0] for i in points]
|
x = [i[0] for i in points]
|
||||||
y = [i[1] for i in points]
|
y = [i[1] for i in points]
|
||||||
ax.scatter( x,y, s=20, marker='o', **kwargs)
|
# ax.scatter( x,y, s=20, marker='o', **kwargs)
|
||||||
|
ax.scatter( x,y, marker='o', **kwargs)
|
||||||
|
|
||||||
|
|
||||||
if __name__=="__main__":
|
if __name__=="__main__":
|
||||||
|
|
|
||||||
118
voronoi.py
Normal file
118
voronoi.py
Normal file
|
|
@ -0,0 +1,118 @@
|
||||||
|
#/usr/bin/env python
|
||||||
|
|
||||||
|
from utils import tour,LOG,LOGN,x,y
|
||||||
|
import triangulation
|
||||||
|
|
||||||
|
def nodes( triangles ):
|
||||||
|
"""Compute the locations of the centers of all the circumscribed circles of the given triangles"""
|
||||||
|
for triangle in triangles:
|
||||||
|
(cx,cy),r = triangulation.circumcircle(triangle)
|
||||||
|
yield (cx,cy)
|
||||||
|
|
||||||
|
|
||||||
|
def edge_in( edge, edges ):
|
||||||
|
"""Return True if the given edge (or its symetric) is in the given polygon."""
|
||||||
|
n,m = edge
|
||||||
|
assert( len(n) == 2 )
|
||||||
|
assert( len(m) == 2 )
|
||||||
|
return (n,m) in edges or (m,n) in edges
|
||||||
|
|
||||||
|
|
||||||
|
def neighbours( triangle, polygons ):
|
||||||
|
"""Returns the set of triangles in candidates that have an edge in common with the given triangle."""
|
||||||
|
for polygon in polygons:
|
||||||
|
if polygon == triangle:
|
||||||
|
continue
|
||||||
|
|
||||||
|
# Convert list of points to list of edges, because we want to find EDGE neighbours.
|
||||||
|
edges_poly = list(tour(list(polygon )))
|
||||||
|
assert( len(list(edges_poly)) > 0 )
|
||||||
|
edges_tri = list(tour(list(triangle)))
|
||||||
|
assert( len(list(edges_tri)) > 0 )
|
||||||
|
|
||||||
|
# If at least one of the edge that are in availables polygons are also in the given triangle.
|
||||||
|
# Beware the symetric edges.
|
||||||
|
# if any( edge_in( edge, edges_tri ) for edge in edges_poly ):
|
||||||
|
# yield polygon
|
||||||
|
for edge in edges_poly:
|
||||||
|
if edge_in( edge, edges_tri ):
|
||||||
|
yield polygon
|
||||||
|
break
|
||||||
|
|
||||||
|
|
||||||
|
def dual( triangles ):
|
||||||
|
graph = {}
|
||||||
|
|
||||||
|
def add_edge( current, neighbor ):
|
||||||
|
if current in graph:
|
||||||
|
if neighbor not in graph[current]:
|
||||||
|
graph[current].append( neighbor )
|
||||||
|
else:
|
||||||
|
graph[current] = [ neighbor ]
|
||||||
|
|
||||||
|
for triangle in triangles:
|
||||||
|
assert( len(triangle) == 3 )
|
||||||
|
current_node = triangulation.circumcircle(triangle)[0]
|
||||||
|
assert( len(current_node) == 2 )
|
||||||
|
|
||||||
|
for neighbor_triangle in neighbours( triangle, triangles ):
|
||||||
|
neighbor_node = triangulation.circumcircle(neighbor_triangle)[0]
|
||||||
|
assert( len(neighbor_node) == 2 )
|
||||||
|
|
||||||
|
add_edge( current_node, neighbor_node )
|
||||||
|
add_edge( neighbor_node, current_node )
|
||||||
|
|
||||||
|
return graph
|
||||||
|
|
||||||
|
|
||||||
|
def edges_of( graph ):
|
||||||
|
# edges = set()
|
||||||
|
edges = []
|
||||||
|
for k in graph:
|
||||||
|
for n in graph[k]:
|
||||||
|
if k != n and (k,n) not in edges and (n,k) not in edges:
|
||||||
|
# edges.add( (k,n) )
|
||||||
|
edges.append( (k,n) )
|
||||||
|
|
||||||
|
return edges
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
import sys
|
||||||
|
import random
|
||||||
|
import utils
|
||||||
|
import uberplot
|
||||||
|
import triangulation
|
||||||
|
import matplotlib.pyplot as plot
|
||||||
|
|
||||||
|
if len(sys.argv) > 1:
|
||||||
|
scale = 100
|
||||||
|
nb = int(sys.argv[1])
|
||||||
|
points = [ (scale*random.random(),scale*random.random()) for i in range(nb)]
|
||||||
|
else:
|
||||||
|
points = [
|
||||||
|
(0,40),
|
||||||
|
(100,60),
|
||||||
|
(40,0),
|
||||||
|
(50,100),
|
||||||
|
(90,10),
|
||||||
|
# (50,50),
|
||||||
|
]
|
||||||
|
|
||||||
|
fig = plot.figure()
|
||||||
|
|
||||||
|
triangles = triangulation.delaunay_bowyer_watson( points )
|
||||||
|
delaunay_edges = triangulation.edges_of( triangles )
|
||||||
|
|
||||||
|
voronoi_graph = dual( triangles )
|
||||||
|
voronoi_edges = edges_of( voronoi_graph )
|
||||||
|
print voronoi_edges
|
||||||
|
|
||||||
|
ax = fig.add_subplot(111)
|
||||||
|
ax.set_aspect('equal')
|
||||||
|
uberplot.scatter_segments( ax, delaunay_edges, facecolor = "blue" )
|
||||||
|
uberplot.plot_segments( ax, delaunay_edges, edgecolor = "blue" )
|
||||||
|
uberplot.scatter_segments( ax, voronoi_edges, facecolor = "red" )
|
||||||
|
uberplot.plot_segments( ax, voronoi_edges, edgecolor = "red" )
|
||||||
|
plot.show()
|
||||||
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue