def plotBackground(areaPoly=None, ax=None, globalOrigin=None): """ plots the background from the tiff-file given. In the future, maybe data is taken from google maps or something similar? #local coordinates in areaPoly, with origin in origin origin is given in sweref99 coordinates, not local. """ if not areaPoly: raise Exception('need area polygon in order to plot background') if not ax: fig=plt.figure() ax=fig.add_subplot(111, aspect='equal') figCorner=(595000, 6725000) #for this specific area, not general if not globalOrigin: globalOrigin=figCorner #now, let our global origin be in the origin.. w=5000 #for this specific image.. h=5000 figorigin=np.array(figCorner)-np.array(globalOrigin) limits=[figorigin[0], figorigin[0]+w, figorigin[1], figorigin[1]+h] folder=os.path.dirname(os.path.abspath(__file__)) folder=os.path.join(folder, 'GIS') map=LinearSegmentedColormap.from_list('lightgray', ['#666666', '#C5C5C5']) #our own cmap bg=mpimg.imread(os.path.join(folder,'672_59_11.tif')) im = plt.imshow(bg, cmap=map,origin='lower', extent=limits) #now, adjust to our polygon.. limits=list(fun.polygonLim(areaPoly)) w=max(10, max(limits)/10.) limits[0]-=w #to get some space to polygon limits[1]+=w limits[2]-=w limits[3]+=w ax.axis(limits) return ax
def __init__(self, origin=None, globalOrigin=None,areaPoly=None, gridtype=None): if not areaPoly: raise Exception('areaPoly must be given.') if not origin: origin=(0,0) if not globalOrigin: globalOrigin=(596120, 6727530) #sweref99..located on map.. nice position.. use as default. self.areaPoly=areaPoly xmin,xmax,ymin,ymax=fun.polygonLim(areaPoly) side=10 self.lim=np.array([xmin-0.5*side,xmax+0.5*side, ymin-0.5*side, ymax+0.5*side]) self.A=fun.polygon_area(areaPoly) self.Ainv=1./self.A #used a lot.. faster to just compute this once. self.origin=origin self.globalOrigin=globalOrigin self.type=gridtype x,y,z=GIS.readTerrain(globalOrigin=globalOrigin , areaPoly=areaPoly) #get a list of how x and y varies.. strictly ascending xlist=x[:,0] #just the variations, not the 2D-matrix ylist=y[0,:] self.interpol=RectBivariateSpline(xlist, ylist, z) #used pretty much everytime we need the height of a specific point. Implemented in fortran and very fast nx.Graph.__init__(self) self.t_x=x self.t_y=y self.t_z=z self.roadWidth=4 #width of road self.overlap={} #will later be filled. A speedup thing self.weightFunction=normalizedPitchDist #reference to exter self.areaCover=go.roadAreaCoverage(self) self.moviefig=None #may be used for movies later self.cmdfolder=os.path.split(os.path.dirname(os.path.abspath(__file__)))[0]
def __init__(self,G=None, generate=False, dens=1, dbh_mean=0.5, dbh_std=0.1): if not G: raise Exception('by design, you need G for terrain to work. (globalVar(), see sim.tools.py)') self.G=G self.trees=[] self.stumps=[] self.roots=[] self.holes=[] self.piles=[] self.obstacles=[] #should hold all the above, except boulders. self.stumpFile='undefined' self.treeFile='undefined' self.stumpsPerH=0 self.boulderFreq=0 self.meanBoulderV=0 #the following stuff are only used when the stand files are used. should maybe be separated. if not G.areaPoly: #create from A, square raise Exception('got too little information about the area, need areaPoly polygon. ') self.areaPoly=G.areaPoly self.area=polygon_area(G.areaPoly) lim=fun.polygonLim(self.areaPoly) self.xlim=list(lim[0:2]) self.ylim=list(lim[2:4]) if self.G and self.G.gridL: self._fixGrid(L=self.G.gridL) else: self._fixGrid() if not generate: self._fileini() else: self.generateTrees(dens, dbh_mean, dbh_std)
def __init__(self,L=24, xyRatio=1, origin=None, globalOrigin=None,angle=None, areaPoly=None): ExtendedGraph.__init__(self, origin=origin, globalOrigin=globalOrigin,areaPoly=areaPoly, gridtype='triGridGraph') digits=3 #used later.. C=L/2. #preference questions, this does not span entirely all of space but is a good compromise self.L=L self.C=C dx=L dy=L*round(sqrt(3)/2., digits) cart=fun.getCartesian #xl=np.arange(0,Nx*dx, dx, dtype """The strategy is to first cover an extra large area, and then take away the nodes that are outside. for a square area, the maximum "x-distance" is sqrt(2) times the side. This corresponds to angle pi/4 or 5pi/4. The strategy is to always use this maximum length and then take away the ones outisde the area. This is an easy but inefficient algorithm, there is certainly room for speed up if required. But when coding this, most of the time is spent somewhere else so it doesn't matter really to optimize this part. """ xmin,xmax,ymin,ymax=fun.polygonLim(areaPoly) x1=np.arange(xmin,ceil(sqrt(xmax**2+ymax**2)), dx, dtype=np.float) x2=np.arange(xmin-dx/2., ceil(sqrt(xmax**2+ymax**2)), dx, dtype=np.float) yl=np.arange(ymin,ceil(sqrt(xmax**2+ymax**2)), dy, dtype=np.float) #hypothenuse in another way if not angle: angle=0 #G=nx.Graph( L=L, type='sqGridGraph', C=C) self.lim=np.array([xmin-0.5*L,xmax+0.5*L, ymin-0.5*L, ymax+0.5*L]) el=0 direction=angle+pi/2. for yloc in yl: if (round(yloc/dy))%2==0: xl=x1 xtype='x1' else: xl=x2 xtype='x2' for index,xloc in enumerate(xl): if yloc==0 or angle==0: sl=[1] else: sl=[1,-1] for sign in sl: x,y=tuple(cart((xloc,sign*yloc), origin=(0,0), direction=direction, fromLocalCart=True)) x,y=round(x,digits), round(y,digits) #x,y is now real coordinates, transformed through angle. if not inside((x,y),areaPoly): continue self.add_node((x, y)) el+=1 if y != 0: if index != 0: neig=tuple(cart([xloc-dx/2., round(yloc-dy,digits)], origin=(0,0), direction=direction, fromLocalCart=True)) neig=round(neig[0],digits), round(neig[1],digits) if inside(neig, areaPoly): self.add_edge((x,y), neig, weight=L, visits=0, visited_from_node=[],c=0) neig=tuple(cart([xloc+dx/2., yloc-dy,digits], origin=(0,0), direction=direction, fromLocalCart=True)) neig=round(neig[0],digits), round(neig[1],digits) if inside(neig, areaPoly): self.add_edge((x,y), neig, weight=L, visits=0, visited_from_node=[],c=0) if index != 0: self.add_edge(tuple([x,round(y,digits)]),tuple([x-dx, round(y,digits)]), weight=L, visits=0, visited_from_node=[],c=0) rem=True 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 elements=el self.elements=el self.L=L self.density=elements/self.A
def __init__(self,L=24, xyRatio=1,origin=None, globalOrigin=None,areaPoly=None, diagonals=False, angle=None): ExtendedGraph.__init__(self, origin=origin, globalOrigin=globalOrigin,areaPoly=areaPoly, gridtype='sqGridGraph') C=L/2. self.C=C self.L=L if angle ==None: #find the longest edge, and use its angle print "get the angle" angle=getAngleFromLongestEdge(areaPoly, origin) print "got the angle.", angle while angle>pi/2. or angle<0: #if it is.. most often does not enter loop if angle<0: angle+=pi/2. else: angle-=pi/2. dx=L dy=L cart=fun.getCartesian digits=3 #we round of to this in order to avoid numerical errors. 1mm is enough :) """The strategy is to first cover an extra large area, and then take away the nodes that are outside. for a square area, the maximum "x-distance" is sqrt(2) times the side. This corresponds to angle pi/4 or 5pi/4. The strategy is to always use this maximum length and then take away the ones outisde the area.""" d=1/sqrt(2)+0.001 direction=angle+pi/2. xmin,xmax,ymin,ymax=fun.polygonLim(areaPoly) xl=np.arange(xmin+C,ceil(sqrt(xmax**2+ymax**2)), dx, dtype=np.float) #hypothenuse yl=np.arange(ymin+C,ceil(sqrt(xmax**2+ymax**2)), dy, dtype=np.float) el=0 for xloc in xl: for yloc in yl: if yloc==0 or angle==0: sl=[1] else: sl=[1,-1] for sign in sl: x, y=tuple(cart((xloc,sign*yloc), origin=(0,0), direction=direction, fromLocalCart=True)) x,y=round(x,digits), round(y,digits) if not inside((x,y),areaPoly): continue self.add_node((x, y)) el+=1 #neigbor 'backwards' in y-dir neig=tuple(cart((xloc,sign*(yloc)-dy), origin=(0,0), direction=direction, fromLocalCart=True)) neig=round(neig[0],digits), round(neig[1],digits) if inside(neig, areaPoly): self.add_edge((x,y), neig, weight=self.edgeWeightCalc((x,y), neig), visits=0, visited_from_node=[], c=0) if diagonals and xloc != 0: neig=tuple(cart((xloc-dx,sign*(yloc-dy)), origin=(0,0), direction=direction, fromLocalCart=True)) neig=round(neig[0],digits), round(neig[1],digits) if inside(neig, areaPoly): self.add_edge((x,y), neig, weight=self.edgeWeightCalc((x,y), neig), visits=0, visited_from_node=[],c=0) neig=tuple(cart((xloc+dx,sign*(yloc-dy)), origin=(0,0), direction=direction, fromLocalCart=True)) neig=round(neig[0],digits), round(neig[1],digits) if inside(neig, areaPoly): self.add_edge((x,y), neig, weight=self.edgeWeightCalc((x,y), neig),visits=0, visited_from_node=[],c=0) if True or xloc != 0: neig=tuple(cart((xloc-dx,sign*yloc), origin=(0,0), direction=direction, fromLocalCart=True)) neig=round(neig[0],digits), round(neig[1],digits) if inside(neig, areaPoly): self.add_edge((x,y),neig, weight=self.edgeWeightCalc((x,y), neig), visits=0, visited_from_node=[],c=0) rem=True 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 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=el self.elements=el self.density=elements/self.A
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
def __init__(self,L=None, xyRatio=1, origin=None, globalOrigin=None,angle=None, areaPoly=None, weightFunction=weightFromLength): """The strategy is to first cover an extra large area, and then take away the nodes that are outside. for a square area, the maximum "x-distance" is sqrt(2) times the side. This corresponds to angle pi/4 or 5pi/4. The strategy is to always use this maximum length and then take away the ones outisde the area. This is an easy but inefficient algorithm, there is certainly room for speed up if required. But when coding this, most of the time is spent somewhere else so it doesn't matter really to optimize this part. The square grid has been updated with a better algorithm for this. It might be a good idea to copy this algorithm to this part, but it is not done now. Another improvement could be to optimize the inside() function. It currently does unnecessary many point in polygon tests, which is time consuming for polygons with many nodes. """ C=12 digits=3 #used later.. if L==None: L=C/(sin(1/3.0*pi)*0.5) ExtendedGraph.__init__(self, origin=origin, globalOrigin=globalOrigin,areaPoly=areaPoly, L=L, C=C,gridtype='triGridGraph', weightFunction=weightFunction) #C=L/2. #preference questions, this does not span entirely all of space but is a good compromise self.L=L self.C=C dx=L dy=L*round(sqrt(3)/2., digits) cart=fun.getCartesian xmin,xmax,ymin,ymax=fun.polygonLim(areaPoly) x1=np.arange(xmin,ceil(sqrt(xmax**2+ymax**2)), dx, dtype=np.float) x2=np.arange(xmin-dx/2., ceil(sqrt(xmax**2+ymax**2)), dx, dtype=np.float) yl=np.arange(ymin,ceil(sqrt(xmax**2+ymax**2)), dy, dtype=np.float) #hypothenuse in another way if not angle: angle=0 self.lim=np.array([xmin-0.5*L,xmax+0.5*L, ymin-0.5*L, ymax+0.5*L]) direction=angle+pi/2. for yloc in yl: if (round(yloc/dy))%2==0: xl=x1 else: xl=x2 for index,xloc in enumerate(xl): x,y=tuple(cart((xloc,yloc), origin=(0,0), direction=direction, fromLocalCart=True)) x,y=round(x,digits), round(y,digits) self.add_node((x, y)) if y != 0: neig=tuple(cart([xloc-dx/2., round(yloc-dy,digits)], origin=(0,0), direction=direction, fromLocalCart=True)) neig=round(neig[0],digits), round(neig[1],digits) self.add_edge((x,y), neig, weight=self.edgeWeightCalc((x,y),neig), visits=0, visited_from_node=[],c=0) neig=tuple(cart([xloc+dx/2., yloc-dy,digits], origin=(0,0), direction=direction, fromLocalCart=True)) neig=round(neig[0],digits), round(neig[1],digits) self.add_edge((x,y), neig, weight=self.edgeWeightCalc((x,y),neig), visits=0, visited_from_node=[],c=0) self.add_edge((x,y),tuple([round(x-dx,digits), round(y,digits)]), weight=self.edgeWeightCalc((x,y),tuple([round(x-dx,digits), round(y,digits)])), visits=0, visited_from_node=[],c=0) 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 __init__(self,L=24, xyRatio=1,origin=None, globalOrigin=None,areaPoly=None, diagonals=False, angle=None, shift=(0,0), weightFunction=weightFromLength): C=L/2.0 ExtendedGraph.__init__(self, origin=origin, globalOrigin=globalOrigin,areaPoly=areaPoly, L=L, C=C, gridtype='sqGridGraph', weightFunction=weightFunction) xmin,xmax,ymin,ymax=fun.polygonLim(areaPoly) origin=self.origin if angle ==None: #find the longest edge, and use its angle angle, shift=self.getAngleFromLongestEdge() print "got the angle.", angle*360/(2*3.14), shift while angle>pi/2. or angle<0: #if it is.. most often does not enter loop if angle<0: angle+=pi/2. else: angle-=pi/2. dx=L dy=L cart=fun.getCartesian digits=3 #we round of to this in order to avoid numerical errors. 1mm is enough :) """The strategy is to first cover an extra large area, and then take away the nodes that are outside. for a square area, the maximum "x-distance" is sqrt(2) times the side. This corresponds to angle pi/4 or 5pi/4. The strategy is to always use this maximum length and then take away the ones outisde the area.""" d=1/sqrt(2)+0.001 #direction is by definition not bigger that 90 degrees: ym=sqrt((xmax-xmin)**2+(ymax-ymin)**2) xlmin=-ceil(sin(pi/2.-angle)*(ymax-ymin)/L)*L xlmax=ceil(sin(angle)*(xmax-xmin)/L)*L xl=np.arange(shift[0]+xlmin,xlmax, dx, dtype=np.float) yl=np.arange(shift[1],ym, dy, dtype=np.float) for xloc in xl: for yloc in yl: if yloc==0 or angle==0: sl=[1] x, y=tuple(cart((xloc,yloc), origin=origin, direction=angle, fromLocalCart=True)) x,y=round(x,digits), round(y,digits) self.add_node((x, y)) #neigbor 'backwards' in y-dir neig=tuple(cart((xloc,(yloc)-dy), origin=origin, direction=angle, fromLocalCart=True)) neig=round(neig[0],digits), round(neig[1],digits) self.add_edge((x,y), neig, weight=self.edgeWeightCalc((x,y), neig), visits=0, visited_from_node=[], c=0) if diagonals and xloc != 0: neig=tuple(cart((xloc-dx,(yloc-dy)), origin=origin, direction=angle,fromLocalCart=True)) neig=round(neig[0],digits), round(neig[1],digits) self.add_edge((x,y), neig, weight=self.edgeWeightCalc((x,y), neig), visits=0, visited_from_node=[],c=0) neig=tuple(cart((xloc+dx,(yloc-dy)), origin=origin, direction=angle, fromLocalCart=True)) neig=round(neig[0],digits), round(neig[1],digits) self.add_edge((x,y), neig, weight=self.edgeWeightCalc((x,y), neig),visits=0, visited_from_node=[],c=0) neig=tuple(cart((xloc-dx,yloc), origin=origin, direction=angle, fromLocalCart=True)) neig=round(neig[0],digits), round(neig[1],digits) self.add_edge((x,y),neig, weight=self.edgeWeightCalc((x,y), neig), visits=0, visited_from_node=[],c=0) for node in self.nodes(): if not self.inside(node): self.remove_node(node) rem=True 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 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