def create_remote_brick_instance(self, brick: Brick):

        def create_callback(response: dict):

            if "placement_allowed" in response:
                if response["placement_allowed"]:

                    # set the remote asset id
                    #FIXME: does this reference to the brick instance work?
                    brick.object_id = int(response["object_id"])

                else:
                    logger.info("placement of brick {} is not allowed".format(brick))
                    brick.status = BrickStatus.OUTDATED_BRICK

            else:
                logger.warning("protocol error which creating brick {}".format(brick))
                # TODO: should the brick status change?

        logger.debug("creating a brick instance for {}".format(brick))

        # Compute geographical coordinates for bricks
        Extent.calc_world_pos(brick, self.extent_tracker.board, self.extent_tracker.map_extent)

        # Send request creating remote brick instance and save the response
        message = SEND_REC_CREATE_OBJECT_MSG.copy()
        message["shape"] = str(brick.token.shape).replace("BrickShape.", "")
        message["color"] = str(brick.token.color).replace("BrickColor.", "")
        message["position_x"] = brick.map_pos_x
        message["position_y"] = brick.map_pos_y

        self.send_message(message, create_callback)
    def game_mode_change(self, response: dict):

        logger.info("the landscapelab tries to change the game mode")

        if "projection_epsg" in response:
            epsg = int(response["projection_epsg"])
        else:
            epsg = self.config.get("map_settings", "coordinate_reference_system")

        # calculate the main map extent based on the starting location
        start_position = Vector(float(response["start_position_x"]), float(response["start_position_y"]))
        width = float(response["start_extent_x"])
        height = float(response["start_extent_y"])
        start_extent = Extent.around_center(start_position, width, height/width)
        self.extent_tracker.map_extent = start_extent

        # setup the minimap extent
        mm_min_x = float(response["minimap_min_x"])
        mm_min_y = float(response["minimap_min_y"])
        mm_max_x = float(response["minimap_max_x"])
        mm_max_y = float(response["minimap_max_y"])
        minimap_extent = Extent(mm_min_x, mm_min_y, mm_max_x, mm_max_y)

        # change the maps
        self.mini_map.initialize_map(epsg, minimap_extent)
        self.main_map.initialize_map(epsg, start_extent)

        # reset the tracker and feed him the allowed brick combinations
        allowed_bricks = []
        for token_dict in response["used_tokens"]:
            shape = BrickShape[token_dict["shape"]]
            color = BrickColor[token_dict["color"]]
            icon_id = token_dict["icon_name"] 
            brick_config.icon_config[(token_dict["shape"], token_dict["color"])] = icon_id

            disappear = float(token_dict["disappear_after_seconds"])  # FIXME: to be implemented
            token = Token(shape, color, icon_id)  # FIXME: currently the svg is not implemented (coded via icon names)
            allowed_bricks.append(token)
        self.tracker.change_game_mode(allowed_bricks)

        # add new tokens
        for brick in response["existing_tokens"]:
            self.create_local_brick(brick)

        # create the scores for the new game mode
        scores = []
        for score_dict in response["scores"]:
            score_id = int(score_dict["score_id"])
            initial_value = float(score_dict["initial_value"])
            target_value = float(score_dict["target_value"])
            name = ""
            if score_dict["name"]:
                name = score_dict["name"]
            score = Score(score_id, target_value, initial_value, name)
            scores.append(score)
        UISetup.add_progressbars_to_ui(self.progressbars_ui, self.config, scores)

        # finally set to EXTERNAL ProgramStage
        self.program_stage.next()
Example #3
0
    def set_virtual_brick_at_global_pos_of(self, brick: Brick):

        virtual_brick = brick.clone()
        Extent.calc_local_pos(virtual_brick, self.extent_tracker.board,
                              self.extent_tracker.map_extent)

        self.virtual_bricks.append(virtual_brick)
        Tracker.BRICKS_REFRESHED = True
Example #4
0
    def __init__(self, config: Configurator, name: str, extent: Extent,
                 zoom_limits: Tuple[int, int], resolution: Tuple[int, int]):

        self.name = name
        self.config = config
        self.extent_tracker = ExtentTracker.get_instance()
        self.min_zoom, self.max_zoom = zoom_limits

        # set resolution
        self.resolution_x, self.resolution_y = resolution

        # initialize two black images
        self.map_image = [
            ImageHandler.ensure_alpha_channel(
                np.ones((self.resolution_y, self.resolution_x, 3), np.uint8) *
                255),
            ImageHandler.ensure_alpha_channel(
                np.ones(
                    (self.resolution_y, self.resolution_x, 3), np.uint8) * 255)
        ]
        self.current_image = 0

        # crs is initialized with a local configuration but overwritten once a connection with the LL is established
        self.crs = config.get("map_settings", "coordinate_reference_system")
        extent.fit_to_ratio(self.resolution_y / self.resolution_x)
        self.current_extent: Extent = extent

        # set extent modifiers
        pan_up_modifier = np.array([0, 1, 0, 1])
        pan_down_modifier = np.array([0, -1, 0, -1])
        pan_left_modifier = np.array([-1, 0, -1, 0])
        pan_right_modifier = np.array([1, 0, 1, 0])
        self.zoom_in_modifier = np.array([1, 1, -1, -1])
        self.zoom_out_modifier = np.array([-1, -1, 1, 1])

        # get navigation settings
        pan_distance = config.get('map_settings', 'pan_distance')
        zoom_strength = config.get('map_settings', 'zoom_strength')

        # these functions can be used to interact with the map
        # by calling these functions one can pan and zoom on the map
        # the functions will automatically request a new rendered map extent from the QGIS plugin
        # they need accept an unused brick parameter to make it possible to call these functions via UICallback
        self.pan_up = partial(self.modify_extent, pan_up_modifier,
                              pan_distance)
        self.pan_down = partial(self.modify_extent, pan_down_modifier,
                                pan_distance)
        self.pan_left = partial(self.modify_extent, pan_left_modifier,
                                pan_distance)
        self.pan_right = partial(self.modify_extent, pan_right_modifier,
                                 pan_distance)
        self.zoom_in = partial(self.modify_extent, self.zoom_in_modifier,
                               zoom_strength)
        self.zoom_out = partial(self.modify_extent, self.zoom_out_modifier,
                                zoom_strength)
Example #5
0
    def __init__(self,
                 config: Configurator,
                 position: Vector,
                 size: Vector,
                 color: List = None,
                 border_color: List = None,
                 border_weight: float = None):

        super().__init__()

        # overwrite none values with defaults
        if color is None:
            color = config.get("ui_settings", "nav_block_background_color")
        if border_color is None:
            border_color = config.get("ui_settings", "nav_block_border_color")
        if border_weight is None:
            border_weight = config.get("ui_settings",
                                       "nav_block_border_weight")

        # set block position/size
        self.position = position  # only modify with set_position
        self.size = size  # only modify with set_size
        self.area = Extent.from_vectors(position, position + size,
                                        False)  # only modify with set_area
        self.is_ellipse = False

        # set block color
        self.color = (color[0], color[1], color[2])
        self.show_background_color = True

        self.border_thickness: float = border_weight
        self.border_color = (border_color[0], border_color[1], border_color[2])
        self.show_border = True
    def beamer_mouse_callback(self, event, x, y, flags, param):

        if self.program_stage.current_stage == ProgramStage.INTERNAL_MODE \
                or self.program_stage.current_stage == ProgramStage.EXTERNAL_MODE:

            if event == cv2.EVENT_LBUTTONDOWN or event == cv2.EVENT_RBUTTONDOWN:

                color = BrickColor.BLUE_BRICK
                if event == cv2.EVENT_RBUTTONDOWN:
                    color = BrickColor.RED_BRICK

                # create brick on mouse position
                mouse_brick = Extent.remap_brick(Brick(x, y, Token(BrickShape.SQUARE_BRICK, color)),
                                                 
                    self.extent_tracker.beamer, self.extent_tracker.board
                )

                # check for nearby virtual bricks
                virtual_brick = self.tracker.check_min_distance(mouse_brick, self.tracker.virtual_bricks)

                if virtual_brick:
                    # if mouse brick is on top of other virtual brick, remove that brick
                    self.tracker.remove_external_virtual_brick(virtual_brick)
                else:
                    # otherwise add the mouse brick
                    self.tracker.virtual_bricks.append(mouse_brick)

                # set mouse brick refreshed flag
                TableOutputStream.MOUSE_BRICKS_REFRESHED = True
Example #7
0
    def mark_external_bricks_outdated_if_map_updated(self):

        # if the extent changed, set external bricks as outdated
        self.extent_changed = self.extent_tracker.extent_changed
        if self.extent_changed is True:

            logger.debug("recalculate virtual brick position")
            for brick in self.virtual_bricks:
                if brick.status == BrickStatus.EXTERNAL_BRICK:
                    Extent.calc_local_pos(brick, self.extent_tracker.board,
                                          self.extent_tracker.map_extent)

            logger.info("set bricks outdated because extent changed")
            self.invalidate_external_bricks()

            # set the flag back
            self.extent_tracker.extent_changed = False
Example #8
0
    def get_start_extent(self):
        starting_location = Vector(self.config.get("map_settings", "start_x"),
                                   self.config.get("map_settings", "start_y"))

        # extrude start location to start extent
        zoom = self.config.get("map_settings", "start_zoom")

        return Extent.around_center(starting_location, zoom, 1)
    def compute_board_size(self, corners):

        min_x, min_y, max_x, max_y = self.find_min_max(corners)

        # Compute board size
        self.board.width = max_x - min_x
        self.board.height = max_y - min_y

        ExtentTracker.get_instance().board = Extent.from_rectangle(0, 0, self.board.width, self.board.height)
        logger.info('board has been set to {}'.format(ExtentTracker.get_instance().board))
Example #10
0
        def render_callback(response: dict):

            extent = Extent(float(response["extent"]["x_min"]),
                            float(response["extent"]["y_min"]),
                            float(response["extent"]["x_max"]),
                            float(response["extent"]["y_max"]),
                            True)

            # convert response to the bytebuffer
            base64_bytes = response["image"].encode("ascii")
            buffer = base64.standard_b64decode(base64_bytes)

            self.callbacks[response["target"]].refresh(extent, buffer)
    def set_screen_config_info(config):

        monitors = screeninfo.get_monitors()

        config.set("screen_resolution", "width", monitors[0].width)
        config.set("screen_resolution", "height", monitors[0].height)
        config.set("screen_resolution", "pos_x", monitors[0].x - 1)
        config.set("screen_resolution", "pos_y", monitors[0].y - 1)

        beamer_id = config.get("beamer_resolution", "screen_id")
        if beamer_id >= 0:
            # if beamer-id out of bounds use last screen
            beamer_id = min(beamer_id, len(monitors) - 1)

            beamer = monitors[beamer_id]
            config.set("beamer_resolution", "width", beamer.width)
            config.set("beamer_resolution", "height", beamer.height)
            config.set("beamer_resolution", "pos_x", beamer.x - 1)
            config.set("beamer_resolution", "pos_y", beamer.y - 1)

            ExtentTracker.get_instance().beamer = Extent(0, 0, beamer.width, beamer.height)
Example #12
0
 def ellipse(img, area: Extent, color, border_thickness):
     cv.ellipse(img,
                area.get_center().as_point(),
                (area.get_size() / 2).as_point(), 0, 0, 360, color,
                border_thickness)
Example #13
0
 def rectangle(img, area: Extent, color, border_thickness):
     cv.rectangle(img,
                  area.get_upper_left().as_point(),
                  area.get_lower_right().as_point(), color,
                  border_thickness)
Example #14
0
 def set_area(self, area: Extent):
     self.position = area.get_upper_left
     self.size = area.get_size()
     self.area = area
Example #15
0
    def brick_would_land_on_ui(self, brick):

        brick_on_beamer = Extent.remap_brick(brick, self.extent_tracker.board,
                                             self.extent_tracker.beamer)
        return self.ui_root.brick_would_land_on_element(brick_on_beamer)
Example #16
0
 def get_global_area(self) -> Extent:
     pos = self.get_global_pos()
     return Extent.from_vectors(pos, pos + self.size)
Example #17
0
class UIStructureBlock(UIElement):
    def __init__(self,
                 config: Configurator,
                 position: Vector,
                 size: Vector,
                 color: List = None,
                 border_color: List = None,
                 border_weight: float = None):

        super().__init__()

        # overwrite none values with defaults
        if color is None:
            color = config.get("ui_settings", "nav_block_background_color")
        if border_color is None:
            border_color = config.get("ui_settings", "nav_block_border_color")
        if border_weight is None:
            border_weight = config.get("ui_settings",
                                       "nav_block_border_weight")

        # set block position/size
        self.position = position  # only modify with set_position
        self.size = size  # only modify with set_size
        self.area = Extent.from_vectors(position, position + size,
                                        False)  # only modify with set_area
        self.is_ellipse = False

        # set block color
        self.color = (color[0], color[1], color[2])
        self.show_background_color = True

        self.border_thickness: float = border_weight
        self.border_color = (border_color[0], border_color[1], border_color[2])
        self.show_border = True

    # draws the block onto an image
    def draw(self, img):

        if self.visible:

            self.draw_background(img, self.color)
            self.draw_border(img, self.border_color)

            self.draw_hierarchy(img)

    # draws the background of the structure block onto an image
    def draw_background(self, img, color, force=False):

        if self.show_background_color or force:

            if self.is_ellipse:
                # draw ellipse
                UIStructureBlock.ellipse(img, self.get_global_area(), color,
                                         cv.FILLED)

            else:
                # draw rect
                UIStructureBlock.rectangle(img, self.get_global_area(), color,
                                           cv.FILLED)

    # draws the border of the structure block onto an image
    def draw_border(self, img, color, force=False):

        if self.show_border or force:

            if self.is_ellipse:
                # draw ellipse
                UIStructureBlock.ellipse(img, self.get_global_area(), color,
                                         self.border_thickness)

            else:
                # draw rect
                UIStructureBlock.rectangle(img, self.get_global_area(), color,
                                           self.border_thickness)

    # checks if a given brick lies on top of the block or any of it's children
    def brick_on_element(self, brick: Brick) -> bool:
        if self.visible:
            return super().brick_on_element(brick) or self.pos_on_block(
                Vector.from_brick(brick))
        return False

    # checks if a given (unconfirmed) brick would land on top of the block or any of it's children
    def brick_would_land_on_element(self, brick: Brick) -> bool:
        if self.visible:
            return super().brick_would_land_on_element(
                brick) or self.pos_on_block(Vector.from_brick(brick))
        return False

    # checks if any screen coordinate lies on top of
    def pos_on_block(self, pos: Vector) -> bool:
        if self.visible:
            return self.get_global_area().vector_inside(pos)
        return False

    # get the global area as extent
    def get_global_area(self) -> Extent:
        pos = self.get_global_pos()
        return Extent.from_vectors(pos, pos + self.size)

    # overwrites current position
    # also updates area
    def set_position(self, pos: Vector):
        self.area.move_by(pos - self.position)
        super().set_position(pos)

    # overwrites current size and updates area
    def set_size(self, size: Vector):
        self.area = Extent(self.area.get_upper_left(), self.position + size)
        self.size = size

    # overwrites current area and updates size and position
    def set_area(self, area: Extent):
        self.position = area.get_upper_left
        self.size = area.get_size()
        self.area = area

    # draws a rectangle using a given area
    @staticmethod
    def rectangle(img, area: Extent, color, border_thickness):
        cv.rectangle(img,
                     area.get_upper_left().as_point(),
                     area.get_lower_right().as_point(), color,
                     border_thickness)

    # draws a rectangle using a given area
    @staticmethod
    def ellipse(img, area: Extent, color, border_thickness):
        cv.ellipse(img,
                   area.get_center().as_point(),
                   (area.get_size() / 2).as_point(), 0, 0, 360, color,
                   border_thickness)
    def render_brick(self, brick, render_target, virtual=False):
        b = Extent.remap_brick(brick, self.extent_tracker.board, self.extent_tracker.beamer)
        pos = (int(b.centroid_x), int(b.centroid_y))
        icon = self.get_brick_icon(brick, virtual)

        ImageHandler.img_on_background(render_target, icon, pos)
Example #19
0
 def add_external_brick(self, brick: Brick):
     # TODO: maybe add security checks to not add the same brick twice etc?
     Extent.calc_local_pos(brick, self.extent_tracker.board,
                           self.extent_tracker.map_extent)
     self.virtual_bricks.append(brick)
Example #20
0
 def set_size(self, size: Vector):
     self.area = Extent(self.area.get_upper_left(), self.position + size)
     self.size = size