def cut_x(point_list, x): """ 截取x以右的线段 :param point_list: list[Point] :param x: thread x :return: new_point_list[Point] """ new_point_list = [] last_point = None cut = False for point in point_list: if point.px < x: pass elif not cut: if last_point is None: new_point_list.append(point) cut = True else: cur_seg = Segment(last_point, point) par = Segment(Point(x, 0), Point(x, 1)) _, px, py = get_cross_point(cur_seg, par) new_point_list.append(Point(px, py)) cut = True else: new_point_list.append(point) last_point = point return new_point_list
def get_parallel(segment_point0, segment_point1, d): """ 获取离线段距离为d的两条平行线段 :param segment_point0: 线段端点0, Point :param segment_point1: 线段端点1, Point :param d: 距离d :return: segment1(Segment), segment2, """ x0, y0 = segment_point0.px, segment_point0.py x1, y1 = segment_point1.px, segment_point1.py vec = np.array([x1 - x0, y1 - y0]) y = np.linalg.norm(vec) z = vec / y h0 = np.array([z[1], -z[0]]) # 右手边 h1 = np.array([-z[1], z[0]]) # 左手边 xh0, yh0 = x0 + h0[0] * d, y0 + h0[1] * d xh1, yh1 = x1 + h0[0] * d, y1 + h0[1] * d p0, p1 = Point(xh0, yh0), Point(xh1, yh1) segment0 = Segment(begin_point=p0, end_point=p1, name='') # segment0 = [[xh0, yh0], [xh1, yh1]] xh0, yh0 = x0 + h1[0] * d, y0 + h1[1] * d xh1, yh1 = x1 + h1[0] * d, y1 + h1[1] * d # segment1 = [[xh0, yh0], [xh1, yh1]] p0, p1 = Point(xh0, yh0), Point(xh1, yh1) segment1 = Segment(begin_point=p0, end_point=p1, name='') return segment0, segment1
def center_divide(road0, road1): bp0, ep0, bp1, ep1 = road0.point_list[0], road0.point_list[ -1], road1.point_list[0], road1.point_list[-1] if bp0 == bp1 or bp0 == ep1 or ep0 == bp1 or ep0 == ep1: return for i, seg0 in enumerate(road0.seg_list): for j, seg1 in enumerate(road1.seg_list): if calc_include_angle2( seg0, seg1) < math.sqrt(3) / 2 and is_segment_cross( seg0, seg1): _, px, py = get_cross_point(seg0, seg1) if px is None: print 'None' cr0 = Point(px, py) cr0.cross, cr0.cross_name, cr0.cross_other_seg = 1, road1.name, j cr0.cross_seg = i bp, ep = seg0.begin_point, seg0.end_point w0, w1 = get_dist(cr0, bp), get_dist(cr0, ep) if w0 > 1e-5 and w1 > 1e-5: road0.cross_list.append(cr0) cr1 = Point(px, py) cr1.cross, cr1.cross_name, cr1.cross_other_seg = 1, road0.name, i cr1.cross_seg = j bp, ep = seg1.begin_point, seg1.end_point w0, w1 = get_dist(cr1, bp), get_dist(cr1, ep) if w0 > 1e-5 and w1 > 1e-5: road1.cross_list.append(cr1) return
def load_sqlite_road(): """ 从sqlite3中读取路网 :return: list of Road """ conn = sqlite3.connect('./data/hz.db3') cursor = conn.cursor() cursor.execute( "select s_id, seq, longti, lati from tb_seg_point order by s_id, seq") xy_dict = {} for items in cursor: rid = int(items[0]) l, b = map(float, items[2:4]) l, b = wgs84togcj02(l, b) x, y = bl2xy(b, l) pt = Point(x, y) try: xy_dict[rid].append(pt) except KeyError: xy_dict[rid] = [pt] road_list = [] # cnt0, cnt1 = 0, 0 for rid, items in xy_dict.iteritems(): r = Road("", 0, rid) r.set_point_list(items) # cnt0 += len(r.point_list) road_list.append(r) road_simplify(r) # cnt1 += len(r.point_list) cursor.close() conn.close() return road_list
def center_cross(road0, road1): """ 检查道路与其他道路的交叉,并且合并交叉点 只有在道路尽头才会发生,因此和其他道路如有merge,应该不进行操作 :param road0: Road :param road1: Road :return: """ bp, ep = road0.point_list[0], road0.point_list[-1] min_dist = 1e10 sel_seg = None for seg in road1.seg_list: dist = point2segment2(bp, seg) if dist < min_dist: min_dist, sel_seg = dist, seg if min_dist < 50: if road0.bs == 1: return if is_segment_cross(road0.seg_list[0], sel_seg) or calc_include_angle2( road0.seg_list[0], sel_seg) > 0.8: return _, px, py = get_cross_point(road0.seg_list[0], sel_seg) new_point_list = [Point(px, py)] for pt in road0.point_list: new_point_list.append(pt) road0.set_point_list(new_point_list) road0.gene_segment() return min_dist = 1e10 sel_seg = None for seg in road1.seg_list: dist = point2segment2(ep, seg) if dist < min_dist: min_dist, sel_seg = dist, seg if min_dist < 50: if road0.es == 1: return if is_segment_cross(road0.seg_list[-1], sel_seg) or calc_include_angle2( road0.seg_list[-1], sel_seg) > 0.8: return _, px, py = get_cross_point(road0.seg_list[-1], sel_seg) road0.add_point(Point(px, py)) road0.gene_segment()
def par_cross(road0, road1): """ 类似par divide,但是要标记每个pt点的进出路口情况 :param road0: :param road1: :return: """ rid0, rid1 = road0.rid, road1.rid rbp0, rep0, rbp1, rep1 = road0.point_list[0], road0.point_list[ -1], road1.point_list[0], road1.point_list[-1] if rbp0 == rbp1 or rbp0 == rep1 or rep0 == rbp1 or rep0 == rep1: return for i, seg0 in enumerate(road0.seg_list): for j, seg1 in enumerate(road1.seg_list): if calc_include_angle2(seg0, seg1) > 0.8: # 平行 continue if is_segment_cross(seg0, seg1): d, px, py = get_cross_point(seg0, seg1) bp0, ep0 = seg0.begin_point, seg0.end_point bp1, ep1 = seg1.begin_point, seg1.end_point cr = Point(px, py) if bp0 == cr: if cr == rep1 or cr == rbp1: pass else: if d < 0: road0.point_list[i].cross = 1 else: road0.point_list[i].cross = 2 elif ep0 == cr: if cr == rep1 or cr == rbp1: pass else: if d < 0 and not (): road0.point_list[i + 1].cross = 1 else: road0.point_list[i + 1].cross = 2 if bp1 == cr: if cr == rep0 or cr == rbp0: pass else: if d < 0: road1.point_list[j].cross = 2 else: road1.point_list[j].cross = 1 elif ep1 == cr: if cr == rep0 or cr == rbp0: pass else: if d < 0: road1.point_list[j + 1].cross = 2 else: road1.point_list[j + 1].cross = 1 return
def cut_y(point_list, y): """ 截取y以下的线段 :param point_list: list[Point] :param y: thread y :return: new_point_list[Point] """ new_point_list = [] last_point = None for point in point_list: if point.py < y: new_point_list.append(point) else: cur_seg = Segment(last_point, point) par = Segment(Point(0, y), Point(1, y)) _, px, py = get_cross_point(cur_seg, par) new_point_list.append(Point(px, py)) break last_point = point return new_point_list
def point_project_segment(point, segment): """ :param point: Point :param segment: Segment :return: Point """ pt = [point.px, point.py] p0 = [segment.begin_point.px, segment.begin_point.py] p1 = [segment.end_point.px, segment.end_point.py] pt, _, _ = point_project(pt, p0, p1) return Point(pt[0], pt[1])
def point_project_segment(point, segment): """ :param point: Point :param segment: Segment :return: Point """ x, y = point.px, point.py x0, y0 = segment.begin_point.px, segment.begin_point.py x1, y1 = segment.end_point.px, segment.end_point.py pt, _, _ = point_project([x, y], [x0, y0], [x1, y1]) return Point(pt[0], pt[1])
def load_double_road(): conn = cx_Oracle.connect("hz/[email protected]/orcl") cursor = conn.cursor() cursor.execute( "select sp.s_id, sp.seq, sp.longti, sp.lati, s.s_name, s.direction, s.begin_id, s.end_id" ", s.length from tb_seg_point sp, tb_segment s where sp.s_id = s.s_id and s.rank = '快速路'" " order by sp.s_id, sp.seq") xy_dict = {} info_dict = defaultdict(list) road_name = {} for items in cursor: rid = int(items[0]) l, b = map(float, items[2:4]) l, b = wgs84togcj02(l, b) x, y = bl2xy(b, l) pt = Point(x, y) name = items[4] uname = name.decode('utf-8') road_name[rid] = uname # if name is not None: # name = name.decode('utf-8') if name != '艮山西路': continue direction = items[5] if direction == '3': continue bid, eid = items[6:8] length = items[8] if direction == '2': bid, eid = eid, bid try: xy_dict[rid].append(pt) except KeyError: xy_dict[rid] = [pt] rs = RoadSegment(rid, bid, eid, direction, name, length) info_dict[name].append(rs) # add rid rid_list = [] for name, road_list in info_dict.iteritems(): rid_list.extend(gene_one_road(road_list)) road_list = [] for road in rid_list: rid = road.rid pt_list = xy_dict[rid] new_road = Road(road_name[rid], 0, rid) new_road.set_point_list(pt_list) road_list.append(new_road) return road_list
def center_offset(road0, road1): """ 起点和终点偏移到路上 :param road0: Road 目标道路 :param road1: Road 待偏移到的道路 :return: """ # 当端点接近某路口时,需要偏移该端点,修正为路口 OFFSET_DIST = 1000 bp, ep = road0.point_list[0], road0.point_list[-1] for pt in road1.cross_list: dist = get_dist(pt, bp) if 1e-5 < dist < OFFSET_DIST: pt.cross = 0 if pt.cross_name == road0.name: # 说明与road0相交 pos = pt.cross_other_seg + 1 else: pos = 0 pt_list = [Point(pt.px, pt.py)] pt_list.extend(road0.point_list[pos:]) road0.set_point_list(pt_list) road0.gene_segment() return for pt in road1.cross_list: dist = get_dist(pt, ep) if 1e-5 < dist < OFFSET_DIST: pt.cross = 0 if pt.cross_name == road0.name: # 说明与road0相交 pos = pt.cross_other_seg + 1 else: pos = len(road0.point_list) pt_list = road0.point_list[:pos] pt_list.append(Point(pt.px, pt.py)) road0.set_point_list(pt_list) road0.gene_segment() # print road0.name, "end point fix to ", road1.name, pt.px, pt.py return
def load_oracle_road(): """ 从oracle中读取路网 :return: list of Road """ conn = cx_Oracle.connect("hz/[email protected]/orcl") cursor = conn.cursor() cursor.execute( "select sp.s_id, sp.seq, sp.longti, sp.lati, s.s_name, s.direction" " from tb_seg_point sp, tb_segment s " "where sp.s_id = s.s_id and (s.rank = '快速路' or s.rank = '高速公路' or s.s_name = '天目山路'" " or s.s_name = '艮山西路' or s.s_name = '文一路' or s.s_name = '文一西路')" " order by s_id, seq") xy_dict = {} road_name = {} for items in cursor: rid = int(items[0]) l, b = map(float, items[2:4]) l, b = wgs84togcj02(l, b) x, y = bl2xy(b, l) pt = Point(x, y) name = items[4] if name is not None: name = name.decode('utf-8') if name != u'艮山西路': continue direction = items[5] if direction != '3': continue road_name[rid] = name try: last_pt = xy_dict[rid][-1] if last_pt == pt: continue xy_dict[rid].append(pt) except KeyError: xy_dict[rid] = [pt] road_list = [] # cnt0, cnt1 = 0, 0 for rid, items in xy_dict.iteritems(): r = Road(road_name[rid], 0, rid) r.set_point_list(items) # cnt0 += len(r.point_list) road_list.append(r) # road_simplify(r) # cnt1 += len(r.point_list) cursor.close() conn.close() return road_list
def center_dup(road): """ 道路去重(一般在道路增加点后) :param road: Road :return: """ last_pt = Point(0, 0) new_pt_list = [] for pt in road.point_list: if pt == last_pt: continue new_pt_list.append(pt) last_pt = pt road.point_list = new_pt_list road.gene_segment()
def center_simplify(road): """ 简化 :param road: :return: """ pts = road.point_list xy_list = [] for pt in pts: xy_list.append([pt.px, pt.py]) xy_list = dog_last(xy_list) road.point_list = [] for xy in xy_list: pt = Point(xy[0], xy[1]) road.add_point(pt) road.gene_segment()
def cut_from_segment(segment, d): """ 从segment里面切开距离为d的线段 :param segment: Segment :param d: :return: segment0, segment1 """ x0, y0 = segment.begin_point.px, segment.begin_point.py x1, y1 = segment.end_point.px, segment.end_point.py vec = np.array([x1 - x0, y1 - y0]) y = np.linalg.norm(vec) z0 = vec / y # 单位向量 xd, yd = x0 + z0[0] * d, y0 + z0[1] * d cr = Point(xd, yd) s0 = Segment(segment.begin_point, cr) s1 = Segment(cr, segment.end_point) return s0, s1
def par_divide(road0, road1): """ as center divide, divide cross point for each other :param road0: :param road1: :return: """ bp0, ep0, bp1, ep1 = road0.point_list[0], road0.point_list[ -1], road1.point_list[0], road1.point_list[-1] if bp0 == bp1: road0.bs, road1.bs = 1, 1 return elif bp0 == ep1: road0.bs, road1.es = 1, 1 return elif ep0 == bp1: road0.es, road1.bs = 1, 1 return elif ep0 == ep1: road0.es, road1.es = 1, 1 return for i, seg0 in enumerate(road0.seg_list): for j, seg1 in enumerate(road1.seg_list): if calc_include_angle2(seg0, seg1) > 0.8: # 平行 continue if is_segment_cross(seg0, seg1): _, px, py = get_cross_point(seg0, seg1) cr0 = Point(px, py) cr0.cross, cr0.cross_name, cr0.cross_other_seg = 1, road1.rid, j cr0.cross_seg = i bp, ep = seg0.begin_point, seg0.end_point w0, w1 = get_dist(cr0, bp), get_dist(cr0, ep) if w0 > 1e-5 and w1 > 1e-5: road0.cross_list.append(cr0) cr1 = Point(px, py) cr1.cross, cr1.cross_name, cr1.cross_other_seg = 1, road0.rid, i cr1.cross_seg = j bp, ep = seg1.begin_point, seg1.end_point w0, w1 = get_dist(cr1, bp), get_dist(cr1, ep) if w0 > 1e-5 and w1 > 1e-5: road1.cross_list.append(cr1) return
def load_oracle_road(): """ 从原始做好的oracle路网中读取路网 :return: list of Road """ conn = cx_Oracle.connect("hz/[email protected]/orcl") cursor = conn.cursor() cursor.execute( "select sp.s_id, sp.seq, sp.longti, sp.lati, s.s_name, s.direction" " from tb_seg_point sp, tb_segment s " "where sp.s_id = s.s_id and s.rank != '次要道路' and s.rank != '连杆道路'" " order by s_id, seq") xy_dict = {} name_dic = {} # name dir_dict = {} # direction for items in cursor: rid = int(items[0]) l, b = map(float, items[2:4]) l, b = wgs84togcj02(l, b) x, y = bl2xy(b, l) pt = Point(x, y) name = items[4] ort = int(items[5]) try: xy_dict[rid].append(pt) except KeyError: xy_dict[rid] = [pt] name_dic[rid] = name dir_dict[rid] = ort road_list = [] # cnt0, cnt1 = 0, 0 for rid, items in xy_dict.iteritems(): ort = dir_dict[rid] if ort == 2: items.reverse() r = Road(name_dic[rid], ort, rid) r.set_point_list(items) # cnt0 += len(r.point_list) road_list.append(r) road_simplify(r) # cnt1 += len(r.point_list) cursor.close() conn.close() return road_list
def get_main_road(): conn = cx_Oracle.connect("hz/[email protected]/orcl") cursor = conn.cursor() sql = "select sp.s_id, sp.seq, sp.longti, sp.lati, s.s_name, s.direction " \ "from tb_segment s, tb_seg_point sp where sp.s_id = s.s_id and " \ "s.s_name like '%德胜%' and (s.rank = '快速路')" \ " order by s_id, seq" cursor.execute(sql) xy_dict = {} name_dic = {} # name dir_dict = {} # direction for items in cursor: rid = int(items[0]) l, b = map(float, items[2:4]) x, y = bl2xy(b, l) pt = Point(x, y) name = items[4] ort = int(items[5]) try: xy_dict[rid].append(pt) except KeyError: xy_dict[rid] = [pt] name_dic[rid] = name dir_dict[rid] = ort road_list = [] # cnt0, cnt1 = 0, 0 for rid, items in xy_dict.iteritems(): ort = dir_dict[rid] if ort == 2: items.reverse() r = Road(name_dic[rid], ort, rid) r.set_point_list(items) r.gene_segment() # cnt0 += len(r.point_list) road_list.append(r) conn.close() return road_list
def par_simplify(road): last_pt = None pt_list = [] # 先除去重复点 for pt in road.point_list: if last_pt is not None: dist = get_dist(last_pt, pt) if dist > 1e-5: pt_list.append(pt) else: pt_list.append(pt) last_pt = pt pts = road.point_list # 然后用doglas简化算法 xy_list = [] for pt in pts: xy_list.append([pt.px, pt.py]) xy_list = dog_last(xy_list) road.point_list = [] for xy in xy_list: pt = Point(xy[0], xy[1]) road.add_point(pt) road.gene_segment()
def par_merge(road0, road1): """ 一条线段的起点与另一条(平行线段)的终点相接 :param road0: :param road1: :return: road0, road1重新生成道路 """ THREAD = 10 bp0, ep0, bp1, ep1 = road0.point_list[0], road0.point_list[ -1], road1.point_list[0], road1.point_list[-1] try: if bp0 == ep1 or bp1 == ep0: return except TypeError: print 'par merge', road0.rid, road1.rid, 'TypeError' return # 在生成平行线后两条道路之间必然(除非是一直线上)有空隙或者交叉 # 这个THREAD值不能太大,否则和对向车道也能查找到一起 if get_dist(bp0, ep1) < THREAD: begin_seg, end_seg = road0.seg_list[0], road1.seg_list[-1] # 首先是平行 if calc_include_angle2(begin_seg, end_seg) <= 0.8: return if is_segment_cross(begin_seg, end_seg): # 相交时cut _, px, py = get_cross_point(begin_seg, end_seg) cr = Point(px, py) road0.point_list[0] = cr road1.point_list[-1] = cr road0.gene_segment() road1.gene_segment() else: # 不相交时延长 _, px, py = get_cross_point(begin_seg, end_seg) cr = Point(px, py) pt_list = [cr] pt_list.extend(road0.point_list) road0.point_list = pt_list road1.point_list.append(cr) road0.gene_segment() road1.gene_segment() elif get_dist(bp1, ep0) < THREAD: begin_seg, end_seg = road1.seg_list[0], road0.seg_list[-1] # 首先是平行 if calc_include_angle2(begin_seg, end_seg) <= 0.8: return if is_segment_cross(begin_seg, end_seg): # 相交时cut _, px, py = get_cross_point(begin_seg, end_seg) cr = Point(px, py) road1.point_list[0] = cr road0.point_list[-1] = cr road0.gene_segment() road1.gene_segment() else: # 不相交时延长 _, px, py = get_cross_point(begin_seg, end_seg) cr = Point(px, py) pt_list = [cr] pt_list.extend(road1.point_list) road1.point_list = pt_list road0.point_list.append(cr) road0.gene_segment() road1.gene_segment()
def par_offset(road0, road1): """ 边缘点的起点或终点从路中央偏移到路上 一定偏移到偶数序号的道路(中心线右手边) :param road0: Road 待修正的道路道路 :param road1: Road 偏移到的(与road0垂直)道路 :return: """ OFFSET = 80 if road1.rid & 1: return # 当端点接近某道路且该道路没有路口交点时,需要偏移该端点,延长至下一个道路 # 端点必须没有和其他线段相交 bp, ep = road0.point_list[0], road0.point_list[-1] # 首先是起点 min_dist = 1e10 sel_seg = None for seg in road1.seg_list: dist = point2segment2(bp, seg) if dist < min_dist: min_dist, sel_seg = dist, seg # 寻找延长至的道路线段 if min_dist < OFFSET: if road0.bs == 1: return min_dist = 1e10 for pt in road1.cross_list: dist = get_dist(pt, bp) min_dist = min(dist, min_dist) if min_dist > OFFSET: _, px, py = get_cross_point(sel_seg, road0.seg_list[0]) cr = Point(px, py) # 该延长线应落在预计道路sel_seg上 # 不然与其余道路有可能偏离在50米内 extended_segment = Segment(cr, bp) if not is_segment_cross(extended_segment, sel_seg): return pt_list = [cr] pt_list.extend(road0.point_list[:]) road0.set_point_list(pt_list) road0.gene_segment() return min_dist = 1e10 sel_seg = None for seg in road1.seg_list: dist = point2segment2(ep, seg) if dist < min_dist: min_dist, sel_seg = dist, seg if min_dist < OFFSET: if road0.es == 1: return min_dist = 1e10 for pt in road1.cross_list: dist = get_dist(pt, ep) min_dist = min(dist, min_dist) if min_dist > OFFSET: _, px, py = get_cross_point(sel_seg, road0.seg_list[-1]) cr = Point(px, py) extended_segment = Segment(cr, bp) if not is_segment_cross(extended_segment, sel_seg): return road0.point_list.append(cr) road0.gene_segment() return
def par(): PAR = 40 road_data = load_model2road('./road_new/center1.txt') par_road = [] # road_index = 0 for i, road in enumerate(road_data): name, point_list = road.name, road.point_list rid = road.rid last_pt = None road0, road1 = Road(name, 0, rid * 2), Road(name, 0, rid * 2 + 1) road0.set_grid_set(road.grid_set) road1.set_grid_set(road.grid_set) # road_index += 2 seg_list0, seg_list1 = [], [] for pt in point_list: if last_pt is not None: # 获取两条平移线段 seg0, seg1 = get_parallel(last_pt, pt, PAR) seg_list0.append(seg0) seg1.set_invert() seg_list1.append(seg1) last_pt = pt # 计算线段之间的交点 last_seg = None for j, seg in enumerate(seg_list0): if last_seg is None: road0.add_point(seg.begin_point) else: _, px, py = get_cross_point(last_seg, seg) if px is None: # 平行 road0.add_point(seg.begin_point) else: cp = Point(px, py) road0.add_point(cp) last_seg = seg road0.add_point(last_seg.end_point) last_seg = None for seg in reversed(seg_list1): if last_seg is None: road1.add_point(seg.begin_point) else: _, px, py = get_cross_point(last_seg, seg) if px is None: # 平行 road1.add_point(seg.begin_point) else: cp = Point(px, py) road1.add_point(cp) last_seg = seg road1.add_point(last_seg.end_point) # 并生成线段 road0.gene_segment() road1.gene_segment() par_road.append(road0) par_road.append(road1) # for test # save_par('./road/par_0.txt', par_road) # 端点处有merge的可能 for i, road0 in enumerate(par_road): for j, road1 in enumerate(par_road): if i < j and road_near(road0, road1): par_merge(road0, road1) # for road in par_road: # par_check(road) save_par('./road_new/par.txt', par_road)