def get_cell_from_string(str_id): raw_id = long(str_id) if raw_id < 0: # overflow cell_id = s2sphere.CellId(raw_id) return s2sphere.Cell.from_face_pos_level(cell_id.face(), cell_id.pos(), 10) else: return s2sphere.Cell(s2sphere.CellId(raw_id))
def __init__(self, queries, lat, lon, level): """ I copied most of this code from Map-A-Droid. """ ll = s2sphere.LatLng.from_degrees(lat, lon) cell = s2sphere.CellId().from_lat_lng(ll) cellId = cell.parent(level).id() cell = s2sphere.Cell(s2sphere.CellId(cellId)) path = [] for v in range(0, 4): vertex = s2sphere.LatLng.from_point(cell.get_vertex(v)) path.append([vertex.lat().degrees, vertex.lng().degrees]) mb_path = [] for v in range(0, 4): vertex = s2sphere.LatLng.from_point(cell.get_vertex(v)) mb_path.append([vertex.lng().degrees, vertex.lat().degrees]) mb_path.append(mb_path[0]) stringfence = "" for coordinates in path: stringfence = f"{stringfence}{coordinates[0]} {coordinates[1]}," stringfence = f"{stringfence}{path[0][0]} {path[0][1]}" count = queries.count_in_cell(stringfence) self.path = path self.mapbox_path = mb_path self.stops = count[0] + count[1] self.portals = count[2]
def test_create_subsetting_area_with_two_cells_check_distance_from_centre_is_roughly_the_same_for_both(): cap = spatial.create_subsetting_area([5221390301001263407, 5221390302696205321]) cap_centre = s2sphere.CellId.from_point(cap.axis()) dist_1 = cap_centre.to_lat_lng().get_distance(s2sphere.CellId(5221390301001263407).to_lat_lng()).radians dist_2 = cap_centre.to_lat_lng().get_distance(s2sphere.CellId(5221390302696205321).to_lat_lng()).radians assert cap.contains(s2sphere.CellId(5221390301001263407).to_point()) assert cap.contains(s2sphere.CellId(5221390302696205321).to_point()) assert round(dist_1, 8) == round(dist_2, 8)
def find_common_cell(edge): u, v, w = edge _u = s2.CellId(u) _v = s2.CellId(v) while _u != _v and not _u.is_face(): _u = _u.parent() _v = _v.parent() if _u.is_face(): # if u is a face then v will be a face too, only need to check u return 0 return _u
def distance_between_s2cellids(s2cellid1, s2cellid2): if isinstance(s2cellid1, int): s2cellid1 = s2.CellId(s2cellid1) elif isinstance(s2cellid1, np.int64): s2cellid1 = s2.CellId(int(s2cellid1)) if isinstance(s2cellid2, int): s2cellid2 = s2.CellId(s2cellid2) elif isinstance(s2cellid2, np.int64): s2cellid2 = s2.CellId(int(s2cellid2)) distance = s2cellid1.to_lat_lng().get_distance(s2cellid2.to_lat_lng()).radians return distance * APPROX_EARTH_RADIUS
def create_subsetting_area(CellIds, angle=0, buffer_multiplier=None): """ Builds a bounding s2.Cap covering the CellIds + `angle` value buffer finds a midpoint from the points passed and uses the largest distance as minimal radius for the neighbourhood, if just one point, that distance is zero and angle is needed to specify the radius for the cap. Can also specify angle == 'double' to use the largest distance as buffer :param CellIds: :param angle: angle/distance for buffer :param buffer_multiplier: float, use the largest distance between points as a buffer for the area, final radius for the Cap = largest distance * buffer_multiplier + angle OR final radius for the Cap = largest distance + largest distance * buffer_multiplier + angle (if the multiplier is less than 1, the subsetting area has to at least cover the points passed to generate the area) :return: s2.Cap """ def sum_pts(pts): p = None for p_n in pts: if p is None: p = p_n else: p = p + p_n return p pts = [s2.CellId(p).to_point() for p in CellIds] if len(pts) > 1: # find a midpoint and distance dist to the farthest point pts = [s2.CellId(p).to_point() for p in CellIds] mid_point = sum_pts(pts).normalize() dist = 0 for p in pts: d = s2.LatLng.from_point(mid_point).get_distance( s2.LatLng.from_point(p)).radians if d > dist: dist = d else: mid_point = pts[0] dist = 0 if buffer_multiplier is not None: if buffer_multiplier < 1: dist = dist + (dist * buffer_multiplier) else: dist = dist * buffer_multiplier if isinstance(angle, s2.Angle): angle = angle + s2.Angle.from_radians(dist) else: angle = s2.Angle.from_radians(angle + dist) area = s2.Cap.from_axis_angle(mid_point, angle) return area
def process_weather(self, json_data): self.weather_total += 1 if args.no_weather: return to_keep = [ "s2_cell_id", "latitude", "longitude", "cloud_level", "rain_level", "snow_level", "fog_level", "wind_direction", "gameplay_weather", "severity", "warn_weather", "world_time", "last_updated" ] weather = {} # This is for mon alt's fork. It's almost RM, but not quite. # As if this writing, RM doesn't have support for weather # 02/28/18 if 'coords' in json_data: id = json_data['s2_cell_id'] weather[id] = json_data wh_weather = weather[id].copy() # Map all the fields weather[id]['severity'] = json_data['alert_severity'] weather[id]['last_updated'] = time.gmtime( json_data['time_changed']) weather[id]['warn_weather'] = json_data['warn'] # Day =1 night = 2 weather[id]['world_time'] = json_data['day'] # condition weather[id]['gameplay_weather'] = json_data['condition'] # Mon alt sends the coordinates, but we do not actually need them. cell_id = s2sphere.CellId(long(id)) cell = s2sphere.Cell(cell_id) center = s2sphere.LatLng.from_point(cell.get_center()) weather[id]['latitude'] = center.lat().degrees weather[id]['longitude'] = center.lng().degrees # This is a WAG until I get more info weather[id]['cloud_level'] = 0 weather[id]['rain_level'] = 0 weather[id]['snow_level'] = 0 weather[id]['fog_level'] = 0 weather[id]['wind_direction'] = 0 # And this is stock RM else: pass # copies all the keys we want for the DB weather[id] = { key: weather[id][key] for key in weather[id] if key in to_keep } log.debug("%s", weather) # put it into the db queue db_queue.put((Weather, weather)) if args.webhooks: wh_queue.put(('weather', wh_weather))
def coords_of_cell(cell_id): cell = s2sphere.Cell(s2sphere.CellId(int(cell_id))) coords = [] for value in range(0, 4): vertex = s2sphere.LatLng.from_point(cell.get_vertex(value)) coords.append([vertex.lat().degrees, vertex.lng().degrees]) return coords
def check_children(parent): for parent, kid in self.edges(parent): if self.is_link(kid): closest_links_to_cell.append(kid) elif neighbourhood_of_g_node.may_intersect( s2.Cell(s2.CellId(kid))): check_children(kid)
def cell_id_to_json(cellid_l): cellid = s2sphere.CellId(cellid_l) cell = s2sphere.Cell(cellid) def get_vertex(v): vertex = s2sphere.LatLng.from_point(cell.get_vertex(v)) return { 'lat': vertex.lat().degrees, 'lng': vertex.lng().degrees } shape = [get_vertex(v) for v in range(0, 4)] return { 'id': str(cellid.id()), 'id_signed': cellid.id(), 'token': cellid.to_token(), 'pos': cellid.pos(), 'face': cellid.face(), 'level': cellid.level(), 'll': { 'lat': cellid.to_lat_lng().lat().degrees, 'lng': cellid.to_lat_lng().lng().degrees }, 'shape': shape }
def s2info(): # need to make this work for GET and POST ids = request.args.get("id") or request.form['id'] or '' return jsonify({ 'cells': [cell_id_to_json(s2sphere.CellId(long(id))) for id in ids.split(',')] })
def get(self): hour_limit = float(request.args.get('hours', DEFAULT_HOUR_LIMIT)) print(f'HOUR_LIMIT: {hour_limit}') cell_id = request.args['cell_token'] print(f'CELL_ID: {cell_id}') level = s2sphere.CellId.from_token(cell_id).level() print(f'LEVEL: {level}') data = [] cells = itertools.chain( map(lambda c: self.level_cell(c, REGIONAL_LEVEL), [cell_id])) for cell in cells: # get from database local_cells = [] results = InfectionModel.query(cell.id()) for r in results: local_cells.extend([(r.local_cell, t) for t in r.timestamps]) # filter timestamps local_cells = [{ 'cell_token': s2sphere.CellId(c).to_token(), 'timestamp': ts } for c, ts in local_cells if datetime.now() - datetime.fromtimestamp(int(ts) / 1000) < timedelta( hours=hour_limit)] # add to data data.extend(local_cells) return {'data': data}
def get_weather(): with session_scope() as session: weathers = session.query(Weather) markers = [] for weather in weathers: cell = s2sphere.Cell( s2sphere.CellId(weather.s2_cell_id).parent(10)) center = s2sphere.LatLng.from_point(cell.get_center()) converted_s2_cell_id = s2sphere.CellId.from_lat_lng( s2sphere.LatLng.from_degrees(center.lat().degrees, center.lng().degrees)).parent(10) markers.append({ 'id': 'weather-' + str(weather.id), 'coords': [(get_vertex(cell, v)) for v in range(0, 4)], 'center': (center.lat().degrees, center.lng().degrees), 'condition': weather.condition, 'alert_severity': weather.alert_severity, 'warn': weather.warn, 'day': weather.day, 's2_cell_id': converted_s2_cell_id.id() }) return markers
def test_grabs_point_indexes_from_s2(mocker): mocker.patch.object(s2sphere.CellId, 'from_lat_lng', return_value=s2sphere.CellId(id_=123456789)) point_index = spatial.generate_index_s2(53.483959, -2.244644) assert point_index == 123456789 s2sphere.CellId.from_lat_lng.assert_called_once_with( s2sphere.LatLng.from_degrees(53.483959, -2.244644))
def _hexid2latlng(self, hexid): # convert hexid to latlng of cellcenter cellid = s2.CellId().from_token(hexid) cell = s2.Cell(cellid) point = cell.get_center() latlng = s2.LatLng(0, 0).from_point(point).__repr__() _, latlng = latlng.split(' ', 1) lat, lng = latlng.split(',', 1) lat = float(lat) lng = float(lng) return lat, lng
def get_feature(self, s): c = s2sphere.Cell(s2sphere.CellId(s)) y = [ s2sphere.LatLng.from_point(c.get_vertex(i)) for i in [0, 1, 2, 3, 0] ] x = [[(x.lng().degrees, x.lat().degrees) for x in y]] g = geojson.Polygon(x) f = geojson.Feature(geometry=g, properties={ 's2id': str(s), 'lvl': str(c.level()) }) return f
def get_cellid_from_latlng(lat, lng, level=20): ll = s2sphere.LatLng.from_degrees(lat, lng) cell = s2sphere.CellId().from_lat_lng(ll) return cell.parent(level).to_token()
def get_position_from_cell(cell_id): cell = s2sphere.CellId(id_=int(cell_id)).to_lat_lng() return s2sphere.math.degrees(cell.lat().radians), \ s2sphere.math.degrees(cell.lng().radians), 0
def middle_of_cell(cell_id): cell = s2sphere.CellId(cell_id) lat_lng = cell.to_lat_lng() return lat_lng.lat().degrees, lat_lng.lng().degrees
def get_cell_level(cell_id): return s2sphere.Cell(s2sphere.CellId(cell_id)).level()
Usage Example: python s2-cellid2latlong.py 9279882692622716928 Running s2-cellid2latlong.py v2016-08-12 S2 Level = 24 36.114574473973924 , -115.18062802526205 """ import s2sphere import argparse version_string = "s2-cellid2latlong.py v2016-08-12" print("Running " + version_string + "\n") # Handle command line args parser = argparse.ArgumentParser( description= 'Convert a 64 bit Google S2 cellid to a lat, long and S2 cellid level') parser.add_argument("cellid", type=int, help="Google S2 cellid") args = parser.parse_args() s2cell = s2sphere.CellId(args.cellid) print("S2 Level = " + str(s2cell.level())) print( repr(s2cell.to_lat_lng().lat().degrees) + " , " + repr(s2cell.to_lat_lng().lng().degrees)) #print(s2cell.to_token())
def s2_id2coords(s2_id): ll = s2sphere.CellId(s2_id).to_lat_lng() lat = ll.lat().degrees lng = ll.lng().degrees print("%f %f" % (lat, lng))
#!/usr/bin/python import sys, s2sphere ll = s2sphere.CellId(int(sys.argv[1])).to_lat_lng() sys.stdout.write(str(ll)[8:])
import s2sphere r = s2sphere.RegionCoverer() p1 = s2sphere.LatLng.from_degrees(34.2471243765, 118.192198189) p2 = s2sphere.LatLng.from_degrees(35.2430777118, 116.9997801738) r.min_level = 8 r.max_level = 8 r.max_cells = 100 print("ma", r.max_cells) cell_ids = r.get_covering(s2sphere.LatLngRect.from_point_pair(p1, p2)) # print(cell_ids) points2 = [] for i in cell_ids: print(i.face()) p0, p1 = s2sphere.CellId( i.id()).to_lat_lng().lat().degrees, s2sphere.CellId( i.id()).to_lat_lng().lng().degrees print(p0, p1) points2.append([float(p1), float(p0)]) # print("*",s2sphere.CellId(i.id())) cellids = [ 3874239171631513600, 3874274356003602432, 3874872490329112576, 3874942859073290240, 3874978043445379072, 3875013227817467904, 3875048412189556736, 3875083596561645568, 3875118780933734400, 3875259518422089728 ] points3 = [] for i in cellids:
def parseData(self, *args): log.info('Starting Data processing thread') while True: map_objects = self.process_queue.get() # decode b64 delivered message from ++ response = b64decode(map_objects) try: # decde raw protos to JSON gmo = GetMapObjectsResponse() gmo.ParseFromString(response) except google.protobuf.message.DecodeError: log.error("Caught exception decoding message.") continue gmo_response = json.loads(MessageToJson(gmo)) try: weather = gmo_response['clientWeather'] for cell in weather: alerts = None for alert in cell.get("alerts", {}): alert = alert.get("severity", None) self.weatherConditions.update({ cell['s2CellId']: (cell['gameplayWeather']['gameplayCondition'], alerts) }) except KeyError: weather = None fort_count = 0 pokestop_count = 0 gym_count = 0 forts = [] gyms = [] raids = [] # grab all the forts we got from the GMO request # as we don't care about spawns for i, cell in enumerate(gmo_response['mapCells']): fort = cell.get('forts', None) if fort: forts += fort fort_count += len(fort) # iterate over our forts and handle them for f in forts: f_type = f.get('type', 0) f_raid = f.get('raidInfo', None) f_id = f['id'] f_lat = f['latitude'] f_lng = f['longitude'] # get lv10 s2 cell for weather p = s2sphere.LatLng.from_degrees(f_lat, f_lng) cell = s2sphere.CellId().from_lat_lng(p).parent(10) cellid = ctypes.c_int64(cell.id()).value # parse gym info from the map if f_type == 0 and (f_raid or not self.gym_db.find_one({'id': f_id})): gym_count += 1 gym_details = self.gym_db.find_one({'id': f_id}) gym, raid = parseGym(f, gym_details) gym['weather'] = self.weatherConditions.get( str(cellid), None) # log.info(f"Found gym {gym_details['name']}") if raid: gym['raid'] = raid raids.append(gym) gyms.append(gym) elif self.gym_db.find_one({'id': f_id}): gym_count += 1 # gym_details = self.gym_db.find_one({'id': f_id}) # log.info(f"Found gym {gym_details['name']}") gym_details = self.gym_db.find_one({'id': f_id}) gym, raid = parseGym(f, gym_details) gyms.append(gym) # self.gym_db.update_one({'id': f_id}, # {'$set': {'lastSeen': datetime.datetime.utcnow(), # 'isExRaidEligible': gym.get('isExRaidEligible')} # }).modified_count # parse pokestop details elif f_type == 'CHECKPOINT': pokestop_count += 1 if not self.pokestop_db.find_one({'id': f_id}): log.info(f"Discovered new pokestop {f_id}") doc = { 'id': f_id, 'added': datetime.datetime.utcnow(), 'name': None, 'location': { 'type': 'Point', 'coordinates': [f_lng, f_lat] } } self.pokestop_db.insert_one(doc).inserted_id # pos = device['position'] log.info( f"Found {fort_count} forts. {gym_count} Gyms {pokestop_count} Pokestops {len(raids)} Raids" ) # push our results to their queues. if gyms: self.gym_db_queue.put(gyms) # self.pokestop_db.put(pokestops) if raids: self.raid_queue.put(raids) self.raid_db_queue.put(raids)
def get_position_from_cell_id(cell_id): cell = s2sphere.CellId(id_=cell_id).to_lat_lng() return (math.degrees(cell._LatLng__coords[0]), math.degrees(cell._LatLng__coords[1]), 0)
def __init__(self, cell_id): self.cell_id = cell_id self.cell_level = s2sphere.CellId(self.cell_id).level() self.cell_lat = s2sphere.CellId(self.cell_id).to_lat_lng().lat().degrees self.cell_lon = s2sphere.CellId(self.cell_id).to_lat_lng().lng().degrees