def grid(vertex, b): #Sammelt Numerische Werte aus Variables-Objekt pForward = singleton.gridpForward pTurn = singleton.gridpTurn lMin = singleton.gridlMin lMax = singleton.gridlMax suggested_vertices = [] weiter = True #Berechnet den Vektor des letzten Weges zu diesem Punkt previous_vector = np.array(vertex.coords - vertex.neighbours[len(vertex.neighbours) - 1].coords) previous_vector = previous_vector / np.linalg.norm(previous_vector) n = np.array([-previous_vector[1], previous_vector[0]]) #Geradeaus v = random.uniform(lMin, lMax) * previous_vector random_number = random.randint(0, 100) if random_number <= pForward: k = Vertex(vertex.coords + v) suggested_vertices.append(k) weiter = False #Rechts v = random.uniform(lMin, lMax) * previous_vector random_number = random.randint(0, 100) if random_number <= pTurn * b * b: k = Vertex(vertex.coords + n) suggested_vertices.append(k) weiter = True #Links v = random.uniform(lMin, lMax) * previous_vector random_number = random.randint(0, 100) if random_number <= pTurn * b * b: k = Vertex(vertex.coords - n) suggested_vertices.append(k) weiter = True #Seed! if not weiter: vertex.seed = True singleton.global_lists.vertex_queue.append([vertex, 0]) return suggested_vertices
def radial(center, vertex, b): #Sammelt Numerische Werte aus Variables-Objekt pForward = singleton.radialpForward pTurn = singleton.radialpTurn lMin = singleton.radiallMin lMax = singleton.radiallMax #Berechnet Radialvector und Vektor des letzten Weges zu diesem Punkt radialvector = vertex.coords - center previous_vector = np.array(vertex.coords - vertex.neighbours[len(vertex.neighbours) - 1].coords) previous_vector = previous_vector / np.linalg.norm(previous_vector) suggested_vertices = [] weiter = False #Berechnet, ob der Vektor eher Radial oder Tangential verlaeuft alpha = case_differentiation(previous_vector, radialvector) previous_vector = rotate(alpha, previous_vector) #Geradeaus v = random.uniform(lMin, lMax) * previous_vector random_number = random.randint(0, 100) if random_number <= pForward: k = Vertex(vertex.coords + v) suggested_vertices.append(k) #Rechts v = random.uniform(lMin, lMax) * previous_vector random_number = random.randint(0, 100) if random_number <= pTurn * b * b: k = Vertex(vertex.coords + rotate(90, v)) suggested_vertices.append(k) weiter = True #Links v = random.uniform(lMin, lMax) * previous_vector random_number = random.randint(0, 100) if random_number <= pTurn * b * b: k = Vertex(vertex.coords - rotate(90, v)) suggested_vertices.append(k) weiter = True #Seed! if not weiter: vertex.seed = True singleton.global_lists.vertex_queue.append([vertex, 0]) return suggested_vertices
def organic(vertex, b): # Sammelt Numerische Werte aus Variables-Objekt pForward = singleton.organicpForward pTurn = singleton.organicpTurn lMin = singleton.organiclMin lMax = singleton.organiclMax suggested_vertices = [] weiter = False # Berechnet den Vektor des letzten Weges zu diesem Punkt previous_vector = np.array(vertex.coords - vertex.neighbours[len(vertex.neighbours) - 1].coords) previous_vector = previous_vector / np.linalg.norm(previous_vector) # Geradeaus v = random.uniform(lMin, lMax) * previous_vector random_number = random.randint(0, 100) if random_number <= pForward: k = Vertex(vertex.coords + rotate(np.random.uniform(-30, 30), v)) suggested_vertices.append(k) # Rechts v = random.uniform(lMin, lMax) * previous_vector random_number = random.randint(0, 100) if random_number <= b * pTurn: k = Vertex(vertex.coords + rotate(np.random.uniform(-120, -60), v)) suggested_vertices.append(k) weiter = True # Links v = random.uniform(lMin, lMax) * previous_vector random_number = random.randint(0, 100) if random_number <= b * pTurn: k = Vertex(vertex.coords + rotate(np.random.uniform(60, 120), v)) suggested_vertices.append(k) weiter = True # Seed! if not weiter: vertex.seed = True singleton.global_lists.vertex_queue.append([vertex, 0]) return suggested_vertices
def seed(vertex,b): pSeed=singleton.pSeed lMin=singleton.seedlMin lMax=singleton.seedlMax suggested_vertices=[] l=len(vertex.neighbours) v1=rotate(90,vertex.neighbours[0].coords-vertex.coords) v2=None if l==1: v2=v1 elif l==2: v2=rotate(90,vertex.neighbours[1].coords-vertex.coords)*-1 else: return [] v1=v1/np.linalg.norm(v1) v2=v2/np.linalg.norm(v2) #Rechts if b*b*pSeed>np.random.randint(0,100): l=np.random.uniform(lMin,lMax) k=np.random.uniform(0,1) coords=((1-k)*v1+k*v2)*l k=Vertex(vertex.coords+coords) k.minor_road=True suggested_vertices.append(k) v1=v1*-1 v2=v2*-1 #Links if b*b*pSeed>np.random.randint(0,100): l=np.random.uniform(lMin,lMax) k=np.random.uniform(0,1) coords=((1-k)*v1+k*v2)*l k=Vertex(vertex.coords+coords) k.minor_road=True suggested_vertices.append(k) return suggested_vertices
def reconstruct(path=None): if path is None: import os import procedural_city_generation path=os.path.dirname(procedural_city_generation.__file__)+"/outputs/output.json" import json try: with open(path,'r') as d: data=d.read() except IOError: print "Input could not be located. Try to run the previous program in the chain first." return 0 data=json.loads(data) from procedural_city_generation.roadmap.Vertex import Vertex import numpy as np vertex_list=[] vertex_list=[0]*len(data) for x in data: y=data[x] k=Vertex(np.array(y[0])) k.minor_road,k.seed,k.neighboursindizes=y[1],y[2],y[3] vertex_list[int(x)]=k index=0 for k in vertex_list: for x in k.neighboursindizes: k.neighbours.append(vertex_list[x]) k.selfindex=index index+=1 setliste=[] return vertex_list
def minor_road(vertex, b): # Sammelt Numerische Werte aus Variables-Objekt pForward = singleton.minor_roadpForward pTurn = singleton.minor_roadpTurn lMin = singleton.minor_roadlMin lMax = singleton.minor_roadlMax suggested_vertices = [] # Berechnet den Vektor des letzten Weges zu diesem Punkt previous_vector = np.array(vertex.coords - vertex.neighbours[len(vertex.neighbours) - 1].coords) previous_vector = previous_vector / np.linalg.norm(previous_vector) n = np.array([-previous_vector[1], previous_vector[0]]) # Geradeaus v = random.uniform(lMin, lMax) * previous_vector random_number = random.randint(0, 100) if random_number < pForward * b: k = Vertex(vertex.coords + v) # k.neighbours.append(vertex) k.minor_road = True suggested_vertices.append(k) # Rechts v = random.uniform(lMin, lMax) * previous_vector random_number = random.randint(0, 100) if random_number < pTurn * b: k = Vertex(vertex.coords + n) # k.neighbours.append(vertex) k.minor_road = True suggested_vertices.append(k) # Links v = random.uniform(lMin, lMax) * previous_vector random_number = random.randint(0, 100) if random_number < pTurn * b: k = Vertex(vertex.coords - n) # k.neighbours.append(vertex) k.minor_road = True suggested_vertices.append(k) return suggested_vertices
def minor_road(vertex, b): #Sammelt Numerische Werte aus Variables-Objekt pForward=singleton.minor_roadpForward pTurn=singleton.minor_roadpTurn lMin=singleton.minor_roadlMin lMax=singleton.minor_roadlMax suggested_vertices=[] #Berechnet den Vektor des letzten Weges zu diesem Punkt previous_vector=np.array(vertex.coords-vertex.neighbours[len(vertex.neighbours)-1].coords) previous_vector=previous_vector/np.linalg.norm(previous_vector) n=np.array([-previous_vector[1], previous_vector[0]]) #Geradeaus v=random.uniform(lMin, lMax)*previous_vector random_number=random.randint(0, 100) if random_number<pForward*b: k=Vertex(vertex.coords+v) #k.neighbours.append(vertex) k.minor_road=True suggested_vertices.append(k) #Rechts v=random.uniform(lMin, lMax)*previous_vector random_number=random.randint(0, 100) if random_number<pTurn*b: k=Vertex(vertex.coords+n) #k.neighbours.append(vertex) k.minor_road=True suggested_vertices.append(k) #Links v=random.uniform(lMin, lMax)*previous_vector random_number=random.randint(0, 100) if random_number<pTurn*b: k=Vertex(vertex.coords-n) #k.neighbours.append(vertex) k.minor_road=True suggested_vertices.append(k) return suggested_vertices
def seed(vertex, b): pSeed = singleton.pSeed lMin = singleton.seedlMin lMax = singleton.seedlMax suggested_vertices = [] l = len(vertex.neighbours) v1 = rotate(90, vertex.neighbours[0].coords - vertex.coords) v2 = None if l == 1: v2 = v1 elif l == 2: v2 = rotate(90, vertex.neighbours[1].coords - vertex.coords) * -1 else: return [] v1 = v1 / np.linalg.norm(v1) v2 = v2 / np.linalg.norm(v2) #Rechts if b * b * pSeed > np.random.randint(0, 100): l = np.random.uniform(lMin, lMax) k = np.random.uniform(0, 1) coords = ((1 - k) * v1 + k * v2) * l k = Vertex(vertex.coords + coords) k.minor_road = True suggested_vertices.append(k) v1 = v1 * -1 v2 = v2 * -1 #Links if b * b * pSeed > np.random.randint(0, 100): l = np.random.uniform(lMin, lMax) k = np.random.uniform(0, 1) coords = ((1 - k) * v1 + k * v2) * l k = Vertex(vertex.coords + coords) k.minor_road = True suggested_vertices.append(k) return suggested_vertices
def config(): """ Starts the program up with all necessary things. Reads the inputs, creates the Singleton objects properly, sets up the heightmap for later, makes sure all Vertices in the axiom have the correct neighbor. Could need a rework in which the Singletons are unified and not broken as they are now. Returns ------- variables : Variables object Singleton with all numeric values which are not to be changed at runtime singleton.global_lists : singleton.global_lists object Singleton with the Global Lists which will be altered at runtime """ import json from collections import namedtuple import os import procedural_city_generation from procedural_city_generation.additional_stuff.Singleton import Singleton path = os.path.dirname(procedural_city_generation.__file__) singleton = Singleton("roadmap") #Creates Singleton-Variables object from namedtuple from procedural_city_generation.roadmap.Vertex import Vertex, set_plotbool #Creates Vertex objects from coordinates singleton.axiom = [ Vertex(np.array([float(x[0]), float(x[1])])) for x in singleton.axiom ] set_plotbool(singleton.plot) #Finds the longest possible length of a connection between to vertices singleton.maxLength = max(singleton.radiallMax, singleton.gridlMax, singleton.organiclMax, singleton.minor_roadlMax, singleton.seedlMax) import os from procedural_city_generation.roadmap.config_functions.input_image_setup import input_image_setup singleton.img, singleton.img2 = input_image_setup( path + "/inputs/rule_pictures/" + singleton.rule_image_name, path + "/inputs/density_pictures/" + singleton.density_image_name) from procedural_city_generation.roadmap.config_functions.find_radial_centers import find_radial_centers singleton.center = find_radial_centers(singleton) singleton.center = [ np.array([ singleton.border[0] * ((x[1] / singleton.img.shape[1]) - 0.5) * 2, singleton.border[1] * (((singleton.img.shape[0] - x[0]) / singleton.img.shape[0]) - 0.5) * 2 ]) for x in singleton.center ] from procedural_city_generation.roadmap.config_functions.setup_heightmap import setup_heightmap setup_heightmap(singleton, path) with open(path + "/temp/border.txt", 'w') as f: f.write(str(singleton.border[0]) + " " + str(singleton.border[1])) singleton.global_lists = Global_Lists() singleton.global_lists.vertex_list.extend(singleton.axiom) singleton.global_lists.coordsliste = [ x.coords for x in singleton.global_lists.vertex_list ] def setNeighbours(vertex): """ Correctly Sets up the neighbors for a vertex from the axiom. Parameters ---------- vertex : vertex Object """ d = np.inf neighbour = None for v in singleton.axiom: if v is not vertex: dneu = np.linalg.norm(v.coords - vertex.coords) if dneu < d: d = dneu neighbour = v vertex.neighbours = [neighbour] for k in singleton.axiom: setNeighbours(k) from scipy.spatial import cKDTree singleton.global_lists.tree = cKDTree(singleton.global_lists.coordsliste, leafsize=160) return singleton
def check(suggested_vertex, neighbour, newfront): """ Performs the following checks on a suggestes vertex and the suggested connection between this vertex and his last neighbour: 1) Is the vertex out of bounds If yes, dont add this Vertex 2) Is the vertex too close to an existing vertex If yes, change the vector that is checked in 4 and 5 from [neighbor-suggested_vertex] to [neighbor-closest_existing_point] 3) Does the the vector intersect an existing connection (road) If yes, only create the connection up until that intersection. Add that intersection to the Global_lists and fix the neighbor attribute of the existing connection that was "intersected". 4) Does the vector stop shortly before an existing connection If yes, extend the connection up until that intersection. Add that intersection to the Global_lists and fix the neighbor attribute of the existing connection that was "intersected". If none of the above, simply add this vertex to the global_lists and the new front and return the newfront. This is the only place aftert config, where Vertices get added to the Global Lists. Every Time A vertex is added, the cKDTree used to find the closest vertices has to be updated. Parameters ---------- suggested_vertex : Vertex object neighbour : Vertex object newfront : list<Vertex> Returns ------- newfront : list<Vertex> """ #Checks if Neighborbar is in Bounds if (abs(suggested_vertex.coords[0]) > singleton.border[0] - singleton.maxLength) or ( abs(suggested_vertex.coords[1]) > singleton.border[1] - singleton.maxLength): return newfront #Finds all nearby Vertex and their distances distances, nearvertex = singleton.global_lists.tree.query( suggested_vertex.coords, 10, distance_upper_bound=singleton.maxLength) l = len(singleton.global_lists.vertex_list) nearvertex = [ singleton.global_lists.vertex_list[x] for x in nearvertex if x < l ] #Distances[0] is the distance to the nearest Vertex, nearve: if distances[0] < singleton.min_distance: #If the nearest Vertex is not a neighbor if nearvertex[0] not in neighbour.neighbours: #Find the best solution - as in the closest intersection bestsol = np.inf solvertex = None for k in nearvertex: for n in k.neighbours: if n in nearvertex: #and not in doneliste sol = get_intersection( neighbour.coords, nearvertex[0].coords - neighbour.coords, k.coords, n.coords - k.coords) if sol[0] > 0.00001 and sol[0] < 0.99999 and sol[ 1] > 0.00001 and sol[1] < 0.99999 and sol[ 0] < bestsol: bestsol = sol[0] solvertex = [n, k] # If there is at least one solution, intersect that solution # See docstring #3 and #4 if solvertex is not None: solvertex[1].neighbours.remove(solvertex[0]) solvertex[0].neighbours.remove(solvertex[1]) newk = Vertex(neighbour.coords + bestsol * (nearvertex[0].coords - neighbour.coords)) singleton.global_lists.vertex_list.append(newk) singleton.global_lists.coordsliste.append(newk.coords) singleton.global_lists.tree = cKDTree( singleton.global_lists.coordsliste, leafsize=160) neighbour.connection(newk) solvertex[1].connection(newk) solvertex[0].connection(newk) return newfront else: #If there is no solution, the Vertex is clear #See docstring finish nearvertex[0].connection(neighbour) return newfront bestsol = np.inf solvertex = None #If there is not an existing vertex too close, do the same thing but with # The vector between the suggested vertex and its neighbro for k in nearvertex: for n in k.neighbours: if n in nearvertex: #and not in doneliste sol = get_intersection( neighbour.coords, suggested_vertex.coords - neighbour.coords, k.coords, n.coords - k.coords) if sol[0] > 0.00001 and sol[0] < 1.499999 and sol[ 1] > 0.00001 and sol[1] < 0.99999 and sol[0] < bestsol: bestsol = sol[0] solvertex = [n, k] if solvertex is not None: solvertex[1].neighbours.remove(solvertex[0]) solvertex[0].neighbours.remove(solvertex[1]) newk = Vertex(neighbour.coords + bestsol * (suggested_vertex.coords - neighbour.coords)) singleton.global_lists.vertex_list.append(newk) singleton.global_lists.coordsliste.append(newk.coords) singleton.global_lists.tree = cKDTree( singleton.global_lists.coordsliste, leafsize=160) neighbour.connection(newk) solvertex[1].connection(newk) solvertex[0].connection(newk) return newfront #If the Vertex is clear to go, add him and return newfront. suggested_vertex.connection(neighbour) newfront.append(suggested_vertex) singleton.global_lists.vertex_list.append(suggested_vertex) singleton.global_lists.coordsliste.append(suggested_vertex.coords) singleton.global_lists.tree = cKDTree(singleton.global_lists.coordsliste, leafsize=160) return newfront