def bisect_angle(a, b, c, epsilon=0.2, radius=1): """ finds point d such that bd bisects the lines ab and bc.""" ax = a.x - b.x ay = a.y - b.y cx = c.x - b.x cy = c.y - b.y a1 = mg.MyNode(((ax, ay))/np.linalg.norm((ax, ay))) c1 = mg.MyNode(((cx, cy))/np.linalg.norm((cx, cy))) # if vectors are close to parallel, find vector that is perpendicular to ab # if they are not, then find the vector that bisects a and c if abs(np.cross(a1.loc, c1.loc)) < 0 + epsilon: # print("vectors {0}{1} and {1}{2} are close to //)".format(a,b,c) dx = -ay dy = ax else: dx = (a1.x + c1.x)/2 dy = (a1.y + c1.y)/2 # convert d values into a vector of length radius dscale = ((dx, dy)/np.linalg.norm((dx, dy)))*radius myd = mg.MyNode(dscale) # make d a node in space, not vector around b d = mg.MyNode((myd.x + b.x, myd.y + b.y)) return d
def testGraphLattice(n, xshift=0, yshift=0, scale=1): """returns a square lattice of dimension nxn """ nodelist = {} for j in range(0, n**2): x = (math.fmod(j, n))*scale + xshift y = (math.floor(j/n))*scale + yshift nodelist[j] = mg.MyNode((x, y)) edgelist = defaultdict(list) for i in nodelist.keys(): ni = nodelist[i] for j in nodelist.keys(): nj = nodelist[j] if ni != nj: if distance(ni, nj) == scale: edgelist[ni].append(nj) myedgelist = [] for n1 in edgelist.keys(): n2s = edgelist[n1] for n2 in n2s: myedgelist.append(mg.MyEdge((n1, n2))) lattice = graphFromMyEdges(myedgelist) lattice.name = "lattice" return lattice
def rescale_mygraph(myG, rezero=np.array([0, 0]), rescale=np.array([1, 1])): """returns a new graph (with no interior properties defined), rescaled under a linear function newloc = (oldloc-rezero)*rescale where all of those are (x,y) numpy arrays. Default of rezero = (0,0) and rescale = (1,1) means the locations of nodes in the new and old graph are the same. """ scaleG = mg.MyGraph() for e in myG.myedges(): n0 = e.nodes[0] n1 = e.nodes[1] nn0 = mg.MyNode((n0.loc-rezero)*rescale) nn1 = mg.MyNode((n1.loc-rezero)*rescale) scaleG.add_edge(mg.MyEdge((nn0, nn1))) return scaleG
def graphFromJSON(jsonobj): """returns a new mygraph from a json object. calculates interior node and graph properties from the properties of the edges. """ edgelist = [] # read all the edges from json for feature in jsonobj['features']: # check that there are exactly 2 nodes numnodes = len(feature['geometry']['coordinates']) if numnodes != 2: raise AssertionError("JSON line feature has {} " "coordinates instead of 2".format(numnodes)) c0 = feature['geometry']['coordinates'][0] c1 = feature['geometry']['coordinates'][1] isinterior = feature['properties']['interior'] isroad = feature['properties']['road'] isbarrier = feature['properties']['barrier'] n0 = mg.MyNode(c0) n1 = mg.MyNode(c1) edge = mg.MyEdge((n0, n1)) edge.road = json.loads(isroad) edge.interior = json.loads(isinterior) edge.barrier = json.loads(isbarrier) edgelist.append(edge) # create a new graph from the edge list, and calculate # necessary graph properties from the road new = graphFromMyEdges(edgelist) new.road_edges = [e for e in new.myedges() if e.road] new.road_nodes = [n for n in new.G.nodes() if is_roadnode(n, new)] new.interior_nodes = [n for n in new.G.nodes() if is_interiornode(n, new)] new.barrier_nodes = [n for n in new.G.nodes() if is_barriernode(n, new)] # defines all the faces in the graph new.inner_facelist # defines all the faces with no road nodes in the graph as interior parcels new.define_interior_parcels() return new, edgelist
def shortest_path_setup(myA, p, roads_only=False): """ sets up graph to be ready to find the shortest path from a parcel to the road. if roads_only is True, only put fake edges for the interior parcel to nodes that are already connected to a road. """ fake_interior = p.centroid __add_fake_edges(myA, p) fake_road_origin = mg.MyNode((305620, 8022470)) for i in myA.road_nodes: if len(myA.G.neighbors(i)) > 2: _fake_edge(myA, fake_road_origin, i) return fake_interior, fake_road_origin
def testGraphEquality(): n = {} n[1] = mg.MyNode((0, 0)) n[2] = mg.MyNode((0, 1)) n[3] = mg.MyNode((1, 1)) n[4] = mg.MyNode((1, 0)) n[5] = mg.MyNode((0, 0)) # actually equal n[6] = mg.MyNode((0.0001, 0.0001)) # within rounding n[7] = mg.MyNode((0.1, 0.1)) # within threshold n[8] = mg.MyNode((0.3, 0.3)) # actually different G = mg.MyGraph(name="S0") G.add_edge(mg.MyEdge((n[1], n[2]))) G.add_edge(mg.MyEdge((n[2], n[3]))) G.add_edge(mg.MyEdge((n[3], n[4]))) G.add_edge(mg.MyEdge((n[4], n[5]))) G.add_edge(mg.MyEdge((n[5], n[6]))) G.add_edge(mg.MyEdge((n[6], n[7]))) G.add_edge(mg.MyEdge((n[7], n[8]))) return G, n
def graphFromShapes(shapes, name, rezero=np.array([0, 0])): nodedict = dict() plist = [] for s in shapes: nodes = [] for k in s.points: k = k - rezero myN = mg.MyNode(k) if myN not in nodedict: nodes.append(myN) nodedict[myN] = myN else: nodes.append(nodedict[myN]) edges = [(nodes[i], nodes[i+1]) for i in range(0, len(nodes)-1)] plist.append(mg.MyFace(edges)) myG = mg.MyGraph(name=name) for p in plist: for e in p.edges: myG.add_edge(mg.MyEdge(e.nodes)) return myG
def find_negative(d, b): """finds the vector -d when b is origen """ negx = -1*(d.x - b.x) + b.x negy = -1*(d.y - b.y) + b.y dneg = mg.MyNode((negx, negy)) return dneg
def __centroid_test(): n = {} n[1] = mg.MyNode((0, 0)) n[2] = mg.MyNode((0, 1)) n[3] = mg.MyNode((1, 1)) n[4] = mg.MyNode((1, 0)) n[5] = mg.MyNode((0.55, 0)) n[6] = mg.MyNode((0.5, 0.9)) n[7] = mg.MyNode((0.45, 0)) n[8] = mg.MyNode((0.4, 0)) n[9] = mg.MyNode((0.35, 0)) n[10] = mg.MyNode((0.3, 0)) n[11] = mg.MyNode((0.25, 0)) nodeorder = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 1] nodetups = [(n[nodeorder[i]], n[nodeorder[i+1]]) for i in range(0, len(nodeorder)-1)] edgelist = [mg.MyEdge(i) for i in nodetups] f1 = mg.MyFace(nodetups) S0 = graphFromMyFaces([f1]) S0.define_roads() S0.define_interior_parcels() S0.plot_roads(parcel_labels=True) return S0, f1, n, edgelist
def testGraph(): n = {} n[1] = mg.MyNode((0, 0)) n[2] = mg.MyNode((0, 1)) n[3] = mg.MyNode((0, 2)) n[4] = mg.MyNode((0, 3)) n[5] = mg.MyNode((1, 2)) n[6] = mg.MyNode((1, 3)) n[7] = mg.MyNode((0, 4)) n[8] = mg.MyNode((-1, 4)) n[9] = mg.MyNode((-1, 3)) n[10] = mg.MyNode((-1, 2)) n[11] = mg.MyNode((1, 4)) n[12] = mg.MyNode((-2, 3)) lat = mg.MyGraph(name="S0") lat.add_edge(mg.MyEdge((n[1], n[2]))) lat.add_edge(mg.MyEdge((n[2], n[3]))) lat.add_edge(mg.MyEdge((n[2], n[5]))) lat.add_edge(mg.MyEdge((n[3], n[4]))) lat.add_edge(mg.MyEdge((n[3], n[5]))) lat.add_edge(mg.MyEdge((n[3], n[9]))) lat.add_edge(mg.MyEdge((n[4], n[5]))) lat.add_edge(mg.MyEdge((n[4], n[6]))) lat.add_edge(mg.MyEdge((n[4], n[7]))) lat.add_edge(mg.MyEdge((n[4], n[8]))) lat.add_edge(mg.MyEdge((n[4], n[9]))) lat.add_edge(mg.MyEdge((n[5], n[6]))) lat.add_edge(mg.MyEdge((n[6], n[7]))) lat.add_edge(mg.MyEdge((n[7], n[8]))) lat.add_edge(mg.MyEdge((n[8], n[9]))) lat.add_edge(mg.MyEdge((n[9], n[10]))) lat.add_edge(mg.MyEdge((n[3], n[10]))) lat.add_edge(mg.MyEdge((n[2], n[10]))) lat.add_edge(mg.MyEdge((n[7], n[11]))) lat.add_edge(mg.MyEdge((n[6], n[11]))) lat.add_edge(mg.MyEdge((n[10], n[12]))) lat.add_edge(mg.MyEdge((n[8], n[12]))) return lat