def get_sites_nearby_scene(_scene, queryset_sites): result = [] _workspace = _scene.workspace _region = mymap.Region(_scene.region) _center = _region.get_center() queryset_sites = queryset_sites.filter(site_type='outdoor') for _site in queryset_sites: _point = mymap.Point(_site.lng, _site.lat) # 宏站按距离进行判断 delta_lng = abs(_point.lng - _center.lng) delta_lat = abs(_point.lat - _center.lat) if delta_lng > 0.13 or delta_lat > 0.1: # 0.13/0.1 大约代表 22公里左右的限制 continue else: # 得到的时包含最小距离和最大距离的tuple dis_boder = _point.distance(_region) if dis_boder[0] < DISTANCE_NEAR: dis_center = _point.distance(_center) is_in = _point.in_region(_region) result.append( OutdoorSiteNearbyScene( workspace=_workspace, scene=_scene, site=_site, distance_to_center=dis_center, distance_to_border_near=dis_boder[0], distance_to_border_far=dis_boder[1], in_scene=is_in, )) return result
def get_scene_cover_sites(scene, sites_nearby_scene): _sites_nearby_scene = [] for item in sites_nearby_scene: if not item.in_scene: _sites_nearby_scene.append(item) if len(_sites_nearby_scene) == 1: _sites_nearby_scene[0].cover_order = 1 else: region = mymap.Region(scene.region) center = region.get_center() ordered_sites_near_reg = sorted( _sites_nearby_scene, key=lambda e: e.distance_to_border_near) # 以最近的站点的方向为基准方向 site1 = ordered_sites_near_reg[0].site ordered_sites_near_reg[0].cover_order = 1 p1 = mymap.Point(site1.lng, site1.lat) ordered_sites_near_reg[0].azimuth = int(p1.azimuth(center)) azimuth1 = center.azimuth(p1) azimuth2 = 0 i = 1 while i < len(ordered_sites_near_reg): # 计算当前的站址 和 中心点 角度 _site = ordered_sites_near_reg[i].site _p = mymap.Point(_site.lng, _site.lat) _azimuth = center.azimuth(_p) if abs(_azimuth - azimuth1) < 90: i += 1 continue azimuth2 = _azimuth ordered_sites_near_reg[i].cover_order = 2 ordered_sites_near_reg[i].azimuth = int(_p.azimuth(center)) break i += 1 while i < len(ordered_sites_near_reg): _site = ordered_sites_near_reg[i].site _p = mymap.Point(_site.lng, _site.lat) _azimuth = center.azimuth(_p) if abs(_azimuth - azimuth1) < 90 or abs(_azimuth - azimuth2) < 90: i += 1 continue ordered_sites_near_reg[i].cover_order = 3 ordered_sites_near_reg[i].azimuth = int(_p.azimuth(center)) break
def get_indoor_sites_in_scene(_scene, queryset_sites): result = [] _workspace = _scene.workspace _region = mymap.Region(_scene.region) queryset_sites = queryset_sites.filter(site_type="indoor") for _site in queryset_sites: _point = mymap.Point(_site.lng, _site.lat) if _point.in_region(_region): result.append( IndoorSiteInScene( workspace=_workspace, site=_site, scene=_scene, )) return result
def __init__(self, fmt_str): # 可以接收 json_str 或者 单引号的类似json_str结构 # 也可以接收 {[,]; 连接的经纬度 if "'" in fmt_str: fmt_str = fmt_str.replace("'", '"') try: reg_dict = json.loads(fmt_str) except ValueError: # 去掉全部的 {} 和 [] points = fmt_str.replace('{', '').replace('}', '').replace( '[', '').replace(']', '') # 每对经纬度之间时以;间隔的 points = points.split(';') # 经度和纬度间以,分割 points = (s.split(',') for s in points) points = [mymap.Point(*_l) for _l in points] else: if 'ends' in reg_dict.keys(): points = [mymap.Point(**p) for p in reg_dict['ends']] else: raise ValueError("输入参数中应包含'ends'") # 去掉points中相邻的重复点位 temp_point = None list_point = [] for point in points: if point != temp_point: temp_point = point list_point.append(point) # 闭合区域的第一个点和最后一个点应该相同, 为计算方便,默认去掉在ends里不包含最后一个重复的点 # 如果第一个点和最后一点个相同, 则去除 if list_point[0] == list_point[-1]: list_point = list_point[0:-1] if len(list_point) < 3: raise ValueError('一个闭合区域区域至少要包含3个不重合的经纬度点') # 如果使用生成器,只能遍历一次,转化成tuple对象就不再有此限制 self.ends = tuple(_p for _p in list_point)
def new_object(self, request, **kwargs): result = { 'errmsg': [], } form = SiteForm(request.POST) if form.is_valid(): obj = form.save(commit=False) # 格式化经纬度精度 _point = mymap.Point(obj.lng, obj.lat) obj.lng = _point.lng obj.lat = _point.lat _workspace = WorkSpace.objects.get(**kwargs) obj.workspace = _workspace obj.save() _workspace.save() else: for key, value in form.errors.items(): result['errmsg'].append('{}:{}'.format(key, value)) return result
def edit_object(self, request, **kwargs): result = { 'errmsg': [], } # 在request.POST中, data数据是修改前的原数据 data = request.POST.get('data') # data 是json格式数据 data = json.loads(data) unique_cols = Cell.get_unique_fields() obj_dict = { key: value for key, value in data.items() if key in unique_cols } _workspace = WorkSpace.objects.get(**kwargs) obj_dict['workspace'] = _workspace # 数据库数据 _cell = Cell.objects.get(**obj_dict) inital_data = _cell.to_dict() # 格式化新数据 record = copy(request.POST) # 修改为可编辑状态 record._mutable = True # 格式化数据 lng = request.POST.get('lng') lat = request.POST.get('lat') _point = mymap.Point(lng, lat) record['lng'] = _point.lng record['lat'] = _point.lat form = CellForm(instance=_cell, initial=inital_data, data=record) if form.has_changed(): if form.is_valid(): form.save() _workspace.save() else: for key, value in form.errors.items(): result['errmsg'].append('{}:{}'.format(key, value)) else: result['errmsg'].append('未作修改') return result
def new_object(self, request, **kwargs): result = { 'errmsg': [], } form = CellForm(request.POST) if form.is_valid(): # 格式化经纬度 _point = mymap.Point(form.cleaned_data['lng'], form.cleaned_data['lat']) _workspace = WorkSpace.objects.get(**kwargs) _site = None try: _site = Site.objects.get(workspace=_workspace, lng=_point.lng, lat=_point.lat) except Site.DoesNotExist: site_name = get_site_name(form.cleaned_data['cell_name']) _site = Site( workspace=_workspace, site_name=site_name, site_type=form.cleaned_data['cell_type'], lng=_point.lng, lat=_point.lat, is_auto_created=True, ) _site.save() _workspace.save() finally: cell = form.save(commit=False) cell.workspace = _workspace cell.site = _site cell.save() _workspace.save() else: for key, value in form.errors.items(): result['errmsg'].append('{}:{}'.format(key, value)) return result
def upload(self, request, **kwargs): result = { 'errmsg': [], } _workspace = WorkSpace.objects.get(**kwargs) # 获取文件并读取内容 file = request.FILES.get('file') df = myfuncs.read_csv(file) # 检查文件头信息 missing_cols 存储缺少的列 missing_cols = [] fields = Site.get_upload_fields() cols = {field['verbose_name']: field['name'] for field in fields} for col in cols.keys(): if col not in df.columns: missing_cols.append(col) if missing_cols: result['errmsg'].append('导入文件缺少 "{}" 列'.format( '、'.join(missing_cols))) else: # 检查完毕, 表头正常 只需要模板列, 并将列头重命名为内部名 df = df[cols.keys()] df = df.rename(columns=cols) # object_list 保存验证正常的 实例 object_list = [] # df.to_dict(orient='records') 将DataFrame转化成字典的列表 for _index, record in enumerate(df.to_dict(orient='records'), start=1): # 格式化 record lng 和 lat try: _point = mymap.Point(record['lng'], record['lat']) except ValueError as e: result['errmsg'].append(str(e)) else: record['lng'] = _point.lng record['lat'] = _point.lat # 需要对site_type数据进行处理 form = SiteForm(data=record) if form.is_valid(): # form.save(commit=False) 保存为Scene对象 但是不存储到数据库 obj = form.save(commit=False) obj.workspace = _workspace object_list.append(obj) else: for key in form.errors.keys(): # 存在错误的情况, 将错误加入到errmsg result['errmsg'].append('文件第{}行存在错误: {}:{}'.format( _index, key, form.errors[key])) if not result['errmsg']: # 只有完全不存在errmsg, 才进行批量的存储到数据库的操作 # 获取当前最大的id值 sites_exist = Site.objects.all() maxid_exist = sites_exist.aggregate( models.Max('id'))['id__max'] maxid_exist = maxid_exist if maxid_exist else 0 # 给新增的scene添加id id_new = maxid_exist + 1 siteid_list = [] for site in object_list: site.id = id_new siteid_list.append(site.id) id_new += 1 from django.db.utils import IntegrityError try: Site.objects.bulk_create(object_list) _workspace.save() except IntegrityError: # 存在重合站址 not_unique = [] # 对object_list 按照lng和lat进行排序 sorted_sites = sorted(object_list, key=lambda x: (x.lng, x.lat), reverse=False) # 存储对比的临时数据 _lng = 0 _lat = 0 _obj_1 = None for _obj in sorted_sites: if _obj.lng == _lng and _obj.lat == _lat: not_unique.append((_obj_1, _obj)) else: _lng = _obj.lng _lat = _obj.lat _obj_1 = _obj if not_unique: result['errmsg'].append('存在{}对重合站址'.format( len(not_unique))) for _item in not_unique: result['errmsg'].append( '{},{},{}和{},{},{}为重合站址'.format( _item[0].site_name, _item[0].lng, _item[0].lat, _item[1].site_name, _item[1].lng, _item[1].lat)) return result
def upload(self, request, **kwargs): result = { 'errmsg': [], } _workspace = WorkSpace.objects.get(**kwargs) # 获取文件并读取内容 file = request.FILES.get('file') df = myfuncs.read_csv(file) # 检查文件头信息 missing_cols 存储缺少的列 missing_cols = [] fields = Cell.get_upload_fields() cols = {field['verbose_name']: field['name'] for field in fields} for col in cols.keys(): if col not in df.columns: missing_cols.append(col) if missing_cols: result['errmsg'].append('导入文件缺少 "{}" 列'.format( '、'.join(missing_cols))) else: # 检查完毕, 表头正常 只需要模板列, 并将列头重命名为内部名 df = df[cols.keys()] df = df.rename(columns=cols) # 存储cell cells = [] # df.to_dict(orient='records') 将DataFrame转化成字典的列表 for _index, record in enumerate(df.to_dict(orient='records'), start=1): cell_form = CellForm(data=record) if cell_form.is_valid(): # 格式化经纬度 point = mymap.Point(record['lng'], record['lat']) _site = None try: # 查找已存在的站址数据 _site = Site.objects.get(workspace=_workspace, lng=point.lng, lat=point.lat) except Site.DoesNotExist: # 如果不存在则需要新建 site_name = get_site_name(record['cell_name']) _site = Site( workspace=_workspace, site_type=cell_form.cleaned_data['cell_type'], site_name=site_name, lng=point.lng, lat=point.lat, is_auto_created=True, ) _site.save() finally: cell = cell_form.save(commit=False) cell.workspace = _workspace cell.site = _site cells.append(cell) else: for key, value in cell_form.errors.items(): result['errmsg'].append('{}:{}'.format(key, value)) if not result['errmsg']: # 只有完全不窜在errmsg, 才进行批量的存储到数据库的操作 bulk_create() from django.db.utils import IntegrityError try: Cell.objects.bulk_create(cells) _workspace.save() except IntegrityError as e: # 存在冲突数据 result['errmsg'].append(str(e)) return result
def get_center(self): border = self.get_border() return mymap.Point((border['maxlng'] + border['minlng']) / 2, (border['maxlat'] + border['minlat']) / 2)