def draw_color_bar(self, painter, rect): h1, s1, v1, _ = self.light.getHsv() h2, s2, v2, _ = self.dark.getHsv() painter.save() painter.setClipRect(rect) painter.setClipping(True) #painter.fillRect(rect, QBrush(self.dark)) if self.orientation == Qt.Horizontal: num_intervalls = rect.width() else: num_intervalls = rect.height() section = QRect() num_intervalls_shown = num_intervalls * self.height / 100 l = range(num_intervalls - num_intervalls_shown, num_intervalls) l.reverse() for i in l: if self.orientation == Qt.Horizontal: section.setRect(rect.x() + i, rect.y(), 1, rect.heigh()) else: section.setRect(rect.x(), rect.y() + i, rect.width(), 1) ratio = float(i) / float(num_intervalls) color = QColor() color.setHsv(h1 + int(ratio * (h2 - h1) + 0.5), s1 + int(ratio * (s2 - s1) + 0.5), v1 + int(ratio * (v2 - v1) + 0.5)) painter.fillRect(section, color) painter.restore()
def draw_color_bar(self, painter, rect): h1, s1, v1, _ = self.light.getHsv() h2, s2, v2, _ = self.dark.getHsv() painter.save() painter.setClipRect(rect) painter.setClipping(True) # painter.fillRect(rect, QBrush(self.dark)) if self.orientation == Qt.Horizontal: num_intervalls = rect.width() else: num_intervalls = rect.height() section = QRect() num_intervalls_shown = num_intervalls * self.height / 100 l = range(num_intervalls - num_intervalls_shown, num_intervalls) l.reverse() for i in l: if self.orientation == Qt.Horizontal: section.setRect(rect.x() + i, rect.y(), 1, rect.heigh()) else: section.setRect(rect.x(), rect.y() + i, rect.width(), 1) ratio = float(i) / float(num_intervalls) color = QColor() color.setHsv( h1 + int(ratio * (h2 - h1) + 0.5), s1 + int(ratio * (s2 - s1) + 0.5), v1 + int(ratio * (v2 - v1) + 0.5) ) painter.fillRect(section, color) painter.restore()
def on_sectionResized(self, logicalIndex: int): if self.isSectionHidden(logicalIndex): return leafIndex = QModelIndex(self._pd.leafIndex(logicalIndex)) if leafIndex.isValid(): leafsList = QModelIndexList( self._pd.leafs(self._pd.findRootIndex(leafIndex))) for n in range(leafsList.indexOf(leafIndex), 0, -1): logicalIndex -= 1 w = self.viewport().width() h = self.viewport().height() pos = self.sectionViewportPosition(logicalIndex) r = QRect(pos, 0, w - pos, h) if self.orientation() == Qt.Horizontal: if self.isRightToLeft(): r.setRect(0, 0, pos + self.sectionSize(logicalIndex), h) else: r.setRect(0, pos, w, h - pos) self.viewport().update(r.normalized())
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)
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)
def on_sectionResized(self, logicalIndex: int): if self.isSectionHidden(logicalIndex): return leafIndex = QModelIndex(self._pd.leafIndex(logicalIndex)) if leafIndex.isValid(): leafsList = QModelIndexList(self._pd.leafs(self._pd.findRootIndex(leafIndex))) for n in range(leafsList.indexOf(leafIndex), 0, -1): logicalIndex-=1 w = self.viewport().width() h = self.viewport().height() pos = self.sectionViewportPosition(logicalIndex) r = QRect(pos, 0, w - pos, h) if self.orientation() == Qt.Horizontal: if self.isRightToLeft(): r.setRect(0, 0, pos + self.sectionSize(logicalIndex), h) else: r.setRect(0, pos, w, h - pos) self.viewport().update(r.normalized()) def setModel(self, model): super().setModel(model) model.layoutChanged.connect(self.layoutChanged) self.layoutChanged() def layoutChanged(self): if self.model(): self._pd.initFromNewModel(self.orientation(), self.model()) axis = ("column", "row")[self.orientation()!=Qt.Horizontal] cnt = getattr(self.model(), axis+"Count")(QModelIndex()) if cnt: self.initializeSections(0, cnt-1) MultiIndexHeaderView=HierarchicalHeaderView class DataFrameModel(QtCore.QAbstractTableModel): #na_values:least|greatest - for sorting options = {"striped": True, "stripesColor": "#fafafa", "na_values": "least", "tooltip_min_len": 21} def __init__(self, dataframe=None): super().__init__() self.setDataFrame(dataframe if dataframe is not None else pd.DataFrame()) def setDataFrame(self, dataframe): self.df = dataframe.copy() # self.df_full = self.df self.layoutChanged.emit() def rowCount(self, parent): return len(self.df) def columnCount(self, parent): return len(self.df.columns) def readLevel(self, y=0, xs=0, xe=None, orient=None): c = getattr(self.df, ("columns", "index")[orient!=HorizontalHeaderDataRole]) if not hasattr(c, "levels"): #not MultiIndex return [QtGui.QStandardItem(str(i)) for i in c] sibl = [] section_start, v, xe = xs, None, xe or len(c) for i in range(xs, xe): label = c.labels[y][i] if label!=v: if y+1<len(c.levels) and i>xs: children = self.readLevel(y+1, section_start, i, orient=orient) sibl[-1].appendRow(children) item = QtGui.QStandardItem(str(c.levels[y][label])) sibl.append(item) section_start = i v=label if y+1<len(c.levels): children = self.readLevel(y+1, section_start, orient=orient) sibl[-1].appendRow(children) return sibl def data(self, index, role): row, col = index.row(), index.column() if role in (Qt.DisplayRole, Qt.ToolTipRole): ret = self.df.iat[row, col] if ret is not None and ret==ret: #convert to str except for None, NaN, NaT if isinstance(ret, float): ret = "{:n}".format(ret) elif isinstance(ret, datetime.date): #FIXME: show microseconds optionally ret = ret.strftime(("%x", "%c")[isinstance(ret, datetime.datetime)]) else: ret = str(ret) if role == Qt.ToolTipRole: if len(ret)<self.options["tooltip_min_len"]: ret = "" return ret elif role == Qt.BackgroundRole: if self.options["striped"] and row%2: return QBrush(QColor(self.options["stripesColor"])) elif role in (HorizontalHeaderDataRole, VerticalHeaderDataRole): hm = QtGui.QStandardItemModel() hm.appendRow(self.readLevel(orient=role)) return hm def reorder(self, oldIndex, newIndex, orientation): "Reorder columns / rows" horizontal = orientation==Qt.Horizontal cols = list(self.df.columns if horizontal else self.df.index) cols.insert(newIndex, cols.pop(oldIndex)) self.df = self.df[cols] if horizontal else self.df.T[cols].T return True # def filter(self, filt=None): # self.df = self.df_full if filt is None else self.df[filt] # self.layoutChanged.emit() def headerData(self, section, orientation, role): if role != Qt.DisplayRole: return label = getattr(self.df, ("columns", "index")[orientation!=Qt.Horizontal])[section] # return label if type(label) is tuple else label return ("\n", " | ")[orientation!=Qt.Horizontal].join(str(i) for i in label) if type(label) is tuple else str(label) def dataFrame(self): return self.df def sort(self, column, order): # print("sort", column, order) #FIXME: double sort after setSortingEnabled(True) if len(self.df): asc = order==Qt.AscendingOrder na_pos = 'first' if (self.options["na_values"]=="least")==asc else 'last' self.df.sort_values(self.df.columns[column], ascending=asc, inplace=True, na_position=na_pos) self.layoutChanged.emit() if __name__=="__main__": import sys, locale locale.setlocale(locale.LC_ALL, '') #system locale settings app = QtGui.QApplication(sys.argv) form = QtGui.QWidget() form.setAttribute(Qt.WA_DeleteOnClose) #http://stackoverflow.com/a/27178019/1119602 form.setMinimumSize(700, 260) view = QtGui.QTableView() QtGui.QVBoxLayout(form).addWidget(view) form.show() #Prepare data tuples=[('bar', 'one', 'q'), ('bar', 'two', 'q'), ('baz', 'one', 'q'), ('baz', 'two', 'q'), ('foo', 'one', 'q'), ('foo', 'two', 'q'), ('qux', 'one', 'q'), ('qux', 'two', 'q')] index = pd.MultiIndex.from_tuples(tuples, names=['first', 'second', 'third']) df=pd.DataFrame(pd.np.random.randn(6, 6), index=index[:6], columns=index[:6]) print("DataFrame:\n%s"%df) #Prepare view # oldh, oldv = view.horizontalHeader(), view.verticalHeader() # oldh.setParent(form), oldv.setParent(form) #Save old headers for some reason MultiIndexHeaderView(Qt.Horizontal, view) MultiIndexHeaderView(Qt.Vertical, view) view.horizontalHeader().setMovable(True) #reorder DataFrame columns manually #Set data view.setModel(DataFrameModel(df)) view.resizeColumnsToContents() view.resizeRowsToContents() #Set sorting enabled (after setting model) view.setSortingEnabled(True) sys.exit(app.exec())
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)
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)
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 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)
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)
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 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)
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 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)
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
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
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()