def scalePolygon(polygon, orig_size, new_size): ret_poly = QPolygon() for point_idx in range(polygon.size()): point = polygon.point(point_idx) scaled_point = scalePoint(point, orig_size, new_size) ret_poly.append(scaled_point) return ret_poly
def updateOverlay(self, rect=None): # Redraw the overlay image from scratch using the location image and current location. self.image.overlay_image.fill(Qt.transparent) painter = QPainter(self.image.overlay_image) painter.setBackgroundMode(Qt.TransparentMode) painter.setCompositionMode(QPainter.CompositionMode_Source) for location in self.locations: if self.draw_location[location]: color = self.location_colors[location] if self.edit_properties_location == location and self.editing_properties: color = self.edit_area_selection_color lineColor = QColor(color) lineColor.setAlpha(255) brushColor = QColor(color) brushColor.setAlpha(128) painter.setPen(lineColor) painter.setBrush(brushColor) painter.drawPolygon(self.locations[location]) if (self.current_selection is not None) or (self.new_selection is not None): lineColor = QColor(self.edit_area_selection_color) lineColor.setAlpha(255) brushColor = QColor(self.edit_area_selection_color) brushColor.setAlpha(128) painter.setPen(lineColor) painter.setBrush(brushColor) if self.new_selection is not None: # Create a temporary polygon as the new selection is being drawn. if self.current_selection is not None: current_selection = QPolygon(self.current_selection) if self.subtract_new_selection: current_selection = current_selection.subtracted( self.new_selection) else: current_selection = current_selection.united( self.new_selection) painter.drawPolygon(current_selection) elif self.subtract_new_selection == False: painter.drawPolygon(self.new_selection) else: painter.drawPolygon(self.current_selection) painter.end() if rect is None: self.image.update() else: self.image.update(rect)
def startAreaEdit(self, edit_type): if self.editing_properties: self.endPropertyEdit() self.editing_area = True if edit_type == LocationFunction.ADD_LOCATION_AREA: self.edit_existing_location = None # else edit_existing_location was set to the correct location by startPropertyEdit() # Make sure all active selections have been cleared. self.clearAreaSelection() # If we're going to edit an existing area, stop drawing it and copy it to the active selection. if self.edit_existing_location is not None: self.draw_location[self.edit_existing_location] = False self.current_selection = QPolygon( self.locations[self.edit_existing_location]) self.edit_existing_location = self.edit_existing_location # Setup the buttons in the configuration toolbar, and disable the original buttons to edit an area. clearLayoutAndFixHeight(self.configuration_layout) for button_text in ["Done", "Cancel"]: button = QPushButton(button_text, self.widget) button.clicked[bool].connect(partial(self.endAreaEdit, button_text)) self.configuration_layout.addWidget(button) self.current_selection_label = QLabel(self.widget) self.configuration_layout.addWidget(self.current_selection_label) self.configuration_layout.addStretch(1) self.edit_area_button[LocationFunction.ADD_LOCATION_AREA].setEnabled( False) self.edit_area_button[LocationFunction.EDIT_EXISTING_AREA].setEnabled( False) self.updateOverlay()
def readLocationsFromFile(self): if os.path.isfile(self.location_file): stream = open(self.location_file, 'r') try: contents = yaml.load(stream) if "polygons" not in contents or "locations" not in contents: rospy.logerr( "YAML file found at " + self.location_file + ", but does not seem to have been written by this tool. I'm starting locations from scratch." ) else: location_keys = contents["locations"] location_polygons = contents["polygons"] for index, location in enumerate(location_keys): self.locations[location] = QPolygon() self.locations[location].setPoints( location_polygons[index]) self.locations[location] = scalePolygon( self.locations[location], self.map_size, self.image_size) (_, self.location_colors[location] ) = self.getUniqueNameAndColor() self.draw_location[location] = True except yaml.YAMLError: rospy.logerr( "File found at " + self.location_file + ", but cannot be parsed by YAML parser. I'm starting locations from scratch." ) stream.close() else: rospy.logwarn( "Location file not found at " + self.location_file + ". I'm starting locations from scratch and will attempt to write to this location before exiting." )
def mouseMoveEvent(self, event): if self.editing_area: # First make sure we update the region corresponding to the old mark. old_overlay_update_rect = self.get_rectangular_polygon( self.new_selection_start_point, self.new_selection_end_point) # Draw new mark, taking some care to reduce the size of the polygon's bottom right corner by (1,1). self.new_selection_end_point = event.pos() self.new_selection = self.get_rectangular_polygon( self.new_selection_start_point, self.new_selection_end_point) self.new_selection = self.new_selection.boundingRect() self.new_selection.setHeight(self.new_selection.height() - 1) self.new_selection.setWidth(self.new_selection.width() - 1) self.new_selection = QPolygon(self.new_selection, True) # Next determine the region that needs to be update because of the new mark. new_overlay_update_rect = self.get_rectangular_polygon( self.new_selection_start_point, self.new_selection_end_point) overlay_update_region = (old_overlay_update_rect + new_overlay_update_rect).boundingRect() self.updateOverlay(overlay_update_region)
def get_rectangular_polygon(self, pt1, pt2): return QPolygon( [pt1, QPoint(pt1.x(), pt2.y()), pt2, QPoint(pt2.x(), pt1.y())])
def inflatePolygon(polygon): union = QPolygon() # grid on [-1, 1] for x, y in zip(range(-1, 2), range(-1, 2)): union = union.united(polygon.translated(x, y)) return union