示例#1
0
    def __init__(self, h, v, parent=None):
        super(MyGUI, self).__init__(parent)

        self.points = obj.PointObjects({
            '_ids':
            ['tether_Atrium', 'tether_Ventricle', 'AVCanal', 'Midline'],
            'colors': ['#6eadd8', '#ff7f0e', 'red', '#c4c4c4'],
            'markers': ['o', 'o', 'X', '-x'],
            'ms': [3, 3, 5, 5],
            'is_instance': [0, 0, 0, 0],
            'coords': [np.array([])] * 4
        })
        self.file_name = ''
        self.stacks = np.zeros((3, 3, 2, v, h))
        self.channels = ['ch0', 'ch1']
        self.widgets = {}

        self.createLoadSaveGroupBox()
        self.createObjectsControlGroupBox()
        self.createTZCControlGroupBox()
        self.createCanvas2DGroupBox()
        self.createCanvas3DGroupBox()

        self.setEnableState(False)

        mainLayout = QVBoxLayout()

        split3 = QSplitter(Qt.Vertical)
        split3.setMinimumWidth(0)

        split1 = QSplitter(Qt.Horizontal)
        split2 = QSplitter(Qt.Horizontal)

        split3.addWidget(self.groupObjectsControl)
        split3.addWidget(self.groupTZCControl)
        split2.addWidget(self.groupCanvas2DBox)
        split2.addWidget(self.groupCanvas3DBox)
        split1.addWidget(split3)
        split1.addWidget(split2)

        mainLayout.addWidget(self.groupLoadSave)
        mainLayout.addWidget(split1)

        self.setLayout(mainLayout)
        self.resize(1.2 * 960, 1.2 * 413)
        self.setWindowTitle('Manual annotation tool')
        QApplication.setStyle('Macintosh')
示例#2
0
 def __init__(self, *args, **kwargs):
     super().__init__(*args, **kwargs)
     
     sp = QSizePolicy()
     sp.setHorizontalPolicy(QSizePolicy.Expanding)
     sp.setVerticalPolicy(QSizePolicy.Expanding)
     sp.setVerticalStretch(1)
     
     wb_city_data = load_workbook(filename=r'DSTU-H_B_V.1.1-27_2010.xlsx', 
                                  read_only=True, data_only=True)
     self.__ws_city_I_ser_m_sj = wb_city_data['Лист1']
     self.__ws_city_t_z = wb_city_data['Т2. Температура зовн. пов.']
     
     self.__cityChoice = QComboBox()
     self.__cityChoice.addItems(c[0].value for c in 
                                self.__ws_city_I_ser_m_sj['A6':'A605'] if c[0].value)
     
     self.__q_0Edit = KwNumberEdit(.5)
     self.__V_budEdit = KwNumberEdit(480)
     
     self.__NEdit = QSpinBox()
     self.__NEdit.setRange(1, 999)
     self.__NEdit.setSuffix(' чол')
     self.__NEdit.setValue(6)
     
     self.__t_gvEdit = QSpinBox()
     self.__t_gvEdit.setRange(25, 70)
     self.__t_gvEdit.setSingleStep(5)
     self.__t_gvEdit.setSuffix(' \N{DEGREE CELSIUS}')
     self.__t_gvEdit.setValue(45)
     
     self.__a_gvEdit = QSpinBox()
     self.__a_gvEdit.setRange(15, 99)
     self.__a_gvEdit.setSuffix(' л/добу')
     self.__a_gvEdit.setValue(35)
     
     self.__f_zEdit = KwNumberEdit(.8)
     self.__varthetaEdit = KwNumberEdit(1.7)
     self.__S_0Edit = KwNumberEdit(1.723)
     self.__F_rEdit = KwNumberEdit(1)
     self.__eta_0Edit = KwNumberEdit(0.813)
     self.__ULEdit = KwNumberEdit(4.6)
     self.__aEdit = KwNumberEdit(.007)
     self.__bEdit = KwNumberEdit(1.27E-5)
     self.__c_paEdit = KwNumberEdit(3.16)
     
     self.__P_tpEdit = KwNumberEdit(14.1)
     self.__epsilon_tpEdit = KwNumberEdit(5.5)
     self.__epsilon_elEdit = KwNumberEdit(.88)
     self.__P_elEdit = KwNumberEdit(2.6)
     
     self.__t_co_1Edit = QSpinBox()
     self.__t_co_1Edit.setRange(25, 70)
     self.__t_co_1Edit.setSingleStep(5)
     self.__t_co_1Edit.setSuffix(' \N{DEGREE CELSIUS}')
     self.__t_co_1Edit.setValue(35)
     
     self.__t_co_2Edit = QSpinBox()
     self.__t_co_2Edit.setRange(20, 60)
     self.__t_co_2Edit.setSingleStep(5)
     self.__t_co_2Edit.setSuffix(' \N{DEGREE CELSIUS}')
     self.__t_co_2Edit.setValue(30)
     
     self.__eta_KEdit = KwNumberEdit(.93)
     self.__Q_n_rEdit = KwNumberEdit(35600)
     self.__c_gazEdit = KwNumberEdit(.55)
     self.__c_elEdit = KwNumberEdit(.25)
     
     self.__q_gruEdit = KwNumberEdit(21)
     
     self.__d_gruEdit = QSpinBox()
     self.__d_gruEdit.setRange(5, 99)
     self.__d_gruEdit.setSuffix('  мм')
     self.__d_gruEdit.setValue(25)
     
     self.__l_0_gruEdit = KwNumberEdit(1.7)
     
     calcButton = QPushButton('Визначити')
     calcButton.setObjectName('calcButton')
     
     self.__outputConsoleBrowser = KwConsoleBrowser(setup={'font': {'name': 
           QFont('Hack').family(), 'size': 8}, 'color': 'rgb(255, 255, 255)', 
           'background_color': 'rgba(0, 0, 0, 218)', 'line_wrap': False})
     self.__outputConsoleBrowser.setSizePolicy(sp)
     
     graphWidget = QMainWindow()
     graphWidget.setMinimumWidth(380)
     
     self.__graphCanvas = self.__createFigureCanvas()
     self.__graphNavigationToolbar = NavigationToolbar(self.__graphCanvas, self)
     graphWidget.addToolBar(Qt.TopToolBarArea, self.__graphNavigationToolbar)
     
     graphWidget.setCentralWidget(self.__graphCanvas)
     
     cityLayout = QFormLayout()
     cityLayout.addRow('Місто:', self.__cityChoice)
     
     soGroup = QGroupBox('Для системи опалення (СО):')
     soInputLayout = QFormLayout(soGroup)
     
     soInputLayout.addRow('Питома потужність тепловтрат, q<sub>0</sub>, '
                          'Вт/(м<sup>3</sup>\N{MIDDLE DOT}\N{DEGREE CELSIUS}):', 
                          self.__q_0Edit)
     soInputLayout.addRow("Об'єм будинку по зовнішніх обмірах, V<sub>буд</sub>, "
                          "м<sup>3</sup>:", self.__V_budEdit)
     
     sgvGroup = QGroupBox(u'Для системи гарячого водопостачання (СГК):')
     sgvInputLayout = QFormLayout(sgvGroup)
     sgvInputLayout.addRow('Кількість мешканців у будинку, N:', self.__NEdit)
     sgvInputLayout.addRow('Температура гарячої води, t<sub>гв</sub>:', self.__t_gvEdit)
     sgvInputLayout.addRow('Добова витрата гарячої води на 1 особу, a<sub>гв</sub>:',
                           self.__a_gvEdit)
     
     sgkGroup = QGroupBox('Для системи геліоколекторів (СГК):')
     sgkInputLayout = QFormLayout(sgkGroup)
     sgkInputLayout.addRow('Ступінь заміщення тепловтрат СГВ, f<sub>з</sub>:', self.__f_zEdit)
     sgkInputLayout.addRow('Параметр, \u03D1:', self.__varthetaEdit)
     sgkInputLayout.addRow('Площа 1-го геліоколектора, S<sub>0</sub>, м<sup>2</sup>:',
                           self.__S_0Edit)
     sgkInputLayout.addRow('F<sub>r</sub>:', self.__F_rEdit)
     sgkInputLayout.addRow('Оптичний ККД, \N{GREEK SMALL LETTER ETA}:', self.__eta_0Edit)
     sgkInputLayout.addRow('Коефіцієнт тепловтрат, UL, Вт/(м<sup>2</sup>)'
                           '\N{MIDDLE DOT}\N{DEGREE CELSIUS}):', self.__ULEdit)
     sgkInputLayout.addRow('a:', self.__aEdit)
     sgkInputLayout.addRow('b:', self.__bEdit)
     sgkInputLayout.addRow('c<sub>pa</sub>, кДж/(кг\N{MIDDLE DOT}\N{DEGREE CELSIUS}):',
                           self.__c_paEdit)
     
     tpGroup = QGroupBox('Для теплової помпи (ТП):')
     tpInputLayout = QFormLayout(tpGroup)
     tpInputLayout.addRow('Теплова потужність, P<sub>тп</sub>, кВт:', self.__P_tpEdit)
     tpInputLayout.addRow('Тепловий к.к.д, \N{GREEK SMALL LETTER EPSILON}'
                          '<sub>тп</sub>', self.__epsilon_tpEdit)
     tpInputLayout.addRow('Електричний к.к.д., \N{GREEK SMALL LETTER EPSILON}'
                          '<sub>ел</sub>:', self.__epsilon_elEdit)
     tpInputLayout.addRow('Електрична потужність, P<sub>ел</sub>, кВт:', self.__P_elEdit)
     tpInputLayout.addRow('Т-ра нагрітої води для СО підлоги, t<sub>co 1</sub>:',
                          self.__t_co_1Edit)
     tpInputLayout.addRow('Т-ра охолодженої води для СО підлоги, t<sub>co 2</sub>:',
                          self.__t_co_2Edit)
     tpInputLayout.addRow('К.к.д. згоряння палива, eta_K:', self.__eta_KEdit)
     tpInputLayout.addRow('Нижча теплота згоряння палива, Q<sub>n r</sub>, кДж/м<sup>3</sup>:',
                          self.__Q_n_rEdit)
     tpInputLayout.addRow('Вартість 1 м<sup>3</sup> газу, c<sub>газ</sub>, грн/м<sup>3</sup>:',
                          self.__c_gazEdit)
     tpInputLayout.addRow('Вартість 1 кВт\N{MIDDLE DOT}год, c<sub>ел</sub>, '
                          'грн/м<sup>3</sup>:', self.__c_elEdit)
     
     gruGroup = QGroupBox('Для ґрунту і контуру СО підлоги:')
     gruInputEdit = QFormLayout(gruGroup)
     gruInputEdit.addRow('Питома тепловіддача ґрунту, q<sub>ґр</sub>, '
                         'Вт/м<sup>2</sup>:', self.__q_gruEdit)
     gruInputEdit.addRow('Внутрішній діаметр, d, мм:', self.__d_gruEdit)
     gruInputEdit.addRow('Питома довжина тепловідбору, l<sub>0</sub>, '
                         'м/м<sup>2</sup>:', self.__l_0_gruEdit)
     
     inputScrollArea = QScrollArea()
     inputScrollArea.setWidgetResizable(True)
     inputScrollArea.setSizePolicy(sp)
     
     inputDataPanel = QWidget()
     inputDataLayout = QVBoxLayout(inputDataPanel)
     
     inputDataLayout.addLayout(cityLayout)
     inputDataLayout.addWidget(soGroup)
     inputDataLayout.addWidget(sgvGroup)
     inputDataLayout.addWidget(sgkGroup)
     inputDataLayout.addWidget(tpGroup)
     inputDataLayout.addWidget(gruGroup)
     
     inputScrollArea.setWidget(inputDataPanel)
     
     inputWidget = QWidget()
     inputLayout = QFormLayout(inputWidget)
     #inputLayout.setContentsMargins(0, 0, 0, 0)
     inputLayout.setRowWrapPolicy(QFormLayout.WrapAllRows)
     inputLayout.addRow('Вхідні дані:', inputScrollArea)
     inputLayout.addWidget(calcButton)
     
     consoleViewWidget = QWidget()
     consoleViewLayout = QFormLayout(consoleViewWidget)
     consoleViewLayout.setRowWrapPolicy(QFormLayout.WrapAllRows)
     consoleViewLayout.addRow(u'Результати:', self.__outputConsoleBrowser)
     
     contentSplitter = QSplitter(Qt.Horizontal)
     contentSplitter.setStretchFactor(0, 1)
     contentSplitter.setStretchFactor(1, 0)
     contentSplitter.setSizes([350, 380])
     contentSplitter.setChildrenCollapsible(False)
     
     ioSplitter = QSplitter(Qt.Vertical)
     ioSplitter.setStretchFactor(0, 1)
     ioSplitter.setStretchFactor(1, 0)
     ioSplitter.setSizes([200, 320])
     ioSplitter.setChildrenCollapsible(False)
     ioSplitter.setMinimumWidth(380)
     
     ioSplitter.addWidget(inputWidget)
     ioSplitter.addWidget(consoleViewWidget)
     
     contentSplitter.addWidget(ioSplitter)
     contentSplitter.addWidget(graphWidget)
     
     self.setCentralWidget(contentSplitter)
     
     self.resize(1200, 640)
     
     # <<<
     for inputValueWidget in inputWidget.findChildren((QAbstractSpinBox,
                                                       KwNumberEdit)):
         inputValueWidget.valueChanged.connect(self._reset_output_data)
     
     for inputValueWidget in inputWidget.findChildren(QComboBox):
         inputValueWidget.activated.connect(self._reset_output_data)
     
     calcButton.clicked.connect(self.calc_script)
示例#3
0
class Visualization:
    def __init__(self, world):
        """
        Main Interface between the OpenGL stuff and the simulator.
        Initializes the camera, and the opengl-widget.
        controlls the speed of the simulation.
        :param world: the world class
        """
        self._world = world
        self._last_light_rotation = 0
        self._rounds_per_second = 10
        self._reset_flag = False
        self._running = False
        self._app = None
        self._viewer = None
        self._gui = None
        self._splitter = None
        self._recording = False
        self._animation = world.config_data.animation
        self._auto_animation = world.config_data.auto_animation
        self._manual_animation_speed = world.config_data.manual_animation_speed
        self.light_rotation = False
        self.grid_size = world.grid.size

        # create the QApplication
        self._app = QApplication([])

        # create camera for the visualization
        # if grid is 2D, set to orthographic projection (it is better for 2D)
        if self._world.grid.get_dimension_count() == 2:
            self._camera = Camera(
                self._world.config_data.window_size_x,
                self._world.config_data.window_size_y,
                self._world.config_data.look_at, self._world.config_data.phi,
                self._world.config_data.theta, self._world.config_data.radius,
                self._world.config_data.fov,
                self._world.config_data.cursor_offset,
                self._world.config_data.render_distance, "ortho",
                self._world.grid.get_scaling())
        else:
            self._camera = Camera(
                self._world.config_data.window_size_x,
                self._world.config_data.window_size_y,
                self._world.config_data.look_at, self._world.config_data.phi,
                self._world.config_data.theta, self._world.config_data.radius,
                self._world.config_data.fov,
                self._world.config_data.cursor_offset,
                self._world.config_data.render_distance, "perspective",
                self._world.grid.get_scaling())

        # create the opengl widget
        self._viewer = OGLWidget(self._world, self._camera)
        self._viewer.glInit()
        self.recorder = Recorder(self._world, self._viewer)

        # create and show the main Window
        self._splitter = QSplitter()
        self._splitter.closeEvent = close
        self._splitter.setMinimumWidth(self._world.config_data.window_size_x)
        self._splitter.setMinimumHeight(self._world.config_data.window_size_y)
        self._splitter.setWindowTitle("Simulator")

        self._splitter.show()

        # create gui
        # creating the gui has to happen after showing the window, so the gui can access
        # opengl variables and programs during creation
        self._gui_module = importlib.import_module('components.gui.' +
                                                   self._world.config_data.gui)

        # the key press handler
        def key_press_event(event):
            self._gui_module.key_handler(event.key(), self._world, self)

        # loading key handler from gui module
        if "key_handler" in dir(self._gui_module):
            self._viewer.keyPressEventHandler = key_press_event
            self._splitter.keyPressEvent = key_press_event
        else:
            show_msg("No key_handler(key, vis) function found in gui module!",
                     Level.WARNING, self._splitter)

        # loading gui from gui module
        if "create_gui" in dir(self._gui_module):
            self._gui = self._gui_module.create_gui(self._world, self)
            if self._gui is not None and issubclass(self._gui.__class__,
                                                    QWidget):
                self._splitter.addWidget(self._gui)
                self._splitter.keyPressEvent = self._viewer.keyPressEvent
                self._splitter.keyReleaseEvent = self._viewer.keyReleaseEvent
                self._splitter.addWidget(self._viewer)
                self._splitter.setSizes([
                    self._world.config_data.window_size_x * 0.25,
                    self._world.config_data.window_size_x * 0.75
                ])
            else:
                # noinspection PyUnresolvedReferences
                show_msg(
                    "The create_gui(world, vis) function in gui module didn't return a QWidget."
                    + "Expected a QWidget or a subclass, but got %s." %
                    self._gui.__class__.__name__, Level.WARNING,
                    self._splitter)
                self._splitter.addWidget(self._viewer)

        else:
            show_msg(
                "No create_gui(world, vis) function found in gui module. GUI not created",
                Level.INFO, self._splitter)
            self._splitter.addWidget(self._viewer)

        # waiting for the simulation window to be fully active
        while not self._splitter.windowHandle().isExposed():
            self._process_events()
        # first update and draw call.
        self._viewer.update_scene()

    def is_recording(self):
        return self._recording

    def _process_events(self):
        self._app.processEvents()
        if self._reset_flag:
            raise ResetException()

    def reset(self):
        """
        stops the simulation.
        deletes all data in the visualization.
        resets the camera
        :return:
        """
        self._reset_flag = False
        self._running = False
        self._viewer.agent_offset_data = {}
        self._viewer.agent_update_flag = True
        self._viewer.item_offset_data = {}
        self._viewer.item_update_flag = True
        self._viewer.location_offset_data = {}
        self._viewer.location_update_flag = True
        self._viewer.update_data()
        self._camera.reset()
        self._viewer.update_scene()

    def wait_for_thread(self, thread: Thread, window_message, window_title):
        """
        executes a thread and shows a loading window till the thread stops.
        blocks the gui, while thread runs.
        :param thread: the thread
        :param window_message: the displayed message
        :param window_title: the title of the loading window
        :return:
        """

        loading_window = LoadingWindow(window_message, window_title)
        if self._gui is not None and issubclass(self._gui.__class__, QWidget):
            self._gui.setDisabled(True)
        thread.start()
        while thread.is_alive():
            try:
                self._process_events()
            except VisualizationError as ve:
                show_msg(ve, Level.CRITICAL, self._splitter)
                exit(1)
        thread.join()
        loading_window.close()
        self._gui.setDisabled(False)

    def rotate_light(self):
        """
        rotates the light direction at a steady degrees/second velocity independent of the CPU-clock or framerate.
        :return:
        """
        # rotation of light only in 3d
        if self._world.grid.get_dimension_count() > 2:
            # 20° per second rotation
            if self._last_light_rotation == 0:
                self._last_light_rotation = time.perf_counter()
            else:
                angle = (time.perf_counter() - self._last_light_rotation) * 20
                self._last_light_rotation = time.perf_counter()
                self._viewer.rotate_light(angle)
                self._viewer.glDraw()

    def start_stop(self):
        """
        starts and pauses the simulation
        :return:
        """
        self._running = not self._running

    def _wait_while_not_running(self):
        """
        helper function.
        waits until the running flag is set.
        :return:
        """
        sleep_time = 1.0 / 120.0
        self._process_events()
        if self.light_rotation:
            self.rotate_light()
        while not self._running:
            # sleeping for 1/120 secs, for responsive GUI
            time.sleep(sleep_time)
            if self.light_rotation:
                self.rotate_light()
            self._process_events()

    def animate(self, round_start_time, speed):
        """
        loop for animating the movement of agents and carried items
        :param round_start_time: the start of the round
        :param speed: speed of the animation in 1/steps. less or equal zero = automatic mode
        """
        if speed < 0:
            # draw at location according to the passed time and the rps
            half_round_time = (1.0 / self._rounds_per_second) / 2.0
            now = time.perf_counter()
            while (now - round_start_time) < half_round_time:
                self._viewer.set_animation_percentage(
                    min(1, (now - round_start_time) / half_round_time))
                self._process_events()
                self._viewer.glDraw()
                now = time.perf_counter()
        else:
            # draw at location according to the selected animation speed
            for i in range(1, max(1, speed)):
                self._viewer.set_animation_percentage(float(i / max(1, speed)))
                self._process_events()
                self._viewer.glDraw()

        self._viewer.set_animation_percentage(1)
        self._viewer.glDraw()

        # reset the previous position after animation.
        # not reseting it causes a visual bug if the matter didn't move.
        for agent in self._viewer.agent_offset_data:
            current_data = self._viewer.agent_offset_data[agent]
            self._viewer.agent_offset_data[agent] = (current_data[0],
                                                     current_data[1],
                                                     agent.coordinates,
                                                     current_data[3])
        for item in self._viewer.item_offset_data:
            current_data = self._viewer.item_offset_data[item]
            self._viewer.item_offset_data[item] = (current_data[0],
                                                   current_data[1],
                                                   item.coordinates,
                                                   current_data[3])
        self._viewer.agent_update_flag = True
        self._viewer.item_update_flag = True

    def run(self, round_start_timestamp):
        """
        main function for running the simulation with the visualization.
        At this time, its just error handling here.. the simulation and drawing stuff starts in the run_iteration method
        :param round_start_timestamp: timestamp of the start of the round.
        :return:
        """
        # TODO: MARK - print stuff here to find exact seg fault location
        try:
            self._run_iteration(round_start_timestamp)
        except VisualizationError as ve:
            if ve.level == Level.INFO:
                show_msg(ve.msg, ve.level, self.get_main_window())
            if ve.level == Level.CRITICAL:
                show_msg(ve.msg, ve.level, self.get_main_window())
                exit(1)
            if ve.level == Level.WARNING:
                try:
                    self._run_iteration(round_start_timestamp)
                    show_msg(ve.msg, ve.level, self.get_main_window())
                except VisualizationError as ve:
                    show_msg(ve.msg, ve.level, self.get_main_window())
                    if ve.level != Level.INFO:
                        exit(1)

    def _run_iteration(self, round_start_timestamp):
        """
        Controls the "waiting time", so the rounds_per_second value is being kept at the specified value.
        :param round_start_timestamp: timestamp of the start of the round.
        :return:
        """
        # update and draw/animate scene
        self._viewer.update_data()
        if self._animation:
            self.animate(
                round_start_timestamp,
                -1 if self._auto_animation else self._manual_animation_speed)
        else:
            self._viewer.glDraw()

        # waiting until simulation starts
        self._wait_while_not_running()

        # record round
        if self._recording:
            self.recorder.record_round()
            self._splitter.setWindowTitle("Simulator, recorded: %d rounds" %
                                          len(self.recorder.records))

        # waiting until enough time passed to do the next simulation round.
        time_elapsed = time.perf_counter() - round_start_timestamp
        # sleeping time - max 1/120 s for a responsive GUI
        sleep_time = min(1.0 / 120, (1.0 / self._rounds_per_second) / 10.0)
        max_wait_time = 1 / self._rounds_per_second
        while time_elapsed < max_wait_time:
            time.sleep(sleep_time)
            # check if still running... if not wait (important for low rounds_per_second values)
            self._wait_while_not_running()
            time_elapsed = time.perf_counter() - round_start_timestamp

    def remove_agent(self, agent):
        """
        removes an agent from the visualization.
        it wont be deleted immediately! not until the next round.
        if you want an immediate deletion of the agent, then call this function, then, update_data and after that
        glDraw of the OpenGLWidget.

        :param agent: the agent (not the id, the instance) to be deleted
        :return:
        """
        self._viewer.agent_update_flag = True
        if agent in self._viewer.agent_offset_data:
            del self._viewer.agent_offset_data[agent]

    def agent_changed(self, agent):
        """
        updates the offset, color and carry data of the agent in the visualization.
        it wont be an immediate update. it will update in the beginning of the next "run" call / after current round.
        :param agent: the agent that has changed (the instance)
        :return:
        """
        self._viewer.agent_update_flag = True
        prev_pos = agent.coordinates
        if agent in self._viewer.agent_offset_data:
            prev_pos = self._viewer.agent_offset_data[agent][0]
        self._viewer.agent_offset_data[agent] = (agent.coordinates,
                                                 agent.color, prev_pos, 1.0 if
                                                 agent.is_carried() else 0.0)

    def remove_item(self, item):
        """
        removes an item from the visualization.
        :param item: the item (not the id, the instance) to be deleted
        :return:
        """
        self._viewer.item_update_flag = True
        if item in self._viewer.item_offset_data:
            del self._viewer.item_offset_data[item]

    def item_changed(self, item):
        """
        updates the offset, color and carry data of the item in the visualization.
        :param item: the item ( not the id, the instance) to be deleted
        :return:
        """
        self._viewer.item_update_flag = True
        prev_pos = item.coordinates
        if item in self._viewer.item_offset_data:
            prev_pos = self._viewer.item_offset_data[item][0]

        self._viewer.item_offset_data[item] = (item.coordinates, item.color,
                                               prev_pos, 1.0
                                               if item.is_carried() else 0.0)

    def remove_location(self, location):
        """
        removes a location from the visualization.
        :param location: the location (not the id, the instance) to be deleted
        :return:
        """
        self._viewer.location_update_flag = True
        if location in self._viewer.location_offset_data:
            del self._viewer.location_offset_data[location]

    def location_changed(self, location):
        """
        updates the offset and color data of the location in the visualization.
        :param location: the location ( not the id, the instance) to be deleted
        :return:
        """
        self._viewer.location_update_flag = True
        self._viewer.location_offset_data[location] = (location.coordinates,
                                                       location.color)

    def update_visualization_data(self):
        self._viewer.update_data()

    # setters and getters for various variables in the visualization

    def set_rounds_per_second(self, rounds_per_second):
        self._rounds_per_second = rounds_per_second

    def get_rounds_per_second(self):
        return self._rounds_per_second

    def reset_camera_position(self):
        self._camera.reset()
        self._viewer.update_scene()

    def set_field_of_view(self, fov: float):
        self._camera.set_fov(fov)
        self._viewer.update_programs_projection_matrix()
        self._viewer.update_cursor_data()
        self._viewer.glDraw()

    def get_field_of_view(self):
        return self._camera.get_fov()

    def set_drag_sensitivity(self, s: float):
        self._viewer.drag_sensitivity = s

    def get_drag_sensitivity(self):
        return self._viewer.drag_sensitivity

    def set_zoom_sensitivity(self, s: float):
        self._viewer.zoom_sensitivity = s

    def get_zoom_sensitivity(self):
        return self._viewer.zoom_sensitivity

    def set_rotation_sensitivity(self, s: float):
        self._viewer.rotation_sensitivity = s

    def get_rotation_sensitivity(self):
        return self._viewer.rotation_sensitivity

    def get_projection_type(self):
        return self._camera.get_projection_type()

    def set_projection_type(self, projection_type):
        self._camera.set_projection_type(projection_type)
        self._viewer.update_programs_projection_matrix()
        self._viewer.glDraw()

    def get_background_color(self):
        return self._viewer.background

    def set_background_color(self, color):
        self._viewer.set_background_color(color)

    def get_grid_line_color(self):
        return self._viewer.programs["grid"].get_line_color()

    def set_grid_line_color(self, color):
        self._viewer.programs["grid"].set_line_color(color)

    def get_grid_border_color(self):
        return self._viewer.programs["grid"].get_border_color()

    def set_grid_border_color(self, color):
        self._viewer.programs["grid"].set_border_color(color)

    def get_grid_line_width(self):
        return self._viewer.programs["grid"].width

    def set_grid_line_width(self, width):
        self._viewer.programs["grid"].set_width(width)
        self._viewer.glDraw()

    def get_grid_line_scaling(self):
        return self._viewer.programs["grid"].get_line_scaling()

    def set_grid_line_scaling(self, scaling):
        self._viewer.programs["grid"].set_line_scaling(scaling)
        self._viewer.glDraw()

    def get_grid_coordinates_color(self):
        return self._viewer.programs["grid"].get_model_color()

    def set_grid_coordinates_color(self, color):
        self._viewer.programs["grid"].set_model_color(color)
        self._viewer.glDraw()

    def get_grid_coordinates_scaling(self):
        return self._viewer.programs["grid"].get_model_scaling()

    def set_grid_coordinates_scaling(self, scaling):
        self._viewer.programs["grid"].set_model_scaling(scaling)
        self._viewer.glDraw()

    def get_render_distance(self):
        return self._camera.get_render_distance()

    def set_render_distance(self, render_distance):
        self._camera.set_render_distance(render_distance)
        self._viewer.update_programs_projection_matrix()
        self._viewer.glDraw()

    def get_show_lines(self):
        return self._viewer.programs["grid"].show_lines

    def set_show_lines(self, show_lines: bool):
        self._viewer.programs["grid"].show_lines = show_lines
        self._viewer.glDraw()

    def get_show_border(self):
        return self._viewer.programs["grid"].show_border

    def set_show_border(self, show_border: bool):
        self._viewer.programs["grid"].show_border = show_border
        self._viewer.glDraw()

    def get_show_coordinates(self):
        return self._viewer.programs["grid"].show_coordinates

    def set_show_coordinates(self, show_coordinates: bool):
        self._viewer.programs["grid"].show_coordinates = show_coordinates
        self._viewer.glDraw()

    def get_show_center(self):
        return self._viewer.show_center

    def set_show_center(self, show_center: bool):
        self._viewer.show_center = show_center
        self._viewer.glDraw()

    def get_show_focus(self):
        return self._viewer.show_focus

    def set_show_focus(self, show_focus: bool):
        self._viewer.show_focus = show_focus
        self._viewer.glDraw()

    def take_screenshot(self, quick):
        self._viewer.take_screenshot(quick)

    def recalculate_grid(self, size):
        self.grid_size = size
        self._viewer.programs["grid"].update_offsets(
            self._world.grid.get_box(size))
        self._viewer.glDraw()

    def get_agent_scaling(self):
        return self._viewer.programs["agent"].get_model_scaling()

    def set_agent_scaling(self, scaling):
        self._viewer.programs["agent"].set_model_scaling(scaling)
        self._viewer.glDraw()

    def get_item_scaling(self):
        return self._viewer.programs["item"].get_model_scaling()

    def set_item_scaling(self, scaling):
        self._viewer.programs["item"].set_model_scaling(scaling)
        self._viewer.glDraw()

    def get_location_scaling(self):
        return self._viewer.programs["location"].get_model_scaling()

    def set_location_scaling(self, scaling):
        self._viewer.programs["location"].set_model_scaling(scaling)
        self._viewer.glDraw()

    def set_on_cursor_click_matter_type(self, matter_type):
        if matter_type == MatterType.ITEM or matter_type == MatterType.AGENT or matter_type == MatterType.LOCATION:
            self._viewer.cursor_type = matter_type
            self._viewer.update_cursor_data()

    def is_running(self):
        return self._running

    def get_added_matter_color(self):
        return self._viewer.added_matter_color

    def set_added_matter_color(self, color):
        self._viewer.added_matter_color = color

    def start_recording(self):
        self.recorder.record_round()
        self._splitter.setWindowTitle("Simulator, recorded: %d rounds" %
                                      len(self.recorder.records))
        self._recording = True

    def get_viewer_res(self):
        return self._viewer.width(), self._viewer.height()

    def stop_recording(self):
        self._recording = False

    def export_recording(self):
        if len(self.recorder.records) == 0:
            show_msg("No rounds recorded. Nothing to export.", Level.INFO,
                     self._splitter)
            return
        if self._running:
            self.start_stop()
        self._viewer.set_show_info_frame(False)
        self._viewer.set_enable_cursor(False)
        if "set_disable_sim" in dir(self._gui_module):
            self._gui_module.set_disable_sim(True)
        else:
            show_msg(
                "No 'set_disable_sim(disable_flag)' function in gui module found."
                "\nRunning simulation within recording mode may result in undefined behavior!",
                Level.WARNING, self._splitter)

        self.recorder.show(self.do_export)

        # loop
        while self.recorder.is_open():
            self._process_events()

        # go back to the main window
        if "set_disable_sim" in dir(self._gui_module):
            self._gui_module.set_disable_sim(False)

        self._viewer.agent_update_flag = True
        self._viewer.item_update_flag = True
        self._viewer.location_update_flag = True
        self._viewer.update_data()
        self._viewer.set_show_info_frame(True)
        self._viewer.set_enable_cursor(True)

    def do_export(self, rps, width, height, codec, first_frame_idx,
                  last_frame_idx, animation):

        if not os.path.exists("outputs/videos") or not os.path.isdir(
                "outputs/videos"):
            os.mkdir("outputs/videos")
        directory = "."
        if os.path.exists("outputs/videos") and os.path.isdir(
                "outputs/videos"):
            directory = "outputs/videos"
        path = TopQFileDialog(self._splitter).getSaveFileName(
            options=(TopQFileDialog.Options()),
            filter="*.mp4;;*.avi;;*.mkv",
            directory=directory)
        if path[0] == '':
            return

        if path[0].endswith("mp4") or path[0].endswith(
                ".avi") or path[0].endswith(".mkv"):
            fullpath = path[0]
        else:
            fullpath = path[0] + path[1].replace('*', '')

        if animation:
            animation_steps = int(30 / rps)
            if animation_steps < 1:
                animation_steps = 1
        else:
            animation_steps = 1

        writer = cv2.VideoWriter(fullpath, cv2.VideoWriter_fourcc(*codec),
                                 rps * animation_steps, (width, height))
        self._viewer.setDisabled(True)
        # creating and opening loading window
        lw = LoadingWindow("", "Exporting Video...")
        lw.show()
        out_of = (last_frame_idx - first_frame_idx + 1) * animation_steps
        for i in range(first_frame_idx - 1, last_frame_idx):
            # render and write frame
            self._viewer.inject_record_data(self.recorder.records[i])
            # animate
            for j in range(1, animation_steps + 1):
                # process events so the gui thread does respond to interactions..
                self._process_events()
                # update loading windows text and progress bar
                processing = (i - first_frame_idx + 1) * animation_steps + j
                lw.set_message("Please wait!\nExporting frame %d/%d..." %
                               (processing, out_of))
                lw.set_progress(processing, out_of)
                self._viewer.set_animation_percentage(j / animation_steps)
                self._viewer.glDraw()
                img = self._viewer.get_frame_cv(width, height)
                writer.write(img)
        self._viewer.inject_record_data(self.recorder.records[last_frame_idx -
                                                              1])
        writer.release()
        lw.close()
        self._viewer.setDisabled(False)
        self._viewer.resizeGL(self._viewer.width(), self._viewer.height())
        self._viewer.update_scene()
        show_msg("Video exported successfully!", Level.INFO, self._splitter)

    def delete_recording(self):
        self.recorder = Recorder(self._world, self._viewer)
        self._splitter.setWindowTitle("Simulator")

    def set_antialiasing(self, value):
        if value <= 0:
            self._viewer.disable_aa()
        else:
            self._viewer.enable_aa(value)

    def take_vector_screenshot(self):
        if self._world.grid.__class__.__name__ == "TriangularGrid":
            if not os.path.exists("outputs/screenshots") or not os.path.isdir(
                    "outputs/screenshots"):
                os.mkdir("outputs/screenshots")
            directory = "."
            if os.path.exists("outputs/screenshots") and os.path.isdir(
                    "outputs/screenshots"):
                directory = "outputs/screenshots"

            path = TopQFileDialog(self._splitter).getSaveFileName(
                options=(TopQFileDialog.Options()),
                filter="*.svg",
                directory=directory)
            if path[0] == '':
                return

            if path[0].endswith(".svg"):
                create_svg(self._world, path[0])
            else:
                create_svg(self._world, path[0] + ".svg")
        else:
            show_msg(
                "Not implemented yet.\nWorks only with Triangular Grid for now!\nSorry!",
                Level.WARNING, self._splitter)

    def set_animation(self, animation):
        if not animation:
            self._viewer.set_animation_percentage(1)
        self._animation = animation

    def get_animation(self):
        return self._animation

    def set_auto_animation(self, auto_animation):
        self._auto_animation = auto_animation

    def get_auto_animation(self):
        return self._auto_animation

    def set_manual_animation_speed(self, manual_animation_speed):
        self._manual_animation_speed = manual_animation_speed

    def get_manual_animation_speed(self):
        return self._manual_animation_speed

    def get_main_window(self):
        return self._splitter

    def set_reset_flag(self):
        self._reset_flag = True