def showMoveHelper(self, visible=True): """show help text In empty HandBoards""" if visible: if not self.__moveHelper: splitter = QGraphicsRectItem(self) hbCenter = self.rect().center() splitter.setRect(hbCenter.x() * 0.5, hbCenter.y(), hbCenter.x() * 1, 1) helpItems = [splitter] for name, yFactor in [(m18n('Move Exposed Tiles Here'), 0.5), (m18n('Move Concealed Tiles Here'), 1.5)]: helper = QGraphicsSimpleTextItem(name, self) helper.setScale(3) nameRect = QRectF() nameRect.setSize(helper.mapToParent(helper.boundingRect()).boundingRect().size()) center = QPointF(hbCenter) center.setY(center.y() * yFactor) helper.setPos(center - nameRect.center()) if self.sceneRotation() == 180: rotateCenter(helper, 180) helpItems.append(helper) self.__moveHelper = self.scene().createItemGroup(helpItems) self.__moveHelper.setVisible(True) else: if self.__moveHelper: self.__moveHelper.setVisible(False)
def decoratePlayer(self, player): """show player info on the wall""" side = player.front sideCenter = side.center() name = side.nameLabel if player.handBoard: player.newHandContent = player.computeNewHand() name.setText(' - '.join( [player.localName, unicode(player.newHandContent.total())])) else: name.setText(player.localName) name.resetTransform() if side.rotation() == 180: rotateCenter(name, 180) nameRect = QRectF() nameRect.setSize( name.mapToParent(name.boundingRect()).boundingRect().size()) name.setPos(sideCenter - nameRect.center()) player.colorizeName() side.windTile.setWind(player.wind, self.game.roundsFinished) side.windTile.resetTransform() side.windTile.setPos( sideCenter.x() * 1.63, sideCenter.y() - side.windTile.rect().height() / 2.5) side.nameLabel.show() side.windTile.show()
def grab_svg(scene): """ Return a SVG rendering of the scene contents. Parameters ---------- scene : :class:`CanvasScene` """ from PyQt4.QtSvg import QSvgGenerator svg_buffer = QBuffer() gen = QSvgGenerator() gen.setOutputDevice(svg_buffer) items_rect = scene.itemsBoundingRect().adjusted(-10, -10, 10, 10) if items_rect.isNull(): items_rect = QRectF(0, 0, 10, 10) width, height = items_rect.width(), items_rect.height() rect_ratio = float(width) / height # Keep a fixed aspect ratio. aspect_ratio = 1.618 if rect_ratio > aspect_ratio: height = int(height * rect_ratio / aspect_ratio) else: width = int(width * aspect_ratio / rect_ratio) target_rect = QRectF(0, 0, width, height) source_rect = QRectF(0, 0, width, height) source_rect.moveCenter(items_rect.center()) gen.setSize(target_rect.size().toSize()) gen.setViewBox(target_rect) painter = QPainter(gen) # Draw background. painter.setBrush(QBrush(Qt.white)) painter.drawRect(target_rect) # Render the scene scene.render(painter, target_rect, source_rect) painter.end() buffer_str = str(svg_buffer.buffer()) return unicode(buffer_str.decode("utf-8"))
def drawToolButtonContent(self, option, painter, widget): if option.state & QStyle.State_Enabled: pixmap = widget.pixmap(QIcon.Normal) else: pixmap = widget.pixmap(QIcon.Disabled) if not pixmap.isNull(): margin = self._pixel_metrics[QStyle.PM_DefaultFrameWidth] + self._pixel_metrics[QStyle.PM_ButtonMargin] if option.features & QStyleOptionToolButton.MenuButtonPopup and option.direction == Qt.LeftToRight: right_offset = 1 else: right_offset = 0 content_rect = QRectF(self.proxy().subControlRect(QStyle.CC_ToolButton, option, QStyle.SC_ToolButton, widget)).adjusted(margin, margin, -margin-right_offset, -margin) pixmap_rect = QRectF(pixmap.rect()) pixmap_rect.moveCenter(content_rect.center()) painter.setRenderHint(QPainter.Antialiasing, True) painter.setCompositionMode(QPainter.CompositionMode_SourceOver) painter.drawPixmap(pixmap_rect.topLeft(), pixmap)
def decoratePlayer(self, player): """show player info on the wall""" side = player.front sideCenter = side.center() name = side.nameLabel if player.handBoard: player.newHandContent = player.computeNewHand() name.setText(' - '.join([player.localName, unicode(player.newHandContent.total())])) else: name.setText(player.localName) name.resetTransform() if side.rotation() == 180: rotateCenter(name, 180) nameRect = QRectF() nameRect.setSize(name.mapToParent(name.boundingRect()).boundingRect().size()) name.setPos(sideCenter - nameRect.center()) player.colorizeName() side.windTile.setWind(player.wind, self.game.roundsFinished) side.windTile.resetTransform() side.windTile.setPos(sideCenter.x()*1.63, sideCenter.y()-side.windTile.rect().height()/2.5) side.nameLabel.show() side.windTile.show()
def draw(self, painter, size=None): """ :Arguments: painter : QPainter Opened painter on which to draw """ bounding_rect = QRectF() position = self.position transfer_function = self.transfer_function font = QFont(self.font) text_color = self.text_color line_color = self.line_color line_thickness = self.line_thickness value_range = self.value_range if size is None: viewport = painter.viewport() # viewport rectangle mat, ok = painter.worldMatrix().inverted() if not ok: raise ValueError( "Transformation matrix of painter is singular.") viewport = mat.mapRect(viewport) else: viewport = size # First, prepare the gradient w = viewport.width() h = viewport.height() #print("Size of viewport: {0}x{1}".format(w, h)) gr = QLinearGradient() nb_values = ceil(w / 5.0) brush_color = QColor() for i in range(int(nb_values)): brush_color.setRgbF(*transfer_function.rgba(i / nb_values)) gr.setColorAt(i / nb_values, brush_color) # Second, find its position metric = QFontMetricsF(font, painter.device()) font_test = [str(i) * 5 for i in range(10)] lim_width = 0 lim_height = 0 for t in font_test: rect = metric.boundingRect(t) lim_width = max(lim_width, rect.width()) lim_height = max(lim_height, rect.height()) lim_height *= 3 length = self.scale_length shift_length = (1 - length) / 2 width = self.scale_width shift_width = self.scale_shift_width delta_value = value_range[1] - value_range[0] if position == "Top": scale_rect = QRectF(shift_length * w, shift_width * h, length * w, width * h) limit_rect(scale_rect, viewport, lim_width, lim_height) gr.setStart(scale_rect.left(), scale_rect.center().y()) gr.setFinalStop(scale_rect.right(), scale_rect.center().y()) start_pos = scale_rect.bottomLeft() end_pos = scale_rect.bottomRight() elif position == "Right": scale_rect = QRectF((1 - shift_width - width) * w, shift_length * h, width * w, length * h) limit_rect(scale_rect, viewport, lim_width, lim_height) gr.setStart(scale_rect.center().x(), scale_rect.bottom()) gr.setFinalStop(scale_rect.center().x(), scale_rect.top()) start_pos = scale_rect.bottomLeft() end_pos = scale_rect.topLeft() elif position == "Bottom": scale_rect = QRectF(shift_length * w, (1 - shift_width - width) * h, length * w, width * h) limit_rect(scale_rect, viewport, lim_width, lim_height) gr.setStart(scale_rect.left(), scale_rect.center().y()) gr.setFinalStop(scale_rect.right(), scale_rect.center().y()) start_pos = scale_rect.topLeft() end_pos = scale_rect.topRight() elif position == "Left": scale_rect = QRectF(shift_width * w, shift_length * h, width * w, length * h) limit_rect(scale_rect, viewport, lim_width, lim_height) gr.setStart(scale_rect.center().x(), scale_rect.bottom()) gr.setFinalStop(scale_rect.center().x(), scale_rect.top()) start_pos = scale_rect.bottomRight() end_pos = scale_rect.topRight() else: raise ValueError("Invalid scale position: %s" % position) shift_pos = (end_pos - start_pos) / delta_value if position in ["Left", "Right"]: is_vertical = True length = scale_rect.height() else: is_vertical = False length = scale_rect.width() # Get the ticks ticks = self.selectValues(length, is_vertical, painter) if len(ticks) == 0: return ticks_str, ticks_extra = self._tick2str(ticks) # Figure the shifts dist_to_bar = self.text_to_bar max_width = 0 max_height = 0 for t in ticks_str: rect = metric.boundingRect(t) max_width = max(rect.width(), max_width) max_height = max(rect.height(), max_height) if position == "Left": shift_left = dist_to_bar shift_top = None elif position == "Right": shift_left = -dist_to_bar - max_width shift_top = None elif position == "Top": shift_left = None shift_top = dist_to_bar else: shift_left = None shift_top = -dist_to_bar - max_height painter.save() painter.translate(viewport.topLeft()) #print("viewport.topLeft() = {0}x{1}".format(viewport.left(), viewport.top())) painter.setBrush(gr) line_pen = QPen(line_color) line_pen.setWidth(line_thickness) painter.setPen(line_pen) painter.drawRect(scale_rect) bounding_rect |= scale_rect #print("Scale rect: +{0}+{1}x{2}x{3}".format(scale_rect.left(), #scale_rect.top(), scale_rect.width(), scale_rect.height())) painter.setFont(font) painter.setPen(text_color) for ts, t in zip(ticks_str, ticks): r = metric.boundingRect(ts) pos = start_pos + shift_pos * (t - value_range[0]) if shift_left is None: pos.setX(pos.x() - r.width() / 2) else: pos.setX(pos.x() + shift_left) if shift_top is None: pos.setY(pos.y() - r.height() / 2) else: pos.setY(pos.y() + shift_top) r.moveTo(pos) real_rect = painter.drawText( r, Qt.TextDontClip | Qt.AlignVCenter | Qt.AlignHCenter, ts) bounding_rect |= real_rect if ticks_extra is not None or self.unit: unit = self.unit exp_width = width = space_width = 0 exp_txt = "" r = exp_r = unit_r = QRectF() exp_font = None if ticks_extra is not None: exp_txt = u"×10" r = metric.boundingRect(exp_txt) exp_font = QFont(font) exp_size = self.exp_size if exp_font.pixelSize() != -1: exp_font.setPixelSize(exp_size * exp_font.pixelSize()) else: exp_font.setPointSizeF(exp_size * exp_font.pointSizeF()) exp_metric = QFontMetricsF(exp_font, painter.device()) exp_r = exp_metric.boundingRect(ticks_extra) if unit: unit_r = metric.boundingRect(unit) total_width = r.width() + exp_r.width() + unit_r.width() total_height = max(r.height(), unit_r.height()) + exp_r.height() / 2 pos = scale_rect.topRight() log_debug("top right of scale bar = (%g,%g)" % (pos.x(), pos.y())) log_debug("Size of image = (%d,%d)" % (w, h)) log_debug("Size of text = (%g,%g)" % (total_width, total_height)) if position == "Bottom": pos.setY(pos.y() + scale_rect.height() + dist_to_bar) pos.setX(pos.x() - total_width) elif position == "Top": pos.setY(pos.y() - dist_to_bar - total_height) pos.setX(pos.x() - total_width) else: # position == "left" or "right" pos.setX(pos.x() - (scale_rect.width() + total_width) / 2) if pos.x() < 0: pos.setX(dist_to_bar) elif pos.x() + total_width + dist_to_bar > w: pos.setX(w - total_width - dist_to_bar) pos.setY(pos.y() - dist_to_bar - total_height) log_debug("Display unit at position: (%g,%g)" % (pos.x(), pos.y())) if ticks_extra is not None: r.moveTo(pos) real_rect = painter.drawText( r, Qt.TextDontClip | Qt.AlignVCenter | Qt.AlignHCenter, exp_txt) bounding_rect |= real_rect pos.setX(pos.x() + r.width()) pos.setY(pos.y() - metric.ascent() / 2) exp_r.moveTo(pos) painter.setFont(exp_font) real_rect = painter.drawText( exp_r, Qt.TextDontClip | Qt.AlignVCenter | Qt.AlignHCenter, ticks_extra) bounding_rect |= real_rect pos.setY(pos.y() + metric.ascent() / 2) if unit: pos.setX(pos.x() + space_width + exp_r.width()) unit_r.moveTo(pos) painter.setFont(font) real_rect = painter.drawText( unit_r, Qt.TextDontClip | Qt.AlignVCenter | Qt.AlignHCenter, unit) bounding_rect |= real_rect # Draw the ticks now painter.setPen(line_pen) tick_size = self.tick_size if is_vertical: width = scale_rect.width() * tick_size else: width = scale_rect.height() * tick_size pen_width = painter.pen().widthF() if pen_width == 0: pen_width = 1.0 for t in ticks: pos1 = start_pos + shift_pos * (t - value_range[0]) pos2 = QPointF(pos1) if is_vertical: pos1.setX(scale_rect.left() + pen_width) pos2.setX(pos1.x() + width - pen_width) painter.drawLine(pos1, pos2) pos1.setX(scale_rect.right() - pen_width) pos2.setX(pos1.x() - width + pen_width) painter.drawLine(pos1, pos2) else: pos1.setY(scale_rect.top() + pen_width) pos2.setY(pos1.y() + width - pen_width) painter.drawLine(pos1, pos2) pos1.setY(scale_rect.bottom() - pen_width) pos2.setY(pos1.y() - width + pen_width) painter.drawLine(pos1, pos2) painter.restore() bounding_rect = bounding_rect.adjusted(-pen_width, -pen_width, pen_width, pen_width) return bounding_rect
def rebuild( self ): """ Rebuilds the data for this scene to draw with. """ global XChartWidgetItem if ( XChartWidgetItem is None ): from projexui.widgets.xchartwidget.xchartwidgetitem \ import XChartWidgetItem self._buildData = {} # build the grid location x = 8 y = 8 w = self.sceneRect().width() h = self.sceneRect().height() hpad = self.horizontalPadding() vpad = self.verticalPadding() hmax = self.horizontalRuler().maxNotchSize(Qt.Horizontal) left_offset = hpad + self.verticalRuler().maxNotchSize(Qt.Vertical) right_offset = left_offset + hpad top_offset = vpad bottom_offset = top_offset + vpad + hmax left = x + left_offset right = w - right_offset top = y + top_offset bottom = h - bottom_offset rect = QRectF() rect.setLeft(left) rect.setRight(right) rect.setBottom(bottom) rect.setTop(top) self._buildData['grid_rect'] = rect # rebuild the ruler data self.rebuildGrid() self._dirty = False # rebuild all the items padding = self.horizontalPadding() + self.verticalPadding() grid = self.sceneRect() filt = lambda x: isinstance(x, XChartWidgetItem) items = filter(filt, self.items()) height = float(grid.height()) if height == 0: ratio = 1 else: ratio = grid.width() / height count = len(items) if ( not count ): return if ( ratio >= 1 ): radius = (grid.height() - padding * 2) / 2.0 x = rect.center().x() y = rect.center().y() dx = radius * 2.5 dy = 0 else: radius = (grid.width() - padding * 2) / 2.0 x = rect.center().x() y = rect.center().y() dx = 0 dy = radius * 2.5 for item in items: item.setPieCenter(QPointF(x, y)) item.setRadius(radius) item.rebuild() x += dx y += dy if ( self._trackerItem and self._trackerItem() ): self._trackerItem().rebuild(self._buildData['grid_rect'])
def rebuild(self): """ Rebuilds the data for this scene to draw with. """ global XChartWidgetItem if (XChartWidgetItem is None): from projexui.widgets.xchartwidget.xchartwidgetitem \ import XChartWidgetItem self._buildData = {} # build the grid location x = 8 y = 8 w = self.sceneRect().width() h = self.sceneRect().height() hpad = self.horizontalPadding() vpad = self.verticalPadding() hmax = self.horizontalRuler().maxNotchSize(Qt.Horizontal) left_offset = hpad + self.verticalRuler().maxNotchSize(Qt.Vertical) right_offset = left_offset + hpad top_offset = vpad bottom_offset = top_offset + vpad + hmax left = x + left_offset right = w - right_offset top = y + top_offset bottom = h - bottom_offset rect = QRectF() rect.setLeft(left) rect.setRight(right) rect.setBottom(bottom) rect.setTop(top) self._buildData['grid_rect'] = rect # rebuild the ruler data self.rebuildGrid() self._dirty = False # rebuild all the items padding = self.horizontalPadding() + self.verticalPadding() grid = self.sceneRect() filt = lambda x: isinstance(x, XChartWidgetItem) items = filter(filt, self.items()) height = float(grid.height()) if height == 0: ratio = 1 else: ratio = grid.width() / height count = len(items) if (not count): return if (ratio >= 1): radius = (grid.height() - padding * 2) / 2.0 x = rect.center().x() y = rect.center().y() dx = radius * 2.5 dy = 0 else: radius = (grid.width() - padding * 2) / 2.0 x = rect.center().x() y = rect.center().y() dx = 0 dy = radius * 2.5 for item in items: item.setPieCenter(QPointF(x, y)) item.setRadius(radius) item.rebuild() x += dx y += dy if (self._trackerItem and self._trackerItem()): self._trackerItem().rebuild(self._buildData['grid_rect'])
def alignImages(data, alignment_data, translation, rotation): """ Align the images in data using the points found in alignment_data. Arguments: - data, TrackingData: data set to align - alignment_data, TrackingData: data set used for the alignment - translation, (str|int): type of translation. Valid values are: * "Bounding-box centre" * "Barycentre" * Any point if in alignment_data - rotation, (str,int,int): type of rotation. The first value is the rotation type. For now, it has to be "TwoPoint". The two other values are the points id used for the rotation. """ # First, check the alignment data is valid #pts = alignment_data[alignment_data.images_name[0]].points() a = scipy.zeros(len(data), dtype=float) if rotation is not None: assert len(rotation) == 3 assert rotation[0] == "TwoPoint" r1 = rotation[1] r2 = rotation[2] for d in alignment_data: if not r1 in d: raise AlgoException("Image %s doesn't contain point %d." % (d._current_image, r1)) if not r2 in d: raise AlgoException("Image %s doesn't contain point %d." % (d._current_image, r2)) # Then, compute the rotation vecs = scipy.zeros((len(data), 2), dtype=float) for i, d in enumerate(alignment_data): v = d[r2] - d[r1] vecs[i, :] = (v.x(), v.y()) a = scipy.arctan2(vecs[:, 1], vecs[:, 0]) a = a[0] - a # At last, compute the translation using the reference refs = scipy.zeros((len(data), 2), dtype=float) if translation == "Bounding-box centre": for i, d in enumerate(alignment_data): mat, _ = d.matrix().inverted() p1 = None rect = QRectF() for p in d.positions(): p = mat.map(p) if p1 is None: p1 = p else: rect |= QRectF(p1, p).normalized() mid_pos = rect.center() refs[i, :] = (mid_pos.x(), mid_pos.y()) elif translation == "Barycentre": for i, d in enumerate(alignment_data): mat, _ = d.matrix().inverted() mid_pos = mat.map(sum(d.positions(), QPointF())/len(d)) refs[i, :] = (mid_pos.x(), mid_pos.y()) else: for i, d in enumerate(alignment_data): mat, _ = d.matrix().inverted() if not translation in d: s = "Error, point %d is not in image %s. Cannot use it to align images." raise AlgoException(s % (translation, d.image_name)) pos = mat.map(d[translation]) refs[i, :] = (pos.x(), pos.y()) moved_refs = refs*cos(a)[:, newaxis] + c_[-refs[:, 1], refs[:, 0]]*sin(a)[:, newaxis] moved_refs = moved_refs[0, :] - moved_refs a *= 180/math.pi return moved_refs, a
def draw(self, painter, size = None): """ :Arguments: painter : QPainter Opened painter on which to draw """ bounding_rect = QRectF() position = self.position transfer_function = self.transfer_function font = QFont(self.font) text_color = self.text_color line_color = self.line_color line_thickness = self.line_thickness value_range = self.value_range if size is None: viewport = painter.viewport() # viewport rectangle mat, ok = painter.worldMatrix().inverted() if not ok: raise ValueError("Transformation matrix of painter is singular.") viewport = mat.mapRect(viewport) else: viewport = size # First, prepare the gradient w = viewport.width() h = viewport.height() #print("Size of viewport: {0}x{1}".format(w, h)) gr = QLinearGradient() nb_values = ceil(w/5.0) brush_color = QColor() for i in range(int(nb_values)): brush_color.setRgbF(*transfer_function.rgba(i/nb_values)) gr.setColorAt(i/nb_values, brush_color) # Second, find its position metric = QFontMetricsF(font, painter.device()) font_test = [ str(i)*5 for i in range(10) ] lim_width = 0 lim_height = 0 for t in font_test: rect = metric.boundingRect(t) lim_width = max(lim_width, rect.width()) lim_height = max(lim_height, rect.height()) lim_height *= 3 length = self.scale_length shift_length = (1-length)/2 width = self.scale_width shift_width = self.scale_shift_width delta_value = value_range[1]-value_range[0] if position == "Top": scale_rect = QRectF(shift_length*w, shift_width*h, length*w, width*h) limit_rect(scale_rect, viewport, lim_width, lim_height) gr.setStart(scale_rect.left(), scale_rect.center().y()) gr.setFinalStop(scale_rect.right(), scale_rect.center().y()) start_pos = scale_rect.bottomLeft() end_pos = scale_rect.bottomRight() elif position == "Right": scale_rect = QRectF((1-shift_width-width)*w, shift_length*h, width*w, length*h) limit_rect(scale_rect, viewport, lim_width, lim_height) gr.setStart(scale_rect.center().x(), scale_rect.bottom()) gr.setFinalStop(scale_rect.center().x(), scale_rect.top()) start_pos = scale_rect.bottomLeft() end_pos = scale_rect.topLeft() elif position == "Bottom": scale_rect = QRectF(shift_length*w, (1-shift_width-width)*h, length*w, width*h) limit_rect(scale_rect, viewport, lim_width, lim_height) gr.setStart(scale_rect.left(), scale_rect.center().y()) gr.setFinalStop(scale_rect.right(), scale_rect.center().y()) start_pos = scale_rect.topLeft() end_pos = scale_rect.topRight() elif position == "Left": scale_rect = QRectF(shift_width*w, shift_length*h, width*w, length*h) limit_rect(scale_rect, viewport, lim_width, lim_height) gr.setStart(scale_rect.center().x(), scale_rect.bottom()) gr.setFinalStop(scale_rect.center().x(), scale_rect.top()) start_pos = scale_rect.bottomRight() end_pos = scale_rect.topRight() else: raise ValueError("Invalid scale position: %s" % position) shift_pos = (end_pos-start_pos)/delta_value if position in ["Left", "Right"]: is_vertical = True length = scale_rect.height() else: is_vertical = False length = scale_rect.width() # Get the ticks ticks = self.selectValues(length, is_vertical, painter) if len(ticks) == 0: return ticks_str, ticks_extra = self._tick2str(ticks) # Figure the shifts dist_to_bar = self.text_to_bar max_width = 0 max_height = 0 for t in ticks_str: rect = metric.boundingRect(t) max_width = max(rect.width(), max_width) max_height = max(rect.height(), max_height) if position == "Left": shift_left = dist_to_bar shift_top = None elif position == "Right": shift_left = -dist_to_bar-max_width shift_top = None elif position == "Top": shift_left = None shift_top = dist_to_bar else: shift_left = None shift_top = -dist_to_bar-max_height painter.save() painter.translate(viewport.topLeft()) #print("viewport.topLeft() = {0}x{1}".format(viewport.left(), viewport.top())) painter.setBrush(gr) line_pen = QPen(line_color) line_pen.setWidth(line_thickness) painter.setPen(line_pen) painter.drawRect(scale_rect) bounding_rect |= scale_rect #print("Scale rect: +{0}+{1}x{2}x{3}".format(scale_rect.left(), #scale_rect.top(), scale_rect.width(), scale_rect.height())) painter.setFont(font) painter.setPen(text_color) for ts,t in zip(ticks_str, ticks): r = metric.boundingRect(ts) pos = start_pos+shift_pos*(t-value_range[0]) if shift_left is None: pos.setX( pos.x() - r.width()/2 ) else: pos.setX( pos.x() + shift_left ) if shift_top is None: pos.setY( pos.y() - r.height()/2) else: pos.setY( pos.y() + shift_top ) r.moveTo(pos) real_rect = painter.drawText(r, Qt.TextDontClip | Qt.AlignVCenter | Qt.AlignHCenter, ts) bounding_rect |= real_rect if ticks_extra is not None or self.unit: unit = self.unit exp_width = width = space_width = 0 exp_txt = "" r = exp_r = unit_r = QRectF() exp_font = None if ticks_extra is not None: exp_txt = u"×10" r = metric.boundingRect(exp_txt) exp_font = QFont(font) exp_size = self.exp_size if exp_font.pixelSize() != -1: exp_font.setPixelSize(exp_size*exp_font.pixelSize()) else: exp_font.setPointSizeF(exp_size*exp_font.pointSizeF()) exp_metric = QFontMetricsF(exp_font, painter.device()) exp_r = exp_metric.boundingRect(ticks_extra) if unit: unit_r = metric.boundingRect(unit) total_width = r.width()+exp_r.width()+unit_r.width() total_height = max(r.height(),unit_r.height())+exp_r.height()/2 pos = scale_rect.topRight() log_debug("top right of scale bar = (%g,%g)" % (pos.x(), pos.y())) log_debug("Size of image = (%d,%d)" % (w,h)) log_debug("Size of text = (%g,%g)" % (total_width, total_height)) if position == "Bottom": pos.setY(pos.y() + scale_rect.height() + dist_to_bar) pos.setX(pos.x() - total_width) elif position == "Top": pos.setY(pos.y() - dist_to_bar - total_height) pos.setX(pos.x() - total_width) else: # position == "left" or "right" pos.setX(pos.x() - (scale_rect.width() + total_width)/2) if pos.x() < 0: pos.setX(dist_to_bar) elif pos.x()+total_width+dist_to_bar > w: pos.setX(w - total_width - dist_to_bar) pos.setY(pos.y() - dist_to_bar - total_height) log_debug("Display unit at position: (%g,%g)" % (pos.x(), pos.y())) if ticks_extra is not None: r.moveTo(pos) real_rect = painter.drawText(r, Qt.TextDontClip | Qt.AlignVCenter | Qt.AlignHCenter, exp_txt) bounding_rect |= real_rect pos.setX( pos.x() + r.width() ) pos.setY( pos.y() - metric.ascent()/2 ) exp_r.moveTo(pos) painter.setFont(exp_font) real_rect = painter.drawText(exp_r, Qt.TextDontClip | Qt.AlignVCenter | Qt.AlignHCenter, ticks_extra) bounding_rect |= real_rect pos.setY(pos.y() + metric.ascent()/2) if unit: pos.setX(pos.x() + space_width + exp_r.width()) unit_r.moveTo(pos) painter.setFont(font) real_rect = painter.drawText(unit_r, Qt.TextDontClip | Qt.AlignVCenter | Qt.AlignHCenter, unit) bounding_rect |= real_rect # Draw the ticks now painter.setPen(line_pen) tick_size = self.tick_size if is_vertical: width = scale_rect.width()*tick_size else: width = scale_rect.height()*tick_size pen_width = painter.pen().widthF() if pen_width == 0: pen_width = 1.0 for t in ticks: pos1 = start_pos + shift_pos*(t-value_range[0]) pos2 = QPointF(pos1) if is_vertical: pos1.setX(scale_rect.left() + pen_width) pos2.setX(pos1.x() + width - pen_width) painter.drawLine(pos1, pos2) pos1.setX(scale_rect.right() - pen_width) pos2.setX(pos1.x() - width + pen_width) painter.drawLine(pos1, pos2) else: pos1.setY(scale_rect.top() + pen_width) pos2.setY(pos1.y() + width - pen_width) painter.drawLine(pos1, pos2) pos1.setY(scale_rect.bottom() - pen_width) pos2.setY(pos1.y() - width + pen_width) painter.drawLine(pos1, pos2) painter.restore() bounding_rect = bounding_rect.adjusted(-pen_width, -pen_width, pen_width, pen_width) return bounding_rect
def alignImages(data, alignment_data, translation, rotation): """ Align the images in data using the points found in alignment_data. Arguments: - data, TrackingData: data set to align - alignment_data, TrackingData: data set used for the alignment - translation, (str|int): type of translation. Valid values are: * "Bounding-box centre" * "Barycentre" * Any point if in alignment_data - rotation, (str,int,int): type of rotation. The first value is the rotation type. For now, it has to be "TwoPoint". The two other values are the points id used for the rotation. """ # First, check the alignment data is valid #pts = alignment_data[alignment_data.images_name[0]].points() a = scipy.zeros(len(data), dtype=float) if rotation is not None: assert len(rotation) == 3 assert rotation[0] == "TwoPoint" r1 = rotation[1] r2 = rotation[2] for d in alignment_data: if not r1 in d: raise AlgoException("Image %s doesn't contain point %d." % (d._current_image, r1)) if not r2 in d: raise AlgoException("Image %s doesn't contain point %d." % (d._current_image, r2)) # Then, compute the rotation vecs = scipy.zeros((len(data), 2), dtype=float) for i, d in enumerate(alignment_data): v = d[r2] - d[r1] vecs[i, :] = (v.x(), v.y()) a = scipy.arctan2(vecs[:, 1], vecs[:, 0]) a = a[0] - a # At last, compute the translation using the reference refs = scipy.zeros((len(data), 2), dtype=float) if translation == "Bounding-box centre": for i, d in enumerate(alignment_data): mat, _ = d.matrix().inverted() p1 = None rect = QRectF() for p in d.positions(): p = mat.map(p) if p1 is None: p1 = p else: rect |= QRectF(p1, p).normalized() mid_pos = rect.center() refs[i, :] = (mid_pos.x(), mid_pos.y()) elif translation == "Barycentre": for i, d in enumerate(alignment_data): mat, _ = d.matrix().inverted() mid_pos = mat.map(sum(d.positions(), QPointF()) / len(d)) refs[i, :] = (mid_pos.x(), mid_pos.y()) else: for i, d in enumerate(alignment_data): mat, _ = d.matrix().inverted() if not translation in d: s = "Error, point %d is not in image %s. Cannot use it to align images." raise AlgoException(s % (translation, d.image_name)) pos = mat.map(d[translation]) refs[i, :] = (pos.x(), pos.y()) moved_refs = refs * cos(a)[:, newaxis] + c_[-refs[:, 1], refs[:, 0]] * sin( a)[:, newaxis] moved_refs = moved_refs[0, :] - moved_refs a *= 180 / math.pi return moved_refs, a