예제 #1
0
class SelectArea(QLabel):
    doneSignal = pyqtSignal(QPixmap)

    def __init__(self, *args, **kwargs):
        super(SelectArea, self).__init__(*args, **kwargs)

        self.pixmap = take_screenshot()

        self.setPixmap(self.pixmap)

        self.setCursor(Qt.CrossCursor)

        self.setWindowFlags(Qt.WindowStaysOnTopHint | Qt.FramelessWindowHint)
        self.showFullScreen()
        self.move(0, 0)
        self.resize(self.pixmap.size())

        self.selected = QRect(0, 0, 0, 0)
        self.first_point = None

    def paintEvent(self, event):
        super(SelectArea, self).paintEvent(event)

        painter = QPainter(self)

        drawRegion = QRegion(self.pixmap.rect())
        drawRegion = drawRegion.subtract(QRegion(self.selected))

        painter.setClipRegion(drawRegion)

        painter.setBrush(QBrush(QColor(0, 0, 0, 120)))
        painter.drawRect(self.pixmap.rect())

        painter.setClipping(False)

        if self.selected:
            # направляющие линии

            painter.setPen(QPen(QColor(255, 255, 255)))
            painter.setBrush(QBrush(QColor(0, 0, 0, 0)))

            vertical = self.selected.normalized()
            vertical.setLeft(-1)
            vertical.setRight(self.pixmap.rect().right() + 1)

            horizontal = self.selected.normalized()
            horizontal.setTop(-1)
            horizontal.setBottom(self.pixmap.rect().bottom() + 1)

            painter.drawRects(
                vertical,
                horizontal
            )

            # координаты начала

            bound = self.pixmap.rect()
            bound.setBottomRight(self.selected.topLeft() - QPoint(5, 5))

            painter.drawText(
                bound,
                Qt.AlignBottom | Qt.AlignRight,
                '(%d, %d)' % (self.selected.topLeft().x(), self.selected.topLeft().y())
            )

            # ширина/высота

            bound = self.pixmap.rect()
            bound.setTopLeft(self.selected.bottomRight() + QPoint(5, 5))

            painter.drawText(
                bound,
                Qt.AlignTop | Qt.AlignLeft,
                '(%d, %d)' % (self.selected.width(), self.selected.height())
            )

    def keyPressEvent(self, event):
        key = event.key()
        if key == Qt.Key_Escape:
            self.close()

    def mousePressEvent(self, event):
        self.first_point = event.pos()
        self.selected.setTopLeft(self.first_point)

    def mouseMoveEvent(self, event):
        self.move_selection(event.pos())

    def mouseReleaseEvent(self, event):
        self.move_selection(event.pos())
        self.finish()

    def move_selection(self, now_point):
        self.selected = QRect(self.first_point, now_point).normalized()
        self.update()

    def finish(self):
        self.doneSignal.emit(self.pixmap.copy(self.selected))
        self.close()
예제 #2
0
파일: infotool.py 프로젝트: xCherry/Roam
class InfoTool(TouchMapTool):
    infoResults = pyqtSignal(dict)

    def __init__(self, canvas, snapradius=2):
        super(InfoTool, self).__init__(canvas)
        self.radius = snapradius

        self.band = QgsRubberBand(self.canvas)
        self.band.setColor(QColor.fromRgb(224, 162, 16))
        self.band.setWidth(3)

        self.selectband = None
        self.selectrect = QRect()
        self.dragging = False
        self.selectionlayers = []

    def getFeatures(self, rect):
        self.band.reset()
        for layer in self.selectionlayers.itervalues():
            if (not layer.type() == QgsMapLayer.VectorLayer
                    or layer.geometryType() == QGis.NoGeometry):
                continue

            rect = self.toLayerCoordinates(layer, rect)

            rq = QgsFeatureRequest().setFilterRect(rect)\
                                    .setFlags(QgsFeatureRequest.ExactIntersect)\
                                    .setSubsetOfAttributes([])
            features = []
            for feature in layer.getFeatures(rq):
                if feature.isValid():
                    features.append(feature)

            yield layer, features

    def toSearchRect(self, point):
        searchRadius = self.canvas.extent().width() * (self.radius / 100.0)

        point = self.toMapCoordinates(point)

        rect = QgsRectangle()
        rect.setXMinimum(point.x() - searchRadius)
        rect.setXMaximum(point.x() + searchRadius)
        rect.setYMinimum(point.y() - searchRadius)
        rect.setYMaximum(point.y() + searchRadius)
        return rect

    def canvasPressEvent(self, event):
        if self.pinching:
            return

        self.dragging = False
        self.selectrect.setRect(0, 0, 0, 0)

        self.selectband = QgsRubberBand(self.canvas, QGis.Polygon)
        self.selectband.setColor(QColor.fromRgb(0, 0, 255, 65))
        self.selectband.setWidth(5)

    def canvasMoveEvent(self, event):
        if self.pinching:
            return

        if not event.buttons() == Qt.LeftButton:
            return

        if not self.dragging:
            self.selectrect.setTopLeft(event.pos())
            self.dragging = True
        self.selectrect.setBottomRight(event.pos())

        maptoolutils.setRubberBand(self.canvas, self.selectrect,
                                   self.selectband)

    def canvasReleaseEvent(self, event):
        if self.pinching:
            return

        if self.dragging:
            geometry = self.selectband.asGeometry()
            if not geometry:
                return

            rect = geometry.boundingBox()
        else:
            rect = self.toSearchRect(event.pos())

        self.dragging = False
        self.selectband.reset()

        results = OrderedDict((l, f) for l, f in self.getFeatures(rect))
        self.infoResults.emit(results)
예제 #3
0
class ImageAreaSelector (QtGui.QWidget):
    '''This widget provides means to visually crop a portion of
    an image by selecting it'''
     # pylint: disable=W0612
    NAME = 'ImageAreaSelector'
    DESCRIPTION = 'A widget used to select part of an image'
    AUTHOR = 'Gabriele "Whisky" Visconti'
    WEBSITE = ''
    # pylint: enable=W0612
    
    selection_changed = QtCore.pyqtSignal()
    
    def __init__(self, pixmap, parent=None):
        '''Constructor'''
        QtGui.QWidget.__init__(self, parent)
        self._pixmap = pixmap
        
        self._selection_rect = QRect() 
        self._image_origin = QPoint()
        self._resize_start = None
        self._drag_start = None
        self._handle_size = QSize(-10, -10)
        self._painter = QtGui.QPainter()
        self._hl_color1 = QtGui.QPalette().color(QtGui.QPalette.Highlight)
        self._hl_color2 = QtGui.QPalette().color(QtGui.QPalette.Highlight)
        self._hl_color2.setAlpha(150)
        self._zoom = 1.0
        
        self.adjust_minum_size()
        self.setBackgroundRole(QtGui.QPalette.Dark)
        self.setMouseTracking(True)
        self.setCursor(Qt.CrossCursor)
        
# -------------------- [BEGIN] QT_OVERRIDE

    def mousePressEvent (self, event):
        '''Overrides QWidget's mousePressEvent. Handles starting
        a new selection, starting a drag operation'''
        # pylint: disable=C0103
        mouse_pos = event.pos() / self._zoom
        sel_rect = self._selection_rect
        
        if not event.button() == Qt.LeftButton:
            return
        
        if (not sel_rect.isNull()) and sel_rect.contains(mouse_pos, True):
            handle_rect = QRect(sel_rect.bottomRight(), self._handle_size)
            if handle_rect.contains(mouse_pos):
                self._resize_start = mouse_pos
            else:
                self._drag_start = mouse_pos
        else:
            self._resize_start = mouse_pos
            sel_rect.setTopLeft    (mouse_pos)
            self._selection_rect.setSize(QSize(0, 0))
        

    
    def mouseMoveEvent (self, event):
        '''Overrides QWidget's mouseMoveEvent. Handles resizing
        and dragging operations on selection'''
        # pylint: disable=C0103
        sel_rect = self._selection_rect
        if self._resize_start:
            resize_end = event.pos() / self._zoom
            sel_rect.setBottomRight(sel_rect.bottomRight() +
                                    (resize_end - self._resize_start))
            self._resize_start = resize_end
            self.make_selection_square()
            self.update()
        elif self._drag_start is not None:
            drag_end = event.pos() / self._zoom
            sel_rect.translate(drag_end - self._drag_start)
            self._drag_start = drag_end
            self.update()
            
        # cursor shape:
        mouse_pos = event.pos() / self._zoom
        if (not sel_rect.isNull()) and sel_rect.contains(mouse_pos, True):
            handle_rect = QRect(sel_rect.bottomRight(), self._handle_size)
            if handle_rect.contains(mouse_pos):
                self.setCursor(Qt.SizeFDiagCursor)
            else:
                self.setCursor(Qt.OpenHandCursor)
                
        else:
            self.setCursor(Qt.CrossCursor)
        
            
    
    def mouseReleaseEvent (self, event):
        '''Overrides QWidget's mouseReleaseEvent. Handles ending a resizing or
        draggin operation on the selection'''
        # pylint: disable=C0103
        self._selection_rect = self._selection_rect.normalized()
        self._resize_start = None
        self._drag_start = None
        self.update()
        if not self._selection_rect.isNull():
            self.selection_changed.emit()
        
    
    def paintEvent(self, event):
        '''Overrides QWidtget's paintEvent.'''
        # pylint: disable=C0103
        QtGui.QWidget.paintEvent(self, event)
        self._painter.begin(self)
        pixmap_dest_rect = QRect(self._image_origin * self._zoom, 
                                 self._pixmap.size()*self._zoom)
        self._painter.drawPixmap(pixmap_dest_rect, self._pixmap)
        if not self._selection_rect.isNull():
            # preparing the darkened frame:
            sel_rect = self._selection_rect.normalized()
            frame = QtGui.QPixmap(event.rect().size())
            frame.fill(QtGui.QColor(0, 0, 0, 127))
            frame_painter = QtGui.QPainter(frame)
            # erase the selected area from the frame:
            frame_painter.setCompositionMode(
                                QtGui.QPainter.CompositionMode_DestinationIn)
            sel_rect_scaled = QRect(sel_rect.topLeft() * self._zoom,
                                    sel_rect.size() * self._zoom)
            frame_painter.fillRect(sel_rect_scaled, QtGui.QColor(0, 0, 0, 0))
            # draw selection border :
            frame_painter.setCompositionMode(
                                QtGui.QPainter.CompositionMode_SourceOver)
            frame_painter.setPen(self._hl_color1)
            frame_painter.drawRect(sel_rect_scaled)
            # draw the resize grip (if possible)
            if sel_rect_scaled.width() > 20 and sel_rect_scaled.height() > 20:
                handle_rect = QRect(sel_rect_scaled.bottomRight(), 
                                    self._handle_size)
                frame_painter.fillRect(handle_rect, self._hl_color2)
                frame_painter.drawRect(handle_rect)
            frame_painter.end()
            # painting the darkened frame:
            self._painter.drawPixmap(0, 0, frame)
            
        self._painter.end()
        
        
    def resizeEvent(self, event):
        '''Overrides QWidget's resizeEvent. Handles image centering.'''
        # pylint: disable=C0103
        self.adjust_image_origin()
        
# -------------------- [END] QT_OVERRIDE

    def adjust_image_origin(self):
        '''Recalculates the top left corner's image position, so the
        image is painted centered'''
        # pylint: disable=C0103
        new_size = self.size() / self._zoom
        pix_size = self._pixmap.size()
        
        dx = (new_size.width()  - pix_size.width() ) /2
        dy = (new_size.height() - pix_size.height()) /2
        
        new_image_origin = QPoint(dx, dy)
        self._selection_rect.translate(new_image_origin - self._image_origin)
        self._image_origin = new_image_origin
        log.info('image origin: %s' % new_image_origin)
        
    def select_unscaled(self):
        '''Selects, if possible, a 96 x 96 square centered around the original
        image. In this way the image won't be scaled but won't take up all the 
        96 x 96 area.'''
        # pylint: disable=C0103
        pix_size = self._pixmap.size()
        if pix_size.width() <= 96 and pix_size.height() <= 96:
            viewport_size = self.size()
            x =   (viewport_size.width () - 96) / 2
            y =   (viewport_size.height() - 96) / 2
            self._selection_rect.setTopLeft(QPoint(x, y))
            self._selection_rect.setSize(QSize(96, 96))
            self.update()
            self.selection_changed.emit()
            
            
    def select_all(self):
        '''Selects the whole image. Currently broken for images taller
        than wide.'''
        # TODO: make me work!
        self._selection_rect.setTopLeft(self._image_origin)
        self._selection_rect.setSize(self._pixmap.size())
        self.update()
        self.selection_changed.emit()
        
        
    def rotate_left(self):
        '''Rotates the image counterclockwise.'''
        self._pixmap = self._pixmap.transformed(QtGui.QTransform().rotate(-90))
        self.adjust_minum_size()
        self.adjust_image_origin()
        self.update()
        self.selection_changed.emit()


    def rotate_right(self):
        '''Rotates the image clockwise'''
        self._pixmap = self._pixmap.transformed(QtGui.QTransform().rotate(90))
        self.adjust_minum_size()
        self.adjust_image_origin()
        self.update()
        self.selection_changed.emit()
        
    
    def adjust_minum_size(self):
        '''Sets the new minimum size, calculated upon the image size
        and the _zoom factor.'''
        pixmap = self._pixmap
        if pixmap.width() < 96 or pixmap.height() < 96:
            min_size = QSize(96, 96)
        else:
            min_size = pixmap.size()
            
        self.setMinimumSize(min_size*self._zoom)


    def make_selection_square(self):
        '''Modify the selected area making it square'''
        wid = self._selection_rect.width ()
        self._selection_rect.setSize(QSize(wid, wid))
        
    
    def set_zoom(self, zoomlevel):
        '''Sets the specified zoomlevel'''
        self._zoom = zoomlevel
        self.adjust_minum_size()
        self.adjust_image_origin()
        self.update()
        self.selection_changed.emit()
        
        
    def fit_zoom(self):
        '''Chooses a zoomlevel that makes visible the entire image.
        Currently broken.'''
        widget_wid = self.size().width ()
        widget_hei = self.size().height()
        
        pixmap_wid = self._pixmap.width ()
        pixmap_hei = self._pixmap.height()
        
        self._zoom = (min(widget_wid, widget_hei) / 
                      min(pixmap_wid, pixmap_hei))
                      
        self.adjust_minum_size()
        self.adjust_image_origin()
        self.update()
        self.selection_changed.emit()
        
    def get_selected_pixmap(self):
        '''Returns the pixmap contained in the selection rect.
        Currently doesn't handle transparency correctly'''
        sel_rect_scaled = QRect(self._selection_rect.topLeft() * self._zoom,
                                self._selection_rect.size() * self._zoom)
        return QtGui.QPixmap.grabWidget(self, sel_rect_scaled)
예제 #4
0
class ArkMapToolInteractive(QgsMapTool):

    _active = False

    _dragging = False
    _panningEnabled = False

    _zoomingEnabled = False
    _zoomRubberBand = None  #QgsRubberBand()
    _zoomRect = None # QRect()

    _snappingEnabled = False
    _snapper = None  #QgsMapCanvasSnapper()
    _snappingMarker = None  # QgsVertexMarker()

    _showSnappableVertices = False
    _snappableVertices = []  # [QgsPoint()]
    _snappableMarkers = []  # [QgsVertexMarker()]

    def __init__(self, canvas, snappingEnabled=False, showSnappableVertices=False):
        super(ArkMapToolInteractive, self).__init__(canvas)
        self._snappingEnabled = snappingEnabled
        self._showSnappableVertices = showSnappableVertices

    def __del__(self):
        if self._active:
            self.deactivate()

    def isActive(self):
        return self._active

    def activate(self):
        super(ArkMapToolInteractive, self).activate()
        self._active = True
        self._startSnapping()

    def deactivate(self):
        self._active = False
        if self._snappingEnabled:
            self._stopSnapping()
        if (self._zoomRubberBand is not None):
            self.canvas().scene().removeItem(self._zoomRubberBand)
            self._zoomRubberBand = None
        super(ArkMapToolInteractive, self).deactivate()

    def setAction(self, action):
        super(ArkMapToolInteractive, self).setAction(action)
        self.action().triggered.connect(self._activate)

    def _activate(self):
        self.canvas().setMapTool(self)

    def panningEnabled(self):
        return self._panningEnabled

    def setPanningEnabled(self, enabled):
        self._panningEnabled = enabled

    def zoomingEnabled(self):
        return self._zoomingEnabled

    def setZoomingEnabled(self, enabled):
        self._zoomingEnabled = enabled

    def snappingEnabled(self):
        return self._snappingEnabled

    def setSnappingEnabled(self, enabled):
        if (self._snappingEnabled == enabled):
            return
        self._snappingEnabled = enabled
        if not self._active:
            return
        if enabled:
            self._startSnapping()
        else:
            self._stopSnapping()

    def _startSnapping(self):
        self._snapper = QgsMapCanvasSnapper()
        self._snapper.setMapCanvas(self.canvas())
        if self._showSnappableVertices:
            self._startSnappableVertices()

    def _stopSnapping(self):
        self._deleteSnappingMarker()
        self._snapper = None
        if self._showSnappableVertices:
            self._stopSnappableVertices()

    def showSnappableVertices(self):
        return self._showSnappableVertices

    def setShowSnappableVertices(self, show):
        if (self._showSnappableVertices == show):
            return
        self._showSnappableVertices = show
        if not self._active:
            return
        if show:
            self._startSnappableVertices()
        else:
            self._stopSnappableVertices()

    def _startSnappableVertices(self):
        self.canvas().layersChanged.connect(self._layersChanged)
        self.canvas().extentsChanged.connect(self._redrawSnappableMarkers)
        QgsProject.instance().snapSettingsChanged.connect(self._layersChanged)
        self._layersChanged()

    def _stopSnappableVertices(self):
        self._deleteSnappableMarkers()
        self._snappableLayers = []
        self.canvas().layersChanged.disconnect(self._layersChanged)
        self.canvas().extentsChanged.disconnect(self._redrawSnappableMarkers)
        QgsProject.instance().snapSettingsChanged.disconnect(self._layersChanged)

    def canvasMoveEvent(self, e):
        super(ArkMapToolInteractive, self).canvasMoveEvent(e)
        if not self._active:
            return
        e.ignore()
        if (self._panningEnabled and e.buttons() & Qt.LeftButton):
            # Pan map mode
            if not self._dragging:
                self._dragging = True
                self.setCursor(QCursor(Qt.ClosedHandCursor))
            self.canvas().panAction(e)
            e.accept()
        elif (self._zoomingEnabled and e.buttons() & Qt.RightButton):
            # Zoom map mode
            if not self._dragging:
                self._dragging = True
                self.setCursor(QCursor(Qt.ClosedHandCursor))
                self._zoomRubberBand = QgsRubberBand(self.canvas(), QGis.Polygon)
                color = QColor(Qt.blue)
                color.setAlpha(63)
                self._zoomRubberBand.setColor(color)
                self._zoomRect = QRect(0, 0, 0, 0)
                self._zoomRect.setTopLeft(e.pos())
            self._zoomRect.setBottomRight(e.pos())
            if self._zoomRubberBand is not None:
                self._zoomRubberBand.setToCanvasRectangle(self._zoomRect)
                self._zoomRubberBand.show()
            e.accept()
        elif self._snappingEnabled:
            mapPoint, snapped = self._snapCursorPoint(e.pos())
            if (snapped):
                self._createSnappingMarker(mapPoint)
            else:
                self._deleteSnappingMarker()

    def canvasReleaseEvent(self, e):
        super(ArkMapToolInteractive, self).canvasReleaseEvent(e)
        e.ignore()
        if (e.button() == Qt.LeftButton):
            if self._dragging:
                # Pan map mode
                self.canvas().panActionEnd(e.pos())
                self.setCursor(capture_point_cursor)
                self._dragging = False
                e.accept()
        elif (e.button() == Qt.RightButton):
            if self._dragging:
                # Zoom mode
                self._zoomRect.setBottomRight(e.pos())
                if (self._zoomRect.topLeft() != self._zoomRect.bottomRight()):
                    coordinateTransform = self.canvas().getCoordinateTransform()
                    ll = coordinateTransform.toMapCoordinates(self._zoomRect.left(), self._zoomRect.bottom())
                    ur = coordinateTransform.toMapCoordinates(self._zoomRect.right(), self._zoomRect.top())
                    r = QgsRectangle()
                    r.setXMinimum(ll.x())
                    r.setYMinimum(ll.y())
                    r.setXMaximum(ur.x())
                    r.setYMaximum(ur.y())
                    r.normalize()
                    if (r.width() != 0 and r.height() != 0):
                        self.canvas().setExtent(r)
                        self.canvas().refresh()
                self._dragging = False
                if (self._zoomRubberBand is not None):
                    self.canvas().scene().removeItem(self._zoomRubberBand)
                    self._zoomRubberBand = None
                e.accept()

    def keyPressEvent(self, e):
        super(ArkMapToolInteractive, self).keyPressEvent(e)
        if (e.key() == Qt.Key_Escape):
            self.canvas().unsetMapTool(self)
            e.accept()

    def _snapCursorPoint(self, cursorPoint):
        res, snapResults = self._snapper.snapToBackgroundLayers(cursorPoint)
        if (res != 0 or len(snapResults) < 1):
            return self.toMapCoordinates(cursorPoint), False
        else:
            # Take a copy as QGIS will delete the result!
            snappedVertex = QgsPoint(snapResults[0].snappedVertex)
            return snappedVertex, True

    def _createSnappingMarker(self, snapPoint):
        if (self._snappingMarker is None):
            self._snappingMarker = QgsVertexMarker(self.canvas())
            self._snappingMarker.setIconType(QgsVertexMarker.ICON_CROSS)
            self._snappingMarker.setColor(Qt.magenta)
            self._snappingMarker.setPenWidth(3)
        self._snappingMarker.setCenter(snapPoint)

    def _deleteSnappingMarker(self):
        if (self._snappingMarker is not None):
            self.canvas().scene().removeItem(self._snappingMarker)
            self._snappingMarker = None

    def _createSnappableMarkers(self):
        if (not self._showSnappableVertices or not self._snappingEnabled):
            return
        extent = self.canvas().extent()
        for vertex in self._snappableVertices.asMultiPoint():
            if (extent.contains(vertex)):
                marker = QgsVertexMarker(self.canvas())
                marker.setIconType(QgsVertexMarker.ICON_X)
                marker.setColor(Qt.gray)
                marker.setPenWidth(1)
                marker.setCenter(vertex)
                self._snappableMarkers.append(marker)

    def _deleteSnappableMarkers(self):
        for marker in self._snappableMarkers:
            self.canvas().scene().removeItem(marker)
        del self._snappableMarkers[:]

    def _layersChanged(self):
        if (not self._showSnappableVertices or not self._snappingEnabled):
            return
        self._buildSnappableLayers()
        self._deleteSnappableMarkers()
        self._createSnappableMarkers()

    def _redrawSnappableMarkers(self):
        if (not self._showSnappableVertices or not self._snappingEnabled):
            return
        self._deleteSnappableMarkers()
        self._createSnappableMarkers()

    def _buildSnappableLayers(self):
        if (not self._showSnappableVertices or not self._snappingEnabled):
            return
        vertices = []
        for layer in self.canvas().layers():
            ok, enabled, type, units, tolerance, avoid = QgsProject.instance().snapSettingsForLayer(layer.id())
            if (ok and enabled and not layer.isEditable()):
                for feature in layer.getFeatures():
                    geometry = feature.geometry()
                    if geometry is None:
                        pass
                    elif geometry.type() == QGis.Point:
                        vertices.extend([geometry.asPoint()])
                    elif geometry.type() == QGis.Line:
                        vertices.extend(geometry.asPolyline())
                    elif geometry.type() == QGis.Polygon:
                        lines = geometry.asPolygon()
                        for line in lines:
                            vertices.extend(line)
        self._snappableVertices = QgsGeometry.fromMultiPoint(vertices)
        self._snappableVertices.simplify(0)
class MincutConnec(QgsMapTool):

    canvasClicked = pyqtSignal()

    def __init__(self, iface, controller):
        """ Class constructor """

        self.iface = iface
        self.canvas = self.iface.mapCanvas()
        self.controller = controller
        # Call superclass constructor and set current action
        QgsMapTool.__init__(self, self.canvas)

        self.dragging = False

        # Vertex marker
        color = QColor(255, 100, 255)
        self.vertex_marker = QgsVertexMarker(self.canvas)
        self.vertex_marker.setIconType(QgsVertexMarker.ICON_CIRCLE)
        self.vertex_marker.setColor(color)
        self.vertex_marker.setIconSize(15)
        self.vertex_marker.setPenWidth(3)

        # Rubber band
        self.rubber_band = QgsRubberBand(self.canvas, QGis.Line)
        self.rubber_band.setColor(color)
        self.rubber_band.setWidth(1)

        # Select rectangle
        self.select_rect = QRect()

        # TODO: Parametrize
        self.connec_group = ["Wjoin", "Tap", "Fountain", "Greentap"]
        #self.snapperManager = SnappingConfigManager(self.iface)
        self.snapper = QgsMapCanvasSnapper(self.canvas)

    def activate(self):
        pass

    def canvasPressEvent(self, event):  #@UnusedVariable
        self.select_rect.setRect(0, 0, 0, 0)
        self.rubber_band.reset()

    def canvasMoveEvent(self, event):
        """ With left click the digitizing is finished """

        if event.buttons() == Qt.LeftButton:
            if not self.dragging:
                self.dragging = True
                self.select_rect.setTopLeft(event.pos())
            self.select_rect.setBottomRight(event.pos())
            self.set_rubber_band()

        else:
            # Hide highlight
            self.vertex_marker.hide()

            # Get the click
            x = event.pos().x()
            y = event.pos().y()
            event_point = QPoint(x, y)

            # Snapping
            (retval, result) = self.snapper.snapToBackgroundLayers(
                event_point)  # @UnusedVariable

            # That's the snapped point
            if result:
                # Check feature
                for snap_point in result:
                    element_type = snap_point.layer.name()
                    if element_type in self.connec_group:
                        # Get the point
                        point = QgsPoint(snap_point.snappedVertex)
                        # Add marker
                        self.vertex_marker.setCenter(point)
                        self.vertex_marker.show()
                        break

    def canvasReleaseEvent(self, event):
        """ With left click the digitizing is finished """

        if event.button() == Qt.LeftButton:

            # Get the click
            x = event.pos().x()
            y = event.pos().y()
            event_point = QPoint(x, y)

            # Not dragging, just simple selection
            if not self.dragging:

                # Snap to node
                (retval, result) = self.snapper.snapToBackgroundLayers(
                    event_point)  # @UnusedVariable

                # That's the snapped point
                if result:
                    # Check feature
                    for snapped_point in result:
                        element_type = snapped_point.layer.name()
                        if element_type in self.connec_group:
                            feat_type = 'connec'
                        else:
                            continue

                        point = QgsPoint(
                            snapped_point.snappedVertex)  # @UnusedVariable
                        # layer.removeSelection()
                        # layer.select([result[0].snappedAtGeometry])

                        #snapped_point.layer.removeSelection()
                        snapped_point.layer.select(
                            [snapped_point.snappedAtGeometry])

            else:

                # Set valid values for rectangle's width and height
                if self.select_rect.width() == 1:
                    self.select_rect.setLeft(self.select_rect.left() + 1)

                if self.select_rect.height() == 1:
                    self.select_rect.setBottom(self.select_rect.bottom() + 1)

                self.set_rubber_band()
                self.select_multiple_features(self.selected_rectangle)
                self.dragging = False

            # Refresh map canvas
            self.rubber_band.reset()
            self.refresh_map_canvas()

    def set_rubber_band(self):

        # Coordinates transform
        transform = self.canvas.getCoordinateTransform()

        # Coordinates
        ll = transform.toMapCoordinates(self.select_rect.left(),
                                        self.select_rect.bottom())
        lr = transform.toMapCoordinates(self.select_rect.right(),
                                        self.select_rect.bottom())
        ul = transform.toMapCoordinates(self.select_rect.left(),
                                        self.select_rect.top())
        ur = transform.toMapCoordinates(self.select_rect.right(),
                                        self.select_rect.top())

        # Rubber band
        self.rubber_band.reset()
        self.rubber_band.addPoint(ll, False)
        self.rubber_band.addPoint(lr, False)
        self.rubber_band.addPoint(ur, False)
        self.rubber_band.addPoint(ul, False)
        self.rubber_band.addPoint(ll, True)

        self.selected_rectangle = QgsRectangle(ll, ur)

    def select_multiple_features(self, rectangle):

        if self.connec_group is None:
            return

        if QGis.QGIS_VERSION_INT >= 21600:

            # Selection for all connec group layers
            for layer_name in self.connec_group:
                # Get layer by his name
                layer = self.controller.get_layer_by_layername(layer_name,
                                                               log_info=True)
                if layer:
                    self.group_pointers_connec.append(layer)
                    layer.selectByRect(rectangle)

        else:
            for layer_name in self.connec_group:
                self.iface.setActiveLayer(layer)
                layer.removeSelection()
                layer.select(rectangle, True)
예제 #6
0
class InfoTool(TouchMapTool):
    infoResults = pyqtSignal(dict)

    def __init__(self, canvas, snapradius = 2):
        super(InfoTool, self).__init__(canvas)
        self.radius = snapradius

        self.band = QgsRubberBand(self.canvas)
        self.band.setColor(QColor.fromRgb(224,162,16))
        self.band.setWidth(3)

        self.selectband = None
        self.selectrect = QRect()
        self.dragging = False
        self.selectionlayers = []

    def getFeatures(self, rect, firstonly=False):
        self.band.reset()
        for layer in self.selectionlayers.itervalues():
            if (not layer.type() == QgsMapLayer.VectorLayer
                or layer.geometryType() == QGis.NoGeometry):
                continue

            rect = self.toLayerCoordinates(layer, rect)
            rq = QgsFeatureRequest().setFilterRect(rect)\
                                    .setFlags(QgsFeatureRequest.ExactIntersect)\
                                    .setSubsetOfAttributes([])
            features = []
            if firstonly:
                try:
                    feature = layer.getFeatures(rq).next()
                    if feature.isValid():
                        features.append(feature)
                except StopIteration:
                    continue
            else:
                for feature in layer.getFeatures(rq):
                    if feature.isValid():
                        features.append(feature)

            yield layer, features

    def toSearchRect(self, point):
        point = self.toMapCoordinates(point)
        rect = QgsRectangle(point.x(), point.y(), point.x() + 10, point.y() + 10)
        return rect

    def canvasPressEvent(self, event):
        if self.pinching:
            return

        self.dragging = False
        self.selectrect.setRect(0, 0, 0, 0)

        self.selectband = QgsRubberBand(self.canvas, QGis.Polygon )
        self.selectband.setColor(QColor.fromRgb(0,0,255, 65))
        self.selectband.setWidth(5)

    def canvasMoveEvent(self, event):
        if self.pinching:
            return

        if not event.buttons() == Qt.LeftButton:
            return

        if not self.dragging:
            self.selectrect.setTopLeft(event.pos())
            self.dragging = True
        self.selectrect.setBottomRight(event.pos())

        maptoolutils.setRubberBand(self.canvas, self.selectrect, self.selectband)

    def canvasReleaseEvent(self, event):
        if self.pinching:
            return

        if self.dragging:
            geometry = self.selectband.asGeometry()
            if not geometry:
                return

            rect = geometry.boundingBox()
            firstonly = False
        else:
            firstonly = True
            rect = self.toSearchRect(event.pos())

        self.dragging = False
        self.selectband.reset()

        results = OrderedDict((l,f) for l, f in self.getFeatures(rect))
        self.infoResults.emit(results)
예제 #7
0
class MapToolInteractive(QgsMapTool):
    """Tool to interact with map, including panning, zooming, and snapping"""
    def __init__(self, canvas, snappingEnabled=False):
        super(MapToolInteractive, self).__init__(canvas)
        self._active = False
        self._dragging = False
        self._panningEnabled = False
        self._zoomingEnabled = False
        self._zoomRubberBand = None  # QgsRubberBand()
        self._zoomRect = None  # QRect()
        self._snappingEnabled = snappingEnabled
        self._snapper = None  # QgsMapCanvasSnapper()
        self._snappingMarker = None  # QgsVertexMarker()

    def __del__(self):
        if self._active:
            self.deactivate()

    def isActive(self):
        return self._active

    def activate(self):
        super(MapToolInteractive, self).activate()
        self._active = True
        self._startSnapping()

    def deactivate(self):
        self._active = False
        if self._snappingEnabled:
            self._stopSnapping()
        if (self._zoomRubberBand is not None):
            self.canvas().scene().removeItem(self._zoomRubberBand)
            self._zoomRubberBand = None
        super(MapToolInteractive, self).deactivate()

    def setAction(self, action):
        super(MapToolInteractive, self).setAction(action)
        self.action().triggered.connect(self._activate)

    def _activate(self):
        self.canvas().setMapTool(self)

    def panningEnabled(self):
        return self._panningEnabled

    def setPanningEnabled(self, enabled):
        self._panningEnabled = enabled

    def zoomingEnabled(self):
        return self._zoomingEnabled

    def setZoomingEnabled(self, enabled):
        self._zoomingEnabled = enabled

    def snappingEnabled(self):
        return self._snappingEnabled

    def setSnappingEnabled(self, enabled):
        if (self._snappingEnabled == enabled):
            return
        self._snappingEnabled = enabled
        if not self._active:
            return
        if enabled:
            self._startSnapping()
        else:
            self._stopSnapping()

    def _startSnapping(self):
        self._snapper = QgsMapCanvasSnapper()
        self._snapper.setMapCanvas(self.canvas())

    def _stopSnapping(self):
        self._deleteSnappingMarker()
        self._snapper = None

    def canvasMoveEvent(self, e):
        super(MapToolInteractive, self).canvasMoveEvent(e)
        if not self._active:
            return
        e.ignore()
        if (self._panningEnabled and e.buttons() & Qt.LeftButton):
            # Pan map mode
            if not self._dragging:
                self._dragging = True
                self.setCursor(QCursor(Qt.ClosedHandCursor))
            self.canvas().panAction(e)
            e.accept()
        elif (self._zoomingEnabled and e.buttons() & Qt.RightButton):
            # Zoom map mode
            if not self._dragging:
                self._dragging = True
                self.setCursor(QCursor(Qt.ClosedHandCursor))
                self._zoomRubberBand = QgsRubberBand(self.canvas(),
                                                     QGis.Polygon)
                color = QColor(Qt.blue)
                color.setAlpha(63)
                self._zoomRubberBand.setColor(color)
                self._zoomRect = QRect(0, 0, 0, 0)
                self._zoomRect.setTopLeft(e.pos())
            self._zoomRect.setBottomRight(e.pos())
            if self._zoomRubberBand is not None:
                self._zoomRubberBand.setToCanvasRectangle(self._zoomRect)
                self._zoomRubberBand.show()
            e.accept()
        elif self._snappingEnabled:
            mapPoint, mapPointV2, snapped = self._snapCursorPoint(e.pos())
            if (snapped):
                self._createSnappingMarker(mapPoint)
            else:
                self._deleteSnappingMarker()

    def canvasReleaseEvent(self, e):
        super(MapToolInteractive, self).canvasReleaseEvent(e)
        e.ignore()
        if (e.button() == Qt.LeftButton):
            if self._dragging:
                # Pan map mode
                self.canvas().panActionEnd(e.pos())
                self.setCursor(CapturePointCursor)
                self._dragging = False
                e.accept()
        elif (e.button() == Qt.RightButton):
            if self._dragging:
                # Zoom mode
                self._zoomRect.setBottomRight(e.pos())
                if (self._zoomRect.topLeft() != self._zoomRect.bottomRight()):
                    coordinateTransform = self.canvas().getCoordinateTransform(
                    )
                    ll = coordinateTransform.toMapCoordinates(
                        self._zoomRect.left(), self._zoomRect.bottom())
                    ur = coordinateTransform.toMapCoordinates(
                        self._zoomRect.right(), self._zoomRect.top())
                    r = QgsRectangle()
                    r.setXMinimum(ll.x())
                    r.setYMinimum(ll.y())
                    r.setXMaximum(ur.x())
                    r.setYMaximum(ur.y())
                    r.normalize()
                    if (r.width() != 0 and r.height() != 0):
                        self.canvas().setExtent(r)
                        self.canvas().refresh()
                self._dragging = False
                if (self._zoomRubberBand is not None):
                    self.canvas().scene().removeItem(self._zoomRubberBand)
                    self._zoomRubberBand = None
                e.accept()

    def keyPressEvent(self, e):
        super(MapToolInteractive, self).keyPressEvent(e)
        if (e.key() == Qt.Key_Escape):
            self.canvas().unsetMapTool(self)
            e.accept()

    def _snapCursorPoint(self, cursorPoint):
        res, snapResults = self._snapper.snapToBackgroundLayers(cursorPoint)
        if (res != 0 or len(snapResults) < 1):
            clicked = self.toMapCoordinates(cursorPoint)
            clickedV2 = QgsPointV2(clicked)
            return clicked, clickedV2, False
        else:
            # Take a copy as QGIS will delete the result!
            snapped = QgsPoint(snapResults[0].snappedVertex)
            snappedV2 = QgsPointV2(snapped)
            return snapped, snappedV2, True

    def _createSnappingMarker(self, snapPoint):
        if (self._snappingMarker is None):
            self._snappingMarker = QgsVertexMarker(self.canvas())
            self._snappingMarker.setIconType(QgsVertexMarker.ICON_CROSS)
            self._snappingMarker.setColor(Qt.magenta)
            self._snappingMarker.setPenWidth(3)
        self._snappingMarker.setCenter(snapPoint)

    def _deleteSnappingMarker(self):
        if (self._snappingMarker is not None):
            self.canvas().scene().removeItem(self._snappingMarker)
            self._snappingMarker = None
예제 #8
0
class SelectByRect(QgsMapTool):
    def __init__(self, canvas):
        self.mCanvas = canvas
        QgsMapTool.__init__(self, canvas)
        self.mCursor = Qt.ArrowCursor
        self.mRubberBand = None
        self.mDragging = False
        self.mSelectRect = QRect()

#     QgsRubberBand* mRubberBand;
#     def reset(self):
#         self.startPoint = None
#         self.endPoint = None
#         self.isDrawing = False
#         SelectByRect.RubberRect.reset(QGis.Polygon)
#         self.layer = self.canvas.currentLayer()

    def canvasPressEvent(self, e):
        self.mSelectRect.setRect(0, 0, 0, 0)
        self.mRubberBand = QgsRubberBand(self.mCanvas, QGis.Polygon)
#         self.reset()
#         self.startPoint = self.toMapCoordinates(e.pos())
#         self.isDrawing = True

    def canvasMoveEvent(self, e):
        if (e.buttons() != Qt.LeftButton):
            return
        if (not self.mDragging):
            self.mDragging = True
            self.mSelectRect.setTopLeft(e.pos())
        self.mSelectRect.setBottomRight(e.pos())
        QgsMapToolSelectUtils.setRubberBand(self.mCanvas, self.mSelectRect,
                                            self.mRubberBand)
#         if not self.isDrawing:
#             return
#         SelectByRect.RubberRect.reset(QGis.Polygon)
#         self.endPoint = self.toMapCoordinates(e.pos())
#         self.rect = QgsRectangle(self.startPoint, self.endPoint)
#         SelectByRect.RubberRect.addGeometry(QgsGeometry.fromRect(self.rect), None)
#         SelectByRect.RubberRect.show()

    def canvasReleaseEvent(self, e):
        selectedFeatures = None
        vlayer = QgsMapToolSelectUtils.getCurrentVectorLayer(self.mCanvas)
        if (vlayer == None):
            if (self.mRubberBand != None):
                self.mRubberBand.reset(QGis.Polygon)
                del self.mRubberBand
                self.mRubberBand = None
                self.mDragging = False
            return

        if (not self.mDragging):
            QgsMapToolSelectUtils.expandSelectRectangle(
                self.mSelectRect, vlayer, e.pos())
        else:
            if (self.mSelectRect.width() == 1):
                self.mSelectRect.setLeft(self.mSelectRect.left() + 1)
            if (self.mSelectRect.height() == 1):
                self.mSelectRect.setBottom(self.mSelectRect.bottom() + 1)

        if (self.mRubberBand != None):
            QgsMapToolSelectUtils.setRubberBand(self.mCanvas, self.mSelectRect,
                                                self.mRubberBand)
            selectGeom = self.mRubberBand.asGeometry()
            # QgsMapToolSelectUtils.setSelectFeatures( self.mCanvas, selectGeom, e )
            selectedFeatures = QgsMapToolSelectUtils.setSelectFeatures1(
                self.mCanvas, selectGeom, e)
            del selectGeom

            self.mRubberBand.reset(QGis.Polygon)
            del self.mRubberBand
            self.mRubberBand = None
        self.mDragging = False
        self.emit(SIGNAL("getSelectedFeatures"), selectedFeatures)
예제 #9
0
class ArkMapToolInteractive(QgsMapTool):

    _active = False

    _dragging = False
    _panningEnabled = False

    _zoomingEnabled = False
    _zoomRubberBand = None  #QgsRubberBand()
    _zoomRect = None # QRect()

    _snappingEnabled = False
    _snapper = None  #QgsMapCanvasSnapper()
    _snappingMarker = None  # QgsVertexMarker()

    _showSnappableVertices = False
    _snappableVertices = []  # [QgsPoint()]
    _snappableMarkers = []  # [QgsVertexMarker()]

    def __init__(self, canvas, snappingEnabled=False, showSnappableVertices=False):
        super(ArkMapToolInteractive, self).__init__(canvas)
        self._snappingEnabled = snappingEnabled
        self._showSnappableVertices = showSnappableVertices

    def __del__(self):
        if self._active:
            self.deactivate()

    def isActive(self):
        return self._active

    def activate(self):
        super(ArkMapToolInteractive, self).activate()
        self._active = True
        self._startSnapping()

    def deactivate(self):
        self._active = False
        if self._snappingEnabled:
            self._stopSnapping()
        if (self._zoomRubberBand is not None):
            self.canvas().scene().removeItem(self._zoomRubberBand)
            self._zoomRubberBand = None
        super(ArkMapToolInteractive, self).deactivate()

    def setAction(self, action):
        super(ArkMapToolInteractive, self).setAction(action)
        self.action().triggered.connect(self._activate)

    def _activate(self):
        self.canvas().setMapTool(self)

    def panningEnabled(self):
        return self._panningEnabled

    def setPanningEnabled(self, enabled):
        self._panningEnabled = enabled

    def zoomingEnabled(self):
        return self._zoomingEnabled

    def setZoomingEnabled(self, enabled):
        self._zoomingEnabled = enabled

    def snappingEnabled(self):
        return self._snappingEnabled

    def setSnappingEnabled(self, enabled):
        if (self._snappingEnabled == enabled):
            return
        self._snappingEnabled = enabled
        if not self._active:
            return
        if enabled:
            self._startSnapping()
        else:
            self._stopSnapping()

    def _startSnapping(self):
        self._snapper = QgsMapCanvasSnapper()
        self._snapper.setMapCanvas(self.canvas())
        if self._showSnappableVertices:
            self._startSnappableVertices()

    def _stopSnapping(self):
        self._deleteSnappingMarker()
        self._snapper = None
        if self._showSnappableVertices:
            self._stopSnappableVertices()

    def showSnappableVertices(self):
        return self._showSnappableVertices

    def setShowSnappableVertices(self, show):
        if (self._showSnappableVertices == show):
            return
        self._showSnappableVertices = show
        if not self._active:
            return
        if show:
            self._startSnappableVertices()
        else:
            self._stopSnappableVertices()

    def _startSnappableVertices(self):
        self.canvas().layersChanged.connect(self._layersChanged)
        self.canvas().extentsChanged.connect(self._redrawSnappableMarkers)
        QgsProject.instance().snapSettingsChanged.connect(self._layersChanged)
        self._layersChanged()

    def _stopSnappableVertices(self):
        self._deleteSnappableMarkers()
        self._snappableLayers = []
        self.canvas().layersChanged.disconnect(self._layersChanged)
        self.canvas().extentsChanged.disconnect(self._redrawSnappableMarkers)
        QgsProject.instance().snapSettingsChanged.disconnect(self._layersChanged)

    def canvasMoveEvent(self, e):
        super(ArkMapToolInteractive, self).canvasMoveEvent(e)
        if not self._active:
            return
        e.ignore()
        if (self._panningEnabled and e.buttons() & Qt.LeftButton):
            # Pan map mode
            if not self._dragging:
                self._dragging = True
                self.setCursor(QCursor(Qt.ClosedHandCursor))
            self.canvas().panAction(e)
            e.accept()
        elif (self._zoomingEnabled and e.buttons() & Qt.RightButton):
            # Zoom map mode
            if not self._dragging:
                self._dragging = True
                self.setCursor(QCursor(Qt.ClosedHandCursor))
                self._zoomRubberBand = QgsRubberBand(self.canvas(), QGis.Polygon)
                color = QColor(Qt.blue)
                color.setAlpha(63)
                self._zoomRubberBand.setColor(color)
                self._zoomRect = QRect(0, 0, 0, 0)
                self._zoomRect.setTopLeft(e.pos())
            self._zoomRect.setBottomRight(e.pos())
            if self._zoomRubberBand is not None:
                self._zoomRubberBand.setToCanvasRectangle(self._zoomRect)
                self._zoomRubberBand.show()
            e.accept()
        elif self._snappingEnabled:
            mapPoint, snapped = self._snapCursorPoint(e.pos())
            if (snapped):
                self._createSnappingMarker(mapPoint)
            else:
                self._deleteSnappingMarker()

    def canvasReleaseEvent(self, e):
        super(ArkMapToolInteractive, self).canvasReleaseEvent(e)
        e.ignore()
        if (e.button() == Qt.LeftButton):
            if self._dragging:
                # Pan map mode
                self.canvas().panActionEnd(e.pos())
                self.setCursor(capture_point_cursor)
                self._dragging = False
                e.accept()
        elif (e.button() == Qt.RightButton):
            if self._dragging:
                # Zoom mode
                self._zoomRect.setBottomRight(e.pos())
                if (self._zoomRect.topLeft() != self._zoomRect.bottomRight()):
                    coordinateTransform = self.canvas().getCoordinateTransform()
                    ll = coordinateTransform.toMapCoordinates(self._zoomRect.left(), self._zoomRect.bottom())
                    ur = coordinateTransform.toMapCoordinates(self._zoomRect.right(), self._zoomRect.top())
                    r = QgsRectangle()
                    r.setXMinimum(ll.x())
                    r.setYMinimum(ll.y())
                    r.setXMaximum(ur.x())
                    r.setYMaximum(ur.y())
                    r.normalize()
                    if (r.width() != 0 and r.height() != 0):
                        self.canvas().setExtent(r)
                        self.canvas().refresh()
                self._dragging = False
                if (self._zoomRubberBand is not None):
                    self.canvas().scene().removeItem(self._zoomRubberBand)
                    self._zoomRubberBand = None
                e.accept()

    def keyPressEvent(self, e):
        super(ArkMapToolInteractive, self).keyPressEvent(e)
        if (e.key() == Qt.Key_Escape):
            self.canvas().unsetMapTool(self)
            e.accept()

    def _snapCursorPoint(self, cursorPoint):
        res, snapResults = self._snapper.snapToBackgroundLayers(cursorPoint)
        if (res != 0 or len(snapResults) < 1):
            return self.toMapCoordinates(cursorPoint), False
        else:
            # Take a copy as QGIS will delete the result!
            snappedVertex = QgsPoint(snapResults[0].snappedVertex)
            return snappedVertex, True

    def _createSnappingMarker(self, snapPoint):
        if (self._snappingMarker is None):
            self._snappingMarker = QgsVertexMarker(self.canvas())
            self._snappingMarker.setIconType(QgsVertexMarker.ICON_CROSS)
            self._snappingMarker.setColor(Qt.magenta)
            self._snappingMarker.setPenWidth(3)
        self._snappingMarker.setCenter(snapPoint)

    def _deleteSnappingMarker(self):
        if (self._snappingMarker is not None):
            self.canvas().scene().removeItem(self._snappingMarker)
            self._snappingMarker = None

    def _createSnappableMarkers(self):
        if (not self._showSnappableVertices or not self._snappingEnabled):
            return
        extent = self.canvas().extent()
        for vertex in self._snappableVertices.asMultiPoint():
            if (extent.contains(vertex)):
                marker = QgsVertexMarker(self.canvas())
                marker.setIconType(QgsVertexMarker.ICON_X)
                marker.setColor(Qt.gray)
                marker.setPenWidth(1)
                marker.setCenter(vertex)
                self._snappableMarkers.append(marker)

    def _deleteSnappableMarkers(self):
        for marker in self._snappableMarkers:
            self.canvas().scene().removeItem(marker)
        del self._snappableMarkers[:]

    def _layersChanged(self):
        if (not self._showSnappableVertices or not self._snappingEnabled):
            return
        self._buildSnappableLayers()
        self._deleteSnappableMarkers()
        self._createSnappableMarkers()

    def _redrawSnappableMarkers(self):
        if (not self._showSnappableVertices or not self._snappingEnabled):
            return
        self._deleteSnappableMarkers()
        self._createSnappableMarkers()

    def _buildSnappableLayers(self):
        if (not self._showSnappableVertices or not self._snappingEnabled):
            return
        vertices = []
        for layer in self.canvas().layers():
            ok, enabled, type, units, tolerance, avoid = QgsProject.instance().snapSettingsForLayer(layer.id())
            if (ok and enabled and not layer.isEditable()):
                for feature in layer.getFeatures():
                    geometry = feature.geometry()
                    if geometry is None:
                        pass
                    elif geometry.type() == QGis.Point:
                        vertices.extend([geometry.asPoint()])
                    elif geometry.type() == QGis.Line:
                        vertices.extend(geometry.asPolyline())
                    elif geometry.type() == QGis.Polygon:
                        lines = geometry.asPolygon()
                        for line in lines:
                            vertices.extend(line)
        self._snappableVertices = QgsGeometry.fromMultiPoint(vertices)
        self._snappableVertices.simplify(0)
예제 #10
0
class InfoTool(QgsMapTool):
    def __init__(self, canvas, snapradius=2):
        super(InfoTool, self).__init__(canvas)
        self.canvas = canvas
        self.radius = snapradius

        self.selectband = QgsRubberBand(self.canvas, QGis.Polygon)
        self.selectrect = QRect()
        self.dragging = False
        self.selectionlayers = []

    def getFeatures(self, rect, firstonly=False):
        # The MS SQL driver seems to crash with a empty rectangle.
        # Need to check QGIS to patch issue
        if rect.isEmpty():
            return

        for layer in self.selectionlayers.itervalues():
            if (not layer.type() == QgsMapLayer.VectorLayer or
                    layer.geometryType() == QGis.NoGeometry):
                continue

            rect = self.toLayerCoordinates(layer, rect)
            rq = QgsFeatureRequest().setFilterRect(rect) \
                .setFlags(QgsFeatureRequest.ExactIntersect)
            features = []
            for feature in layer.getFeatures(rq):
                if feature.isValid():
                    features.append(feature)

            yield layer, features

    def toSearchRect(self, point):
        size = 20
        rect = QRectF()
        rect.setLeft(point.x() - size)
        rect.setRight(point.x() + size)
        rect.setTop(point.y() - size)
        rect.setBottom(point.y() + size)

        transform = self.canvas.getCoordinateTransform()
        ll = transform.toMapCoordinates(rect.left(), rect.bottom())
        ur = transform.toMapCoordinates(rect.right(), rect.top())

        rect = QgsRectangle(ur, ll)
        return rect

    def canvasPressEvent(self, event):
        self.dragging = False
        self.selectrect.setRect(0, 0, 0, 0)

        self.selectband = QgsRubberBand(self.canvas, QGis.Polygon)
        self.selectband.setColor(QColor.fromRgb(0, 0, 255, 65))
        self.selectband.setWidth(5)

    def canvasMoveEvent(self, event):
        if not event.buttons() == Qt.LeftButton:
            return

        if not self.dragging:
            self.selectrect.setTopLeft(event.pos())
            self.dragging = True
        self.selectrect.setBottomRight(event.pos())

        maptoolutils.setRubberBand(self.canvas, self.selectrect, self.selectband)

    def canvasReleaseEvent(self, event):
        if self.dragging:
            geometry = self.selectband.asGeometry()
            if not geometry:
                return

            rect = geometry.boundingBox()
            firstonly = False
        else:
            firstonly = True
            rect = self.toSearchRect(event.pos())

        self.dragging = False
        self.selectband.reset()

        results = OrderedDict((l, f) for l, f in self.getFeatures(rect))

        RoamEvents.selectioncleared.emit()
        RoamEvents.selectionchanged.emit(results)
예제 #11
0
class SelectedFeatureByRectTasDraw(QgsMapTool):
    def __init__(self, canvas, distance):
        self.mCanvas = canvas
        QgsMapTool.__init__(self, canvas)
        self.mCursor = Qt.ArrowCursor
        self.mRubberBand = None
        self.mDragging = False
        self.mSelectRect = QRect()
        self.rubberBandLine = None
        self.distance = distance
        self.mSnapper = QgsMapCanvasSnapper(canvas)
#     QgsRubberBand* mRubberBand;
#     def reset(self):
#         self.startPoint = None
#         self.endPoint = None
#         self.isDrawing = False
#         SelectByRect.RubberRect.reset(QGis.Polygon)
#         self.layer = self.canvas.currentLayer()

    def canvasPressEvent(self, e):
        self.mSelectRect.setRect(0, 0, 0, 0)
        self.mRubberBand = QgsRubberBand(self.mCanvas, QGis.Polygon)
        self.startPoint, self.pointID, self.layer = self.snapPoint(e.pos())
#         self.reset()
#         self.startPoint = self.toMapCoordinates(e.pos())
#         self.isDrawing = True

    def canvasMoveEvent(self, e):
        if (e.buttons() != Qt.LeftButton):
            return
        if (not self.mDragging):
            self.mDragging = True
            self.mSelectRect.setTopLeft(e.pos())
        self.mSelectRect.setBottomRight(e.pos())
        QgsMapToolSelectUtils.setRubberBand(self.mCanvas, self.mSelectRect,
                                            self.mRubberBand)
#         if not self.isDrawing:
#             return
#         SelectByRect.RubberRect.reset(QGis.Polygon)
#         self.endPoint = self.toMapCoordinates(e.pos())
#         self.rect = QgsRectangle(self.startPoint, self.endPoint)
#         SelectByRect.RubberRect.addGeometry(QgsGeometry.fromRect(self.rect), None)
#         SelectByRect.RubberRect.show()

    def canvasReleaseEvent(self, e):
        self.endPoint, self.pointID, self.layer = self.snapPoint(e.pos())
        if len(define._newGeometryList) > 0:
            geom = define._newGeometryList[0]
            if geom.intersects(self.mRubberBand.asGeometry()):
                pointArray = geom.asPolyline()
                # pointArray1 = QgisHelper.offsetCurve(pointArray, 1200)
                if self.rubberBandLine != None:
                    self.rubberBandLine.reset(QGis.Line)
                    del self.rubberBandLine
                    self.rubberBandLine = None
                self.rubberBandLine = QgsRubberBand(self.mCanvas, QGis.Line)
                self.rubberBandLine.setColor(Qt.blue)
                bearing = 0.0
                if self.startPoint.y() >= self.endPoint.y() and (
                        math.fabs(self.startPoint.x() - self.endPoint.x()) <
                        math.fabs(self.startPoint.y() - self.endPoint.y())):
                    bearing = Unit.ConvertDegToRad(180)
                elif self.startPoint.x() >= self.endPoint.x() and (
                        math.fabs(self.startPoint.x() - self.endPoint.x()) >
                        math.fabs(self.startPoint.y() - self.endPoint.y())):
                    bearing = Unit.ConvertDegToRad(270)
                elif self.startPoint.x() < self.endPoint.x() and (
                        math.fabs(self.startPoint.x() - self.endPoint.x()) >
                        math.fabs(self.startPoint.y() - self.endPoint.y())):
                    bearing = Unit.ConvertDegToRad(90)
                else:
                    bearing = 0.0

                for point in pointArray:

                    pt = MathHelper.distanceBearingPoint(
                        Point3D(point.x(), point.y()), bearing, self.distance
                    )  # MathHelper.getBearing(self.startPoint, self.endPoint), self.distance)
                    self.rubberBandLine.addPoint(pt)
                gg = self.rubberBandLine.asGeometry()
                g = gg.asPolyline()
                # self.rubberBandLine.show()
                if (self.mRubberBand != None):
                    self.mRubberBand.reset(QGis.Polygon)
                    del self.mRubberBand
                    self.mRubberBand = None
                    self.mDragging = False
                    self.emit(
                        SIGNAL("resultSelectedFeatureByRectTasDraw"), gg,
                        self.distance, bearing
                    )  # MathHelper.getBearing(self.startPoint, self.endPoint))
                return
        vlayer = QgsMapToolSelectUtils.getCurrentVectorLayer(self.mCanvas)
        if (vlayer == None):
            if (self.mRubberBand != None):
                self.mRubberBand.reset(QGis.Polygon)
                del self.mRubberBand
                self.mRubberBand = None
                self.mDragging = False
            return

        if (not self.mDragging):
            QgsMapToolSelectUtils.expandSelectRectangle(
                self.mSelectRect, vlayer, e.pos())
        else:
            if (self.mSelectRect.width() == 1):
                self.mSelectRect.setLeft(self.mSelectRect.left() + 1)
            if (self.mSelectRect.height() == 1):
                self.mSelectRect.setBottom(self.mSelectRect.bottom() + 1)

        if (self.mRubberBand != None):
            QgsMapToolSelectUtils.setRubberBand(self.mCanvas, self.mSelectRect,
                                                self.mRubberBand)
            selectGeom = self.mRubberBand.asGeometry()

            # QgsMapToolSelectUtils.setSelectFeatures( self.mCanvas, selectGeom, e )
            selectedFeatures = QgsMapToolSelectUtils.setSelectFeaturesOrRubberband_Tas_1(
                self.mCanvas, selectGeom, e)
            if len(selectedFeatures) > 0:
                geom = selectedFeatures[0].geometry()
                if geom.intersects(self.mRubberBand.asGeometry()):
                    pointArray = geom.asPolyline()
                    # pointArray1 = QgisHelper.offsetCurve(pointArray, 1200)
                    if self.rubberBandLine != None:
                        self.rubberBandLine.reset(QGis.Line)
                        del self.rubberBandLine
                        self.rubberBandLine = None
                    self.rubberBandLine = QgsRubberBand(
                        self.mCanvas, QGis.Line)
                    self.rubberBandLine.setColor(Qt.blue)
                    bearing = 0.0
                    gg = None
                    if self.startPoint.y() >= self.endPoint.y() and (
                            math.fabs(self.startPoint.x() - self.endPoint.x())
                            < math.fabs(self.startPoint.y() -
                                        self.endPoint.y())):
                        bearing = Unit.ConvertDegToRad(180)
                        gg = self.newCreateLine(geom, self.distance, 180)
                    elif self.startPoint.x() >= self.endPoint.x() and (
                            math.fabs(self.startPoint.x() - self.endPoint.x())
                            > math.fabs(self.startPoint.y() -
                                        self.endPoint.y())):
                        bearing = Unit.ConvertDegToRad(270)
                        gg = self.newCreateLine(geom, self.distance, 270)
                    elif self.startPoint.x() < self.endPoint.x() and (
                            math.fabs(self.startPoint.x() - self.endPoint.x())
                            > math.fabs(self.startPoint.y() -
                                        self.endPoint.y())):
                        bearing = Unit.ConvertDegToRad(90)
                        gg = self.newCreateLine(geom, self.distance, 90)
                    else:
                        bearing = 0.0
                        gg = self.newCreateLine(geom, self.distance, 0)
                    for point in pointArray:
                        pt = MathHelper.distanceBearingPoint(
                            Point3D(point.x(),
                                    point.y()), bearing, self.distance
                        )  #MathHelper.getBearing(self.startPoint, self.endPoint), self.distance)

                        self.rubberBandLine.addPoint(pt)
                    # gg= self.newCreateLine(geom, -self.distance, 0)

                    self.emit(
                        SIGNAL("resultSelectedFeatureByRectTasDraw"), gg,
                        self.distance, bearing
                    )  #MathHelper.getBearing(self.startPoint, self.endPoint))
                    self.rubberBandLine.reset(QGis.Line)
            del selectGeom

            self.mRubberBand.reset(QGis.Polygon)
            del self.mRubberBand
            self.mRubberBand = None
        self.mDragging = False


#         self.canvasMoveEvent(e)
#         if self.layer != None:
#             self.layer.removeSelection()
#             if self.layer.crs().mapUnits() != self.canvas.mapUnits():
#                 if self.layer.crs().mapUnits == QGis.Meters:
#                     lstPoint = QgisHelper.Degree2MeterList([self.startPoint, self.endPoint])
#                 else:
#                     lstPoint = QgisHelper.Meter2DegreeList([self.startPoint, self.endPoint])
#                 rect = QgsRectangle(lstPoint[0], lstPoint[1])
#                 self.layer.select(rect, True)
#             else:
#                 self.layer.select(self.rect, False)
#         else:
#             QMessageBox.warning(None, "Information", "Please select layer!")
#         self.reset()

    def snapPoint(self, p, bNone=False):
        if define._snapping == False:
            return (
                define._canvas.getCoordinateTransform().toMapCoordinates(p),
                None, None)
        snappingResults = self.mSnapper.snapToBackgroundLayers(p)
        if (snappingResults[0] != 0 or len(snappingResults[1]) < 1):

            if bNone:
                return (None, None, None)
            else:
                return (define._canvas.getCoordinateTransform().
                        toMapCoordinates(p), None, None)
        else:
            return (snappingResults[1][0].snappedVertex,
                    snappingResults[1][0].snappedAtGeometry,
                    snappingResults[1][0].layer)

    def newCreateLine(self, geom, dist, angle):
        if define._units != QGis.Meters:
            dist = define._qgsDistanceArea.convertMeasurement(
                dist, QGis.Meters, QGis.Degrees, False)[0]
        g = geom.offsetCurve(dist, 0, 2, 2)
        pointArrayOld = geom.asPolyline()
        pointArrayNew = g.asPolyline()
        if MathHelper.calcDistance(
                pointArrayNew[0], pointArrayOld[0]) > MathHelper.calcDistance(
                    pointArrayNew[0], pointArrayOld[len(pointArrayOld) - 1]):
            array = []
            i = len(pointArrayNew) - 1
            while i >= 0:
                array.append(pointArrayNew[i])
                i -= 1
            pointArrayNew = array
        if angle == 0:
            if pointArrayNew[0].y() < pointArrayOld[0].y():
                g = geom.offsetCurve(-dist, 0, 2, 2)
                pointArrayNew = g.asPolyline()
        elif angle == 90:
            if pointArrayNew[0].x() < pointArrayOld[0].x():
                g = geom.offsetCurve(-dist, 0, 2, 2)
                pointArrayNew = g.asPolyline()
        elif angle == 180:
            if pointArrayNew[0].y() > pointArrayOld[0].y():
                g = geom.offsetCurve(-dist, 0, 2, 2)
                pointArrayNew = g.asPolyline()
        elif angle == 270:
            if pointArrayNew[0].x() > pointArrayOld[0].x():
                g = geom.offsetCurve(-dist, 0, 2, 2)
                pointArrayNew = g.asPolyline()
        if MathHelper.calcDistance(
                pointArrayNew[0], pointArrayOld[0]) > MathHelper.calcDistance(
                    pointArrayNew[0], pointArrayOld[len(pointArrayOld) - 1]):
            array = []
            i = len(pointArrayNew) - 1
            while i >= 0:
                array.append(pointArrayNew[i])
                i -= 1
            pointArrayNew = array
        i = 0

        while i < len(pointArrayNew) - 1:
            if i == 0:
                i += 1
                continue
            line = None
            if define._units == QGis.Meters:
                if angle == 0:
                    line = QgsGeometry.fromPolyline([
                        pointArrayOld[0],
                        QgsPoint(pointArrayOld[0].x(), 100000000)
                    ])
                elif angle == 90:
                    line = QgsGeometry.fromPolyline([
                        pointArrayOld[0],
                        QgsPoint(100000000, pointArrayOld[0].y())
                    ])
                elif angle == 180:
                    line = QgsGeometry.fromPolyline(
                        [pointArrayOld[0],
                         QgsPoint(pointArrayOld[0].x(), 0)])
                elif angle == 270:
                    line = QgsGeometry.fromPolyline(
                        [pointArrayOld[0],
                         QgsPoint(0, pointArrayOld[0].y())])
            else:
                if angle == 0:
                    line = QgsGeometry.fromPolyline([
                        pointArrayOld[0],
                        QgsPoint(pointArrayOld[0].x(),
                                 pointArrayOld[0].y() + 0.1)
                    ])
                elif angle == 90:
                    line = QgsGeometry.fromPolyline([
                        pointArrayOld[0],
                        QgsPoint(pointArrayOld[0].x() + 0.1,
                                 pointArrayOld[0].y())
                    ])
                elif angle == 180:
                    line = QgsGeometry.fromPolyline([
                        pointArrayOld[0],
                        QgsPoint(pointArrayOld[0].x(),
                                 pointArrayOld[0].y() - 0.1)
                    ])
                elif angle == 270:
                    line = QgsGeometry.fromPolyline([
                        pointArrayOld[0],
                        QgsPoint(pointArrayOld[0].x() - 0.1,
                                 pointArrayOld[0].y())
                    ])
            lineNew = QgsGeometry.fromPolyline([
                MathHelper.distanceBearingPoint(
                    Point3D(pointArrayNew[i].x(), pointArrayNew[i].y()),
                    MathHelper.getBearing(pointArrayNew[i],
                                          pointArrayNew[i - 1]), 100000),
                pointArrayNew[i]
            ])

            if line.intersects(lineNew):
                pointGeom = line.intersection(lineNew)
                intersectPoint = pointGeom.asPoint()
                pointArrayNew.pop(i - 1)
                pointArrayNew.insert(i - 1, intersectPoint)
                break
            else:
                pointArrayNew.pop(i - 1)
                continue
            i += 1
        i = len(pointArrayNew) - 1
        while i > 1:
            line = None
            if define._units == QGis.Meters:
                if angle == 0:
                    line = QgsGeometry.fromPolyline([
                        pointArrayOld[len(pointArrayOld) - 1],
                        QgsPoint(pointArrayOld[len(pointArrayOld) - 1].x(),
                                 100000000)
                    ])
                elif angle == 90:
                    line = QgsGeometry.fromPolyline([
                        pointArrayOld[len(pointArrayOld) - 1],
                        QgsPoint(100000000,
                                 pointArrayOld[len(pointArrayOld) - 1].y())
                    ])
                elif angle == 180:
                    line = QgsGeometry.fromPolyline([
                        pointArrayOld[len(pointArrayOld) - 1],
                        QgsPoint(pointArrayOld[len(pointArrayOld) - 1].x(), 0)
                    ])
                elif angle == 270:
                    line = QgsGeometry.fromPolyline([
                        pointArrayOld[len(pointArrayOld) - 1],
                        QgsPoint(0, pointArrayOld[len(pointArrayOld) - 1].y())
                    ])
            else:
                if angle == 0:
                    line = QgsGeometry.fromPolyline([
                        pointArrayOld[len(pointArrayOld) - 1],
                        QgsPoint(
                            pointArrayOld[len(pointArrayOld) - 1].x(),
                            pointArrayOld[len(pointArrayOld) - 1].y() + 0.1)
                    ])
                elif angle == 90:
                    line = QgsGeometry.fromPolyline([
                        pointArrayOld[len(pointArrayOld) - 1],
                        QgsPoint(
                            pointArrayOld[len(pointArrayOld) - 1].x() + 0.1,
                            pointArrayOld[len(pointArrayOld) - 1].y())
                    ])
                elif angle == 180:
                    line = QgsGeometry.fromPolyline([
                        pointArrayOld[len(pointArrayOld) - 1],
                        QgsPoint(
                            pointArrayOld[len(pointArrayOld) - 1].x(),
                            pointArrayOld[len(pointArrayOld) - 1].y() - 0.1)
                    ])
                elif angle == 270:
                    line = QgsGeometry.fromPolyline([
                        pointArrayOld[len(pointArrayOld) - 1],
                        QgsPoint(
                            pointArrayOld[len(pointArrayOld) - 1].x() - 0.1,
                            pointArrayOld[len(pointArrayOld) - 1].y())
                    ])
            # line = QgsGeometry.fromPolyline([pointArrayOld[len(pointArrayOld) - 1], QgsPoint(pointArrayOld[len(pointArrayOld) - 1].x(), 100000000)])
            lineNew = QgsGeometry.fromPolyline([
                MathHelper.distanceBearingPoint(
                    Point3D(pointArrayNew[i].x(), pointArrayNew[i].y()),
                    MathHelper.getBearing(pointArrayNew[i - 1],
                                          pointArrayNew[i]), 100000),
                pointArrayNew[i - 1]
            ])
            if line.intersects(lineNew):
                pointGeom = line.intersection(lineNew)
                intersectPoint = pointGeom.asPoint()
                pointArrayNew.pop(i)
                pointArrayNew.insert(i, intersectPoint)
                break
            else:
                pointArrayNew.pop(i)
                i -= 1
                continue
            i -= 1
        return QgsGeometry.fromPolyline(pointArrayNew)
예제 #12
0
class ConnecMapTool(ParentMapTool):
    """ Button 20: User select connections from layer 'connec'
    Execute SQL function: 'gw_fct_connect_to_network' """
    def __init__(self, iface, settings, action, index_action):
        """ Class constructor """

        # Call ParentMapTool constructor
        super(ConnecMapTool, self).__init__(iface, settings, action,
                                            index_action)

        self.dragging = False

        # Select rectangle
        self.select_rect = QRect()

    """ QgsMapTools inherited event functions """

    def canvasMoveEvent(self, event):
        """ With left click the digitizing is finished """

        if event.buttons() == Qt.LeftButton:

            if not self.dragging:
                self.dragging = True
                self.select_rect.setTopLeft(event.pos())

            self.select_rect.setBottomRight(event.pos())
            self.set_rubber_band()

        else:

            # Hide marker
            self.vertex_marker.hide()

            # Get the click
            x = event.pos().x()
            y = event.pos().y()
            event_point = QPoint(x, y)

            # Snapping
            (retval, result) = self.snapper.snapToBackgroundLayers(
                event_point)  # @UnusedVariable

            # That's the snapped features
            if result:
                for snapped_feat in result:
                    # Check if it belongs to 'connec' or 'gully' group
                    exist_connec = self.snapper_manager.check_connec_group(
                        snapped_feat.layer)
                    exist_gully = self.snapper_manager.check_gully_group(
                        snapped_feat.layer)
                    if exist_connec or exist_gully:
                        # Get the point and add marker
                        point = QgsPoint(result[0].snappedVertex)
                        self.vertex_marker.setCenter(point)
                        self.vertex_marker.show()
                        break

    def canvasPressEvent(self, event):  #@UnusedVariable

        self.select_rect.setRect(0, 0, 0, 0)
        self.rubber_band.reset(QGis.Polygon)

    def canvasReleaseEvent(self, event):
        """ With left click the digitizing is finished """

        if event.button() == Qt.LeftButton:

            # Get the click
            x = event.pos().x()
            y = event.pos().y()
            event_point = QPoint(x, y)

            # Simple selection
            if not self.dragging:

                # Snap to connec or gully
                (retval, result) = self.snapper.snapToBackgroundLayers(
                    event_point)  # @UnusedVariable

                # That's the snapped features
                if result:
                    # Check if it belongs to 'connec' or 'gully' group
                    exist_connec = self.snapper_manager.check_connec_group(
                        result[0].layer)
                    exist_gully = self.snapper_manager.check_gully_group(
                        result[0].layer)
                    if exist_connec or exist_gully:
                        key = QApplication.keyboardModifiers()
                        # If Ctrl+Shift is clicked: deselect snapped feature
                        if key == (Qt.ControlModifier | Qt.ShiftModifier):
                            result[0].layer.deselect(
                                [result[0].snappedAtGeometry])
                        else:
                            # If Ctrl is not clicked: remove previous selection
                            if key != Qt.ControlModifier:
                                result[0].layer.removeSelection()
                            result[0].layer.select(
                                [result[0].snappedAtGeometry])

                        # Hide marker
                        self.vertex_marker.hide()

            # Multiple selection
            else:

                # Set valid values for rectangle's width and height
                if self.select_rect.width() == 1:
                    self.select_rect.setLeft(self.select_rect.left() + 1)

                if self.select_rect.height() == 1:
                    self.select_rect.setBottom(self.select_rect.bottom() + 1)

                self.set_rubber_band()
                selected_geom = self.rubber_band.asGeometry()  #@UnusedVariable
                self.select_multiple_features(self.selected_rectangle)
                self.dragging = False

                # Refresh map canvas
                self.rubber_band.reset()

        elif event.button() == Qt.RightButton:

            # Check selected records
            number_features = 0
            for layer in self.layer_connec_man:
                number_features += layer.selectedFeatureCount()

            if number_features > 0:
                message = ("Number of features selected in the 'connec' group")
                title = "Interpolate value - Do you want to update values"
                answer = self.controller.ask_question(
                    message, title, parameter=str(number_features))
                if answer:
                    # Create link
                    self.link_selected_features('connec',
                                                self.layer_connec_man)

            if self.layer_gully_man:
                # Check selected records
                number_features = 0
                for layer in self.layer_gully_man:
                    number_features += layer.selectedFeatureCount()

                if number_features > 0:
                    message = (
                        "Number of features selected in the 'gully' group")
                    title = "Interpolate value - Do you want to update values"
                    answer = self.controller.ask_question(
                        message, title, parameter=str(number_features))
                    if answer:
                        # Create link
                        self.link_selected_features('gully',
                                                    self.layer_gully_man)

    def activate(self):

        # Check button
        self.action().setChecked(True)

        # Rubber band
        self.rubber_band.reset()

        # Store user snapping configuration
        self.snapper_manager.store_snapping_options()

        # Clear snapping
        self.snapper_manager.clear_snapping()

        # Set snapping to 'connec' and 'gully'
        self.snapper_manager.snap_to_connec_gully()

        # Change cursor
        cursor = self.get_cursor_multiple_selection()
        self.canvas.setCursor(cursor)

        # Show help message when action is activated
        if self.show_help:
            message = "Right click to use current selection, select connec points by clicking or dragging (selection box)"
            self.controller.show_info(message)

    def deactivate(self):

        # Call parent method
        ParentMapTool.deactivate(self)

    def link_selected_features(self, geom_type, layers):
        """ Link selected @geom_type to the pipe """

        # Check features selected
        number_features = 0
        for layer in layers:
            number_features += layer.selectedFeatureCount()

        if number_features == 0:
            message = "You have to select at least one feature!"
            self.controller.show_warning(message)
            return

        # Get selected features from layers of selected @geom_type
        aux = "{"
        field_id = geom_type + "_id"

        # Iterate over all layers
        for layer in layers:
            if layer.selectedFeatureCount() > 0:
                # Get selected features of the layer
                features = layer.selectedFeatures()
                for feature in features:
                    feature_id = feature.attribute(field_id)
                    aux += str(feature_id) + ", "
                list_feature_id = aux[:-2] + "}"

                # Execute function
                function_name = "gw_fct_connect_to_network"
                sql = ("SELECT " + self.schema_name + "." + function_name + ""
                       "('" + list_feature_id + "', '" + geom_type.upper() +
                       "');")
                self.controller.execute_sql(sql, log_sql=True)
                layer.removeSelection()
        # Refresh map canvas
        self.rubber_band.reset()
        self.refresh_map_canvas()
        self.iface.actionPan().trigger()

    def set_rubber_band(self):

        # Coordinates transform
        transform = self.canvas.getCoordinateTransform()

        # Coordinates
        ll = transform.toMapCoordinates(self.select_rect.left(),
                                        self.select_rect.bottom())
        lr = transform.toMapCoordinates(self.select_rect.right(),
                                        self.select_rect.bottom())
        ul = transform.toMapCoordinates(self.select_rect.left(),
                                        self.select_rect.top())
        ur = transform.toMapCoordinates(self.select_rect.right(),
                                        self.select_rect.top())

        # Rubber band
        self.rubber_band.reset(QGis.Polygon)
        self.rubber_band.addPoint(ll, False)
        self.rubber_band.addPoint(lr, False)
        self.rubber_band.addPoint(ur, False)
        self.rubber_band.addPoint(ul, False)
        self.rubber_band.addPoint(ll, True)

        self.selected_rectangle = QgsRectangle(ll, ur)

    def select_multiple_features(self, selectGeometry):

        if self.layer_connec_man is None and self.layer_gully_man is None:
            return

        key = QApplication.keyboardModifiers()

        # If Ctrl+Shift clicked: remove features from selection
        if key == (Qt.ControlModifier | Qt.ShiftModifier):
            behaviour = QgsVectorLayer.RemoveFromSelection
        # If Ctrl clicked: add features to selection
        elif key == Qt.ControlModifier:
            behaviour = QgsVectorLayer.AddToSelection
        # If Ctrl not clicked: add features to selection
        else:
            behaviour = QgsVectorLayer.AddToSelection

        # Selection for all connec and gully layers
        for layer in self.layer_connec_man:
            layer.selectByRect(selectGeometry, behaviour)

        if self.layer_gully_man:
            for layer in self.layer_gully_man:
                layer.selectByRect(selectGeometry, behaviour)
예제 #13
0
class InfoTool(QgsMapTool):
    def __init__(self, canvas, snapradius = 2):
        super(InfoTool, self).__init__(canvas)
        self.canvas = canvas
        self.radius = snapradius

        self.selectband = QgsRubberBand(self.canvas, QGis.Polygon )
        self.selectrect = QRect()
        self.dragging = False
        self.selectionlayers = []

    def getFeatures(self, rect, firstonly=False):
        # The MS SQL driver seems to crash with a empty rectangle.
        # Need to check QGIS to patch issue
        if rect.isEmpty():
            return

        for layer in self.selectionlayers.itervalues():
            if (not layer.type() == QgsMapLayer.VectorLayer or
                    layer.geometryType() == QGis.NoGeometry):
                continue

            rect = self.toLayerCoordinates(layer, rect)
            rq = QgsFeatureRequest().setFilterRect(rect) \
                .setFlags(QgsFeatureRequest.ExactIntersect)
            features = []
            for feature in layer.getFeatures(rq):
                if feature.isValid():
                    features.append(feature)

            yield layer, features

    def toSearchRect(self, point):
        size = 20
        rect = QRectF()
        rect.setLeft(point.x() - size)
        rect.setRight(point.x() + size)
        rect.setTop(point.y() - size)
        rect.setBottom(point.y() + size)

        transform = self.canvas.getCoordinateTransform()
        ll = transform.toMapCoordinates(rect.left(), rect.bottom())
        ur = transform.toMapCoordinates(rect.right(), rect.top())

        rect = QgsRectangle(ur, ll)
        return rect

    def canvasPressEvent(self, event):
        self.dragging = False
        self.selectrect.setRect(0, 0, 0, 0)

        self.selectband = QgsRubberBand(self.canvas, QGis.Polygon )
        self.selectband.setColor(QColor.fromRgb(0,0,255, 65))
        self.selectband.setWidth(5)

    def canvasMoveEvent(self, event):
        if not event.buttons() == Qt.LeftButton:
            return

        if not self.dragging:
            self.selectrect.setTopLeft(event.pos())
            self.dragging = True
        self.selectrect.setBottomRight(event.pos())

        maptoolutils.setRubberBand(self.canvas, self.selectrect, self.selectband)

    def canvasReleaseEvent(self, event):
        if self.dragging:
            geometry = self.selectband.asGeometry()
            if not geometry:
                return

            rect = geometry.boundingBox()
            firstonly = False
        else:
            firstonly = True
            rect = self.toSearchRect(event.pos())

        self.dragging = False
        self.selectband.reset()

        results = OrderedDict((l,f) for l, f in self.getFeatures(rect))

        RoamEvents.selectioncleared.emit()
        RoamEvents.selectionchanged.emit(results)
class ExtractRasterValue(ParentMapTool):
    """ Button 18. User select nodes and assign raster elevation or value """

    def __init__(self, iface, settings, action, index_action):
        """ Class constructor """

        # Call ParentMapTool constructor
        super(ExtractRasterValue, self).__init__(iface, settings, action, index_action)

        self.dragging = False

        # Vertex marker
        self.vertexMarker = QgsVertexMarker(self.canvas)
        self.vertexMarker.setColor(QColor(255, 25, 25))
        self.vertexMarker.setIconSize(11)
        self.vertexMarker.setIconType(QgsVertexMarker.ICON_BOX)  # or ICON_CROSS, ICON_X
        self.vertexMarker.setPenWidth(5)

        # Rubber band
        self.rubberBand = QgsRubberBand(self.canvas, True)
        mFillColor = QColor(100, 0, 0)
        self.rubberBand.setColor(mFillColor)
        self.rubberBand.setWidth(3)
        mBorderColor = QColor(254, 58, 29)
        self.rubberBand.setBorderColor(mBorderColor)

        # Select rectangle
        self.selectRect = QRect()

        # Init
        self.vectorLayer = None
        self.rasterLayer = None

    def reset(self):
        """ Clear selected features """

        layer = self.vectorLayer
        if layer is not None:
            layer.removeSelection()

        # Graphic elements
        self.rubberBand.reset()

    def set_config_action(self, action_99):
        """ Get the config form action"""
        self.configAction = action_99

    """ QgsMapTools inherited event functions """

    def canvasMoveEvent(self, event):
        """ With left click the digitizing is finished """

        if self.vectorLayer is None:
            return

        if event.buttons() == Qt.LeftButton:

            if not self.dragging:
                self.dragging = True
                self.selectRect.setTopLeft(event.pos())

            self.selectRect.setBottomRight(event.pos())
            self.set_rubber_band()

        else:

            # Hide highlight
            self.vertexMarker.hide()

            # Get the click
            x = event.pos().x()
            y = event.pos().y()
            eventPoint = QPoint(x, y)

            # Snapping
            (retval, result) = self.snapper.snapToBackgroundLayers(eventPoint)  # @UnusedVariable

            # That's the snapped point
            if result <> []:

                # Check Arc or Node
                for snapPoint in result:

                    if snapPoint.layer == self.vectorLayer:

                        # Get the point
                        point = QgsPoint(result[0].snappedVertex)

                        # Add marker
                        self.vertexMarker.setCenter(point)
                        self.vertexMarker.show()

                        break

    def canvasPressEvent(self, event):

        self.selectRect.setRect(0, 0, 0, 0)
        self.rubberBand.reset()

    def canvasReleaseEvent(self, event):
        """ With left click the digitizing is finished """

        if event.button() == Qt.LeftButton:

            # Get the click
            x = event.pos().x()
            y = event.pos().y()
            eventPoint = QPoint(x, y)

            # Node layer
            layer = self.vectorLayer

            # Not dragging, just simple selection
            if not self.dragging:

                # Snap to node
                (retval, result) = self.snapper.snapToBackgroundLayers(eventPoint)  # @UnusedVariable

                # That's the snapped point
                if result <> [] and (result[0].layer.name() == self.vectorLayer.name()):

                    point = QgsPoint(result[0].snappedVertex)  # @UnusedVariable
                    layer.removeSelection()
                    layer.select([result[0].snappedAtGeometry])

                    # Interpolate values
                    self.raster_interpolate()

                    # Hide highlight
                    self.vertexMarker.hide()

            else:

                # Set valid values for rectangle's width and height
                if self.selectRect.width() == 1:
                    self.selectRect.setLeft(self.selectRect.left() + 1)

                if self.selectRect.height() == 1:
                    self.selectRect.setBottom(self.selectRect.bottom() + 1)

                self.set_rubber_band()
                selectGeom = self.rubberBand.asGeometry()  # @UnusedVariable
                self.select_multiple_features(self.selectRectMapCoord)
                self.dragging = False

                # Interpolate values
                self.raster_interpolate()

        elif event.button() == Qt.RightButton:

            # Interpolate values
            self.raster_interpolate()

    def activate(self):

        # Check button
        self.action().setChecked(True)

        # Rubber band
        self.rubberBand.reset()

        # Store user snapping configuration
        self.snapperManager.storeSnappingOptions()

        # Clear snapping
        self.snapperManager.clearSnapping()

        # Get layers
        res = self.find_raster_layers()
        #        if res == 0:
        #            self.controller.show_warning("Raster configuration tool not properly configured.")
        #            return

        # Change cursor
        self.canvas.setCursor(self.cursor)

        # Show help message when action is activated
        if self.show_help:
            message = (
                "Right click to use current selection, select connec points by clicking or dragging (selection box)"
            )
            self.controller.show_info(message, context_name="ui_message")

        # Control current layer (due to QGIS bug in snapping system)
        try:
            if self.canvas.currentLayer().type() == QgsMapLayer.VectorLayer:
                self.canvas.setCurrentLayer(self.layer_arc)
        except:
            self.canvas.setCurrentLayer(self.layer_arc)

    def deactivate(self):

        # Check button
        self.action().setChecked(False)

        # Rubber band
        self.rubberBand.reset()

        # Restore previous snapping
        self.snapperManager.recoverSnappingOptions()

        # Recover cursor
        self.canvas.setCursor(self.stdCursor)

    def nearestNeighbor(self, thePoint):

        ident = self.dataProv.identify(thePoint, QgsRaster.IdentifyFormatValue)
        value = None
        if ident is not None:  # and ident.has_key(choosenBand+1):
            try:
                value = float(ident.results()[int(self.band)])
            except TypeError:
                value = None
        if value == self.noDataValue:
            return None
        return value

    def writeInterpolation(self, f, fieldIdx):

        thePoint = f.geometry().asPoint()
        value = self.nearestNeighbor(thePoint)
        self.vectorLayer.changeAttributeValue(f.id(), fieldIdx, value)

    def raster_interpolate(self):
        """ Interpolate features value from raster """

        # Interpolate values
        if self.vectorLayer is None and self.rasterLayer is None:
            return

        # Get data provider
        layer = self.vectorLayer
        self.dataProv = self.rasterLayer.dataProvider()
        if self.dataProv.srcNoDataValue(int(self.band)):
            self.noDataValue = self.dataProv.srcNoDataValue(int(self.band))
        else:
            self.noDataValue = None

        self.continueProcess = True

        self.fieldIdx = ""
        self.fieldIdx = layer.fieldNameIndex(self.fieldName)

        if self.band == 0:
            self.controller.show_warning("You must choose a band for the raster layer.")
            return
        if self.fieldName == "":
            self.controller.show_warning("You must choose a field to write values.")
            return
        if self.fieldIdx < 0:
            self.controller.show_warning("Selected field does not exist in feature layer.")
            return

        k = 0
        c = 0
        f = QgsFeature()

        # Check features selected
        if layer.selectedFeatureCount() == 0:
            message = "You have to select at least one feature!"
            self.controller.show_warning(message, context_name="ui_message")

            return

        # Check editable
        if not layer.isEditable():
            layer.startEditing()

        # Get selected id's
        ids = self.vectorLayer.selectedFeaturesIds()

        for fid in ids:

            k += 1
            layer.getFeatures(QgsFeatureRequest(fid)).nextFeature(f)
            c += 1
            self.writeInterpolation(f, self.fieldIdx)
            QCoreApplication.processEvents()

        self.controller.show_info(
            "%u values have been updated in layer %s.%s over %u points using %s raster"
            % (c, self.vectorLayer.name(), self.fieldName, k, self.table_raster)
        )

        # Check editable
        if layer.isEditable():
            layer.commitChanges()

        # Refresh map canvas
        self.rubberBand.reset()
        self.iface.mapCanvas().refresh()

    def set_rubber_band(self):

        # Coordinates transform
        transform = self.canvas.getCoordinateTransform()

        # Coordinates
        ll = transform.toMapCoordinates(self.selectRect.left(), self.selectRect.bottom())
        lr = transform.toMapCoordinates(self.selectRect.right(), self.selectRect.bottom())
        ul = transform.toMapCoordinates(self.selectRect.left(), self.selectRect.top())
        ur = transform.toMapCoordinates(self.selectRect.right(), self.selectRect.top())

        # Rubber band
        self.rubberBand.reset()
        self.rubberBand.addPoint(ll, False)
        self.rubberBand.addPoint(lr, False)
        self.rubberBand.addPoint(ur, False)
        self.rubberBand.addPoint(ul, False)
        self.rubberBand.addPoint(ll, True)

        self.selectRectMapCoord = QgsRectangle(ll, ur)

    def select_multiple_features(self, selectGeometry):

        # Default choice
        behaviour = QgsVectorLayer.SetSelection

        # Modifiers
        modifiers = QApplication.keyboardModifiers()

        if modifiers == Qt.ControlModifier:
            behaviour = QgsVectorLayer.AddToSelection
        elif modifiers == Qt.ShiftModifier:
            behaviour = QgsVectorLayer.RemoveFromSelection

        if self.vectorLayer is None:
            return

        # Change cursor
        QApplication.setOverrideCursor(Qt.WaitCursor)

        # Selection
        self.vectorLayer.selectByRect(selectGeometry, behaviour)

        # Old cursor
        QApplication.restoreOverrideCursor()

    def find_raster_layers(self):

        # Query database (form data)
        sql = "SELECT *"
        sql += " FROM " + self.schema_name + ".config_extract_raster_value"

        rows = self.controller.get_rows(sql)

        if not rows:
            self.controller.show_warning("Any data found in table config_extract_raster_value")
            self.configAction.activate(QAction.Trigger)
            return 0

        # Layers
        row = rows[0]
        self.table_raster = row[1]
        self.band = row[2]
        self.table_vector = row[3]
        self.fieldName = row[4]

        # Check if we have any layer loaded
        layers = self.iface.legendInterface().layers()
        if len(layers) == 0:
            return

        # Init layers
        self.rasterLayer = None
        self.vectorLayer = None

        # Iterate over all layers to get the ones specified in 'db' config section
        for cur_layer in layers:

            if cur_layer.name() == self.table_raster:
                self.rasterLayer = cur_layer

            (uri_schema, uri_table) = self.controller.get_layer_source(cur_layer)  # @UnusedVariable
            if uri_table is not None:
                if self.table_vector in uri_table:
                    self.vectorLayer = cur_layer

        # Check config
        if self.vectorLayer is None or self.rasterLayer is None:
            self.configAction.activate(QAction.Trigger)

        # Set snapping
        if self.vectorLayer <> None:
            self.snapperManager.snapToLayer(self.vectorLayer)
        else:
            self.controller.show_warning("Check vector_layer in config form, layer does not exist or is not defined.")
            return 0

        if self.rasterLayer == None:
            self.controller.show_warning("Check raster_layer in config form, layer does not exist or is not defined.")
            return 0

        return 1
class ObstacleAreaJigSelectArea(QgsMapTool):

    def __init__(self, canvas, areaType):
        self.mCanvas = canvas
        self.areaType = areaType
        QgsMapTool.__init__(self, canvas)
        self.mCursor = Qt.ArrowCursor
        self.mRubberBand = None
        self.mDragging = False
        self.mSelectRect = QRect()
        self.mRubberBandResult = None
        self.mSnapper = QgsMapCanvasSnapper(canvas)
        self.lineCount = 0
        self.resultGeomList = []
        self.geomList = []
        self.area = None
        self.isFinished = False
#     QgsRubberBand* mRubberBand;
#     def reset(self):
#         self.startPoint = None
#         self.endPoint = None
#         self.isDrawing = False
#         SelectByRect.RubberRect.reset(QGis.Polygon)
#         self.layer = self.canvas.currentLayer()

    def canvasPressEvent(self, e):
        QgisHelper.ClearRubberBandInCanvas(define._canvas)
        self.mSelectRect.setRect( 0, 0, 0, 0 )
        self.mRubberBand = QgsRubberBand( self.mCanvas, QGis.Polygon )
        self.startPoint, self.pointID, self.layer= self.snapPoint(e.pos())

    def canvasMoveEvent(self, e):
        if self.areaType == ProtectionAreaType.Secondary:
            if self.lineCount == 0:
                define._messageLabel.setText("Select a line or arc representing the INNER edge of the secondary area.")
            elif self.lineCount == 1:
                define._messageLabel.setText("Select a line representing the OUTER edge of the secondary area.")
        elif self.areaType == ProtectionAreaType.Primary:
            define._messageLabel.setText("")
        elif self.areaType == ProtectionAreaType.PrimaryAndSecondary:
            if self.lineCount == 0:
                define._messageLabel.setText("Select a line or arc representing the INNER edge of the FIRST secondary area.")
            elif self.lineCount == 1:
                define._messageLabel.setText("Select a line representing the OUTER edge of the FIRST secondary area.")
            elif self.lineCount == 2:
                define._messageLabel.setText("Select a line or arc representing the INNER edge of the SECOND secondary area.")
            elif self.lineCount == 3:
                define._messageLabel.setText("Select a line representing the OUTER edge of the SECOND secondary area.")
        else:
            define._messageLabel.setText("")


        if ( e.buttons() != Qt.LeftButton ):
            return
        if ( not self.mDragging ):
            self.mDragging = True
            self.mSelectRect.setTopLeft( e.pos() )
        self.mSelectRect.setBottomRight( e.pos() )
        QgsMapToolSelectUtils.setRubberBand( self.mCanvas, self.mSelectRect,self.mRubberBand )

    def canvasReleaseEvent(self, e):
        self.endPoint, self.pointID, self.layer= self.snapPoint(e.pos())

        vlayer = QgsMapToolSelectUtils.getCurrentVectorLayer( self.mCanvas )
        if ( vlayer == None ):
            if ( self.mRubberBand != None):
                self.mRubberBand.reset( QGis.Polygon )
                del self.mRubberBand
                self.mRubberBand = None
                self.mDragging = False
            return


        if (not self.mDragging ):
            QgsMapToolSelectUtils.expandSelectRectangle(self. mSelectRect, vlayer, e.pos() )
        else:
            if ( self.mSelectRect.width() == 1 ):
                self.mSelectRect.setLeft( self.mSelectRect.left() + 1 )
            if ( self.mSelectRect.height() == 1 ):
                self.mSelectRect.setBottom( self.mSelectRect.bottom() + 1 )

        if ( self.mRubberBand != None ):
            QgsMapToolSelectUtils.setRubberBand( self.mCanvas, self.mSelectRect, self.mRubberBand )
            selectGeom = self.mRubberBand.asGeometry()


            selectedFeatures = QgsMapToolSelectUtils.setSelectFeaturesOrRubberband_Tas_1( self.mCanvas, selectGeom, e )
            if len(selectedFeatures) > 0:
                self.lineCount += 1
                geom = selectedFeatures[0].geometry()
                resultArray = QgisHelper.findArcOrLineInLineGeometry(geom, selectGeom)
                # if resultArray != None:
                #     bulge = MathHelper.smethod_60(resultArray[0], resultArray[int(len(resultArray)/2)], resultArray[len(resultArray)-1])
                #     bulge1 = MathHelper.smethod_60(resultArray[len(resultArray)-1], resultArray[int(len(resultArray)/2)], resultArray[0])
                #     n = 0
                pointArray0 = geom.asPolyline()
                self.resultGeomList.append(resultArray)
                self.geomList.append(pointArray0)
                if self.lineCount == 2 and self.areaType != ProtectionAreaType.PrimaryAndSecondary and self.areaType != ProtectionAreaType.Complex:
                    self.area = self.makeArea(self.resultGeomList, self.areaType)
                    pointArray = self.getPointArray(self.resultGeomList).method_14_closed()
                    self.mRubberBandResult = None
                    self.mRubberBandResult = QgsRubberBand( self.mCanvas, QGis.Polygon )
                    self.mRubberBandResult.setFillColor(QColor(255, 255, 255, 100))
                    self.mRubberBandResult.setBorderColor(QColor(0, 0, 0))
                    for point in pointArray:
                        self.mRubberBandResult.addPoint(point)
                    self.mRubberBandResult.show()


                    self.emit(SIGNAL("outputResult"), self.area, self.mRubberBandResult)
                    self.lineCount = 0
                    self.resultGeomList = []
                    self.isFinished = True
                    # self.rubberBandLine.reset(QGis.Line)
                elif self.lineCount == 4 and self.areaType == ProtectionAreaType.PrimaryAndSecondary:
                    self.area = self.makeArea(self.resultGeomList, self.areaType)
                    pointArray = self.getPointArray([self.resultGeomList[1], self.resultGeomList[3]]).method_14_closed()
                    self.mRubberBandResult = None
                    self.mRubberBandResult = QgsRubberBand( self.mCanvas, QGis.Polygon )
                    self.mRubberBandResult.setFillColor(QColor(255, 255, 255, 100))
                    self.mRubberBandResult.setBorderColor(QColor(0, 0, 0))
                    for point in pointArray:
                        self.mRubberBandResult.addPoint(point)
                    self.mRubberBandResult.show()


                    self.emit(SIGNAL("outputResult"), self.area, self.mRubberBandResult)
                    self.lineCount = 0
                    self.resultGeomList = []
                # else:
                #     return
            del selectGeom

            self.mRubberBand.reset( QGis.Polygon )
            del self.mRubberBand
            self.mRubberBand = None
        self.mDragging = False
    def getPointArray(self, geomList):
        pointArrayInner = geomList[0]
        pointArray1Outer = geomList[1]

        innerStartPoint = pointArrayInner[0]
        innerEndPoint = pointArrayInner[1]
        innerBulge = pointArrayInner[2]
        outerStartPoint = pointArray1Outer[0]
        outerEndPoint = pointArray1Outer[1]
        outerBulge = pointArray1Outer[2]

        line0 = QgsGeometry.fromPolyline([innerStartPoint, outerStartPoint])
        line1 = QgsGeometry.fromPolyline([innerEndPoint, outerEndPoint])

        # for i in range(1, len(pointArray0)):

        if line0.intersects(line1):
            tempPoint = outerStartPoint
            outerStartPoint = outerEndPoint
            outerEndPoint = tempPoint
            outerBulge = -outerBulge

        polylineArea = PolylineArea()
        polylineArea.Add(PolylineAreaPoint(innerStartPoint, innerBulge))
        polylineArea.Add(PolylineAreaPoint(innerEndPoint))
        polylineArea.Add(PolylineAreaPoint(outerEndPoint, -outerBulge))
        polylineArea.Add(PolylineAreaPoint(outerStartPoint))
        return polylineArea
    def makeArea(self, geomList, areaType):
        if areaType == ProtectionAreaType.Primary or areaType == ProtectionAreaType.Secondary:
            return self.makePrimaryAreaOrSecondaryArea(geomList, areaType)
        elif areaType == ProtectionAreaType.PrimaryAndSecondary:
            pointArray0 = geomList[0]
            pointArray1 = geomList[1]
            pointArray2 = geomList[2]
            pointArray3 = geomList[3]
            primaryArea = self.makePrimaryAreaOrSecondaryArea([pointArray0, pointArray2], ProtectionAreaType.Primary)
            secondaryArea1 = self.makePrimaryAreaOrSecondaryArea([pointArray0, pointArray1], ProtectionAreaType.Secondary)
            secondaryArea2 = self.makePrimaryAreaOrSecondaryArea([pointArray2, pointArray3], ProtectionAreaType.Secondary)
            return PrimarySecondaryObstacleArea(primaryArea, secondaryArea1, secondaryArea2)
            # if len(geomList[0]) == 2 and len(geomList[1]) == 2 and len(geomList[2]) == 2 and len(geomList[3]) == 2:
            #     for i in range(1, len(geomList)):
            #         pointArray0 = geomList[0]
            #         pointArray1 = geomList[i]
            #         line0 = QgsGeometry.fromPolyline([pointArray0[0], pointArray1[0]])
            #         line1 = QgsGeometry.fromPolyline([pointArray0[len(pointArray0) - 1], pointArray1[len(pointArray1) - 1]])
            #         if line0.intersects(line1):
            #             pointArray1.reverse()
            #     pointArray0 = geomList[0]
            #     pointArray1 = geomList[1]
            #     pointArray2 = geomList[2]
            #     pointArray3 = geomList[3]
            #     area = PrimarySecondaryObstacleArea()
            #     area.set_areas(pointArray0, pointArray1, pointArray2, pointArray3)
            #     return area
            # return None

        return None
    def makePrimaryAreaOrSecondaryArea(self, geomList, areaType):
        pointArrayInner = geomList[0]
        pointArray1Outer = geomList[1]

        innerStartPoint = pointArrayInner[0]
        innerEndPoint = pointArrayInner[1]
        innerBulge = pointArrayInner[2]
        outerStartPoint = pointArray1Outer[0]
        outerEndPoint = pointArray1Outer[1]
        outerBulge = pointArray1Outer[2]

        line0 = QgsGeometry.fromPolyline([innerStartPoint, outerStartPoint])
        line1 = QgsGeometry.fromPolyline([innerEndPoint, outerEndPoint])

        # for i in range(1, len(pointArray0)):

        if line0.intersects(line1):
            tempPoint = Point3D(outerStartPoint.get_X(), outerStartPoint.get_Y())
            outerStartPoint = Point3D(outerEndPoint.get_X(), outerEndPoint.get_Y())
            outerEndPoint = Point3D(tempPoint.get_X(), tempPoint.get_Y())
            outerBulge = -outerBulge
        if areaType == ProtectionAreaType.Primary:
            polylineArea = PolylineArea()
            polylineArea.Add(PolylineAreaPoint(innerStartPoint, innerBulge))
            polylineArea.Add(PolylineAreaPoint(innerEndPoint))
            polylineArea.Add(PolylineAreaPoint(outerEndPoint, -outerBulge))
            polylineArea.Add(PolylineAreaPoint(outerStartPoint))
            return PrimaryObstacleArea(polylineArea)
        elif areaType == ProtectionAreaType.Secondary:
            if innerBulge == 0 and outerBulge == 0:
                return SecondaryObstacleArea(innerStartPoint, innerEndPoint, outerStartPoint, outerEndPoint, MathHelper.getBearing(innerStartPoint, innerEndPoint))
            elif innerBulge != 0 and outerBulge != 0:
                if round(innerBulge, 1) != round(outerBulge, 1):
                    return None
                innerCenterPoint = MathHelper.smethod_71(innerStartPoint, innerEndPoint, innerBulge)
                outerCenterPoint = MathHelper.smethod_71(outerStartPoint, outerEndPoint, outerBulge)

                innerRadius = MathHelper.calcDistance(innerCenterPoint, innerStartPoint);
                outerRadius = MathHelper.calcDistance(outerCenterPoint, outerStartPoint);

                bearing = (MathHelper.getBearing(innerCenterPoint, innerStartPoint) + MathHelper.getBearing(innerCenterPoint, innerEndPoint)) / 2
                innerMiddlePoint = MathHelper.distanceBearingPoint(innerCenterPoint, bearing, innerRadius)
                if round(MathHelper.smethod_60(innerStartPoint, innerMiddlePoint, innerEndPoint), 4) != round(outerBulge, 4):
                    bearing += 3.14159265358979
                    innerMiddlePoint = MathHelper.distanceBearingPoint(innerCenterPoint, bearing, innerRadius)

                bearing = (MathHelper.getBearing(outerCenterPoint, outerStartPoint) + MathHelper.getBearing(outerCenterPoint, outerEndPoint)) / 2
                outerMiddlePoint = MathHelper.distanceBearingPoint(outerCenterPoint, bearing, outerRadius)
                if round(MathHelper.smethod_60(outerStartPoint, outerMiddlePoint, outerEndPoint), 4) != round(outerBulge, 4):
                    bearing += 3.14159265358979
                    outerMiddlePoint = MathHelper.distanceBearingPoint(outerCenterPoint, bearing, outerRadius)
                return SecondaryObstacleArea(innerStartPoint, innerMiddlePoint, innerEndPoint, outerStartPoint, None, outerMiddlePoint, outerEndPoint, innerBulge, innerBulge)
            return None
    def snapPoint(self, p, bNone = False):
        if define._snapping == False:
            return (define._canvas.getCoordinateTransform().toMapCoordinates( p ), None, None)
        snappingResults = self.mSnapper.snapToBackgroundLayers( p )
        if ( snappingResults[0] != 0 or len(snappingResults[1]) < 1 ):

            if bNone:
                return (None, None, None)
            else:
                return (define._canvas.getCoordinateTransform().toMapCoordinates( p ), None, None)
        else:
            return (snappingResults[1][0].snappedVertex, snappingResults[1][0].snappedAtGeometry, snappingResults[1][0].layer)
예제 #16
0
class ImageAreaSelector(QtGui.QWidget):
    '''This widget provides means to visually crop a portion of
    an image by selecting it'''
    # pylint: disable=W0612
    NAME = 'ImageAreaSelector'
    DESCRIPTION = 'A widget used to select part of an image'
    AUTHOR = 'Gabriele "Whisky" Visconti'
    WEBSITE = ''
    # pylint: enable=W0612

    selection_changed = QtCore.pyqtSignal()

    def __init__(self, pixmap, parent=None):
        '''Constructor'''
        QtGui.QWidget.__init__(self, parent)
        self._pixmap = pixmap

        self._selection_rect = QRect()
        self._image_origin = QPoint()
        self._resize_start = None
        self._drag_start = None
        self._handle_size = QSize(-10, -10)
        self._painter = QtGui.QPainter()
        self._hl_color1 = QtGui.QPalette().color(QtGui.QPalette.Highlight)
        self._hl_color2 = QtGui.QPalette().color(QtGui.QPalette.Highlight)
        self._hl_color2.setAlpha(150)
        self._zoom = 1.0

        self.adjust_minum_size()
        self.setBackgroundRole(QtGui.QPalette.Dark)
        self.setMouseTracking(True)
        self.setCursor(Qt.CrossCursor)

# -------------------- [BEGIN] QT_OVERRIDE

    def mousePressEvent(self, event):
        '''Overrides QWidget's mousePressEvent. Handles starting
        a new selection, starting a drag operation'''
        # pylint: disable=C0103
        mouse_pos = event.pos() / self._zoom
        sel_rect = self._selection_rect

        if not event.button() == Qt.LeftButton:
            return

        if (not sel_rect.isNull()) and sel_rect.contains(mouse_pos, True):
            handle_rect = QRect(sel_rect.bottomRight(), self._handle_size)
            if handle_rect.contains(mouse_pos):
                self._resize_start = mouse_pos
            else:
                self._drag_start = mouse_pos
        else:
            self._resize_start = mouse_pos
            sel_rect.setTopLeft(mouse_pos)
            self._selection_rect.setSize(QSize(0, 0))

    def mouseMoveEvent(self, event):
        '''Overrides QWidget's mouseMoveEvent. Handles resizing
        and dragging operations on selection'''
        # pylint: disable=C0103
        sel_rect = self._selection_rect
        if self._resize_start:
            resize_end = event.pos() / self._zoom
            sel_rect.setBottomRight(sel_rect.bottomRight() +
                                    (resize_end - self._resize_start))
            self._resize_start = resize_end
            self.make_selection_square()
            self.update()
        elif self._drag_start is not None:
            drag_end = event.pos() / self._zoom
            sel_rect.translate(drag_end - self._drag_start)
            self._drag_start = drag_end
            self.update()

        # cursor shape:
        mouse_pos = event.pos() / self._zoom
        if (not sel_rect.isNull()) and sel_rect.contains(mouse_pos, True):
            handle_rect = QRect(sel_rect.bottomRight(), self._handle_size)
            if handle_rect.contains(mouse_pos):
                self.setCursor(Qt.SizeFDiagCursor)
            else:
                self.setCursor(Qt.OpenHandCursor)

        else:
            self.setCursor(Qt.CrossCursor)

    def mouseReleaseEvent(self, event):
        '''Overrides QWidget's mouseReleaseEvent. Handles ending a resizing or
        draggin operation on the selection'''
        # pylint: disable=C0103
        self._selection_rect = self._selection_rect.normalized()
        self._resize_start = None
        self._drag_start = None
        self.update()
        if not self._selection_rect.isNull():
            self.selection_changed.emit()

    def paintEvent(self, event):
        '''Overrides QWidtget's paintEvent.'''
        # pylint: disable=C0103
        QtGui.QWidget.paintEvent(self, event)
        self._painter.begin(self)
        pixmap_dest_rect = QRect(self._image_origin * self._zoom,
                                 self._pixmap.size() * self._zoom)
        self._painter.drawPixmap(pixmap_dest_rect, self._pixmap)
        if not self._selection_rect.isNull():
            # preparing the darkened frame:
            sel_rect = self._selection_rect.normalized()
            frame = QtGui.QPixmap(event.rect().size())
            frame.fill(QtGui.QColor(0, 0, 0, 127))
            frame_painter = QtGui.QPainter(frame)
            # erase the selected area from the frame:
            frame_painter.setCompositionMode(
                QtGui.QPainter.CompositionMode_DestinationIn)
            sel_rect_scaled = QRect(sel_rect.topLeft() * self._zoom,
                                    sel_rect.size() * self._zoom)
            frame_painter.fillRect(sel_rect_scaled, QtGui.QColor(0, 0, 0, 0))
            # draw selection border :
            frame_painter.setCompositionMode(
                QtGui.QPainter.CompositionMode_SourceOver)
            frame_painter.setPen(self._hl_color1)
            frame_painter.drawRect(sel_rect_scaled)
            # draw the resize grip (if possible)
            if sel_rect_scaled.width() > 20 and sel_rect_scaled.height() > 20:
                handle_rect = QRect(sel_rect_scaled.bottomRight(),
                                    self._handle_size)
                frame_painter.fillRect(handle_rect, self._hl_color2)
                frame_painter.drawRect(handle_rect)
            frame_painter.end()
            # painting the darkened frame:
            self._painter.drawPixmap(0, 0, frame)

        self._painter.end()

    def resizeEvent(self, event):
        '''Overrides QWidget's resizeEvent. Handles image centering.'''
        # pylint: disable=C0103
        self.adjust_image_origin()

# -------------------- [END] QT_OVERRIDE

    def adjust_image_origin(self):
        '''Recalculates the top left corner's image position, so the
        image is painted centered'''
        # pylint: disable=C0103
        new_size = self.size() / self._zoom
        pix_size = self._pixmap.size()

        dx = (new_size.width() - pix_size.width()) / 2
        dy = (new_size.height() - pix_size.height()) / 2

        new_image_origin = QPoint(dx, dy)
        self._selection_rect.translate(new_image_origin - self._image_origin)
        self._image_origin = new_image_origin
        log.info('image origin: %s' % new_image_origin)

    def select_unscaled(self):
        '''Selects, if possible, a 96 x 96 square centered around the original
        image. In this way the image won't be scaled but won't take up all the 
        96 x 96 area.'''
        # pylint: disable=C0103
        pix_size = self._pixmap.size()
        if pix_size.width() <= 96 and pix_size.height() <= 96:
            viewport_size = self.size()
            x = (viewport_size.width() - 96) / 2
            y = (viewport_size.height() - 96) / 2
            self._selection_rect.setTopLeft(QPoint(x, y))
            self._selection_rect.setSize(QSize(96, 96))
            self.update()
            self.selection_changed.emit()

    def select_all(self):
        '''Selects the whole image. Currently broken for images taller
        than wide.'''
        # TODO: make me work!
        self._selection_rect.setTopLeft(self._image_origin)
        self._selection_rect.setSize(self._pixmap.size())
        self.update()
        self.selection_changed.emit()

    def rotate_left(self):
        '''Rotates the image counterclockwise.'''
        self._pixmap = self._pixmap.transformed(QtGui.QTransform().rotate(-90))
        self.adjust_minum_size()
        self.adjust_image_origin()
        self.update()
        self.selection_changed.emit()

    def rotate_right(self):
        '''Rotates the image clockwise'''
        self._pixmap = self._pixmap.transformed(QtGui.QTransform().rotate(90))
        self.adjust_minum_size()
        self.adjust_image_origin()
        self.update()
        self.selection_changed.emit()

    def adjust_minum_size(self):
        '''Sets the new minimum size, calculated upon the image size
        and the _zoom factor.'''
        pixmap = self._pixmap
        if pixmap.width() < 96 or pixmap.height() < 96:
            min_size = QSize(96, 96)
        else:
            min_size = pixmap.size()

        self.setMinimumSize(min_size * self._zoom)

    def make_selection_square(self):
        '''Modify the selected area making it square'''
        wid = self._selection_rect.width()
        self._selection_rect.setSize(QSize(wid, wid))

    def set_zoom(self, zoomlevel):
        '''Sets the specified zoomlevel'''
        self._zoom = zoomlevel
        self.adjust_minum_size()
        self.adjust_image_origin()
        self.update()
        self.selection_changed.emit()

    def fit_zoom(self):
        '''Chooses a zoomlevel that makes visible the entire image.
        Currently broken.'''
        widget_wid = self.size().width()
        widget_hei = self.size().height()

        pixmap_wid = self._pixmap.width()
        pixmap_hei = self._pixmap.height()

        self._zoom = (min(widget_wid, widget_hei) /
                      min(pixmap_wid, pixmap_hei))

        self.adjust_minum_size()
        self.adjust_image_origin()
        self.update()
        self.selection_changed.emit()

    def get_selected_pixmap(self):
        '''Returns the pixmap contained in the selection rect.
        Currently doesn't handle transparency correctly'''
        sel_rect_scaled = QRect(self._selection_rect.topLeft() * self._zoom,
                                self._selection_rect.size() * self._zoom)
        return QtGui.QPixmap.grabWidget(self, sel_rect_scaled)
예제 #17
0
파일: infotool.py 프로젝트: vpicavet/Roam
class InfoTool(QgsMapTool):
    infoResults = pyqtSignal(dict)

    def __init__(self, canvas, snapradius = 2):
        super(InfoTool, self).__init__(canvas)
        self.canvas = canvas
        self.radius = snapradius

        self.band = QgsRubberBand(self.canvas)
        self.band.setColor(QColor.fromRgb(224,162,16))
        self.band.setWidth(3)

        self.selectband = None
        self.selectrect = QRect()
        self.dragging = False
        self.selectionlayers = []

    def getFeatures(self, rect):
        self.band.reset()
        for layer in self.selectionlayers:
            if (not layer.type() == QgsMapLayer.VectorLayer
                or layer.geometryType() == QGis.NoGeometry):
                continue

            rect = self.toLayerCoordinates(layer, rect)

            rq = QgsFeatureRequest().setFilterRect(rect).setFlags(QgsFeatureRequest.ExactIntersect)
            features = []
            for feature in layer.getFeatures(rq):
                if feature.isValid():
                    features.append(feature)

            yield layer, features

    def toSearchRect(self, point):
        searchRadius =  self.canvas.extent().width() * ( self.radius / 100.0 )

        point = self.toMapCoordinates(point)

        rect = QgsRectangle()
        rect.setXMinimum(point.x() - searchRadius)
        rect.setXMaximum(point.x() + searchRadius)
        rect.setYMinimum(point.y() - searchRadius)
        rect.setYMaximum(point.y() + searchRadius)
        return rect

    def canvasPressEvent(self, event):
        self.dragging = False
        self.selectrect.setRect( 0, 0, 0, 0 )

        self.selectband = QgsRubberBand(self.canvas, QGis.Polygon )
        self.selectband.setColor(QColor.fromRgb(0,0,255, 65))
        self.selectband.setWidth(5)

    def canvasMoveEvent(self, event):
        if not event.buttons() == Qt.LeftButton:
            return

        if not self.dragging:
            self.selectrect.setTopLeft(event.pos())
            self.dragging = True
        self.selectrect.setBottomRight(event.pos())

        maptoolutils.setRubberBand(self.canvas, self.selectrect, self.selectband)

    def canvasReleaseEvent(self, event):
        if self.dragging:
            geometry = self.selectband.asGeometry()
            if not geometry:
                return

            rect = geometry.boundingBox()
        else:
            rect = self.toSearchRect(event.pos())

        self.dragging = False
        self.selectband.reset()

        results = OrderedDict((l,f) for l, f in self.getFeatures(rect))
        print results
        self.infoResults.emit(results)
예제 #18
0
파일: edittool.py 프로젝트: nsashi/Roam
class EditTool(MapTool):
    """
        Inspection tool which copies the feature to a new layer
        and copies selected data from the underlying feature.
    """

    finished = pyqtSignal(object, QgsFeature)
    featuresfound = pyqtSignal(dict)

    def __init__(self, canvas, forms, snapradius=2):
        MapTool.__init__(self, canvas, [])
        self.canvas = canvas
        self.radius = snapradius
        self.forms = forms

        self.band = QgsRubberBand(self.canvas)
        self.band.setColor(QColor.fromRgb(224, 162, 16))
        self.band.setWidth(3)

        self.selectband = None

        self.selectrect = QRect()
        self.dragging = False

        self.cursor = QCursor(
            QPixmap([
                "16 16 3 1", "      c None", ".     c #FF0000",
                "+     c #FFFFFF", "                ", "       +.+      ",
                "      ++.++     ", "     +.....+    ", "    +.     .+   ",
                "   +.   .   .+  ", "  +.    .    .+ ", " ++.    .    .++",
                " ... ...+... ...", " ++.    .    .++", "  +.    .    .+ ",
                "   +.   .   .+  ", "   ++.     .+   ", "    ++.....+    ",
                "      ++.++     ", "       +.+      "
            ]))

    def addForm(self, form):
        self.forms.append(form)
        self.layersupdated.emit(True)

    def layers(self):
        """
        Return a set of layers that this edit tool can work on
        """
        return set([form.QGISLayer for form in self.forms])

    def formsforlayer(self, layer):
        for form in self.forms:
            if form.QGISLayer == layer:
                yield form

    def reset(self):
        self.forms = []
        self.layersupdated.emit(False)

    def getFeatures(self, rect):
        rq = QgsFeatureRequest().setFilterRect(rect)

        self.band.reset()
        for layer in self.layers():
            forms = list(self.formsforlayer(layer))
            rq = QgsFeatureRequest().setFilterRect(rect)
            for feature in layer.getFeatures(rq):
                if feature.isValid():
                    yield feature, forms

    def toSearchRect(self, point):
        searchRadius = self.canvas.extent().width() * (self.radius / 100.0)

        point = self.toMapCoordinates(point)

        rect = QgsRectangle()
        rect.setXMinimum(point.x() - searchRadius)
        rect.setXMaximum(point.x() + searchRadius)
        rect.setYMinimum(point.y() - searchRadius)
        rect.setYMaximum(point.y() + searchRadius)
        return rect

    def canvasPressEvent(self, event):
        self.selectrect.setRect(0, 0, 0, 0)

        self.selectband = QgsRubberBand(self.canvas, QGis.Polygon)
        self.selectband.setColor(QColor.fromRgb(0, 0, 255, 65))
        self.selectband.setWidth(5)

    def canvasMoveEvent(self, event):
        if not event.buttons() == Qt.LeftButton:
            return

        if not self.dragging:
            self.dragging = True
            self.selectrect.setTopLeft(event.pos())
        self.selectrect.setBottomRight(event.pos())

        maptoolutils.setRubberBand(self.canvas, self.selectrect,
                                   self.selectband)

    def canvasReleaseEvent(self, event):
        if self.dragging:
            geometry = self.selectband.asGeometry()
            if not geometry:
                return

            rect = geometry.boundingBox()
        else:
            rect = self.toSearchRect(event.pos())

        self.dragging = False
        self.selectband.reset()

        features = dict(self.getFeatures(rect))

        if len(features) == 1:
            feature = features.keys()[0]
            forms = features.values()[0]
            if len(forms) == 1:
                self.finished.emit(forms[0], feature)
            else:
                self.featuresfound.emit(features)
        elif len(features) > 0:
            self.featuresfound.emit(features)

    def isEditTool(self):
        return True
예제 #19
0
파일: edittool.py 프로젝트: vpicavet/Roam
class EditTool(MapTool):
    """
        Inspection tool which copies the feature to a new layer
        and copies selected data from the underlying feature.
    """
    
    finished = pyqtSignal(object, QgsFeature)
    featuresfound = pyqtSignal(dict)

    def __init__(self, canvas, forms, snapradius = 2):
        MapTool.__init__(self, canvas, [])
        self.canvas = canvas
        self.radius = snapradius
        self.forms = forms
        
        self.band = QgsRubberBand(self.canvas)
        self.band.setColor(QColor.fromRgb(224,162,16))
        self.band.setWidth(3)
        
        self.selectband = None
        
        self.selectrect = QRect()
        self.dragging = False

        self.cursor = QCursor(QPixmap(["16 16 3 1",
            "      c None",
            ".     c #FF0000",
            "+     c #FFFFFF",
            "                ",
            "       +.+      ",
            "      ++.++     ",
            "     +.....+    ",
            "    +.     .+   ",
            "   +.   .   .+  ",
            "  +.    .    .+ ",
            " ++.    .    .++",
            " ... ...+... ...",
            " ++.    .    .++",
            "  +.    .    .+ ",
            "   +.   .   .+  ",
            "   ++.     .+   ",
            "    ++.....+    ",
            "      ++.++     ",
            "       +.+      "]))

    def addForm(self, form):
        self.forms.append(form)
        self.layersupdated.emit(True)

    def layers(self):
        """
        Return a set of layers that this edit tool can work on
        """
        return set([form.QGISLayer for form in self.forms])

    def formsforlayer(self, layer):
        for form in self.forms:
            if form.QGISLayer == layer:
                yield form

    def reset(self):
        self.forms = []
        self.layersupdated.emit(False)

    def getFeatures(self, rect):
        rq = QgsFeatureRequest().setFilterRect(rect)

        self.band.reset()
        for layer in self.layers():
            forms = list(self.formsforlayer(layer))
            rq = QgsFeatureRequest().setFilterRect(rect)
            for feature in layer.getFeatures(rq):
                if feature.isValid():
                    yield feature, forms
                    
    def toSearchRect(self, point):
        searchRadius =  self.canvas.extent().width() * ( self.radius / 100.0 )

        point = self.toMapCoordinates(point)

        rect = QgsRectangle()                                                 
        rect.setXMinimum(point.x() - searchRadius)
        rect.setXMaximum(point.x() + searchRadius)
        rect.setYMinimum(point.y() - searchRadius)
        rect.setYMaximum(point.y() + searchRadius)
        return rect

    def canvasPressEvent(self, event):
        self.selectrect.setRect( 0, 0, 0, 0 )
        
        self.selectband = QgsRubberBand(self.canvas, QGis.Polygon )
        self.selectband.setColor(QColor.fromRgb(0,0,255, 65))
        self.selectband.setWidth(5)
        
    def canvasMoveEvent(self, event):
        if not event.buttons() == Qt.LeftButton:
            return
        
        if not self.dragging:
            self.dragging = True
            self.selectrect.setTopLeft(event.pos())
        self.selectrect.setBottomRight(event.pos())
        
        maptoolutils.setRubberBand(self.canvas, self.selectrect, self.selectband)  
                     
    def canvasReleaseEvent(self, event):
        if self.dragging:
            geometry = self.selectband.asGeometry()
            if not geometry:
                return

            rect = geometry.boundingBox()            
        else:
            rect = self.toSearchRect(event.pos())
            
        self.dragging = False
        self.selectband.reset()
            
        features = dict(self.getFeatures(rect))
        print features
            
        if len(features) == 1:
            feature = features.keys()[0]
            forms = features.values()[0]
            if len(forms) == 1:
                self.finished.emit(forms[0], feature)
            else:
                self.featuresfound.emit(features)
        elif len(features) > 0:
            self.featuresfound.emit(features)

    def isEditTool(self):
        return True
예제 #20
0
class ConnecMapTool(ParentMapTool):
    """ Button 20. User select connections from layer 'connec'
    Execute SQL function: 'gw_fct_connect_to_network' """

    def __init__(self, iface, settings, action, index_action):
        """ Class constructor """

        # Call ParentMapTool constructor
        super(ConnecMapTool, self).__init__(iface, settings, action, index_action)

        self.dragging = False

        # Vertex marker
        self.vertexMarker = QgsVertexMarker(self.canvas)
        self.vertexMarker.setColor(QColor(255, 25, 25))
        self.vertexMarker.setIconSize(11)
        self.vertexMarker.setIconType(QgsVertexMarker.ICON_BOX)  # or ICON_CROSS, ICON_X
        self.vertexMarker.setPenWidth(5)

        # Rubber band
        self.rubberBand = QgsRubberBand(self.canvas, True)
        mFillColor = QColor(100, 0, 0)
        self.rubberBand.setColor(mFillColor)
        self.rubberBand.setWidth(3)
        mBorderColor = QColor(254, 58, 29)
        self.rubberBand.setBorderColor(mBorderColor)

        # Select rectangle
        self.selectRect = QRect()

    def reset(self):
        """ Clear selected features """

        layer = self.layer_connec
        if layer is not None:
            layer.removeSelection()

        # Graphic elements
        self.rubberBand.reset()

    """ QgsMapTools inherited event functions """

    def canvasMoveEvent(self, event):
        """ With left click the digitizing is finished """

        if event.buttons() == Qt.LeftButton:

            if not self.dragging:
                self.dragging = True
                self.selectRect.setTopLeft(event.pos())

            self.selectRect.setBottomRight(event.pos())
            self.set_rubber_band()

        else:

            # Hide highlight
            self.vertexMarker.hide()

            # Get the click
            x = event.pos().x()
            y = event.pos().y()
            eventPoint = QPoint(x, y)

            # Snapping
            (retval, result) = self.snapper.snapToBackgroundLayers(eventPoint)  # @UnusedVariable

            # That's the snapped point
            if result <> []:

                # Check Arc or Node
                for snapPoint in result:

                    if snapPoint.layer == self.layer_connec:

                        # Get the point
                        point = QgsPoint(result[0].snappedVertex)

                        # Add marker
                        self.vertexMarker.setCenter(point)
                        self.vertexMarker.show()

                        break

    def canvasPressEvent(self, event):

        self.selectRect.setRect(0, 0, 0, 0)
        self.rubberBand.reset()

    def canvasReleaseEvent(self, event):
        """ With left click the digitizing is finished """

        if event.button() == Qt.LeftButton:

            # Get the click
            x = event.pos().x()
            y = event.pos().y()
            eventPoint = QPoint(x, y)

            # Node layer
            layer = self.layer_connec

            # Not dragging, just simple selection
            if not self.dragging:

                # Snap to node
                (retval, result) = self.snapper.snapToBackgroundLayers(eventPoint)  # @UnusedVariable

                # That's the snapped point
                if result <> [] and (result[0].layer.name() == self.layer_connec.name()):

                    point = QgsPoint(result[0].snappedVertex)  # @UnusedVariable
                    layer.removeSelection()
                    layer.select([result[0].snappedAtGeometry])

                    # Create link
                    self.link_connec()

                    # Hide highlight
                    self.vertexMarker.hide()

            else:

                # Set valid values for rectangle's width and height
                if self.selectRect.width() == 1:
                    self.selectRect.setLeft(self.selectRect.left() + 1)

                if self.selectRect.height() == 1:
                    self.selectRect.setBottom(self.selectRect.bottom() + 1)

                self.set_rubber_band()
                selectGeom = self.rubberBand.asGeometry()  # @UnusedVariable
                self.select_multiple_features(self.selectRectMapCoord)
                self.dragging = False

                # Create link
                self.link_connec()

        elif event.button() == Qt.RightButton:

            # Create link
            self.link_connec()

    def activate(self):

        # Check button
        self.action().setChecked(True)

        # Rubber band
        self.rubberBand.reset()

        # Store user snapping configuration
        self.snapperManager.storeSnappingOptions()

        # Clear snapping
        self.snapperManager.clearSnapping()

        # Set snapping to arc and node
        self.snapperManager.snapToConnec()

        # Change cursor
        self.canvas.setCursor(self.cursor)

        # Show help message when action is activated
        if self.show_help:
            message = (
                "Right click to use current selection, select connec points by clicking or dragging (selection box)"
            )
            self.controller.show_info(message, context_name="ui_message")

        # Control current layer (due to QGIS bug in snapping system)
        try:
            if self.canvas.currentLayer().type() == QgsMapLayer.VectorLayer:
                self.canvas.setCurrentLayer(self.layer_connec)
        except:
            self.canvas.setCurrentLayer(self.layer_connec)

    def deactivate(self):

        # Check button
        self.action().setChecked(False)

        # Rubber band
        self.rubberBand.reset()

        # Restore previous snapping
        self.snapperManager.recoverSnappingOptions()

        # Recover cursor
        self.canvas.setCursor(self.stdCursor)

    def link_connec(self):
        """ Link selected connec to the pipe """

        # Get selected features (from layer 'connec')
        aux = "{"
        layer = self.layer_connec
        if layer.selectedFeatureCount() == 0:
            message = "You have to select at least one feature!"
            self.controller.show_warning(message, context_name="ui_message")

            return
        features = layer.selectedFeatures()
        for feature in features:
            connec_id = feature.attribute("connec_id")
            aux += str(connec_id) + ", "
        connec_array = aux[:-2] + "}"

        # Execute function
        function_name = "gw_fct_connect_to_network"
        sql = "SELECT " + self.schema_name + "." + function_name + "('" + connec_array + "');"
        self.controller.execute_sql(sql)

        # Refresh map canvas
        self.rubberBand.reset()
        self.iface.mapCanvas().refresh()

    def set_rubber_band(self):

        # Coordinates transform
        transform = self.canvas.getCoordinateTransform()

        # Coordinates
        ll = transform.toMapCoordinates(self.selectRect.left(), self.selectRect.bottom())
        lr = transform.toMapCoordinates(self.selectRect.right(), self.selectRect.bottom())
        ul = transform.toMapCoordinates(self.selectRect.left(), self.selectRect.top())
        ur = transform.toMapCoordinates(self.selectRect.right(), self.selectRect.top())

        # Rubber band
        self.rubberBand.reset()
        self.rubberBand.addPoint(ll, False)
        self.rubberBand.addPoint(lr, False)
        self.rubberBand.addPoint(ur, False)
        self.rubberBand.addPoint(ul, False)
        self.rubberBand.addPoint(ll, True)

        self.selectRectMapCoord = QgsRectangle(ll, ur)

    def select_multiple_features(self, selectGeometry):

        # Default choice
        behaviour = QgsVectorLayer.SetSelection

        # Modifiers
        modifiers = QApplication.keyboardModifiers()

        if modifiers == Qt.ControlModifier:
            behaviour = QgsVectorLayer.AddToSelection
        elif modifiers == Qt.ShiftModifier:
            behaviour = QgsVectorLayer.RemoveFromSelection

        if self.layer_connec is None:
            return

        # Change cursor
        QApplication.setOverrideCursor(Qt.WaitCursor)

        # Selection
        self.layer_connec.selectByRect(selectGeometry, behaviour)

        # Old cursor
        QApplication.restoreOverrideCursor()