def test_h3_set_to_multi_polygon_2k_ring(): h = '8930062838bffff' hexes = h3.k_ring(h, 2) # multi_polygon mp = h3.h3_set_to_multi_polygon(hexes) assert len(mp) == 1 # polygon count matches expected assert len(mp[0]) == 1 # loop count matches expected assert len(mp[0][0]) == 6 * (2 * 2 + 1) # coord count matches expected hexes2 = { '89300628393ffff', '89300628383ffff', '89300628397ffff', '89300628067ffff', '89300628387ffff', '893006283bbffff', '89300628313ffff', '893006283cfffff', '89300628303ffff', '89300628317ffff', '8930062839bffff', h, '8930062806fffff', '8930062838fffff', '893006283d3ffff', '893006283c3ffff', '8930062831bffff', '893006283d7ffff', '893006283c7ffff' } mp2 = h3.h3_set_to_multi_polygon(hexes2) assert len(mp2) == 1 # polygon count matches expected assert len(mp2[0]) == 1 # loop count matches expected assert len(mp2[0][0]) == 6 * (2 * 2 + 1) # coord count matches expected hexes3 = list(h3.k_ring(h, 6)) hexes3.sort() mp3 = h3.h3_set_to_multi_polygon(hexes3) assert len(mp3[0]) == 1 # loop count matches expected
def test_h3_set_to_multi_polygon_contiguous(): # the second hexagon shares v0 and v1 with the first hexes = ['89283082837ffff', '89283082833ffff'] # multi_polygon mp = h3.h3_set_to_multi_polygon(hexes) vertices0 = h3.h3_to_geo_boundary(hexes[0]) vertices1 = h3.h3_to_geo_boundary(hexes[1]) # We shift the expected circular list so that it starts from # multi_polygon[0][0][0], since output starting from any vertex # would be correct as long as it's in order. expected_coords = shift_circular_list( mp[0][0][0], [ vertices1[0], vertices1[1], vertices1[2], vertices0[1], vertices0[2], vertices0[3], vertices0[4], vertices0[5], vertices1[4], vertices1[5], ] ) expected = [[expected_coords]] assert len(mp) == 1 # polygon count matches expected assert len(mp[0]) == 1 # loop count matches expected assert len(mp[0][0]) == 10 # coord count matches expected assert mp == expected
def test_h3_set_to_multi_polygon_single(): h = '89283082837ffff' hexes = {h} # multi_polygon mp = h3.h3_set_to_multi_polygon(hexes) vertices = h3.h3_to_geo_boundary(h) # We shift the expected circular list so that it starts from # multi_polygon[0][0][0], since output starting from any vertex # would be correct as long as it's in order. expected_coords = shift_circular_list( mp[0][0][0], [ vertices[2], vertices[3], vertices[4], vertices[5], vertices[0], vertices[1], ] ) expected = [[expected_coords]] assert mp == expected
def test_h3_set_to_multi_polygon(): h = '8928308280fffff' hexes = h3.k_ring(h, 1) mpoly = h3.h3_set_to_multi_polygon(hexes) out = h3.polyfill_polygon(mpoly[0][0], 9, holes=None, lnglat_order=False) assert out == hexes
def test_h3_set_to_multi_polygon_non_contiguous(): # the second hexagon does not touch the first hexes = {'89283082837ffff', '8928308280fffff'} # multi_polygon mp = h3.h3_set_to_multi_polygon(hexes) assert len(mp) == 2 # polygon count matches expected assert len(mp[0]) == 1 # loop count matches expected assert len(mp[0][0]) == 6 # coord count 1 matches expected assert len(mp[1][0]) == 6 # coord count 2 matches expected
def test_h3_set_to_multi_polygon_hole(): # Six hexagons in a ring around a hole hexes = [ '892830828c7ffff', '892830828d7ffff', '8928308289bffff', '89283082813ffff', '8928308288fffff', '89283082883ffff', ] mp = h3.h3_set_to_multi_polygon(hexes) assert len(mp) == 1 # polygon count matches expected assert len(mp[0]) == 2 # loop count matches expected assert len(mp[0][0]) == 6 * 3 # outer coord count matches expected assert len(mp[0][1]) == 6 # inner coord count matches expected
def test_2_polys(): h = '8928308280fffff' hexes = h3.hex_ring(h, 2) hexes = hexes | {h} # hexes should be a center hex, and the 2-ring around it # (with the 1-ring being absent) out = [ h3.polyfill_polygon(poly[0], 9, holes=poly[1:], lnglat_order=False) for poly in h3.h3_set_to_multi_polygon(hexes, geo_json=False) ] assert set.union(*out) == hexes
def test_2_polys_not_json(): h = '8928308280fffff' hexes = h3.hex_ring(h, 2) hexes = hexes | {h} # hexes should be a center hex, and the 2-ring around it # (with the 1-ring being absent) # not deterministic which poly is first.. poly1, poly2 = h3.h3_set_to_multi_polygon(hexes, geo_json=False) assert {len(poly1), len(poly2)} == {1, 2} for poly in poly1, poly2: for loop in poly: assert loop[0] != loop[-1]
def test_h3_set_to_multi_polygon_single_geo_json(): hexes = ['89283082837ffff'] mp = h3.h3_set_to_multi_polygon(hexes, True) vertices = h3.h3_to_geo_boundary(hexes[0], True) # We shift the expected circular list so that it starts from # multi_polygon[0][0][0], since output starting from any vertex # would be correct as long as it's in order. expected_coords = shift_circular_list( mp[0][0][0], [ vertices[2], vertices[3], vertices[4], vertices[5], vertices[0], vertices[1] ] ) expected = [[expected_coords]] # polygon count matches expected assert len(mp) == 1 # loop count matches expected assert len(mp[0]) == 1 # coord count 7 matches expected according to geojson format assert len(mp[0][0]) == 7 # first coord should be the same as last coord according to geojson format assert mp[0] == mp[-1] # the coord should be (lng, lat) according to geojson format assert mp[0][0][0][0] == approx(-122.42778275313199) assert mp[0][0][0][1] == approx(37.77598951883773) # Discard last coord for testing below, since last coord is # the same as the first one mp[0][0].pop() assert mp == expected
def poc_polar(hotspot, chals): H = Hotspots() haddr = hotspot['address'] hlat, hlng = hotspot['lat'], hotspot['lng'] hname = hotspot['name'] if os.path.exists(hname): files = glob(hname + '\\*') for file in files: os.remove(file) else: os.mkdir(hname) wl = {} #witnesslist rl = { } #received list of hotspots(hotspot of intereset has been witness to these or received from them) c = 299792458 for chal in chals: # loop through challenges for p in chal['path']: #path? if p['challengee'] == haddr: # handles cases where hotspot of interest is transmitting for w in p[ 'witnesses']: #loop through witnesses so we can get rssi at each location challenge received #print('witness',w) lat = H.get_hotspot_by_addr(w['gateway'])['lat'] lng = H.get_hotspot_by_addr(w['gateway'])['lng'] name = H.get_hotspot_by_addr(w['gateway'])['name'] dist_km, heading = utils.haversine_km(hlat, hlng, lat, lng, return_heading=True) fspl = 20 * log10((dist_km + 0.01) * 1000) + 20 * log10( 915000000) + 20 * log10(4 * pi / c) - 27 try: wl[w['gateway']]['lat'] = lat wl[w['gateway']]['lng'] = lng wl[w['gateway']]['rssi'].append(w['signal']) except KeyError: wl[w['gateway']] = { 'rssi': [ w['signal'], ], 'dist_km': dist_km, 'heading': heading, 'fspl': fspl, 'lat': lat, 'lng': lng, 'name': name } else: # hotspot of interest is not transmitting but may be a witness challengee = p['challengee'] name = H.get_hotspot_by_addr(challengee)['name'] for w in p['witnesses']: if w['gateway'] != haddr: continue #print('transmitter ', name) #print('witness ', H.get_hotspot_by_addr(w['gateway'])['name']) # hotspot of interest was a witness lat = H.get_hotspot_by_addr(challengee)['lat'] lng = H.get_hotspot_by_addr(challengee)['lng'] #name=H.get_hotspot_by_addr(w['gateway'])['name'] dist_km, heading = utils.haversine_km(hlat, hlng, lat, lng, return_heading=True) fspl = 20 * log10((dist_km + 0.01) * 1000) + 20 * log10( 915000000) + 20 * log10(4 * pi / c) - 27 try: rl[challengee]['lat'] = lat rl[challengee]['lng'] = lng rl[challengee]['rssi'].append(w['signal']) except KeyError: rl[challengee] = { 'rssi': [ w['signal'], ], 'dist_km': dist_km, 'heading': heading, 'fspl': fspl, 'lat': lat, 'lng': lng, 'name': name } #print('rl:',rl) ratios = [1.0] * 16 rratios = [1.0] * 16 N = len(ratios) - 1 angles = [] rangles = [] #angles = [n / float(N) *2 *pi for n in range(N+1)] angles = list(np.arange(0.0, 2 * np.pi + (2 * np.pi / N), 2 * np.pi / N)) rangles = list(np.arange(0.0, 2 * np.pi + (2 * np.pi / N), 2 * np.pi / N)) #print(angles,len(angles)) #print(ratios,len(ratios)) markers = [] encoded = {} rencoded = {} for w in wl: #for witness in witnesslist #print(wl[w]) mean_rssi = sum(wl[w]['rssi']) / len(wl[w]['rssi']) ratio = wl[w]['fspl'] / mean_rssi * (-1) if ratio > 3.0: ratio = 3.0 elif ratio < -3.0: ratio = -3.0 ratios.append(ratio) angles.append(wl[w]['heading'] * pi / 180) #markers.append(folium.Marker([wl[w]['lat'],wl[w]['lng']],popup=wl[w]['name'])) markers.append([[wl[w]['lat'], wl[w]['lng']], wl[w]['name']]) # the histogram of the data #unique=set(wl[w]['rssi']) #num_unique=len(unique) n, bins, patches = plt.hist( wl[w]['rssi'], 10) #, density=True, facecolor='g', alpha=0.75,) plt.xlabel('RSSI(dB)') plt.ylabel('Count(Number of Packets)') wit = str(wl[w]['name']) plt.title('Packets from ' + hname + ' measured at ' + wit) #plt.text(60, .025, r'$\mu=100,\ \sigma=15$') #plt.xlim(40, 160) #plt.ylim(0, 0.03) plt.grid(True) #plt.show() strFile = str(wl[w]['name']) + '.jpg' strWitness = str(wl[w]['name']) if os.path.isfile(strFile): #print('remove') os.remove(strFile) # Opt.: os.system("rm "+strFile) plt.savefig(hname + '//' + strFile) encoded[strWitness] = base64.b64encode( open(hname + '//' + strFile, 'rb').read()) plt.close() for w in rl: #for witness in witnesslist #print(rl[w]) mean_rssi = sum(rl[w]['rssi']) / len(rl[w]['rssi']) rratio = rl[w]['fspl'] / mean_rssi * (-1) if rratio > 3.0: rratio = 3.0 elif rratio < -3.0: rratio = -3.0 rratios.append(rratio) rangles.append(rl[w]['heading'] * pi / 180) #markers.append([[wl[w]['lat'],wl[w]['lng']],wl[w]['name']]) n, bins, patches = plt.hist( rl[w]['rssi'], 10) #, density=True, facecolor='g', alpha=0.75,) plt.xlabel('RSSI(dB)') plt.ylabel('Count(Number of Packets)') wit = str(rl[w]['name']) plt.title('Packets from ' + wit + ' measured at ' + hname) plt.grid(True) #plt.show() strFile = 'rrr' + str(rl[w]['name']) + '.jpg' strWitness = str(rl[w]['name']) if os.path.isfile(strFile): #print('remove') os.remove(strFile) # Opt.: os.system("rm "+strFile) plt.savefig(hname + '//' + strFile) rencoded[strWitness] = base64.b64encode( open(hname + '//' + strFile, 'rb').read()) plt.close() # create polar chart angles, ratios = zip(*sorted(zip(angles, ratios))) rangles, rratios = zip(*sorted(zip(rangles, rratios))) angles, ratios = (list(t) for t in zip(*sorted(zip(angles, ratios)))) rangles, rratios = (list(t) for t in zip(*sorted(zip(rangles, rratios)))) fig, ax = plt.subplots(subplot_kw=dict(projection='polar')) ax.set_theta_zero_location("N") ax.set_theta_direction(-1) #ax.set_rmax(3) #ax.set_rmin(-3) ax.set_ylim(-3, 3) ax.plot(angles, ratios, marker='^', linestyle='solid', color='tomato', linewidth=2, markersize=5, label='Transmitting') #markerfacecolor='m', markeredgecolor='k', ax.plot(rangles, rratios, marker='v', linestyle='solid', color='dodgerblue', linewidth=1, markersize=5, label='Receiving') #, markerfacecolor='m', markeredgecolor='k' ax.legend(bbox_to_anchor=(0, 1), fancybox=True, framealpha=0, loc="lower left", facecolor='#000000') plt.xlabel('FSPL/RSSI') plt.savefig(hname + '//' + hname + '.png', transparent=True) #plt.show() # add polar chart as a custom icon in map m = folium.Map([hlat, hlng], tiles='stamentoner', zoom_start=18, control_scale=True, max_zoom=20) polargroup = folium.FeatureGroup(name='Polar Plot') icon = folium.features.CustomIcon(icon_image=hname + '//' + hotspot['name'] + '.png', icon_size=(640, 480)) marker = folium.Marker([hlat, hlng], popup=hotspot['name'], icon=icon) polargroup.add_child(marker) # add witness markers hsgroup = folium.FeatureGroup(name='Witnesses') hsgroup.add_child(folium.Marker([hlat, hlng], popup=hotspot['name'])) # add the witness markers for marker in markers: #html = '<img src="data:image/jpg;base64,{}">'.format html = '<p><img src="data:image/jpg;base64,{}" alt="" width=640 height=480 /></p> \ <p><img src="data:image/jpg;base64,{}" alt="" width=640 height=480 /></p>'.format #print('marker',marker) try: iframe = IFrame(html(encoded[marker[1]].decode('UTF-8'), rencoded[marker[1]].decode('UTF-8')), width=640 + 25, height=960 + 40) popup = folium.Popup(iframe, max_width=2650) mark = folium.Marker(marker[0], popup=popup) hsgroup.add_child(mark) except KeyError: # this means this witness never heard from us so there is no marker for it pass # not sure where to put the receive packet histogram so just ignore for now radius = 0.01 center = Point(hlat, hlng) circle = center.buffer(radius) # Degrees Radius gjcircle = shapely.geometry.mapping(circle) circle = center.buffer(radius * 25) # Degrees Radius gjcircle8 = shapely.geometry.mapping(circle) dcgroup = folium.FeatureGroup(name='Distance Circles', show=False) radius = 0.01 center = Point(hlat, hlng) circle = center.buffer(radius) # Degrees Radius gjcircle = shapely.geometry.mapping(circle) circle = gjcircle['coordinates'][0] my_Circle = folium.Circle(location=[hlat, hlng], radius=300, popup='300m', tooltip='300m') dcgroup.add_child(my_Circle) my_Circle = folium.Circle(location=[hlat, hlng], radius=1000, popup='1km', tooltip='1km') dcgroup.add_child(my_Circle) my_Circle = folium.Circle(location=[hlat, hlng], radius=2000, popup='2km', tooltip='2km') dcgroup.add_child(my_Circle) my_Circle = folium.Circle(location=[hlat, hlng], radius=3000, name='circles', popup='3km', tooltip='3km') dcgroup.add_child(my_Circle) my_Circle = folium.Circle(location=[hlat, hlng], radius=4000, popup='4km', tooltip='4km') dcgroup.add_child(my_Circle) my_Circle = folium.Circle(location=[hlat, hlng], radius=5000, popup='5km', tooltip='5km') dcgroup.add_child(my_Circle) my_Circle = folium.Circle(location=[hlat, hlng], radius=10000, popup='10km', tooltip='10km') dcgroup.add_child(my_Circle) h3colorgroup = folium.FeatureGroup(name='h3 Hexagon Grid Color Fill', show=False) style = {'fillColor': '#f5f5f5', 'lineColor': '#ffffbf'} #polygon = folium.GeoJson(gjson, style_function = lambda x: style).add_to(m) h3group = folium.FeatureGroup(name='h3 r11 Hex Grid', show=False) h3namegroup = folium.FeatureGroup(name='h3 r11 Hex Grid Names', show=False) h3fillgroup = folium.FeatureGroup(name='h3 r11 Hex Grid Color Fill', show=True) h3r8namegroup = folium.FeatureGroup(name='h3 r8 Hex Grid Names', show=False) h3r8group = folium.FeatureGroup(name='h3 r8 Hex Grid', show=False) hexagons = list(h3.polyfill(gjcircle, 11)) hexagons8 = list(h3.polyfill(gjcircle8, 8)) polylines = [] lat = [] lng = [] i = 0 #print('hexagon',hexagons[0]) #print(dir(h3)) home_hex = h3.geo_to_h3(hlat, hlng, 11) a = h3.k_ring(home_hex, 7) for h in a: gjhex = h3.h3_to_geo_boundary(h, geo_json=True) gjhex = geometry.Polygon(gjhex) mean_rsrp = -60 folium.GeoJson( gjhex, style_function=lambda x, mean_rsrp=mean_rsrp: { 'fillColor': map_color_rsrp(mean_rsrp), 'color': map_color_rsrp(mean_rsrp), 'weight': 1, 'fillOpacity': 0.5 }, #tooltip='tooltip' ).add_to(h3fillgroup) for hex in hexagons: p2 = h3.h3_to_geo(hex) #p2 = [45.3311, -121.7113] folium.Marker( p2, name='hex_names', icon=DivIcon( #icon_size=(150,36), #icon_anchor=(35,-45), icon_anchor=(35, 0), html='<div style="font-size: 6pt; color : black">' + str(hex) + '</div>', )).add_to(h3namegroup) #m.add_child(folium.CircleMarker(p2, radius=15)) polygons = h3.h3_set_to_multi_polygon([hex], geo_json=False) # flatten polygons into loops. outlines = [loop for polygon in polygons for loop in polygon] polyline = [outline + [outline[0]] for outline in outlines][0] lat.extend(map(lambda v: v[0], polyline)) lng.extend(map(lambda v: v[1], polyline)) polylines.append(polyline) for polyline in polylines: my_PolyLine = folium.PolyLine(locations=polyline, weight=1, color='blue') h3group.add_child(my_PolyLine) polylines = [] lat = [] lng = [] #polylines8 = [] for hex in hexagons8: p2 = h3.h3_to_geo(hex) folium.Marker( p2, name='hex_names', icon=DivIcon( #icon_size=(150,36), #icon_anchor=(35,-45), icon_anchor=(35, 0), html='<div style="font-size: 8pt; color : black">' + str(hex) + '</div>', )).add_to(h3r8namegroup) polygons = h3.h3_set_to_multi_polygon([hex], geo_json=False) # flatten polygons into loops. outlines = [loop for polygon in polygons for loop in polygon] polyline = [outline + [outline[0]] for outline in outlines][0] lat.extend(map(lambda v: v[0], polyline)) lng.extend(map(lambda v: v[1], polyline)) polylines.append(polyline) for polyline in polylines: my_PolyLine = folium.PolyLine(locations=polyline, weight=1, color='blue') h3r8group.add_child(my_PolyLine) # add possible tiles folium.TileLayer('cartodbpositron').add_to(m) folium.TileLayer('cartodbdark_matter').add_to(m) folium.TileLayer('openstreetmap').add_to(m) folium.TileLayer('Mapbox Bright').add_to(m) #folium.TileLayer('stamentoner').add_to(m) # add markers layer #marker_cluster = MarkerCluster().add_to(m) polargroup.add_to(m) #polar plot hsgroup.add_to(m) #hotspots dcgroup.add_to(m) #distance circles h3group.add_to(m) h3namegroup.add_to(m) h3fillgroup.add_to(m) m.keep_in_front(h3group) h3r8group.add_to(m) h3r8namegroup.add_to(m) # add the layer control folium.LayerControl(collapsed=False).add_to(m) m.save(hname + '//' + hname + '_map.html')
def test_h3_set_to_multi_polygon_empty(): out = h3.h3_set_to_multi_polygon([]) assert out == []