def show_points_in_box(points, bboxes, bbox_corners, surfaces, point_masks, is_yx_zb):
      if is_yx_zb:
        bboxes = Bbox3D.convert_from_yx_zb_boxes(bboxes)

      pn_in_box = np.sum(point_masks, 0)

      bn = bboxes.shape[0]
      points_in_boxes = []
      for i in range(bn):
        points_in_boxes.append( points[point_masks[:,i]] )

      pcd0 = points2pcd_open3d(points[:,:3])
      pcd0_aug = points2pcd_open3d(points[:,:3]-np.array([[0,0,4]]))

      corner_pcds = [points2pcd_open3d(corners) for corners in bbox_corners]
      surface_pcds = [points2pcd_open3d(surface) for surface in surfaces]
      points_inb_pcds = [points2pcd_open3d(points[:,:3]) for points in points_in_boxes]
      bboxes_ls0 = [Bbox3D.draw_bbox_open3d(box, 'Z') for box in bboxes]
      frame_mesh = open3d.create_mesh_coordinate_frame(size = 2.0, origin = bboxes[0,0:3])

      points_inb_pcds_valid = [pcd for i,pcd in enumerate(points_inb_pcds) if pn_in_box[i]>0]
      open3d.draw_geometries( bboxes_ls0 + points_inb_pcds_valid + [pcd0_aug])

      show_corners = False
      show_surfaces = False
      show_points_inb = False
      for i in range(bn):
        frame_mesh = open3d.create_mesh_coordinate_frame(size = 2.0, origin = bboxes[i,0:3])
        if show_corners:
          open3d.draw_geometries(bboxes_ls0[i:i+1]+corner_pcds[i:i+1]+[frame_mesh])
        if show_surfaces:
          open3d.draw_geometries(bboxes_ls0[i:i+1]+surface_pcds[i:i+1]+[frame_mesh])
        if show_points_inb:
          open3d.draw_geometries(bboxes_ls0[i:i+1]+points_inb_pcds[i:i+1]+[frame_mesh])
          pass
def gen_bbox(house_fn):
    always_gen_bbox = Debug and 0

    parsed_dir = get_pcl_path(house_fn)
    summary = read_summary(parsed_dir)
    box_intact = 'level_num' in summary and 'wall_num' in summary
    if box_intact and (not always_gen_bbox):
        print(f'skip gen_bbox, summary intact: {parsed_dir}')
        return

    with open(house_fn) as f:
        house = json.loads(f.read())

    scaleToMeters = house['scaleToMeters']
    assert scaleToMeters == 1
    bboxes = defaultdict(list)
    bboxes['house'].append(Bbox3D.bbox_from_minmax(house['bbox']))

    for level in house['levels']:
        if 'bbox' not in level:
            continue
        bboxes['level'].append(Bbox3D.bbox_from_minmax(level['bbox']))
        nodes = level['nodes']
        for node in nodes:
            node_type = node['type']
            if node_type == 'Object':
                modelId = node['modelId']
                category = Suncg.modelId_2_class[modelId]
                bboxes[category].append(Bbox3D.bbox_from_minmax(node['bbox']))
            elif node_type == 'Room':
                if 'bbox' in node:
                    bboxes['room'].append(Bbox3D.bbox_from_minmax(
                        node['bbox']))
                room_bboxes = split_room_parts(house_fn, node['modelId'])
                for c in room_bboxes:
                    bboxes[c] += room_bboxes[c]
            else:
                if 'bbox' in node:
                    bboxes[node_type].append(
                        Bbox3D.bbox_from_minmax(node['bbox']))

    centroid = (np.array(house['bbox']['min']) +
                np.array(house['bbox']['max'])) / 2.0
    mesh_frame = open3d.create_mesh_coordinate_frame(size=0.6, origin=centroid)

    for obj in bboxes:
        if len(bboxes[obj]) > 0:
            bboxes[obj] = np.concatenate(
                [b.reshape([1, 7]) for b in bboxes[obj]], 0)
        else:
            bboxes[obj] = np.array(bboxes[obj]).reshape([-1, 7])

        bboxes[obj] = cam2world_box(bboxes[obj])

    for obj in DSET_METAS0.class_2_label:
        if obj == 'background':
            continue
        if obj not in bboxes:
            bboxes[obj] = np.array(bboxes[obj]).reshape([-1, 7])

    level_num = len(house['levels'])
    if level_num == 1:
        bboxes['wall'] = preprocess_walls(bboxes['wall'])
        bboxes['window'] = preprocess_windows(bboxes['window'], bboxes['wall'])
        bboxes['door'] = preprocess_doors(bboxes['door'], bboxes['wall'])
        bboxes['ceiling_raw'] = bboxes['ceiling'].copy()
        bboxes['floor_raw'] = bboxes['floor'].copy()
        bboxes['ceiling'] = preprocess_cfr(bboxes['ceiling'], bboxes['wall'],
                                           'ceiling')
        bboxes['floor'] = preprocess_cfr(bboxes['floor'], bboxes['wall'],
                                         'floor')

    # save bbox in ply and txt
    object_bbox_dir = os.path.join(parsed_dir, 'object_bbox')
    if not os.path.exists(object_bbox_dir):
        os.makedirs(object_bbox_dir)

    bboxes_num = {}
    for category in bboxes.keys():
        bboxes_num[category] = len(bboxes[category])
        boxes_fn = os.path.join(object_bbox_dir, category + '.txt')
        boxes = np.array(bboxes[category])
        np.savetxt(boxes_fn, boxes)

    #######################
    print(f'parsed_dir: {parsed_dir}')
    write_summary(parsed_dir, 'level_num', level_num, 'a')
    for obj in ['room', 'wall', 'window', 'door', 'floor', 'ceiling']:
        write_summary(parsed_dir, f'{obj}_num', bboxes_num[obj], 'a')

    #######################
    save_ply = False
    if save_ply:
        for category in bboxes.keys():
            for i, bbox in enumerate(bboxes[category]):
                box_dir = os.path.join(object_bbox_dir, '{}'.format(category))
                if not os.path.exists(box_dir):
                    os.makedirs(box_dir)

                box_fn = os.path.join(box_dir, '%d.ply' % (i))
                bbox_cam = world2cam_box(bbox.reshape([1, 7]))[0]
                Bbox3D.draw_bbox_open3d(bbox_cam, 'Y', plyfn=box_fn)