def processAlgorithm(self, progress): apik = apikey(False) if apik is None: raise GeoAlgorithmExecutionException("what3words API key is not defined") w3w = what3words(apikey=apik) filename = self.getParameterValue(self.INPUT) layer = dataobjects.getObjectFromUri(filename) vprovider = layer.dataProvider() fields = vprovider.fields() caps = layer.dataProvider().capabilities() if not (caps & QgsVectorDataProvider.AddAttributes): raise GeoAlgorithmExecutionException("The selected layer does not support adding new attributes.") idxField = fields.indexFromName("3WordAddr") if idxField == -1: vprovider.addAttributes([QgsField("3WordAddr", QVariant.String)]) layer.updateFields() idxField = len(fields) nFeat = layer.featureCount() epsg4326 = QgsCoordinateReferenceSystem("EPSG:4326") transform = QgsCoordinateTransform(layer.crs(), epsg4326) for i, feat in enumerate(layer.getFeatures()): progress.setPercentage(int(100 * i / nFeat)) pt = feat.geometry().vertexAt(0) try: pt4326 = transform.transform(pt.x(), pt.y()) threeWords = ".".join(w3w.getWords(pt4326.y(), pt4326.x())["words"]) except Exception,e : threeWords = "" layer.dataProvider().changeAttributeValues({feat.id() : {idxField: threeWords}})
def processAlgorithm(self, parameters, context, feedback): source = self.parameterAsSource(parameters, self.INPUT, context) fields = source.fields() field = QgsField("w3w", QVariant.String) fields.append(field) apiKey = pluginSetting("apiKey") w3w = what3words(apikey=apiKey) (sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context, fields, source.wkbType(), source.sourceCrs()) features = source.getFeatures() total = 100.0 / source.featureCount() if source.featureCount() else 0 epsg4326 = QgsCoordinateReferenceSystem('EPSG:4326') transform = QgsCoordinateTransform(source.sourceCrs(), epsg4326, QgsProject.instance()) for current, feat in enumerate(features): if feedback.isCanceled(): break feedback.setProgress(int(current * total)) attrs = feat.attributes() pt = feat.geometry().centroid().asPoint() try: pt4326 = transform.transform(pt.x(), pt.y()) threeWords = w3w.reverseGeocode(pt4326.y(), pt4326.x())["words"] except Exception as e: progress.setDebugInfo( "Failed to retrieve w3w address for feature {}:\n{}". format(feat.id(), str(e))) threeWords = "" attrs.append(threeWords) feat.setAttributes(attrs) sink.addFeature(feat, QgsFeatureSink.FastInsert) return {self.OUTPUT: dest_id}
def processAlgorithm(self, progress): apik = pluginSetting("apiKey") if apik is None or apik == "":: raise GeoAlgorithmExecutionException("what3words API key is not defined") filename = self.getParameterValue(self.INPUT) layer = dataobjects.getObjectFromUri(filename) provider = layer.dataProvider() caps = provider.capabilities() if not (caps & QgsVectorDataProvider.AddAttributes): raise GeoAlgorithmExecutionException("The selected layer does not support adding new attributes.") idxField = layer.fieldNameIndex("3WordAddr") if idxField == -1: provider.addAttributes([QgsField("3WordAddr", QVariant.String, "", 254, 0)]) layer.updateFields() idxField = layer.fieldNameIndex("3WordAddr") w3w = what3words(apikey=apik) nFeat = layer.featureCount() epsg4326 = QgsCoordinateReferenceSystem("EPSG:4326") transform = QgsCoordinateTransform(layer.crs(), epsg4326) for i, feat in enumerate(layer.getFeatures()): progress.setPercentage(int(100 * i / nFeat)) pt = feat.geometry().vertexAt(0) try: pt4326 = transform.transform(pt.x(), pt.y()) threeWords = w3w.reverseGeocode(pt4326.y(), pt4326.x())["words"] except Exception as e: progress.setDebugInfo("Failed to retrieve w3w address for feature {}:\n{}".format(feat.id(), str(e))) threeWords = "" provider.changeAttributeValues({feat.id() : {idxField: threeWords}}) self.setOutputValue(self.OUTPUT, filename)
def processAlgorithm(self, progress): apik = apikey(False) if apik is None: raise GeoAlgorithmExecutionException( "what3words API key is not defined") w3w = what3words(apikey=apik) filename = self.getParameterValue(self.INPUT) layer = dataobjects.getObjectFromUri(filename) vprovider = layer.dataProvider() fields = vprovider.fields() caps = layer.dataProvider().capabilities() if not (caps & QgsVectorDataProvider.AddAttributes): raise GeoAlgorithmExecutionException( "The selected layer does not support adding new attributes.") idxField = fields.indexFromName("3WordAddr") if idxField == -1: vprovider.addAttributes([QgsField("3WordAddr", QVariant.String)]) layer.updateFields() idxField = len(fields) nFeat = layer.featureCount() epsg4326 = QgsCoordinateReferenceSystem("EPSG:4326") transform = QgsCoordinateTransform(layer.crs(), epsg4326) for i, feat in enumerate(layer.getFeatures()): progress.setPercentage(int(100 * i / nFeat)) pt = feat.geometry().vertexAt(0) try: pt4326 = transform.transform(pt.x(), pt.y()) threeWords = ".".join( w3w.getWords(pt4326.y(), pt4326.x())["words"]) except Exception, e: threeWords = "" layer.dataProvider().changeAttributeValues( {feat.id(): { idxField: threeWords }})
def __init__(self, canvas): QgsMapTool.__init__(self, canvas) self.setCursor(Qt.CrossCursor) apiKey = pluginSetting("apiKey") self.w3w = what3words(apikey=apiKey)
def setApiKey(self, apikey): self.w3w = what3words(apikey=apikey)
class Add3WordsFieldAlgorithm(GeoAlgorithm): ''' An algorithm that takes a points layer and oututs the same layer but with an additional field containing w3w adresses of points in the input layer. ''' INPUT = 'INPUT' OUTPUT = 'OUTPUT' def processAlgorithm(self, progress): ''' Here is where the algorithm functionality takes places. This method is called when the algorithm is executed''' apik = pluginSetting("apiKey") if apik is None or apik == "":: ''' When there is a problem in a Processing algorithm, a GeoAlgorithmExecutionException should be raised. ''' raise GeoAlgorithmExecutionException("what3words API key is not defined") ''' Get value selected by user. It will always be a string with the path to the layer source. ''' filename = self.getParameterValue(self.INPUT) '''Convert it to a QGIS layer object''' layer = dataobjects.getObjectFromUri(filename) '''Some checking''' provider = layer.dataProvider() caps = provider.capabilities() if not (caps & QgsVectorDataProvider.AddAttributes): raise GeoAlgorithmExecutionException("The selected layer does not support adding new attributes.") ''' Check if there is a field named '3WordAddr'. If it exists already, we will overwrite its content. Otherwise, we create a new one. ''' idxField = layer.fieldNameIndex("3WordAddr") if idxField == -1: provider.addAttributes([QgsField("3WordAddr", QVariant.String, "", 254, 0)]) layer.updateFields() idxField = layer.fieldNameIndex("3WordAddr") w3w = what3words(apikey=apik) nFeat = layer.featureCount() epsg4326 = QgsCoordinateReferenceSystem("EPSG:4326") ''' We use this object to convert point coords from the layer CRS into EPSG:4326, which is needed to call the w3w service ''' transform = QgsCoordinateTransform(layer.crs(), epsg4326) '''Iterate over features''' for i, feat in enumerate(layer.getFeatures()): progress.setPercentage(int(100 * i / nFeat)) '''Get Coordinate in layer CRS''' pt = feat.geometry().vertexAt(0) try: '''Convert to 4326''' pt4326 = transform.transform(pt.x(), pt.y()) '''Convert 4326 coord into w3w address''' threeWords = w3w.reverseGeocode(pt4326.y(), pt4326.x())["words"] except Exception as e: progress.setDebugInfo("Failed to retrieve w3w address for feature {}:\n{}".format(feat.id(), str(e))) threeWords = "" provider.changeAttributeValues({feat.id() : {idxField: threeWords}}) self.setOutputValue(self.OUTPUT, filename)