zoukankan      html  css  js  c++  java
  • 将一个城市的地图按照每1平方公里进行拆分为若干个区域

    将一个城市的地图按照每1平方公里进行拆分为若干个区域(地图使用高德)

    如图:

    核心代码(Python 3.5):

    map_zoning.py
    #!/usr/bin/env python3
    # -*- coding: utf-8 -*-
    
    
    import json
    import math
    import os
    import time
    
    from amap import Map
    
    
    class MapZoning:
        def __init__(self, city, distance=None, map_service=None):
            self.city = city
            self.distance = distance if distance else 1  # 单位km,默认0.5km
            self.earth_radius = 40075.04 / (2 * math.pi)
            self.lat_unit = self.get_lat_unit(self.distance)
            self.map_service = map_service if map_service else Map(os.environ.get('MAP_KEY'))
            self.location_validated = {}  # key:[经度,维度] value: 1验证成功,2超出范围
    
        def get_lat_unit(self, distance):
            """
            获取一定距离的维度单位
            :param distance:
            :return:
            """
            return distance * 360 / (2 * math.pi) / self.earth_radius
    
        def get_lng_unit(self, lat, distance):
            """
            获取一定距离的经度单位
            :param lat:
            :param distance:
            :return:
            """
            return distance * 360 / (2 * math.pi) / math.cos(math.radians(lat)) / self.earth_radius
    
        def _get_area_points(self, quadrant, location):
            """
            获取区域的点
            :param int quadrant:
            :param list location:
            :return list : 矩形四个点,顺序:左上、右上、右下、左下
            """
            if quadrant == 1:
                left_lng = float(location[0])  # 经度
                bottom_lat = float(location[1])  # 维度
                top_lat = round(bottom_lat + self.lat_unit, 6)
                right_lng = round(left_lng + self.get_lng_unit(float(top_lat), self.distance), 6)
            elif quadrant == 2:
                right_lng = float(location[0])
                bottom_lat = float(location[1])
                top_lat = round(bottom_lat + self.get_lat_unit(self.distance), 6)
                left_lng = round(right_lng - self.get_lng_unit(top_lat, self.distance), 6)
            elif quadrant == 3:
                right_lng = float(location[0])
                top_lat = float(location[1])
                left_lng = round(right_lng - self.get_lng_unit(top_lat, self.distance), 6)
                bottom_lat = round(top_lat - self.get_lat_unit(self.distance), 6)
            elif quadrant == 4:
                left_lng = float(location[0])
                top_lat = float(location[1])
                right_lng = round(left_lng + self.get_lng_unit(float(top_lat), self.distance), 6)
                bottom_lat = round(top_lat - self.lat_unit, 6)
            else:
                return None
            return [[left_lng, top_lat], [right_lng, top_lat], [right_lng, bottom_lat], [left_lng, bottom_lat]]
    
        def get_area_points_x(self, quadrant, res_points, points, i_temp):
            if i_temp > 60:
                return
            if quadrant == 1:
                location = points[2]
            elif quadrant == 2:
                location = points[3]
            elif quadrant == 3:
                location = points[0]
            elif quadrant == 4:
                location = points[1]
            else:
                return
            tmp_pos = self._get_area_points(quadrant, location)
            if self.validate_points(tmp_pos):
                res_points.append(tmp_pos)
            i_temp += 1
            self.get_area_points_x(quadrant, res_points, tmp_pos, i_temp)
    
        def get_area_points_y(self, quadrant, res_points, points, i_temp):
            if i_temp > 60:
                return
            if quadrant == 1:
                location = points[0]
            elif quadrant == 2:
                location = points[1]
            elif quadrant == 3:
                location = points[2]
            elif quadrant == 4:
                location = points[3]
            else:
                return
            tmp_pos = self._get_area_points(quadrant, location)
            if self.validate_points(tmp_pos):
                res_points.append(tmp_pos)
            i_temp += 1
            self.get_area_points_x(quadrant, res_points, tmp_pos, 1)
            self.get_area_points_y(quadrant, res_points, tmp_pos, i_temp)
    
        def get_all_area_points(self, quadrant, res_points, location):
            tmp_pos = self._get_area_points(quadrant, location)
            res_points.append(tmp_pos)
            self.get_area_points_x(quadrant, res_points, tmp_pos, 1)
            self.get_area_points_y(quadrant, res_points, tmp_pos, 1)
    
        def validate_points(self, points):
            b_result = False
            for location in points:
                if location[0] < 113.74181 or location[1] < 22.438768 or location[1] > 22.887492 or location[0] > 114.649706:
                    continue
                v_key = ','.join([str(x) for x in location])
                v_value = self.location_validated.get(v_key)
                if not v_value:
                    res = self.map_service.get_get_address(location)
                    address_component = res.get('regeocode').get('addressComponent') if res and res.get('regeocode') else {}
                    if not address_component or address_component.get('citycode') != '0755' or address_component.get(
                            'seaArea'):
                        self.location_validated[v_key] = 2
                    else:
                        b_result = True
                        self.location_validated[v_key] = 1
                elif v_value == 1:
                    b_result = True
            return b_result
    
        def zoning(self):
            print(time.time())
            res_points = []
            location = [114.057868, 22.543099]  # self.map_service.get_geo_code(self.city).split(',')
            self.get_all_area_points(1, res_points, location)
            self.get_all_area_points(2, res_points, location)
            self.get_all_area_points(3, res_points, location)
            self.get_all_area_points(4, res_points, location)
            with open('tmp/points.js', 'w', encoding='utf-8') as _file:
                _file.write('var points = ' + json.dumps(res_points) + ';')
            print(time.time())
            # points = [['113.980092', '22.475719'], ['113.984953', '22.475719'], ['113.984953', '22.471227'],
            #           ['113.980092', '22.471227']]
            # print(self.validate_points(points))
            # print(self.map_service.get_get_address(['113.980092', '22.475719']))
            return res_points
    

      

    amap.py
    #!/usr/bin/env python3
    # -*- coding: utf-8 -*-
    
    
    import logging
    
    import requests
    
    
    class Map:
        def __init__(self, key):
            if not key:
                raise Exception('初始map服务错误无效Key')
            self.key = key
    
        def get_geo_code(self, address):
            """
            获取地理位置编码
            :param address:
            :return:
            """
            api_geocode = 'http://restapi.amap.com/v3/geocode/geo'
            try:
                response = requests.get(api_geocode, {'key': self.key,
                                                      'address': address,
                                                      'output': 'JSON'})
                if response.status_code != 200:
                    return None
                res = response.json()
                if not res:
                    return None
                geocodes = res.get('geocodes')
                if not geocodes:
                    return None
                location = geocodes[0].get('location')
                if not location:
                    return None
                return location
            except Exception as ex:
                logging.error('获取地址位置编码错误:' + str(ex))
                return None
    
        def get_get_address(self, location):
            api = 'http://restapi.amap.com/v3/geocode/regeo'
            try:
                response = requests.get(api, {'key': self.key,
                                              'location': ','.join([str(x) for x in location]),
                                              'output': 'JSON'})
                if response.status_code != 200:
                    return None
                res = response.json()
                if not res:
                    return None
                return res
            except Exception as ex:
                logging.error('获取地址位置错误:' + str(ex))
                return None
    

      

    app.py
    #!/usr/bin/env python3
    # -*- coding: utf-8 -*-
    
    import logging
    
    from os.path import join, dirname
    from dotenv import load_dotenv
    from map_zoning import MapZoning
    
    dotenv_path = join(dirname(__file__), '.env')
    
    load_dotenv(dotenv_path)
    
    if __name__ == '__main__':
        try:
            MapZoning('深圳市').zoning()
        except Exception as ex:
            logging.error(ex)
    

      .env

    # application
    APP_NAME="split_map"
    APP_RUNTIME="dev"
    APP_LOG_LEVEL="INFO"
    APP_LOG_HANDLER="console"
    
    # map
    MAP_KEY="amap_web_api_key"
    

      

  • 相关阅读:
    The nineteenth day
    The eighteen day
    弱读下
    弱读上
    失爆 爆破音
    连读
    The seventeenth day
    The sixteenth day
    React 官方脚手架 create-react-app快速生成新项目
    pc端引入微信公众号文章
  • 原文地址:https://www.cnblogs.com/stones/p/6297276.html
Copyright © 2011-2022 走看看