def inside(self,pos): """ are we inside the polygon? We don't use colission detection directly since we can do some time saving tests """ if self.aPInnerCircleM==None: #created yet? self.aPInnerCircleM, self.aPInnerCircleRadius=fun.getPolygonInnerCircle(self.areaPoly) if fun.insideCircle(pos, self.aPInnerCircleM, self.aPInnerCircleRadius): return True #much faster than below return col.pointInPolygon(pos,self.areaPoly)
def __init__(self, pos, nodes, G,direction=None, machine=None, main=False, radius=None): Road.__init__(self, pos, nodes, G, direction,radius=radius) self.m=machine self.trees=[] self.harvestTrees=0 #used to take care of the overlapping problem.. tL=G.terrain.GetTrees(self.pos, self.radius+1) #+1 to be sure... for tree in tL: if col.pointInPolygon(tree.pos, self.getNodes()): #tree inside road, #check if tree already belongs to a road: if not self._checkIfTaken(tree): self.harvestTrees+=1 self.trees.append(tree) self.startPoint=None #the startpoint of a corridor is where it intersects the mainRoad.This is where the crane is supposed to begin. self.main=main
def generateTrees(self,dens, dbh_mean, dbh_std): """ Generates trees. Can only handle square areas right now. This is only done once, so code is not optimized. """ self.dbh_mean=dbh_mean self.dens=dens self.dbh_std=dbh_std trees=dens*self.area idealCell=[5.0,5.0] W=self.xlim[1]-self.xlim[0] L=self.ylim[1]-self.ylim[0] if self.G: self.G.xlim=self.xlim #override. The polynomial for A given to terrain is master self.G.ylim=self.ylim cellW=W/float(ceil(W/idealCell[0])) #ideal 5*5m, but adapt to the polygon cellL=L/float(ceil(L/idealCell[1])) cellA=cellW*cellL treesPerCell=int(floor(trees*cellA/self.area)) #if the whole cell is in areaPoly xAr=np.arange(self.xlim[0], stop=self.xlim[1], step=cellW) #will omitt last row in x and y, correct yAr=np.arange(self.ylim[0], stop=self.ylim[1], step=cellW) n=0 for x in xAr: for y in yAr: if not col.pointInPolygon((x,y), self.areaPoly): continue tint=[] neighGrids=self.getNeighborObst([x,y]) for i in range(treesPerCell): r=-1 while r<0: r=random.normalvariate(dbh_mean, dbh_std)*0.5 placed=False while not placed: pos=[x+random.uniform(0,cellW), y+random.uniform(0,cellL)] placed=True for neigh in tint: if getDistance(pos, neigh.pos) < r+neigh.radius: placed=False break #just for negih, while is still on if pos[0]-x<r or pos[0]-x>cellW-r or pos[1]-y<r or pos[1]-y>cellL-r: #iterate through neighboring trees. for neigh in neighGrids: if getDistance(neigh.pos, pos)<r+neigh.radius: #collide placed=False break t=Tree(pos, r, terrain=self) if random.uniform(0,1)<0.4: t.marked=True tint.append(t) n=n+1 print "trees left over during generation: ",trees-n, "this is a problem, solve it..." """thoughts around this problem. These trees needs to be distributed inside the cells,
def makeLines(areaPoly, origin, L, C, thMin): """ given an origin and an areaPolygon, this function creates lines from a specific spidernet pattern. """ #first, determine if origin is on border lines. if pointOnPolygonBorder(origin,areaPoly) or not col.pointInPolygon(origin, areaPoly): raise Exception('origin has to be inside polygon') xnorm=[origin, (origin[0]+1, origin[1])] #xaxis, used for angle calc. baseL=None #standard value until determined baseR=None if origin in areaPoly: #origin is on intersection for i in range(len(areaPoly)): #find origin if areaPoly[i]==origin: origInd=i ray1=[areaPoly[origInd], areaPoly[origInd-1]] ray2=[areaPoly[origInd], areaPoly[origInd+1]] baseL=Line(ray1[0], ray1[1], getAngle(ray1, xnorm), order=1) baseR=Line(ray2[0], ray2[1], getAngle(ray2, xnorm), order=1) else: #see if it is on border lines last=areaPoly[-1] for node in areaPoly: ray=[last, node] if col.pointOnLine(ray, origin): """ something is wrong with the angles below. Change to vectors so we get different angles. """ ray1=[origin, ray[0]] ray2=[origin, ray[1]] baseL=Line(ray1[0], ray1[1], angleToXAxis(ray1), order=1) baseR=Line(ray2[0], ray2[1], angleToXAxis(ray2), order=1) break last=node if baseL==None: #origin is inside areaPoly. Make x-axis baseL and baseR p2=findIntersection(list(origin), th=0, areaPoly=areaPoly) baseL=Line(origin, p2, angle=2*pi, order=1) baseR=Line(origin, p2, angle=0, order=1) #smart, huh? :) else: #so, we have the bases.. check if left and right is correct if baseL.angle<baseR.angle: tmp=baseL baseL=baseR baseR=tmp angle=baseL.angle-asin(L*0.5/getDistance(baseL.ray[0], baseL.ray[1])) p2=findIntersection(list(baseL.p1), angle, areaPoly) cyl=getCylindrical(p2, origin=origin) #take it further away from the border p2=getCartesian([cyl[0]-C, cyl[1]], origin=origin) baseL=Line(p1=baseL.p1, p2=p2, angle=angle, order=baseL.order) angle=baseR.angle+asin(L*0.5/getDistance(baseR.ray[0], baseR.ray[1])) p2=findIntersection(list(baseR.p1), angle, areaPoly) cyl=getCylindrical(p2, origin=origin) #take it further away from the border p2=getCartesian([cyl[0]-C, cyl[1]], origin=origin) baseR=Line(p1=baseR.p1, p2=p2, angle=angle, order=baseL.order) print "base lines are done..." lines=[baseR, baseL] th=baseL.angle-baseR.angle dth=th order=1 while True: #create lines, base roads dth=dth/2. if dth<thMin: break #order+=1 newList=copy.deepcopy(lines) for i in range(len(lines)): #iterate through, from right to left line=lines[i] if line.no != baseL.no: th=line.angle+dth point=findIntersection(origin, th, areaPoly) cyl=getCylindrical(point, origin=origin) #take it further away from the border if cyl[0]<=C: continue #line is very short, not worth it. point=getCartesian([cyl[0]-C, cyl[1]], origin=origin) lnew=Line(origin, point, th, order=order) for ind,ltmp in enumerate(newList): if ltmp.no==line.no: newList.insert(ind+1, lnew) break lines=newList #the base roads are done.. now let's find the smaller lines. lines.remove(lines[-1]) #this is baseL..same as baseR, remember? baseL=lines[-1] #the one most to the left #strategy: insert a line between two lines as long as asin(0.5L/length(line))>L while True: added=False newList=copy.deepcopy(lines) order+=1 for i in range(len(lines)): #iterate through, from right to left line=lines[i] if line.no != baseL.no: leftBuddy=lines[i+1] #the one "to the left" rightBuddy=line #in the future, taking terrain into consideration, the angles to left and right buddy wont be the same. But now they are. dth=(leftBuddy.angle-rightBuddy.angle)/2. #the angle between.. th=rightBuddy.angle+dth #angle in rel. to xaxis point=findIntersection(origin, th, areaPoly) #point at other side of areaPoly #now, make it C distance away from border. cyl=getCylindrical(point, origin=origin) point=getCartesian([cyl[0]-C, cyl[1]], origin=origin) d=getDistance(origin, point) if d/tan(dth)>L: #this means that it will be reasonable to place a grid point on line. Create line! y=0.5*L*(1+1/sin(dth))#/(sin(dth)**2) p1=getCartesian([0, y], fromLocalCart=True, origin=origin, direction=th) #where it all starts.. if getDistance(p1, origin)>=d or getDistance(p1,point)<C: continue #don't make line, it has a "negative length" or is too short.. if col.pointInPolygon(p1, areaPoly): lnew=Line(p1, point, th, order=order) for ind,ltmp in enumerate(newList): if ltmp.no==line.no: added=True newList.insert(ind+1, lnew) if not added: break #no more lines to add. lines=newList return lines, baseL, baseR, order
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
def inside(pos,areaPoly): """ max is a list with two elements. max[0]==xmax, max[1]==ymax. """ return col.pointInPolygon(pos,areaPoly)
def readTerrain(globalOrigin=None, areaPoly=None): """ reads in data and returns local grid x,y,z coordinates. Notes: -sweref coordinates are basically in [m], useful. We just need to normalize them to our new origin. -Problem with intersections between the files... how to handle? """ if not globalOrigin: globalOrigin=(596120, 6727530) #located on map.. nice position.. if not areaPoly: areaPoly=[(0,0), (200,0), (200,200), (0,200)] #default.. globalPoly=getGlobalCoordinate(globalOrigin, areaPoly=areaPoly) corn=(595000, 6725000) bordersPoly=[corn, (corn[0]+5000, corn[1]), (corn[0]+5000, corn[1]+5000), (corn[0], corn[1]+5000)] #check if polygon is inside polygon for node in globalPoly: if not col.pointInPolygon(node, globalPoly): raise Exception('areaPolygon is outside of the area that we have maps for.') #so, read in the data for our areaPolygon, or rather square containing it, and #normalize the cooordinates with respect to our origin. range=fun.polygonLim(globalPoly) xrange=range[0:2] yrange=range[2:4] xrange=[xrange[0]-2, xrange[1]+2] yrange=[yrange[0]-2, yrange[1]+2] #now, we should find out which files we need... fileList=getFileList(globalPoly) x, y, z=None, None, None #will later be created xlist, ylist, zlist=[], [], [] m=1 #modulu, to reduce the grid resolution.. should be set from area of polygon.. yold=None if len(fileList)>1: raise Exception('we do not support file overlaps right now..') folder=os.path.join(os.path.dirname(os.path.abspath(__file__)), 'tab') for fname in fileList: f=open(os.path.join(folder, fname+'.asc')) for index, line in enumerate(f): l=line.split() xtmp=int(l[0]) ytmp=int(l[1]) if ytmp>yrange[1]: break #because of how file is organized, we can do this. if xtmp<=xrange[1] and xtmp>=xrange[0] and ytmp>=yrange[0] and xtmp%m==0 and ytmp%m==0: if yold==None: yold=ytmp ztmp=float(l[2]) if ytmp != yold: #new row.. #identify if we're gonna need the next file in line.. if x==None: x=np.array(xlist) y=np.array(ylist) z=np.array(zlist) else: x=np.vstack((x, xlist)) y=np.vstack((y, ylist)) z=np.vstack((z, zlist)) xlist, ylist, zlist = [], [], [] xlist.append(xtmp) ylist.append(ytmp) zlist.append(ztmp) yold=ytmp f.close() x-=globalOrigin[0] y-=globalOrigin[1] x=np.transpose(x) #we want it in the standard form that scipy understands. y=np.transpose(y) #this form corresponds to numpy.mgrid standard, but not numpy.meshgrid z=np.transpose(z) return x,y,z