refactor load/save functions

Use streams instead of filename.
Move load/write functions if modules where logical.
This commit is contained in:
Johann Dreo 2014-05-21 13:42:23 +02:00
commit c37cce25ed
5 changed files with 160 additions and 130 deletions

47
graph.py Normal file
View file

@ -0,0 +1,47 @@
from geometry import x,y
def graph_of( segments ):
graph = {}
for start,end in segments:
graph[start] = graph.get( start, [] )
graph[start].append( end )
graph[end] = graph.get( end, [] )
graph[end].append( start )
return graph
def edges_of( graph ):
edges = set()
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) )
return list(edges)
def nodes_of( graph ):
return graph.keys()
def load( stream ):
graph = {}
for line in stream:
if line.strip()[0] != "#":
skey,svals = line.split(":")
key = tuple((float(i) for i in skey.split(',')))
graph[key] = []
for sp in svals.split():
p = tuple(float(i) for i in sp.split(","))
assert(len(p)==2)
graph[key].append( p )
return graph
def write( graph, stream ):
for k in graph:
stream.write( "%f,%f:" % (x(k),y(k)) )
for p in graph[k]:
stream.write( "%f,%f " % (x(p),y(p)) )
stream.write("\n")

View file

@ -17,6 +17,7 @@ import shortpath
import lindenmayer
import triangulation
import voronoi
import graph
parser = argparse.ArgumentParser()
@ -53,7 +54,8 @@ penrose_segments = set()
if args.penrose:
LOGN( "Load the penrose tiling" )
penrose_segments = utils.load_segments(args.penrose)
with open(args.penrose) as fd:
penrose_segments = utils.load_segments(fd)
else:
LOGN( "Draw the penrose tiling" )
@ -79,11 +81,11 @@ else:
penrose.draw( depth )
# save this intermediate step
LOGN( "\tsegments",len(penrose.segments) )
with open("d%i_penrose.segments" % depth, "w") as fd:
fd.write( str(penrose) )
penrose_segments = penrose.segments
LOGN( "\tsegments",len(penrose_segments) )
with open("d%i_penrose.segments" % depth, "w") as fd:
utils.write_segments( penrose_segments, fd )
########################################################################
@ -94,7 +96,8 @@ trajs = []
if args.tour != [None]:
for tour in args.tour:
trajs.append( utils.load_points(tour) )
with open(tour) as fd:
trajs.append( utils.load_points(fd) )
if args.notsp:
if args.tour == [None] or not args.pheromones:
@ -102,13 +105,14 @@ if args.notsp:
sys.exit(error_codes["NO-TSP"])
if args.pheromones:
phero = utils.load_matrix(args.pheromones)
with open(args.pheromones) as fd:
phero = utils.load_matrix(fd)
else:
LOGN( "Solve the TSP with an Ant Colony Algorithm" )
LOGN( "\tConvert the segment list into an adjacency list graph" )
G = utils.adjacency_from_set( penrose_segments )
G = graph.graph_of( penrose_segments )
LOGN( "\tCompute a tour" )
max_it = 10
@ -130,89 +134,68 @@ else:
trajs.append(traj)
with open("d%i_tour.points" % depth, "w") as fd:
for p in traj:
fd.write("%f %f\n" % p)
utils.write_points( traj, fd )
with open("d%i_pheromones.mat" % depth, "w") as fd:
for row in phero:
key = "%f,%f:" % row
line = key
for k in phero[row]:
val = phero[row][k]
line += "%f,%f=%f " % (k[0],k[1],val)
fd.write( line + "\n" )
utils.write_matrix( phero, fd )
########################################################################
# TRIANGULATION
########################################################################
triangulated = []
if args.triangulation:
triangulation_edges = utils.load_segments(args.triangulation)
with open(args.triangulation) as fd:
triangulated = triangulation.load(args.triangulation)
else:
LOGN( "Compute the triangulation of the penrose vertices" )
points = utils.vertices_of(penrose_segments)
triangles = triangulation.delaunay_bowyer_watson( points, do_plot = False )
# LOGN( "\tCompute the convex hull of",len(points),"points" )
# # Should convert the set into a list
# hull = hull.convex_hull( list(points) )
# hull_edges = list(utils.tour(hull))
# LOGN( "\t\tHull of",len(hull_edges),"edges" )
LOGN( "\tRemove triangles that are not sub-parts of the Penrose tiling" )
# def adjoin_hull(triangle):
# """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)):
# if (p,q) in hull_edges or (q,p) in hull_edges:
# return True
# return False
def acute_triangle(triangle):
"""Return True if the center of the circumcircle of the given triangle lies inside the triangle.
That is if the triangle is acute."""
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
# tri_nohull = list(filter_if_not( adjoin_hull, triangles ))
# Filter out triangles that are obtuse
# 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" )
triangulation_edges = triangulation.edges_of( triangulated )
with open("d%i_triangulation.segments" % depth, "w") as fd:
for p0,p1 in triangulation_edges:
fd.write("%f %f %f %f\n" % (p0[0],p0[1],p1[0],p1[1]) )
with open("d%i_triangulation.triangles" % depth, "w") as fd:
triangulation.write( triangulated, fd )
triangulation_edges = triangulation.edges_of( triangulated )
########################################################################
# VORONOÏ
########################################################################
voronoi_graph = {}
if args.voronoi:
voronoi_graph = utils.load_adjacency(args.voronoi)
with open(args.voronoi) as fd:
voronoi_graph = graph.load( fd )
else:
# LOGN( "Compute the nodes of the Voronoï diagram" )
voronoi_tri_graph = voronoi.dual(triangulated)
voronoi_tri_edges = voronoi.edges_of( voronoi.dual(triangulated) )
voronoi_tri_edges = graph.edges_of( voronoi.dual(triangulated) )
voronoi_tri_centers = voronoi_tri_graph.keys()
voronoi_graph = voronoi.merge_enclosed( voronoi_tri_graph, penrose_segments )
with open("d%i_voronoi.graph" % depth, "w") as fd:
for k in voronoi_graph:
fd.write( "%f,%f:" % (x(k),y(k)) )
for p in voronoi_graph[k]:
fd.write( "%f,%f " % (x(p),y(p)) )
fd.write("\n")
graph.write( voronoi_graph, fd )
voronoi_edges = voronoi.edges_of( voronoi_graph )
voronoi_centers = voronoi_graph.keys()
voronoi_edges = graph.edges_of( voronoi_graph )
voronoi_centers = graph.nodes_of( voronoi_graph )
########################################################################

View file

@ -3,8 +3,8 @@ import sys
import math
from itertools import ifilterfalse as filter_if_not
from utils import tour,LOG,LOGN,x,y
from geometry import mid, middle
from utils import tour,LOG,LOGN
from geometry import mid,middle,x,y
# Based on http://paulbourke.net/papers/triangulate/
# Efficient Triangulation Algorithm Suitable for Terrain Modelling
@ -132,15 +132,6 @@ def bounds( vertices ):
return (xmin,ymin),(xmax,ymax)
def edges_of( triangulation ):
"""Return a list containing the edges of the given list of 3-tuples of points"""
edges = []
for t in triangulation:
for e in tour(list(t)):
edges.append( e )
return edges
def supertriangle( vertices, delta = 0.1 ):
"""Return a super-triangle that encloses all given points.
The super-triangle has its base at the bottom and encloses the bounding box at a distance given by:
@ -345,6 +336,37 @@ def delaunay_bowyer_watson( points, supertri = None, superdelta = 0.1, epsilon =
return triangulation
def edges_of( triangulation ):
"""Return a list containing the edges of the given list of 3-tuples of points"""
edges = []
for t in triangulation:
for e in tour(list(t)):
edges.append( e )
return edges
def load( stream ):
triangles = []
for line in stream:
if line.strip()[0] != "#":
tri = line.split()
assert(len(tri)==3)
triangle = []
for p in tri:
assert(len(p)==2)
point = [ (float(y),float(y)) for i,j in p.split(",")]
triangle.append( point )
triangles.append( triangle )
return triangles
def write( triangles, stream ):
for tri in triangles:
assert(len(tri)==3)
p,q,r = tri
stream.write("%f,%f %f,%f %f,%f\n" % ( x(p),y(p), x(q),y(q), x(r),y(r) ) )
if __name__ == "__main__":
import random
import utils

108
utils.py
View file

@ -17,80 +17,68 @@ def LOGN( *args ):
LOG("\n")
def load_points( filename ):
def load_points( stream ):
points = []
with open(filename) as fd:
for line in fd:
if line.strip()[0] != "#":
p = tuple([float(i) for i in line.split()])
assert(len(p)==2)
points.append( p )
for line in stream:
if line.strip()[0] != "#":
p = tuple([float(i) for i in line.split()])
assert(len(p)==2)
points.append( p )
return points
def load_segments( filename ):
def write_points( points, stream ):
for p in points:
stream.write( "%f,%f\n" % ( x(p),y(p) ) )
def load_segments( stream ):
segments = []
with open(filename) as fd:
for line in fd:
if line.strip()[0] != "#":
edge = [float(i) for i in line.split()]
assert(len(edge)==4)
segments.append( ((edge[0],edge[1]),(edge[2],edge[3])) )
for line in stream:
if line.strip()[0] != "#":
seg = line.strip()
assert(len(seg)==2)
edge = []
for p in seg:
assert(len(p)==2)
point = tuple([float(i) for i in seg])
edge.append( point )
segments.append( edge )
return segments
def load_triangles( filename ):
triangles = []
with open(filename) as fd:
for line in fd:
if line.strip()[0] != "#":
tri = [float(i) for i in line.split()]
assert(len(tri)==6)
triangles.append( ((tri[0],tri[1]),(tri[2],tri[3]),(tri[4],tri[5])) )
return triangles
def write_segments( segments, stream ):
for seg in segments:
for p in seg:
stream.write( "%f,%f " % ( x(p),y(p) ) )
stream.write( "\n" )
def load_matrix( filename ):
def load_matrix( stream ):
matrix = {}
with open(filename) as fd:
for line in fd:
if line.strip()[0] != "#":
skey,svals = line.split(":")
key = tuple((float(i) for i in skey.split(',')))
col = {}
for stri in svals.split():
sk,sv = stri.split("=")
value = float(sv)
k = tuple((float(i) for i in sk.split(",")))
col[k] = value
matrix[key] = col
assert(len(matrix) == len(matrix[key]))
for line in stream:
if line.strip()[0] != "#":
skey,svals = line.split(":")
key = tuple((float(i) for i in skey.split(',')))
col = {}
for stri in svals.split():
sk,sv = stri.split("=")
value = float(sv)
k = tuple((float(i) for i in sk.split(",")))
col[k] = value
matrix[key] = col
assert(len(matrix) == len(matrix[key]))
return matrix
def load_adjacency( filename ):
graph = {}
with open(filename) as fd:
for line in fd:
if line.strip()[0] != "#":
skey,svals = line.split(":")
key = tuple((float(i) for i in skey.split(',')))
graph[key] = []
for sp in svals.split():
p = tuple(float(i) for i in sp.split(","))
assert(len(p)==2)
graph[key].append( p )
return graph
def adjacency_from_set( segments ):
graph = {}
for start,end in segments:
graph[start] = graph.get( start, [] )
graph[start].append( end )
graph[end] = graph.get( end, [] )
graph[end].append( start )
return graph
def write_matrix( mat, stream):
for row in mat:
key = "%f,%f:" % row
line = key
for k in mat[row]:
val = mat[row][k]
line += "%f,%f=%f " % (k[0],k[1],val)
stream.write( line + "\n" )
def vertices_of( segments ):

View file

@ -4,6 +4,7 @@
from utils import tour,LOG,LOGN,x,y
import triangulation
import geometry
import graph
def nodes( triangles ):
"""Compute the locations of the centers of all the circumscribed circles of the given triangles"""
@ -68,17 +69,6 @@ def dual( triangles ):
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
def merge_nodes( graph, n0, n1, n2 ):
"""Merge n0 and n1 nodes as n2 within the given graph."""
@ -179,7 +169,7 @@ if __name__ == "__main__":
delaunay_edges = triangulation.edges_of( triangles )
voronoi_graph = dual( triangles )
voronoi_edges = edges_of( voronoi_graph )
voronoi_edges = graph.edges_of( voronoi_graph )
print voronoi_edges
ax = fig.add_subplot(111)