Exemple #1
0
    def __init__(self):
        super().__init__()
        self._context = None
        self._gl_proxy = GLProxy(self)  # type: GLProxy

        # todo test code
        self._loaded_file_path = None  # type: str
        self.load_file(get_test_file_name())

        # default show b spline control points
        self.set_control_point_visibility(False)

        # for renderer
        # window size for glSetViewPort
        self._window_size = ACRect()  # type: ACRect

        # for zoom
        self._scale = np.array([1, 1, 1], dtype='f4')

        # m v p matrix
        self._perspective_matrix = None  # type: np.array
        self._translate = [0, 0, -8]  # type: np.array
        self._model_view_matrix = create_from_translation(np.array(self._translate), dtype='float32')  # type: np.array
        self._rotate_matrix = create_identity(dtype='f4')

        # rotate matrix for cube
        self._rotate_matrix = np.array(
            [[0.44967501, -0.06625679, -0.89087461, 0.],
             [-0.84477917, 0.29277544, -0.4481853, 0.],
             [0.29048993, 0.95400547, 0.07567401, 0.],
             [0., 0., 0., 1.]])

        self._inited = False  # type: bool

        self.factors = None
        self.area_result = []
        self.quality_result = []
        self.diff_result = []
        self.time_result = []
        self.cage_length = 0
        self.cym_position_error = 0
        self.splited_number = []
        self.cpu_split_number = 0

        self.gl_task = None
        self.show_figure.connect(self.show_diff_result)
Exemple #2
0
class Controller(QObject):
    update_scene = pyqtSignal(name='update_scene')
    show_figure = pyqtSignal(name='show_figure')

    def __init__(self):
        super().__init__()
        self._context = None
        self._gl_proxy = GLProxy(self)  # type: GLProxy

        # todo test code
        self._loaded_file_path = None  # type: str
        self.load_file(get_test_file_name())

        # default show b spline control points
        self.set_control_point_visibility(False)

        # for renderer
        # window size for glSetViewPort
        self._window_size = ACRect()  # type: ACRect

        # for zoom
        self._scale = np.array([1, 1, 1], dtype='f4')

        # m v p matrix
        self._perspective_matrix = None  # type: np.array
        self._translate = [0, 0, -8]  # type: np.array
        self._model_view_matrix = create_from_translation(np.array(self._translate), dtype='float32')  # type: np.array
        self._rotate_matrix = create_identity(dtype='f4')

        # rotate matrix for cube
        self._rotate_matrix = np.array(
            [[0.44967501, -0.06625679, -0.89087461, 0.],
             [-0.84477917, 0.29277544, -0.4481853, 0.],
             [0.29048993, 0.95400547, 0.07567401, 0.],
             [0., 0., 0., 1.]])

        self._inited = False  # type: bool

        self.factors = None
        self.area_result = []
        self.quality_result = []
        self.diff_result = []
        self.time_result = []
        self.cage_length = 0
        self.cym_position_error = 0
        self.splited_number = []
        self.cpu_split_number = 0

        self.gl_task = None
        self.show_figure.connect(self.show_diff_result)

    def add_quality(self, q):
        self.quality_result.append(q)

    def add_time(self, t):
        self.time_result.append(t)

    def add_area(self, a):
        self.area_result.append(a)

    def add_diff_result(self, r):
        self.diff_result.append(r)

    def add_splited_number(self, n):
        self.splited_number.append(n)

    def show_diff_result(self):
        path = self.get_save_path()
        np.save(path + '/split_data', self.diff_result)
        l = list(self.factors)

        triangle_number = self.splited_number
        r_number = [1 / x for x in triangle_number]
        triangle_area = self.area_result
        triangle_quality = self.quality_result

        split_time, deformation_time = self.time_result[0::2], self.time_result[1::2]
        total_time = [x + y for x, y in zip(split_time, deformation_time)]

        # self.diff_result 里面的元素(位置(平均,最大,标准差),法向(平均,最大,标准差))
        position_average_error = [x[0][0] for x in self.diff_result]
        normal_average_error = [x[1][0] for x in self.diff_result]

        #l error
        # fp = '/home/ac/thesis/zju_thesis/figures/clip/l-error0.png'
        # figutil.draw_figure([(l, position_average_error, '', None)],
        #                     u'l取值', u'几何误差',
        #                     save_file_name=fp, show=True, sort_x=False,
        #                     font_size=20, dpi=60)

        #area error
        fp = '/home/ac/thesis/zju_thesis/figures/clip/l-error1.png'
        figutil.draw_figure([(triangle_area, position_average_error, '', None)],
                            u'子三角形平均面积', u'几何误差',
                            save_file_name=fp, show=True, sort_x=True,
                            font_size=20, dpi=60)

        # l-quality
        # fp = '/home/ac/thesis/zju_thesis/figures/clip/l-quality0.png'
        # figutil.draw_figure([(l, triangle_quality, '', None)],
        #                     u'l取值', u'平均三角形质量',
        #                     save_file_name=fp, show=True, sort_x=False,
        #                     font_size=20, dpi=60)

        # number-quality
        # fp = '/home/ac/thesis/zju_thesis/figures/clip/l-quality1.png'
        # figutil.draw_figure([(triangle_number, triangle_quality, '', None)],
        #                     u'三角形数量', u'平均三角形质量',
        #                     save_file_name=fp, show=True, sort_x=True,
        #                     font_size=20, dpi=60)

        # number-quality

        # number-time
        # fp = '/home/ac/thesis/zju_thesis/figures/clip/l-time1.png'
        # figutil.draw_figure([(triangle_number, split_time, '', '分割时间'), (triangle_number, deformation_time, '', '变形时间')],
        #                     u'子三角形数量', u'时间(ms)',
        #                     save_file_name=fp, show=False, sort_x=True,
        #                     font_size=20, dpi=60, legend_loc='upper left')

        # l-time
        # fp = '/home/ac/thesis/zju_thesis/figures/clip/l-time0.png'
        # figutil.draw_figure([(l, split_time, '', '分割时间'), (l, deformation_time, '', '变形时间')],
        #                     u'l取值', u'时间(ms)',
        #                     save_file_name=fp, show=False, font_size=20, dpi=60)

        # figutil.draw_figure([(l, split_time, '', '分割时间'), (l, split_time, '', '分割时间')], u'l取值', u'时间')

        # self.draw_figure(self.area_result, position_average_error, u'子三角形平均面积', u'顶点平均几何误差')
        # figutil.draw_zoom(plt.gcf(), [0, 0.47, 0, 0.06], [0.1, 0.25], 1.1)

    @pyqtSlot()
    def clear_director_control_points(self):
        self._gl_proxy.clear_director_control_points()

    @pyqtSlot(float, float, float)
    def move_control_points(self, x, y, z):
        if self._gl_proxy.normal_control_mode:
            self._gl_proxy.move_control_points(x, y, z)
        else:
            direct_delta = np.array([x / 10, y / 10, z / 10], dtype='f4')
            self._gl_proxy.move_direct_control_point_delta(direct_delta)

        self.update_scene.emit()

    @pyqtSlot(float, float, float)
    def rotate_control_points(self, x, y, z):
        if self._gl_proxy.normal_control_mode:
            if x != 0:
                if x > 0:
                    m = create_from_x_rotation(0.1)
                else:
                    m = create_from_x_rotation(-0.1)
            elif y != 0:
                if y > 0:
                    m = create_from_y_rotation(0.1)
                else:
                    m = create_from_y_rotation(-0.1)
            else:
                if z > 0:
                    m = create_from_z_rotation(0.1)
                else:
                    m = create_from_z_rotation(-0.1)
            self._gl_proxy.rotate_control_points(m)
            self.update_scene.emit()

    @pyqtSlot(int)
    def change_tessellation_level(self, level):
        self._gl_proxy.change_tessellation_level(level)
        self.update_scene.emit()

    @pyqtSlot(float)
    def change_split_factor(self, level):
        self._gl_proxy.change_split_factor(level)
        # self.updateScene.emit()

    @staticmethod
    def check_file_path(file_path):
        if file_path.startswith('file://'):
            file_path = file_path[len('file://'):]
        if not isfile(file_path):
            print('check_file_path:', '文件名错误!')
            return None
        else:
            return file_path

    @pyqtSlot(str)
    def load_file(self, file_path):
        self._loaded_file_path = self.check_file_path(file_path)
        if self._loaded_file_path is None:
            return
        raw_obj = OBJ(file_path=self._loaded_file_path)
        self._gl_proxy.change_model(raw_obj)

    @pyqtSlot()
    def save_ctrl_points(self):
        path = self.get_save_path()
        files = os.listdir(path)
        file_name_prefix = self._loaded_file_path[
                           self._loaded_file_path.rfind('/') + 1:self._loaded_file_path.rfind('.')]
        no = 0
        for f in files:
            if f.startswith(file_name_prefix):
                no += 1
        file_name = '%s/%s_control_points%d' \
                    % (path,
                       file_name_prefix,
                       no)
        points = self._gl_proxy.control_points()
        np.save(file_name, points)

    def get_save_path(self):
        path = self._loaded_file_path[:self._loaded_file_path.rfind('.')] + '_' + self._gl_proxy.get_parameter_str()
        if not exists(path):
            os.mkdir(path)
        return path

    @pyqtSlot(str)
    def load_control_points(self, file_path):
        file_path = self.check_file_path(file_path)
        if file_path is None:
            return
        load = np.load(file_path)
        self._gl_proxy.set_control_points(load)
        self.update_scene.emit()

    @pyqtSlot(int, int)
    def rotate(self, x, y):
        # update _mode_view_matrix
        self._rotate_matrix = multiply(self._rotate_matrix, util.util.create_rotate(2, y, x, 0))
        scale_matrix = create_from_scale(self._scale, dtype='f4')
        self._model_view_matrix = multiply(self._rotate_matrix,
                                           np.dot(scale_matrix, create_from_translation(self._translate, dtype='f4')))

        self.update_scene.emit()

    @pyqtSlot(int, int)
    def move(self, x, y):
        # record rotate_y and rotate_x
        xyz = [x / 100, - y / 100, 0]
        self._translate = [x + y for x, y in zip(self._translate, xyz)]
        # update _mode_view_matrix
        scale_matrix = create_from_scale(self._scale, dtype='f4')
        self._model_view_matrix = multiply(self._rotate_matrix,
                                           np.dot(scale_matrix, create_from_translation(self._translate, dtype='f4')))
        self.update_scene.emit()

    @pyqtSlot(bool)
    def set_control_point_visibility(self, is_show: bool):
        self._gl_proxy.set_control_point_visibility(is_show)

    @pyqtSlot(bool)
    def set_show_real(self, is_show: bool):
        self._gl_proxy.set_show_real(is_show)

    @pyqtSlot(bool)
    def set_show_original(self, is_show: bool):
        self._gl_proxy.set_show_original(is_show)

    @pyqtSlot(bool)
    def set_splited_edge_visibility(self, is_show: bool):
        self._gl_proxy.set_splited_edge_visibility(is_show)

    @pyqtSlot(bool)
    def set_show_triangle_quality_flag(self, is_show: bool):
        self._gl_proxy.set_show_triangle_quality(is_show)

    @pyqtSlot(bool)
    def set_show_normal_diff_flag(self, is_show: bool):
        self._gl_proxy.set_show_normal_diff(is_show)

    @pyqtSlot(bool)
    def set_adjust_control_point(self, is_adjust: bool):
        self._gl_proxy.set_adjust_control_point(is_adjust)

    @pyqtSlot(bool)
    def set_show_position_diff_flag(self, is_show: bool):
        self._gl_proxy.set_show_position_diff(is_show)

    @pyqtSlot(bool)
    def set_show_control_point(self, is_show: bool):
        self._gl_proxy.set_show_control_point(is_show)

    @pyqtSlot(bool)
    def set_show_normal(self, is_show: bool):
        self._gl_proxy.set_show_normal(is_show)

    @pyqtSlot(bool)
    def set_use_pn_normal(self, use: bool):
        self._gl_proxy.set_use_pn_normal(use)

    def set_cpu_splited_number(self, n):
        self.cpu_split_number = n

    @pyqtSlot()
    def begin_test_split_factor(self):
        self.diff_result.clear()
        self.splited_number.clear()
        self.area_result.clear()
        self.quality_result.clear()
        self.time_result.clear()
        step = self._gl_proxy.aux_controller.get_bspline_body_size()
        self.cage_length = reduce(lambda p, x: p + x ** 2, step, 0) ** 0.5
        self.factors = np.arange(0.115, 2 * (3 ** 0.5), 0.02, dtype='f4')
        indices = 0
        original_split_factor = self._gl_proxy.previous_compute_controller.split_factor

        def gl_task1():
            nonlocal indices
            print('from begin_test_split_factor indices:', indices)
            if indices < len(self.factors):
                self.change_split_factor(self.factors[indices])
                self.set_need_comparison()
                indices += 1
                self.update_scene.emit()
            else:
                self.change_split_factor(original_split_factor)
                self.show_figure.emit()
                self.gl_task = None

        self.gl_task = gl_task1
        self.update_scene.emit()

    def set_need_comparison(self):
        self._gl_proxy.set_need_comparison()

    @pyqtSlot()
    def begin_diff_comparison(self):
        self.diff_result.clear()

        def gl_task0():
            is_ac = True
            if self._gl_proxy.algorithm != ALGORITHM_AC:
                self._gl_proxy.algorithm = ALGORITHM_AC
                is_ac = False
            self._gl_proxy.set_need_comparison()

            def gl_task1():
                self._gl_proxy.algorithm = ALGORITHM_CYM
                self._gl_proxy.set_need_comparison()

                def gl_task2():
                    if is_ac:
                        self._gl_proxy.algorithm = ALGORITHM_AC
                    self.gl_task = None
                    for ac, cym, label in zip(*self.diff_result, ['位置', '法向']):
                        print(label + '比对: 平均/最大/标准差')
                        print('ac %e / %e / %e' % (ac[0], ac[1], ac[2]))
                        print('cym %e / %e / %e' % (cym[0], cym[1], cym[2]))
                    self.cym_position_error = self.diff_result[1][0][0]

                self.gl_task = gl_task2
                self.update_scene.emit()

            self.gl_task = gl_task1
            self.update_scene.emit()

        self.gl_task = gl_task0
        self.update_scene.emit()

    @pyqtSlot(int, int, int, int)
    def left_move(self, x1: int, y1: int, x2: int, y2: int):
        y1 = self.window_size.h - y1
        y2 = self.window_size.h - y2
        if self._gl_proxy.normal_control_mode:
            x1, x2 = min(x1, x2), max(x1, x2)
            y1, y2 = min(y1, y2), max(y1, y2)
            self._gl_proxy.set_select_region(x1, y1, x2, y2)
        else:
            i = np.mat(self._model_view_matrix).I
            if self._gl_proxy.direct_control_point_selected():
                direction = np.mat([x2 - x1, y2 - y1, 0, 0], dtype='f4') * i
                self._gl_proxy.move_direct_control_point(np.array(direction, dtype='f4').reshape(4, )[:3] / 300)
            else:
                start_point = np.mat([0, 0, 0, 1], dtype='f4') * i
                end_point_z = -4
                end_point_y = y2 / self.window_size.h * 2 - 1
                end_point_x = x2 / self.window_size.h * 2 - self.window_size.aspect
                end_point = np.mat([end_point_x, end_point_y, end_point_z, 1], dtype='f4') * i
                self._gl_proxy.set_select_point(start_point, end_point - start_point)
        self.update_scene.emit()

    @pyqtSlot()
    def cancel_direct_control_point(self):
        self._gl_proxy.clear_direct_control_point()
        self.update_scene.emit()

    @pyqtSlot(int, int, int)
    def change_control_point_number(self, u: int, v: int, w: int):
        self._gl_proxy.change_control_point_number(u, v, w)
        self.update_scene.emit()

    @pyqtSlot(int)
    def change_control_point_order(self, order: int):
        self._gl_proxy.change_control_point_order(order)
        self.update_scene.emit()

    @pyqtSlot(int)
    def change_algorithm(self, algorithm):
        self._gl_proxy.algorithm = algorithm

    @pyqtSlot(int)
    def zoom(self, delta):
        delta /= 10
        self._scale += delta
        if self._scale[0] == 0:
            self._scale += delta
        scale_matrix = create_from_scale(self._scale, dtype='f4')
        self._model_view_matrix = np.dot(self._rotate_matrix,
                                         np.dot(scale_matrix, create_from_translation(self._translate, dtype='f4')))

        self.print_matrix(self._model_view_matrix)
        # normal
        # self._model_view_matrix = np.array(
        #     [[-1.64843, -1.10888, 0.230428, 0.0],
        #      [1.01591, -1.26784, 1.16642, 0.0],
        #      [-0.500636, 1.07843, 1.60822, 0.0],
        #      [0.0, 0.0, -8.0, 1.0]])

        # deformation
        # self._model_view_matrix = np.array(
        #     [[-1.33853, -0.952707, -0.436706, 0.0],
        #      [0.663226, -1.31852, 0.84363, 0.0],
        #      [-0.81148, 0.49387, 1.40984, 0.0],
        #      [0.27, 0.02, -8.0, 1.0]])

        self.update_scene.emit()

    @staticmethod
    def print_matrix(matrix):
        print('[', end='')
        for j in range(4):
            print('[', end='')
            for i in range(4):
                if i == 3:
                    print(matrix[j, i], end='')
                else:
                    print(matrix[j, i], end=', ')
            if j == 3:
                print(']', end='')
            else:
                print('],')
        print(']')
        print()

    @property
    def window_size(self):
        return self._window_size

    def gl_on_view_port_change(self, *xywh):
        if self.window_size != xywh:
            self.window_size.update(xywh)
            aspect = self.window_size.aspect
            self._perspective_matrix = create_perspective_projection_matrix_from_bounds(-aspect, aspect, -1,
                                                                                        1, 4, 100,
                                                                                        dtype='float32')

    def gl_init(self) -> None:
        glClearColor(1, 1, 1, 1)
        self._gl_proxy.gl_init_global()

    def gl_on_frame_draw(self) -> None:
        glEnable(GL_SCISSOR_TEST)
        glScissor(*self.window_size.xywh)

        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
        glViewport(*self.window_size.xywh)

        if self._gl_proxy:
            if self.gl_task:
                self.gl_task()
            self._gl_proxy.draw(self._model_view_matrix, self._perspective_matrix)

        glDisable(GL_SCISSOR_TEST)

    @pyqtSlot()
    def paint(self):
        if not self._inited:
            self.gl_init()
            self._inited = True
        self.gl_on_frame_draw()

    @pyqtSlot()
    def save_image(self):
        self._gl_proxy.save_image()

    @pyqtSlot(bool)
    def set_use_texture(self, b):
        self._gl_proxy.use_texture(b)

    @pyqtSlot()
    def export_obj(self):
        self._gl_proxy.export_obj()