def pointOnPolygonBorder(point, poly): """ determines if point is on border of polygon """ last=poly[-1] for node in poly: ray=[last, node] if col.pointOnLine(ray, point): return True last=node return False
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