def __init__(self, ): self.tool = ToolKit() self.house_floorplan_list = [] self.index_recombination = [4, 5, 6, 7, 0, 1, 2, 3] self.new_pts = [] self.new_height = [] self.new_height_limit = []
def __init__(self, ): self.threshold = 1e3 self.MAX_GRADIENT_VALUE = 90 self.floor_line_list = [] self.clockwise_line_list = [] self.floor_polygon_list = [] self.tool = ToolKit()
def __init__(self, ): self.house_splitted_dict = {} self.room_info_list = [] self.rest_room_info_list = [] self.room_delete_list = [] self.each_room_dict = {} self.tool = ToolKit()
def __init__(self, ): self.room_door_list = [] self.is_square = False self.tool = ToolKit() self.points_aligned_to_floor = PointAlignedToFloor() self.height_list = [] self.height_limit_list = []
def __init__(self): """init """ self.tool = ToolKit() self.maindoor_list = [] self.maindoor_height_min = 0 self.maindoor_height_max = 0 # whether the four points of the maindoor can form a rectangle self.is_square = False
class PointAlignedToFloor(object): """align point to floor, first two point on the floor """ def __init__(self,): self.tool = ToolKit() self.new_pts_list = [] def align_point_to_floor(self, pts_list, floor_list): """align operator Arguments: floor_list [x1,y1,x2,y2,...] -- floor list pts_list [[x1,y1],[x2,y2],...] -- point list Returns: point list -- [[x1,y1],[x2,y2],...] """ self.new_pts_list = [] for pts in pts_list: # sort, anticlockwise pts = self.tool.calculate_convexhull(pts) if len(pts) > 4: pts = self.six_to_four(pts) pts = self.tool.calculate_convexhull(pts) is_found = False dis_all_list = [] sum_dis_list = [] new_pts = [] for floor_line in floor_list: is_collinear_list = [] dis_list = [] first_two_point_dis = 0 for pts_point in pts: is_collinear, dis = self.tool.is_collinear_three_points(floor_line[0], floor_line[1], pts_point) is_collinear_list.append(is_collinear) dis_list.append(dis) # compute sum of the smallest two dis smallest_num = heapq.nsmallest(2, dis_list) first_two_point_dis = smallest_num[0] + smallest_num[1] sum_dis_list.append(first_two_point_dis) dis_all_list.append(dis_list) if is_collinear_list.count(True) == 2: is_found = True new_pts = self.reorder_point_normal(pts, is_collinear_list) if len(new_pts) == 0: logger.e('find first two closest point error ...') break elif len(new_pts) > 0: self.new_pts_list.append(new_pts) break if not is_found: new_pts = self.reorder_point_abnormal(pts, dis_all_list, sum_dis_list) if len(new_pts) == 0: new_floor_list = [] for floor_line in floor_list: new_floor_list.append(floor_line[0]) floor_poly = Polygon(self.tool.list_to_tuple(new_floor_list)) new_pts = self.reorder_point_dysmorphism(pts, floor_poly) if len(new_pts) == 0: logger.e('find first two closest point error ...') continue else: self.new_pts_list.append(new_pts) if len(self.new_pts_list) != len(pts_list): logger.w('lost object') if len(self.new_pts_list) > 0: return True else: return False def reorder_point_dysmorphism(self, pts, floor_poly): dis_to_polyg_list = [] for point in pts: if floor_poly.contains(Point(point)): dis_to_polyg_list.append(0.) else: dis_to_polyg_list.append(floor_poly.boundary.distance(Point(point))) index_list = self.find_nsmallest_num(dis_to_polyg_list, 2) if index_list == [0, 1] or index_list == [1, 0]: return [pts[1], pts[0], pts[3], pts[2]] elif index_list == [1, 2] or index_list == [2, 1]: return [pts[2], pts[1], pts[0], pts[3]] elif index_list == [2, 3] or index_list == [3, 2]: return [pts[3], pts[2], pts[1], pts[0]] elif index_list == [0, 3] or index_list == [3, 0]: return [pts[0], pts[3], pts[2], pts[1]] else: return [] def reorder_point_abnormal(self, pts, dis_all_list, sum_dis_list): small_index = sum_dis_list.index(min(sum_dis_list)) dis_select = dis_all_list[small_index] smallest_two_dis = heapq.nsmallest(2, dis_select) index_list = [] if smallest_two_dis[0] == smallest_two_dis[1]: index_list = [i for i, v in enumerate(dis_select) if v == smallest_two_dis[0]] else: index_list = [dis_select.index(smallest_two_dis[0]), dis_select.index(smallest_two_dis[1])] if index_list == [0, 1] or index_list == [1, 0]: return [pts[1], pts[0], pts[3], pts[2]] elif index_list == [1, 2] or index_list == [2, 1]: return [pts[2], pts[1], pts[0], pts[3]] elif index_list == [2, 3] or index_list == [3, 2]: return [pts[3], pts[2], pts[1], pts[0]] elif index_list == [0, 3] or index_list == [3, 0]: return [pts[0], pts[3], pts[2], pts[1]] else: return [] def reorder_point_normal(self, pts, is_collinear_list): """reorder point, if len(is_collinear_list) == 2 Arguments: pts -- door/hole point(four) is_collinear_list -- is collinear flag Returns: door/hole list -- clockwise point, the first two point in floor """ if is_collinear_list == [True, True, False, False]: return [pts[1], pts[0], pts[3], pts[2]] elif is_collinear_list == [False, True, True, False]: return [pts[2], pts[1], pts[0], pts[3]] elif is_collinear_list == [False, False, True, True]: return [pts[3], pts[2], pts[1], pts[0]] elif is_collinear_list == [True, False, False, True]: return [pts[0], pts[3], pts[2], pts[1]] else: return [] def six_to_four(self, six_pts_list): points_num = len(six_pts_list) x_list = [] z_list = [] for pts in six_pts_list: x_list.append(pts[0]) z_list.append(pts[1]) center_point = [sum(x_list)/points_num, sum(z_list)/points_num] dis_list = [] for pts in six_pts_list: dis_list.append(self.tool.compute_distance(center_point, pts)) max_4_index_list = self.find_nlargest_num(dis_list, 4) new_pts_list = [] for idx in max_4_index_list: if six_pts_list[idx] not in new_pts_list: new_pts_list.append(six_pts_list[idx]) return new_pts_list def find_nsmallest_num(self, pts_list, n): tmp = [] for i in range(n): tmp.append(pts_list.index(min(pts_list))) pts_list[pts_list.index(min(pts_list))] = n tmp.sort() return tmp def find_nlargest_num(self, pts_list, n): tmp = [] for i in range(n): tmp.append(pts_list.index(max(pts_list))) pts_list[pts_list.index(max(pts_list))] = 0 tmp.sort() return tmp
def __init__(self,): self.tool = ToolKit() self.new_pts_list = []
class FloorTool(object): def __init__(self, ): self.threshold = 1e3 self.MAX_GRADIENT_VALUE = 90 self.floor_line_list = [] self.clockwise_line_list = [] self.floor_polygon_list = [] self.tool = ToolKit() def connect_line_clockwise(self, line_list): """converse floor line in clockwise Arguments: line_list {no order} -- a list of line Returns: [x1, y1, x2, y2, ... ] -- a list of clockwise line """ self.clockwise_line_list = [] self.floor_polygon_list = [] # duplicate overlap line self.floor_line_list = self.deplicate_overlap(line_list) while len(self.floor_line_list) > 0: floor_polygon = self.generate_floor_polygon() if len(floor_polygon) > 0: if floor_polygon[0][0] == floor_polygon[-1][1]: self.floor_polygon_list.append(floor_polygon) else: continue else: break if len(self.floor_polygon_list) > 0: self.clockwise_line_list = self.find_union_polygons() if len(self.clockwise_line_list) > 0: return True else: return False def deplicate_overlap(self, line_list): angle_list = [] for line in line_list: angle = abs(self.tool.comp_line_angle(line)) if angle == 180: angle = 0 if angle == 270: angle = 90 angle_list.append(angle) angle_idx_dict = {} for i, angle in enumerate(angle_list): if angle not in angle_idx_dict.keys(): angle_idx_dict[angle] = [i] else: angle_idx_dict[angle].append(i) clear_line_list = [] for angle, idx_list in angle_idx_dict.items(): collinear_line_list = [] if len(idx_list) > 1: while len(idx_list) > 1: first_line = line_list[idx_list[0]] tmp_collinear_line_list = [] tmp_collinear_line_list.append(first_line) idx_del_list = [] idx_del_list.append(idx_list[0]) for i, idx in enumerate(idx_list): if i > 0: line_idx = line_list[idx] tmp_angle1 = self.tool.comp_line_angle( [line_idx[0], first_line[0]]) tmp_angle2 = self.tool.comp_line_angle( [line_idx[1], first_line[0]]) tmp_angle1 = self.angle_transfer(tmp_angle1) tmp_angle2 = self.angle_transfer(tmp_angle2) if tmp_angle1 != 0 and tmp_angle2 != 0: tmp_angle = 0.5 * (tmp_angle1 + tmp_angle2) elif tmp_angle1 == 0 and tmp_angle2 != 0: tmp_angle = tmp_angle2 elif tmp_angle1 != 0 and tmp_angle2 == 0: tmp_angle = tmp_angle1 else: tmp_angle = 0 tmp_angle = self.angle_transfer(tmp_angle) if tmp_angle == angle: tmp_collinear_line_list.append(line_idx) idx_del_list.append(idx) else: continue if len(tmp_collinear_line_list) > 1: collinear_line_list.append(tmp_collinear_line_list) for idx_del in idx_del_list: idx_list.remove(idx_del) if len(collinear_line_list) > 0: clear_line_list.append(collinear_line_list) del_line_list = [] add_line_list = [] if len(clear_line_list) > 0: for clear_line_4 in clear_line_list: for clear_line_3 in clear_line_4: x_point_list = [] y_point_list = [] for line in clear_line_3: del_line_list.append(line) x_point_list.append(line[0][0]) x_point_list.append(line[1][0]) y_point_list.append(line[0][1]) y_point_list.append(line[1][1]) sorted_point_list = [ list(item) for item in zip(np.sort(x_point_list), np.sort(y_point_list)) ] new_point_list = [] for point in sorted_point_list: if point not in new_point_list: new_point_list.append(point) sorted_line_list = [] for i in range(len(new_point_list) - 1): sorted_line_list.append( [new_point_list[i], new_point_list[i + 1]]) sorted_line_dict = {} for i, sorted_line in enumerate(sorted_line_list): sorted_line_dict[i] = 0 occur_num = 0 for line in clear_line_3: if self.tool.is_on_line( line[0], line[1], sorted_line[0]) and self.tool.is_on_line( line[0], line[1], sorted_line[1]): occur_num += 1 sorted_line_dict[i] = occur_num for index, num in sorted_line_dict.items(): if num == 1: add_line_list.append(sorted_line_list[index]) for del_line in del_line_list: line_list.remove(del_line) for add_line in add_line_list: line_list.append(add_line) return line_list def angle_transfer(self, angle): if angle == 180: angle = 0 if angle == 270 or angle == -90: angle = 90 return angle def clear_line(self, line1, line2): if line1[0] in line2: line2_rest_point = line2[1 - line2.index(line1[0])] angle1 = self.tool.comp_line_angle([line1[1], line2_rest_point]) angle2 = self.tool.comp_line_angle([line1[1], line1[0]]) if (angle1 + angle2) == 0 and angle1 != angle2: return [line1[1], line2_rest_point] if line1[1] in line2: line2_rest_point = line2[1 - line2.index(line1[1])] angle1 = self.tool.comp_line_angle([line1[0], line2_rest_point]) angle2 = self.tool.comp_line_angle([line1[0], line1[1]]) if (angle1 + angle2) == 0 and angle1 != angle2: return [line1[0], line2_rest_point] return [] def find_union_polygons(self): union_floor_line_list = [] if len(self.floor_polygon_list) == 1: return [self.floor_polygon_list[0]] else: multi_polygon = [] for floor_polygon in self.floor_polygon_list: polygon_one = [] for line in floor_polygon: polygon_one.append((line[0][0], line[0][1])) polygon_one = Polygon(polygon_one) if polygon_one.length < 1 or polygon_one.area < 1: continue # print ('polygon_one: ', polygon_one) multi_polygon.append(polygon_one) # print ('multi_polygon: ', multi_polygon) union_polygon = cascaded_union(multi_polygon) multi_polygon = union_polygon if multi_polygon.is_empty: return [] # union_floor_line_list = mapping(multi_polygon)['coordinates'][0] union_polygon_list = mapping(multi_polygon)['coordinates'] union_polygon_dim = np.ndim(union_polygon_list) floor_poly_list = [] if union_polygon_dim == 3: self.floor_line_list = [] union_floor_line_list = union_polygon_list[0] for i in range(len(union_floor_line_list) - 1): line = [[ union_floor_line_list[i][0], union_floor_line_list[i][1] ], [ union_floor_line_list[i + 1][0], union_floor_line_list[i + 1][1] ]] self.floor_line_list.append(line) floor_poly_list.append(self.generate_floor_polygon()) return floor_poly_list else: for union_poly in union_polygon_list: self.floor_line_list = [] union_floor_line_list = union_poly[0] for i in range(len(union_floor_line_list) - 1): line = [[ union_floor_line_list[i][0], union_floor_line_list[i][1] ], [ union_floor_line_list[i + 1][0], union_floor_line_list[i + 1][1] ]] self.floor_line_list.append(line) floor_poly_list.append(self.generate_floor_polygon()) return floor_poly_list def generate_floor_polygon(self): floor_polygon = [] start_line = self.find_start_line(self.floor_line_list) if len(start_line) == 0: return [] floor_polygon.append(start_line) if start_line in self.floor_line_list: self.floor_line_list.remove(start_line) start_line_reverse = [start_line[1], start_line[0]] if start_line_reverse in self.floor_line_list: self.floor_line_list.remove(start_line_reverse) while len(self.floor_line_list) > 0: next_line = self.find_next_line(start_line, self.floor_line_list) if len(next_line) > 0: floor_polygon.append(next_line) start_line = next_line if len(next_line) == 0: return floor_polygon return floor_polygon def find_next_line(self, start_line, line_list): next_line = [] for line in line_list: if line[0] == start_line[1]: next_line = line break elif line[1] == start_line[1]: next_line = [line[1], line[0]] break if len(next_line) == 0: return [] else: if line in self.floor_line_list: self.floor_line_list.remove(line) if next_line in self.floor_line_list: self.floor_line_list.remove(next_line) return next_line def find_start_line(self, line_list): """find start line, for sorted line in clockwise Arguments: line_list -- input line list Returns: [x1, y1] -- the top line """ start_line = [] # find top point top_point = self.find_top_point(line_list) # find two line through the top point two_top_line = [] angles_two_top_line = [] for line in line_list: if line[0] == top_point or line[1] == top_point: angles_two_top_line.append(self.tool.comp_line_angle(line)) two_top_line.append(line) if len(two_top_line) == 2: break if len(angles_two_top_line) == 0: return [] # find the not vertical line top_line_not_vertical = [] for i, angle in enumerate(angles_two_top_line): if angle != 90 and angle != -90: top_line_not_vertical = two_top_line[i] break if len(top_line_not_vertical) == 0: return [] # line clockwise if top_line_not_vertical[0][0] > top_line_not_vertical[1][0]: start_line = [top_line_not_vertical[1], top_line_not_vertical[0]] else: start_line = top_line_not_vertical return start_line def find_top_point(self, line_list): """find the top point Returns: [x1, y1] -- coordinate of one of top point """ top_point = [] # find the top line, one x_list = [] z_list = [] for line in line_list: x_list.append(line[0][0]) x_list.append(line[1][0]) z_list.append(line[0][1]) z_list.append(line[1][1]) max_z = max(z_list) # num_max_z = z_list.count(max_z) index_max_z = z_list.index(max_z) top_point = [x_list[index_max_z], z_list[index_max_z]] return top_point
class BaywindowGenerator(object): def __init__(self, ): self.tool = ToolKit() self.baywindow_list = [] self.baywindow_height = [] self.baywindow_height_limit = [] def generate_baywindow(self, baywindow_mesh_list, floor_list, room_area): self.baywindow_height = [] self.baywindow_height_limit = [] if len(baywindow_mesh_list) == 0: return False xz_list = [] y_list = [] xz_single_list = [] for baywindow_mesh in baywindow_mesh_list: baywindow_xyz = baywindow_mesh['xyz'] for i in range(len(baywindow_xyz) // 3): xz_coordinate = [ float(baywindow_xyz[3 * i]), float(baywindow_xyz[3 * i + 2]) ] y_coorinate = float(baywindow_xyz[3 * i + 1]) if xz_coordinate not in xz_list: xz_list.append(xz_coordinate) if y_coorinate not in y_list: y_list.append(y_coorinate) self.baywindow_height = min(y_list) self.baywindow_height_limit = max(y_list) xz_convexhull_list = self.tool.calculate_convexhull(xz_list) for xz in xz_list: xz_single_list.append(xz[0]) xz_single_list.append(xz[1]) baywindow_area = self.tool.comp_area(xz_single_list) xz_polygon_list = Polygon(self.tool.list_to_tuple(xz_convexhull_list)) floor_polygon_line = [] for i in range(len(floor_list)): floor_polygon_line.append([ (floor_list[i][0][0], floor_list[i][0][1]), (floor_list[i][1][0], floor_list[i][1][1]) ]) line_in_floor_list = self.find_line_in_floor(xz_polygon_list, floor_polygon_line) floor_polygon_list = [] for floor_line in floor_list: floor_polygon_list.append((floor_line[0])) floor_polygon_list = Polygon( self.tool.list_to_tuple(floor_polygon_list)) # region_difference = xz_polygon_list.difference(floor_polygon_list) # line_in_floor_list = self.find_line_in_floor(region_difference, floor_polygon_list) # print ('line_in_floor_list: ', line_in_floor_list) # difference_polygon_list = self.find_difference_polygon(region_difference) line_out_floor_list = [] for line_in_floor in line_in_floor_list: gap = 0.5 out_floor_line_list_05 = [] out_floor_line_list_05, dis_two_list = self.generate_out_floor_line( gap, line_in_floor, floor_polygon_list) line_out_floor_list.append( out_floor_line_list_05[dis_two_list.index(max(dis_two_list))]) self.baywindow_list = self.clockwise_baywindow(line_in_floor_list, line_out_floor_list) if len(self.baywindow_list) > 0: return True else: return False def clockwise_baywindow(self, line_in_floor_list, line_out_floor_list): baywindow_list = [] for i, line_in_floor in enumerate(line_in_floor_list): baywindow = [] # anticlockwise baywindow_convexhull = self.tool.calculate_convexhull([ line_in_floor[0], line_in_floor[1], line_out_floor_list[i][0], line_out_floor_list[i][1] ]) index = [] for in_floor_pts in line_in_floor: for i, pts in enumerate(baywindow_convexhull): if pts == [in_floor_pts[0], in_floor_pts[1]]: index.append(i) if index == [0, 1] or index == [1, 0]: baywindow = [ baywindow_convexhull[1][0], baywindow_convexhull[1][1], baywindow_convexhull[0][0], baywindow_convexhull[0][1], baywindow_convexhull[3][0], baywindow_convexhull[3][1], baywindow_convexhull[2][0], baywindow_convexhull[2][1] ] if index == [1, 2] or index == [2, 1]: baywindow = [ baywindow_convexhull[2][0], baywindow_convexhull[2][1], baywindow_convexhull[1][0], baywindow_convexhull[1][1], baywindow_convexhull[0][0], baywindow_convexhull[0][1], baywindow_convexhull[3][0], baywindow_convexhull[3][1] ] if index == [2, 3] or index == [3, 2]: baywindow = [ baywindow_convexhull[3][0], baywindow_convexhull[3][1], baywindow_convexhull[2][0], baywindow_convexhull[2][1], baywindow_convexhull[1][0], baywindow_convexhull[1][1], baywindow_convexhull[0][0], baywindow_convexhull[0][1] ] if index == [0, 3] or index == [3, 0]: baywindow = [ baywindow_convexhull[0][0], baywindow_convexhull[0][1], baywindow_convexhull[3][0], baywindow_convexhull[3][1], baywindow_convexhull[2][0], baywindow_convexhull[2][1], baywindow_convexhull[1][0], baywindow_convexhull[1][1] ] baywindow_list.append(baywindow) return baywindow_list def generate_out_floor_line(self, gap, line_in_floor, floor_polygon_list): out_floor_line_list = self.tool.find_parallel_line(line_in_floor, gap) dis_two_list = [] for line in out_floor_line_list: dis_list = [] for point in line: if floor_polygon_list.contains(Point(point)): dis_pt_poly = 0 continue dis_pt_poly = self.is_in_polygon(Point(point), floor_polygon_list) dis_list.append(dis_pt_poly) dis_two_list.append(sum(dis_list)) return out_floor_line_list, dis_two_list def is_in_polygon(self, pts, polygon_data): return polygon_data.boundary.distance(pts) def find_difference_polygon(self, region_difference): coordinates_region_difference = mapping( region_difference)['coordinates'] region_dimension = np.ndim(coordinates_region_difference) difference_polygon_list = [] if region_dimension == 3: tmp_polygon_list = [] for polygon_list in coordinates_region_difference[0]: tmp_polygon_list.append([polygon_list[0], polygon_list[1]]) difference_polygon_list.append(tmp_polygon_list) if region_dimension == 4: for region_polygon in coordinates_region_difference: tmp_polygon_list = [] for polygon_list in region_polygon[0]: tmp_polygon_list.append([polygon_list[0], polygon_list[1]]) difference_polygon_list.append(tmp_polygon_list) return difference_polygon_list def find_line_in_floor(self, xz_polygon_list, floor_polygon_list): line_in_floor_list = [] for floor_line in floor_polygon_list: line = LineString(floor_line) # ips = line.intersection(xz_polygon_list) ips = xz_polygon_list.intersection(line) if not ips.is_empty: res = mapping(ips)['coordinates'] if np.array(res).size == 4: line_in_floor_list.append(res) return line_in_floor_list
def __init__(self, ): self.tool = ToolKit() self.baywindow_list = [] self.baywindow_height = [] self.baywindow_height_limit = []
def __init__(self,): self.room_floor_list = [] self.clockwise_line_list = [] self.tool = ToolKit() self.floor_tool = FloorTool()
class DoorGenerator(object): def __init__(self, ): self.room_door_list = [] self.is_square = False self.tool = ToolKit() self.points_aligned_to_floor = PointAlignedToFloor() self.height_list = [] self.height_limit_list = [] # self.height_ori_list = [] def generate_door(self, door_mesh_list, floor_list): """generate all doors Arguments: door_mesh_list -- mesh list floor_list -- floor list Returns: bool -- True or False """ self.room_door_list = [] xz_less_four_points_list = [] self.height_list = [] self.height_limit_list = [] if len(door_mesh_list) == 0: return False # one mesh one door for door_mesh in door_mesh_list: xyz_list = door_mesh['xyz'] y_list = [] xz_list = [] for i in range(len(xyz_list) // 3): xz_coordinate = [ round(float(xyz_list[3 * i]), 3), round(float(xyz_list[3 * i + 2]), 3) ] y_list.append(float(xyz_list[3 * i + 1])) if xz_coordinate not in xz_list: xz_list.append(xz_coordinate) # if len(xz_list) < 4: xz_less_four_points_list.append(xz_list) else: self.room_door_list.append( self.tool.calculate_convexhull(xz_list)) # height if len(y_list) > 0: self.height_list.append(min(y_list)) self.height_limit_list.append(max(y_list)) # input() # deduplication self.room_door_list, self.height_list, self.height_limit_list = self.tool.point_deduplication( self.room_door_list, self.height_list, self.height_limit_list) self.room_door_list, self.height_list, self.height_limit_list = self.tool.eight_points_deduplication( self.room_door_list, self.height_list, self.height_limit_list) align_before_num = len(self.room_door_list) # the points on the door aligned to the floor if self.points_aligned_to_floor.align_point_to_floor( self.room_door_list, floor_list): self.room_door_list = self.points_aligned_to_floor.new_pts_list else: self.room_door_list = [] align_after_num = len(self.room_door_list) if align_after_num == 0: return False if align_after_num < align_before_num: logger.w('door is getting less') new_room_door_list = [] for room_door in self.room_door_list: if not self.tool.is_square(room_door): # self.room_door_list = [] # return False continue new_room_door_list.append([ room_door[0][0], room_door[0][1], room_door[1][0], room_door[1][1], room_door[2][0], room_door[2][1], room_door[3][0], room_door[3][1] ]) self.room_door_list = new_room_door_list if len(self.room_door_list) > 0: return True else: return False
def __init__(self, ): self.at_house_info_dict = [] self.tool = ToolKit()
class ConnectInfoGenerator(object): def __init__(self, ): self.tool = ToolKit() self.house_floorplan_list = [] self.index_recombination = [4, 5, 6, 7, 0, 1, 2, 3] self.new_pts = [] self.new_height = [] self.new_height_limit = [] # self.draw_room = VisHouse() def generate_connect_info(self, house_info_list): self.new_pts = [] self.new_height = 0 self.new_height_limit = 0 for i, room_info in enumerate(house_info_list): room_floor_list = room_info['floor'] for j, room_info_other in enumerate(house_info_list): if i != j: other_door_list = room_info_other['door'] other_hole_list = room_info_other['hole'] other_window_list = room_info_other['window'] other_door_height_list = room_info_other['door_height'] other_hole_height_list = room_info_other['hole_height'] other_window_height_list = room_info_other['window_height'] other_door_height_limit_list = room_info_other[ 'door_height_limit'] other_hole_height_limit_list = room_info_other[ 'hole_height_limit'] other_window_height_limit_list = room_info_other[ 'window_height_limit'] # doorinfo if len(other_door_list) > 0: for k, other_door in enumerate(other_door_list): if self.is_belong_this_room( other_door, room_floor_list, other_door_height_list[k], other_door_height_limit_list[k]): room_info['door'].append(self.new_pts) room_info['door_height'].append( self.new_height) room_info['door_height_limit'].append( self.new_height_limit) # holeinfo if len(other_hole_list) > 0: for k, other_hole in enumerate(other_hole_list): if self.is_belong_this_room( other_hole, room_floor_list, other_hole_height_list[k], other_hole_height_limit_list[k]): room_info['hole'].append(self.new_pts) room_info['hole_height'].append( self.new_height) room_info['hole_height_limit'].append( self.new_height_limit) # windowinfo if len(other_window_list) > 0: for k, other_window in enumerate(other_window_list): if self.is_belong_this_room( other_window, room_floor_list, other_window_height_list[k], other_window_height_limit_list[k]): room_info['window'].append(self.new_pts) room_info['window_height'].append( self.new_height) room_info['window_height_limit'].append( self.new_height_limit) # remove duplicate information room_info['door'], room_info['door_height'], room_info[ 'door_height_limit'] = self.remove_duplicate( room_info['door'], room_info['door_height'], room_info['door_height_limit']) room_info['hole'], room_info['hole_height'], room_info[ 'hole_height_limit'] = self.remove_duplicate( room_info['hole'], room_info['hole_height'], room_info['hole_height_limit']) room_info['window'], room_info['window_height'], room_info[ 'window_height_limit'] = self.remove_duplicate( room_info['window'], room_info['window_height'], room_info['window_height_limit']) # print ('room-type: ', room_info['room']) # self.draw_room.draw_room(room_info) # add connect information house_info_list = self.compute_connect_relationship(house_info_list) return house_info_list def compute_connect_relationship(self, house_info_list): for i, room_info in enumerate(house_info_list): # doorinfo room_info['doorinfo'] = self.add_connect_info( i, room_info, house_info_list, 'door') # holeinfo room_info['holeinfo'] = self.add_connect_info( i, room_info, house_info_list, 'hole') # windowinfo room_info['windowinfo'] = self.add_connect_info( i, room_info, house_info_list, 'window') return house_info_list def add_connect_info(self, idx, room_info, house_info_list, type_='door'): obj_info_list = [] if len(room_info[type_]) > 0: for obj_ in room_info[type_]: obj_info_dict = {} for jdx, other_room_info in enumerate(house_info_list): if idx != jdx: if self.is_appeared(obj_, other_room_info[type_]): obj_info_dict['pts'] = obj_ obj_info_dict['to'] = other_room_info['room'] obj_info_list.append(obj_info_dict) return obj_info_list def is_appeared(self, pts, other_pts_list): one_pts = [pts[0], pts[1], pts[2], pts[3]] for other_pts in other_pts_list: another_pts = [ other_pts[4], other_pts[5], other_pts[6], other_pts[7] ] if one_pts == another_pts: return True return False def remove_duplicate(self, v_list, height_list, height_limit_list): new_v_list = [] new_height_list = [] new_height_limit_list = [] for i, v in enumerate(v_list): if v not in new_v_list: new_v_list.append(v) new_height_list.append(height_list[i]) new_height_limit_list.append(height_limit_list[i]) return new_v_list, new_height_list, new_height_limit_list def is_belong_this_room(self, pts, room_floor_list, height, height_limit): self.new_pts = [] self.new_height = 0 self.new_height_limit = 0 pts_parallel_line_list = self.tool.find_parallel_line( [[pts[4], pts[5]], [pts[6], pts[7]]], 0.1) floor_polygon = self.tool.floor_to_polygon(room_floor_list).buffer( 0.0005) for line in pts_parallel_line_list: for point in line: if floor_polygon.contains(Point(point)): for idx in self.index_recombination: self.new_pts.append(pts[idx]) self.new_height = height self.new_height_limit = height_limit return True return False
class HouseSplitter(object): def __init__(self, ): self.house_splitted_dict = {} self.room_info_list = [] self.rest_room_info_list = [] self.room_delete_list = [] self.each_room_dict = {} self.tool = ToolKit() def split_house(self, house_info_dict): # self.house_info = house_info_dict # single # only find entrydoor entry_room = house_info_dict['maindoor'][0] floorplan = house_info_dict['floorplan'] # print ('entry_room: ', entry_room) self.room_delete_list = [] self.each_room_dict = {} # find entry-room for i, room_info in enumerate(floorplan): if len(room_info['door']) == 0 and len(room_info['hole']) == 0: self.room_delete_list.append(i) if room_info['room'] == entry_room['room']: self.each_room_dict['maindoor'] = [entry_room] self.each_room_dict['floorplan'] = [room_info] self.room_info_list.append(self.each_room_dict) self.room_delete_list.append(i) # delete entry-room self.rest_room_info_list = self.delete_room(self.room_delete_list, floorplan) self.room_delete_list = [] pre_door_list = self.each_room_dict['floorplan'][0]['door'] pre_hole_list = self.each_room_dict['floorplan'][0]['hole'] pre_doorhole_list = [] if len(pre_door_list) > 0: for door in pre_door_list: pre_doorhole_list.append(door) if len(pre_hole_list) > 0: for hole in pre_hole_list: pre_doorhole_list.append(hole) # self.rest_room_info_list while len(self.rest_room_info_list) > 0: new_doorhole_list = [] new_doorhole_list = self.split_room(pre_doorhole_list) pre_doorhole_list = new_doorhole_list if len(new_doorhole_list) == 0: # stairwell break # pass # self.house_splitted_dict['rooms'] = self.room_info_list self.house_splitted_dict = self.room_info_list if len(self.room_info_list) > 0: return True else: return False def split_room(self, pre_doorhole_list): new_doorhole_list = [] self.room_delete_list = [] if len(pre_doorhole_list) > 0 and len(self.rest_room_info_list) > 0: for i, room_info in enumerate(self.rest_room_info_list): door_list = room_info['door'] hole_list = room_info['hole'] door_height_list = room_info['door_height'] door_height_limit_list = room_info['door_height_limit'] hole_height_list = room_info['hole_height'] hole_height_limit_list = room_info['hole_height_limit'] # delete door if len(door_list) > 0: for x, door in enumerate(door_list): if self.is_appeared(door, pre_doorhole_list): next_doorhole = self.find_next_room(room_info) if len(next_doorhole) > 0: for pts in next_doorhole: new_doorhole_list.append(pts) maindoor_dict = {} maindoor_dict['room'] = room_info['room'] maindoor_dict['point'] = door angle, direction = self.tool.compute_door_hole_direction( door) maindoor_dict['angle'] = angle maindoor_dict['direction'] = direction maindoor_dict['height'] = door_height_list[x] maindoor_dict[ 'height_limit'] = door_height_limit_list[x] self.each_room_dict = {} self.each_room_dict['maindoor'] = [maindoor_dict] self.each_room_dict['floorplan'] = [room_info] self.room_info_list.append(self.each_room_dict) self.room_delete_list.append(i) # delete hole if len(hole_list) > 0: for x, hole in enumerate(hole_list): if self.is_appeared(hole, pre_doorhole_list): next_doorhole = self.find_next_room(room_info) if len(next_doorhole) > 0: for pts in next_doorhole: new_doorhole_list.append(pts) maindoor_dict = {} maindoor_dict['room'] = room_info['room'] maindoor_dict['point'] = hole angle, direction = self.tool.compute_door_hole_direction( hole) maindoor_dict['angle'] = angle maindoor_dict['direction'] = direction maindoor_dict['height'] = hole_height_list[x] maindoor_dict[ 'height_limit'] = hole_height_limit_list[x] self.each_room_dict = {} self.each_room_dict['maindoor'] = [maindoor_dict] self.each_room_dict['floorplan'] = [room_info] self.room_info_list.append(self.each_room_dict) self.room_delete_list.append(i) if len(self.room_delete_list) > 0: self.rest_room_info_list = self.delete_room( self.room_delete_list, self.rest_room_info_list) return new_doorhole_list def find_next_room(self, room_info): doorhole_info = [] if len(room_info['door']) > 0: for door in room_info['door']: doorhole_info.append(door) if len(room_info['hole']) > 0: for hole in room_info['hole']: doorhole_info.append(hole) return doorhole_info def is_appeared(self, obj_pts, pts_list): obj_coordnite = [obj_pts[0], obj_pts[1], obj_pts[2], obj_pts[3]] for ori_pts in pts_list: if [ori_pts[4], ori_pts[5], ori_pts[6], ori_pts[7]] == obj_coordnite: return True return False def delete_room(self, delete_list, floorplan): del_reverse_list = sorted(set(delete_list), reverse=True) for idx in del_reverse_list: floorplan.pop(idx) return floorplan
class MainDoorGenerator(object): """maindoor generator Arguments: maindoor_list -- maindoor coordnate list maindoor_height_min -- minimum height of the maindoor maindoor_height_max -- maximum height of the maindoor is_sauqre -- whether the point of maindoor is a square Returns: bool -- True or False """ def __init__(self): """init """ self.tool = ToolKit() self.maindoor_list = [] self.maindoor_height_min = 0 self.maindoor_height_max = 0 # whether the four points of the maindoor can form a rectangle self.is_square = False def get_maindoor(self, maindoor_dict, mesh_dict): """get maindoor list Arguments: maindoor_dict {dict} -- from json_information_acquirer mesh_dict {dict} -- from json_information_acquirer Returns: bool -- True or False """ # logger.i('start generate maindoor ... ') try: maindoor_tmp_dict = {} maindoor_ref_list = [] for roomID, doorinfo in maindoor_dict.items(): maindoor_tmp_dict['roomId'] = roomID maindoor_ref_list = doorinfo['ref'] except Exception as e: return False maindoor_mesh_list = [] for mesh_uid, mesh_value in mesh_dict.items(): if mesh_uid in maindoor_ref_list: maindoor_mesh_list.append(mesh_value) if len(maindoor_mesh_list) == 0: logger.e('cannot find maindoor mesh') return False y_list = [] xz_list = [] for maindoor_mesh in maindoor_mesh_list: maindoor_xyz_list = maindoor_mesh['xyz'] maindoor_faces_list = maindoor_mesh['faces'] for i in range(len(maindoor_xyz_list) // 3): y_list.append(float(maindoor_xyz_list[3 * i + 1])) xz_list.append([ round(float(maindoor_xyz_list[3 * i]), 3), round(float(maindoor_xyz_list[3 * i + 2]), 3) ]) self.maindoor_height_min = round(min(y_list), 3) self.maindoor_height_max = round(max(y_list), 3) self.maindoor_list = self.tool.calculate_convexhull(xz_list) if len(self.maindoor_list) < 4: return False elif len(self.maindoor_list) == 4: return self.tool.is_square(self.maindoor_list) else: return False def determine_entrydoor(self, house_info_list): maindoor_dict = {} maindoor_dict['point'] = [] is_found = False for room_info in house_info_list: door_info_list = room_info['door'] for door_info in door_info_list: if [door_info[0], door_info[1]] in self.maindoor_list: maindoor_dict['point'] = door_info maindoor_dict['room'] = room_info['room'] is_found = True break if is_found: break if len(maindoor_dict['point']) > 0: angle, direction = self.tool.compute_door_hole_direction( maindoor_dict['point']) maindoor_dict['angle'] = angle maindoor_dict['direction'] = direction maindoor_dict['height'] = self.maindoor_height_min maindoor_dict['height_limit'] = self.maindoor_height_max return maindoor_dict else: return {}
class FloorGenerator(object): def __init__(self,): self.room_floor_list = [] self.clockwise_line_list = [] self.tool = ToolKit() self.floor_tool = FloorTool() def generate_floor(self, floor_mesh_list, room_id): """generate floor info Arguments: floor_mesh_list {list} -- floor mesh Returns: bool -- True or False """ if len(floor_mesh_list) == 0: logger.e('%s does not have floor.' % room_id) return False xz_faces_list = [] floor_mesh_list = self.tool.mesh_duplicate(floor_mesh_list) for floor_mesh in floor_mesh_list: xz_list = [] floor_mesh_xyz = floor_mesh['xyz'] floor_mesh_faces = floor_mesh['faces'] for i in range(len(floor_mesh_xyz)//3): xz_list.append([float(floor_mesh_xyz[3*i]), float(floor_mesh_xyz[3*i+2])]) if len(xz_list) == 0: return False xz_sorted_list = [] for index in floor_mesh_faces: xz_sorted_list.append(xz_list[index]) for point in xz_sorted_list: xz_faces_list.append(point) grid_to_line_list = [] for i in range(len(xz_faces_list)//3): if (xz_faces_list[3*i][0] == xz_faces_list[3*i+1][0] and xz_faces_list[3*i][0] == xz_faces_list[3*i+2][0]) or (xz_faces_list[3*i][1] == xz_faces_list[3*i+1][1] and xz_faces_list[3*i][1] == xz_faces_list[3*i+2][1]): continue grid_line_list = self.tool.grid_to_multi_line(xz_faces_list[3*i], xz_faces_list[3*i+1], xz_faces_list[3*i+2]) if grid_line_list[0][0] == grid_line_list[0][1] or grid_line_list[1][0] == grid_line_list[1][1] or grid_line_list[2][0] == grid_line_list[2][1]: continue grid_to_line_list.append(grid_line_list[0]) grid_to_line_list.append(grid_line_list[1]) grid_to_line_list.append(grid_line_list[2]) # count the number of occurrences of a line segment. if ==1, conserve, else, ignore once_line_list = self.tool.find_once_line(grid_to_line_list) once_line_list = self.tool.line_deduplication(once_line_list) if len(once_line_list) == 0: return False self.clockwise_line_list = [] # connect all segments clockwise if self.floor_tool.connect_line_clockwise(once_line_list): if len(self.floor_tool.clockwise_line_list) == 1: self.clockwise_line_list = self.floor_tool.clockwise_line_list[0] else: logger.w('%s appeared multi floor' % room_id) idx_len_list = [] for line_list in self.floor_tool.clockwise_line_list: idx_len_list.append(len(line_list)) self.clockwise_line_list = self.floor_tool.clockwise_line_list[idx_len_list.index(max(idx_len_list))] else: logger.e('%s cannot generate floor: %d' % (room_id, len(self.clockwise_line_list))) return False if self.tool.is_closed(self.clockwise_line_list): self.clockwise_line_list = self.tool.merge_line(self.clockwise_line_list) self.clockwise_line_list = self.tool.overlap_line_deduplication(self.clockwise_line_list) else: return False return True