def getAngle(r1, r2): """ returns the smallest positive radian angle between two rays [p11,p12], [p21,p22] not fully tested """ ray1=np.array(r1) ray2=np.array(r2) inters,p=col.linesIntersect(ray1,ray2, getPoint=True) if inters: pts=[r1[0],r1[1], r2[0], r2[1]] if not tuple(p) in pts: raise Exception('lines are intersecting and not incident, angle not defined') p=np.array(p) points=[] for ray in ray1,ray2: furthestDist=-1 for point in ray: dist=getDistance(p,point) if dist>furthestDist: furthest=point furthestDist=dist points.append(point) p1=np.array(points[0])-p p2=np.array(points[1])-p th=acos(np.dot(p1,p2)/(getDistance(p,p1)*getDistance(p,p2))) if th>pi: if th>2*pi: raise Exception('something is wrong with getAngle') th=pi-th return th
def getPos(self): #returns middle of road if not self.endPoints: #find intersection of nodes.. r1=np.array([self.nodes[0], self.nodes[2]]) r2=np.array([self.nodes[1], self.nodes[3]]) tmp, pos=col.linesIntersect(r1,r2, getPoint=True) pos=list(pos) else: p2=np.array(self.endPoints[1]) d=np.array(self.endPoints[0])-p2 pos=list(p2+0.5*d) return pos
def getAngle(r1, r2): """ returns the smallest positive radian angle between two rays [p11,p12], [p21,p22] not fully tested """ ray1=np.array(r1) ray2=np.array(r2) inters,p=col.linesIntersect(ray1,ray2, getPoint=True) if np.isnan(p[0]): return pi #parallel rays. Angle defined as pi, not 0 if inters: pts=[r1[0],r1[1], r2[0], r2[1]] found=False for ptmp in pts: if getDistance(p, ptmp)<0.001: found=True break if not found: raise Exception('lines are intersecting and not incident, angle not defined') p=np.array(p) points=[] for ray in ray1,ray2: furthestDist=-1 for point in ray: dist=getDistance(p,point) if dist>furthestDist: furthest=point furthestDist=dist points.append(point) p1=np.array(points[0])-p p2=np.array(points[1])-p #due to round-off errors, we get a domain error if e.g. arg=-1.000000000001. thus round arg=np.dot(p1,p2)/(np.linalg.norm(p1)*np.linalg.norm(p2)) th=acos(round(arg,7)) if th>pi: if th>2*pi: raise Exception('something is wrong with getAngle') th=2*pi-th assert th>=0 return th
def findIntersection(origin, th, areaPoly): """ returns the intersection between the ray from origin with angle th and areaPoly. Assumes convex polygon. """ inf=1e4 #find intersection with areaPoly p1=getCartesian([0, inf], origin=origin, direction=th, fromLocalCart=True) p2=list(origin)#getCartesian([0, 0.1], origin=origin, direction=th, fromLocalCart=True) #should be inside polygon ray=np.array([p1,p2]) last=areaPoly[-1] point=None for p in areaPoly: borderRay=np.array([last,p]) int, pInt=col.linesIntersect(borderRay, ray, getPoint=True) if int: point=pInt break #we have found intersection point last=p if point==None: print "areaPoly:", areaPoly raise Exception('line has no intersection with polygon area') return tuple(point)
def __init__(self,L=24, diagonals=False, angle=None, areaPoly=None, origin=None, globalOrigin=None, thMin=pi/7.): C=L/2. ExtendedGraph.__init__(self, origin=origin, globalOrigin=globalOrigin,areaPoly=areaPoly, L=L, C=C,gridtype='spiderGridGraph') G=self #remove later and change to self below. longest=L*1.4 #longest allowed distance between two nodes on a line. eqL=L/6. #length where two points should be merged to one,m which is done in some cases if not areaPoly: #use default areaPoly=[(0,0), (300,0), (200,300), (-100, 200)] if origin: raise Exception('if origin is given, so must areaPoly be...') origin=(0,0) if not origin in areaPoly: raise Exception('only origin at borderpoints supported right now ') else: if not origin: origin=(0,0) if not col.pointInPolygon(origin,areaPoly): raise Exception('so far, SpiderGrid only supports origins on one of the border points') #so, look if origin is on the lines... if it is, swift it just a bit. if pointOnPolygonBorder(origin, areaPoly): while True: #we should never be stuck in this loop. xnew=round(random.uniform(-0.1,0.1),2) ynew=round(random.uniform(-0.1, 0.1),2) pnew=(origin[0]+xnew, origin[1]+ynew) if col.pointInPolygon(pnew, areaPoly): if not pointOnPolygonBorder(pnew, areaPoly): origin=pnew #we found our new one. self.origin=origin break lines=[] thMin*=2 #will be divided below while len(lines)<2: thMin*=0.5 lines, baseL, baseR, orderMax=makeLines(areaPoly, origin, L, C, thMin) #make grid of lines. print "lines done, now make grid" el=0 #will later be filled. G.L=L G.overlap={} #will later be filled. #make a road segments to the ones "to the left". If road that ist drawn to is of higher order, that is the last one from this line. for index, line in enumerate(lines): #make line to the ones on the "left" if line==baseL: break occured=[] #a list of different orders that have occured.. pretty complex. #an order 1 line should not e.g. have lines to all order 4 lines to the left, only one. for left in lines[index+1:]: # the one to the left of "line" if line.order==1 and left.order==1: break #identify the point, p2. line between should be orthogonal to "line" or "left", depending on order. cont=False #continue... for o in occured: if o<=left.order: cont=True #strange procedure, but can't use "continue" here due to above for. if cont: continue #we jump over some lines..think about it and you'll udnerstand occured.append(left.order) if left.order>line.order: #make ray orthogonal to line p1=left.p1 th2=line.angle-pi/2. pTmp=tuple(getCartesian([0, 10000], origin=p1, direction=th2, fromLocalCart=True)) a, p2=col.linesIntersect(np.array([p1,pTmp]), np.array(line.ray), getPoint=True) if not a: p2=line.p2 p2=tuple(p2) if not p2 in line.gridPoints: line.gridPoints.append(p2) else: #make it orthogonal to left p1=line.p1 th2=left.angle+pi/2. pTmp=tuple(getCartesian([0, 10000], origin=p1, direction=th2, fromLocalCart=True)) a, p2=col.linesIntersect(np.array([p1,pTmp]), np.array(left.ray), getPoint=True) if not a: p2=left.p2 p2=tuple(p2) if not p2 in left.gridPoints: left.gridPoints.append(p2) if not a: pass #raise Exception('something wrong, did not find neighbor point') if G.has_node(p1): G.add_node(p1) el+=1 if not p2 in G.nodes(): G.add_node(p2) el+=1 G.add_edge(p1,p2, weight=self.edgeWeightCalc(p1,p2), visits=0, visited_from_node=[], c=0) if left.order <= line.order: break print "add neighbors" #we have the pattern. Add edges to neighbors in not that dens regions for index,line in enumerate(lines): #end points. Usually between two endpoints but not always. if line.no==baseL.no: break #this is the end leftBuddy=lines[index+1] if leftBuddy.angle<line.angle: raise Exception('ordering wrong..') closest=leftBuddy.gridPoints[0] closDist=getDistance(closest, line.p2) for pTmp in leftBuddy.gridPoints[1:]: d=getDistance(pTmp, line.p2) if d<closDist: closDist=d closest=pTmp G.add_edge(line.p2, closest, weight=self.edgeWeightCalc(line.p2, closest), visits=0, visited_from_node=[], c=0) lOrdered=copy.copy(lines) #not deepcopy, line instances are the same lOrdered=sorted(lOrdered, key=lambda line: line.order) for line in lOrdered: #if line.no==baseL.no: continue #now, identify the potential neighbors first. candidatesL=[] candidatesR=[] for cand, left in [(candidatesL, True), (candidatesR, False)]: #left=True if left.. faster for o in range(orderMax+1): if o==0: continue lst=[] if left: lst=[l for l in lines if l.order==o and l.angle>line.angle] nearest=None minAng=1e10 for l in lst: if l.angle<minAng: nearest=l minAng=nearest.angle if nearest: cand.append(nearest) #we have our candidate of this order. else: lst=[l for l in lines if l.order==o and l.angle<line.angle] nearest=None maxAng=-1e10 for l in lst: if l.angle>maxAng: nearest=l maxAng=nearest.angle if nearest: cand.append(nearest) #we have our candidate of this order. line.gridPoints=sorted(line.gridPoints, key=lambda point: -getDistance(point, origin)) #closest first last=line.gridPoints[0] for pTmp in copy.copy(line.gridPoints[1:]): d=getDistance(last,pTmp) if d>longest: nPoints=int(ceil(d/longest))-1 last=pTmp l=d/(nPoints+1) #distance between points for i in range(nPoints): p=tuple(getCartesian([0, (i+1)*l], origin=pTmp, direction=line.angle, fromLocalCart=True)) candidatesL=sorted(candidatesL, key=lambda l: abs(l.angle-line.angle)) candidatesR=sorted(candidatesR, key=lambda l: abs(l.angle-line.angle)) leftRay=np.array([p, getCartesian([0,100], origin=p, direction=line.angle+pi/2., fromLocalCart=True)]) rightRay=np.array([p, getCartesian([0,100], origin=p, direction=line.angle-pi/2., fromLocalCart=True)]) pL=None pR=None for cand in candidatesL: a,p2=col.linesIntersect(np.array(cand.ray), leftRay, getPoint=True) if a: #cand:s are ordered so that this is "the one" for pT in cand.gridPoints: if getDistance(list(pT), p2)<eqL: #2 meters.. same p2=pT break pL=tuple(p2) if not pL in cand.gridPoints: cand.gridPoints.append(pL) break for cand in candidatesR: a,p2=col.linesIntersect(np.array(cand.ray), rightRay, getPoint=True) if a: #cand:s are ordered so that this is "the one" for pT in cand.gridPoints: if getDistance(list(pT), p2)<eqL: #2 meters.. same p2=pT break pR=tuple(p2) if not pR in cand.gridPoints: cand.gridPoints.append(pR) break #now, if both pL and pR, create a straight line. if pL and pR: #new p! a,p=col.linesIntersect(np.array(line.ray), np.array([pL,pR]), getPoint=True) if not a: raise Exception('expected to find p here..') p=tuple(p) if pL: G.add_edge(pL,p,weight=self.edgeWeightCalc(pL,p), visits=0, visited_from_node=[], c=0) if pR: G.add_edge(pR,p, weight=self.edgeWeightCalc(pR,p), visits=0, visited_from_node=[], c=0) if not pL and not pR: G.add_node(p) line.gridPoints.append(tuple(p)) last=pTmp for line in lines: #add edges on the line if len(line.gridPoints)<=1: continue line.gridPoints=sorted(line.gridPoints, key=lambda point: -getDistance(point, origin)) last=line.gridPoints[0] for node in line.gridPoints[1:]: G.add_edge(last, node,weight=self.edgeWeightCalc(last, node), visits=0, visited_from_node=[], c=0) last=node rem=True for n in self.nodes(): if not self.inside(n): self.remove_node(n) while rem: rem=False for n in self.nodes(): #pretty ugly, but a must.. if self.degree(n)<=1: rem=True self.remove_node(n) break self.overlap={} #will later be filled. self.roadWidth=4 self.L=L if not self.origin in self.nodes(): shortest=None short_dist=1e10 for n in self.nodes(): d=fun.getDistance(n, self.origin) if d<short_dist: short_dist=d shortest=n self.origin=shortest elements=len(self.nodes()) self.elements=elements self.density=elements/self.A self.density=elements/self.A