def checkBefore(): # check select+nextFeature f = layer.getFeatures().next() assert f.geometry().asPoint() == QgsPoint(100, 200) assert f[0].toString() == "test"
def testQgsPointRepr(self): p = QgsPoint(123.456, 987.654, 100) self.assertTrue(p.__repr__().startswith('<QgsPoint: PointZ (123.456'))
def testQgsCircularstringRepr(self): cs = QgsCircularString(QgsPoint(1, 2), QgsPoint(2, 3), QgsPoint(3, 4)) self.assertEqual(cs.__repr__(), '<QgsCircularString: CircularString (1 2, 2 3, 3 4)>')
#expectedFailure # ) QGISAPP, CANVAS, IFACE, PARENT = getQgisTestApp() def createEmptyLayer(): layer = QgsVectorLayer("Point", "addfeat", "memory") assert layer.pendingFeatureCount() == 0 return layer def createLayerWithOnePoint(): layer = QgsVectorLayer("Point?field=fldtxt:string&field=fldint:integer", "addfeat", "memory") pr = layer.dataProvider() f = QgsFeature() f.setAttributes([QVariant("test"), QVariant(123)]) f.setGeometry(QgsGeometry.fromPoint(QgsPoint(100,200))) assert pr.addFeatures([f]) assert layer.pendingFeatureCount() == 1 return layer def createJoinLayer(): joinLayer = QgsVectorLayer( "Point?field=x:string&field=y:integer&field=z:integer", "joinlayer", "memory") pr = joinLayer.dataProvider() f1 = QgsFeature() f1.setAttributes([QVariant("foo"), QVariant(123), QVariant(321)]) f1.setGeometry(QgsGeometry.fromPoint(QgsPoint(1,1))) f2 = QgsFeature() f2.setAttributes([QVariant("bar"), QVariant(456), QVariant(654)]) f2.setGeometry(QgsGeometry.fromPoint(QgsPoint(2,2)))
def processAlgorithm(self, parameters, context, feedback): source = self.parameterAsSource(parameters, self.INPUT_VECTOR, context) raster_layer = self.parameterAsRasterLayer(parameters, self.INPUT_RASTER, context) rasterPath = raster_layer.source() rasterDS = gdal.Open(rasterPath, gdal.GA_ReadOnly) geoTransform = rasterDS.GetGeoTransform() fields = QgsFields() fields.append(QgsField('id', QVariant.Int, '', 10, 0)) fields.append(QgsField('poly_id', QVariant.Int, '', 10, 0)) fields.append(QgsField('point_id', QVariant.Int, '', 10, 0)) (sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context, fields, QgsWkbTypes.Point, raster_layer.crs()) outFeature = QgsFeature() outFeature.setFields(fields) fid = 0 polyId = 0 pointId = 0 features = source.getFeatures(QgsFeatureRequest().setDestinationCrs(raster_layer.crs(), context.transformContext())) total = 100.0 / source.featureCount() if source.featureCount() else 0 for current, f in enumerate(features): if feedback.isCanceled(): break if not f.hasGeometry(): continue geom = f.geometry() bbox = geom.boundingBox() xMin = bbox.xMinimum() xMax = bbox.xMaximum() yMin = bbox.yMinimum() yMax = bbox.yMaximum() (startRow, startColumn) = raster.mapToPixel(xMin, yMax, geoTransform) (endRow, endColumn) = raster.mapToPixel(xMax, yMin, geoTransform) # use prepared geometries for faster intersection tests engine = QgsGeometry.createGeometryEngine(geom.constGet()) engine.prepareGeometry() for row in range(startRow, endRow + 1): for col in range(startColumn, endColumn + 1): if feedback.isCanceled(): break (x, y) = raster.pixelToMap(row, col, geoTransform) point = QgsPoint(x, y) if engine.contains(point): outFeature.setGeometry(QgsGeometry(point)) outFeature['id'] = fid outFeature['poly_id'] = polyId outFeature['point_id'] = pointId fid += 1 pointId += 1 sink.addFeature(outFeature, QgsFeatureSink.FastInsert) pointId = 0 polyId += 1 feedback.setProgress(int(current * total)) return {self.OUTPUT: dest_id}
def processAlgorithm(self, feedback): layer = dataobjects.getObjectFromUri( self.getParameterValue(self.VECTOR)) value = float(self.getParameterValue(self.VALUE)) minDistance = float(self.getParameterValue(self.MIN_DISTANCE)) strategy = self.getParameterValue(self.STRATEGY) fields = QgsFields() fields.append(QgsField('id', QVariant.Int, '', 10, 0)) writer = self.getOutputFromName(self.OUTPUT).getVectorWriter( fields, QgsWkbTypes.Point, layer.crs()) da = QgsDistanceArea() features = vector.features(layer) for current, f in enumerate(features): fGeom = f.geometry() bbox = fGeom.boundingBox() if strategy == 0: pointCount = int(value) else: pointCount = int(round(value * da.measureArea(fGeom))) index = QgsSpatialIndex() points = dict() nPoints = 0 nIterations = 0 maxIterations = pointCount * 200 total = 100.0 / pointCount random.seed() while nIterations < maxIterations and nPoints < pointCount: rx = bbox.xMinimum() + bbox.width() * random.random() ry = bbox.yMinimum() + bbox.height() * random.random() pnt = QgsPoint(rx, ry) geom = QgsGeometry.fromPoint(pnt) if geom.within(fGeom) and \ vector.checkMinDistance(pnt, index, minDistance, points): f = QgsFeature(nPoints) f.initAttributes(1) f.setFields(fields) f.setAttribute('id', nPoints) f.setGeometry(geom) writer.addFeature(f) index.insertFeature(f) points[nPoints] = pnt nPoints += 1 feedback.setProgress(int(nPoints * total)) nIterations += 1 if nPoints < pointCount: ProcessingLog.addToLog(ProcessingLog.LOG_INFO, self.tr('Can not generate requested number of random ' 'points. Maximum number of attempts exceeded.')) feedback.setProgress(0) del writer
def processAlgorithm(self, parameters, context, feedback): # Get Parameters and assign to variable to work with server_url = self.parameterAsString(parameters, self.SERVER_URL, context) source_layer = self.parameterAsLayer(parameters, self.SOURCE_LYR, context) startlat_field = self.parameterAsString(parameters, self.STARTLAT_FIELD, context) startlon_field = self.parameterAsString(parameters, self.STARTLON_FIELD, context) endlat_field = self.parameterAsString(parameters, self.ENDLAT_FIELD, context) endlon_field = self.parameterAsString(parameters, self.ENDLON_FIELD, context) date_field = self.parameterAsString(parameters, self.DATE_FIELD, context) time_field = self.parameterAsString(parameters, self.TIME_FIELD, context) travelmode = self.parameterAsString(parameters, self.MODE, context) modelist = [ 'WALK', 'CAR', 'BICYCLE', 'TRANSIT', 'WALK,TRANSIT', 'WALK,BICYCLE' ] travelmode = str(modelist[int(travelmode[0])]) traveloptimize = self.parameterAsString(parameters, self.OPTIMIZE, context) optimizelist = [ 'QUICK', 'TRANSFERS', 'SAFE', 'FLAT', 'GREENWAYS', 'TRIANGLE' ] traveloptimize = str(optimizelist[int(traveloptimize[0])]) additional_params = self.parameterAsString(parameters, self.ADDITIONAL_PARAMS, context) iterinaries = self.parameterAsInt(parameters, self.ITERINARIES, context) total = 100.0 / source_layer.featureCount( ) if source_layer.featureCount( ) else 0 # Initialize progress for progressbar fields = source_layer.fields() # get all fields of the sourcelayer n_source_fields = source_layer.fields().count() fieldlist = [ # Master for attributes and varnames QgsField("Route_LegID", QVariant.Int), QgsField("Route_RouteID", QVariant.Int), QgsField("Route_RelationID", QVariant.Int), QgsField("Route_From", QVariant.String), # ! QgsField("Route_To", QVariant.String), # ! QgsField("Route_Error", QVariant.String), QgsField("Route_ErrorID", QVariant.Int), QgsField("Route_ErrorDescription", QVariant.String), QgsField("Route_URL", QVariant.String), QgsField("Route_From_Lat", QVariant.Double, len=4, prec=8), QgsField("Route_From_Lon", QVariant.Double, len=4, prec=8), QgsField("Route_From_StopId", QVariant.String), QgsField("Route_From_StopCode", QVariant.String), QgsField("Route_From_Name", QVariant.String), QgsField("Route_From_StartTime", QVariant.DateTime), QgsField("Route_To_Lat", QVariant.Double, len=4, prec=8), QgsField("Route_To_Lon", QVariant.Double, len=4, prec=8), QgsField("Route_To_StopId", QVariant.String), QgsField("Route_To_StopCode", QVariant.String), QgsField("Route_To_Name", QVariant.String), QgsField("Route_To_EndTime", QVariant.DateTime), QgsField("Route_Total_Mode", QVariant.String), QgsField("Route_Total_Duration", QVariant.Int), QgsField("Route_Total_Distance", QVariant.Double), QgsField("Route_Total_TransitTime", QVariant.Int), QgsField("Route_Total_WaitingTime", QVariant.Int), QgsField("Route_Total_WalkTime", QVariant.Int), QgsField("Route_Total_WalkDistance", QVariant.Double), QgsField("Route_Total_Transfers", QVariant.Int), QgsField("Route_Leg_StartTime", QVariant.DateTime), QgsField("Route_Leg_DepartureDelay", QVariant.Int), QgsField("Route_Leg_EndTime", QVariant.DateTime), QgsField("Route_Leg_ArrivalDelay", QVariant.Int), QgsField("Route_Leg_Duration", QVariant.Int), QgsField("Route_Leg_Distance", QVariant.Double), QgsField("Route_Leg_Mode", QVariant.String), QgsField("Route_Leg_From_Lat", QVariant.Double, len=4, prec=8), QgsField("Route_Leg_From_Lon", QVariant.Double, len=4, prec=8), QgsField("Route_Leg_From_StopId", QVariant.String), QgsField("Route_Leg_From_StopCode", QVariant.String), QgsField("Route_Leg_From_Name", QVariant.String), QgsField("Route_Leg_From_Departure", QVariant.DateTime), QgsField("Route_Leg_To_Lat", QVariant.Double, len=4, prec=8), QgsField("Route_Leg_To_Lon", QVariant.Double, len=4, prec=8), QgsField("Route_Leg_To_StopId", QVariant.String), QgsField("Route_Leg_To_StopCode", QVariant.String), QgsField("Route_Leg_To_Name", QVariant.String), QgsField("Route_Leg_To_Arrival", QVariant.DateTime) ] for field in fieldlist: fields.append(field) # add fields from the list # Fieldindex as dictionary to avoid a mess fieldindexcounter = 0 # start with index 0 fieldindexdict = {} # empty dictionary for field in fields: # iterate through field list we just created above x = str(field.name()).lower() # convert to lowercase, string fieldindexdict[ fieldindexcounter] = x # assign index as key and fieldname as value if '_url' in x: fieldindex_position_of_last_alwaysneededfield = fieldindexcounter if 'route_total_distance' in x: fieldindex_position_of_routetotaldistance = fieldindexcounter fieldindexcounter += 1 len_fieldindexdict = len(fieldindexdict) # Counter route_legid = 0 route_routeid = 0 route_relationid = 0 route_from = '' route_to = '' notavailablestring = None #'not available' notavailableint = None #0 notavailableothers = None # Pseudopointlist for errors in decode polyline errorlinegeom = [] errorlinegeomp1 = QgsPoint(float(-0.1), float(0.0)) errorlinegeom.append(errorlinegeomp1) errorlinegeomp2 = QgsPoint(float(0.1), float(0.0)) errorlinegeom.append(errorlinegeomp2) # some general settings route_headers = { "accept": "application/json" } # this plugin only works for json responses (sink, dest_id) = self.parameterAsSink( parameters, self.OUTPUT, context, fields, 2, # 2 = wkbType LineString QgsCoordinateReferenceSystem('EPSG:4326')) for current, source_feature in enumerate( source_layer.getFeatures()): # iterate over source route_relationid += 1 # Making Script compatible with earlier versions than QGIS 3.18: If date or time field is a string, do not convert it to a string... use_date = '' use_time = '' try: use_date = str( source_feature[date_field].toString('yyyy-MM-dd')) except: use_date = str(source_feature[date_field]) try: use_time = str(source_feature[time_field].toString('HH:mm:ss')) except: use_time = str(source_feature[time_field]) # Create URL for current feature route_url = ( str(server_url) + "plan?" + # Add Plan request to server url "fromPlace=" + str(source_feature[startlat_field]) + "," + str(source_feature[startlon_field]) + "&toPlace=" + str(source_feature[endlat_field]) + "," + str(source_feature[endlon_field]) + "&mode=" + travelmode + "&date=" + use_date + "&time=" + use_time + "&numItineraries=" + str(iterinaries) + "&optimize=" + traveloptimize + additional_params # Additional Parameters entered as OTP-Readable string -> User responsibility ) #print(route_url) # Reset Error Indicators route_error = 'Success' route_error_bool = False route_errorid = None route_errordescription = None route_errormessage = None route_errornopath = None try: # Try to request route route_request = urllib.request.Request(route_url, headers=route_headers) try: # Try to receive response route_response = urllib.request.urlopen(route_request) try: # Try to read response data response_data = route_response.read() encoding = route_response.info().get_content_charset( 'utf-8') route_data = json.loads(response_data.decode(encoding)) try: # Check if response says Error route_error = 'Error: No Route' route_error_bool = True route_errorid = route_data['error']['id'] route_errordescription = route_data['error']['msg'] try: # not every error delivers this route_errormessage = route_data['error'][ 'message'] except: pass try: # not every error delivers this route_errornopath = route_data['error'][ 'noPath'] except: pass except: route_error = 'Success' route_error_bool = False except: route_error = 'Error: Cannot read response data' route_error_bool = True except: route_error = 'Error: No response received' route_error_bool = True except: route_error = 'Error: Requesting the route failed' route_error_bool = True #print(route_error) try: if not route_data['plan'][ 'itineraries']: # check if response is empty route_error = 'Error: Empty response route' route_error_bool = True except: pass #print(route_data) # Reading response if route_error_bool == False: # Get general informations. Note that not all are available in all responses: use try/except try: route_from_lat = route_data['plan']['from']['lat'] route_from_lon = route_data['plan']['from']['lon'] except: route_from_lat = notavailableint route_from_lon = notavailableint try: route_from_stopid = route_data['plan']['from']['stopId'] except: route_from_stopid = notavailablestring try: route_from_stopcode = route_data['plan']['from'][ 'stopCode'] except: route_from_stopcode = notavailablestring try: route_from_name = route_data['plan']['from']['name'] except: route_from_name = notavailablestring try: route_to_lat = route_data['plan']['to']['lat'] route_to_lon = route_data['plan']['to']['lon'] except: route_to_lat = notavailableint route_to_lon = notavailableint try: route_to_stopid = route_data['plan']['to']['stopId'] except: route_to_stopid = notavailablestring try: route_to_stopcode = route_data['plan']['to']['stopCode'] except: route_to_stopcode = notavailablestring try: route_to_name = route_data['plan']['to']['name'] except: route_to_name = notavailablestring # loop through iterinaries for iter in route_data['plan']['itineraries']: route_routeid += 1 try: route_from_starttime = iter['startTime'] route_from_starttime = datetime.fromtimestamp( int(route_from_starttime) / 1000) route_from_starttime = QDateTime.fromString( str(route_from_starttime), 'yyyy-MM-dd hh:mm:ss') except: route_from_starttime = notavailableothers try: route_to_endtime = iter['endTime'] route_to_endtime = datetime.fromtimestamp( int(route_to_endtime) / 1000) route_to_endtime = QDateTime.fromString( str(route_to_endtime), 'yyyy-MM-dd hh:mm:ss') except: route_to_endtime = notavailableothers try: route_total_duration = iter['duration'] except: route_total_duration = notavailableint route_total_distance = 0 # set to 0 on start of each new route, well take the sum of all legs of a route route_total_mode = travelmode try: route_total_transittime = iter['transitTime'] except: route_total_transittime = notavailableint try: route_total_waitingtime = iter['waitingTime'] except: route_total_waitingtime = notavailableint try: route_total_walktime = iter['walkTime'] except: route_total_walktime = notavailableint try: route_total_walkdistance = iter['walkDistance'] except: route_total_walkdistance = notavailableint try: route_total_transfers = iter['transfers'] except: route_total_transfers = notavailableint #print('From lat: ' + str(route_total_duration)) # loop through legs --> they will become the features of our layer route_leg_totaldistcounter = 0 # set to 0 on start of each new route for leg in iter['legs']: route_legid += 1 new_feature = QgsFeature(fields) try: route_leg_starttime = leg['startTime'] route_leg_starttime = datetime.fromtimestamp( int(route_leg_starttime) / 1000) route_leg_starttime = QDateTime.fromString( str(route_leg_starttime), 'yyyy-MM-dd hh:mm:ss') except: route_leg_starttime = notavailableothers try: route_leg_departuredelay = leg['departureDelay'] except: route_leg_departuredelay = notavailableint try: route_leg_endtime = leg['endTime'] route_leg_endtime = datetime.fromtimestamp( int(route_leg_endtime) / 1000) route_leg_endtime = QDateTime.fromString( str(route_leg_endtime), 'yyyy-MM-dd hh:mm:ss') except: route_leg_endtime = notavailableothers try: route_leg_arrivaldelay = leg['arrivalDelay'] except: route_leg_arrivaldelay = notavailableint try: route_leg_duration = leg['duration'] except: route_leg_duration = notavailableint try: route_leg_distance = leg['distance'] #route_total_distance += route_leg_distance # Field does not exist in response. Build sum of all legs route_total_distance = None except: route_leg_distance = notavailableint #route_total_distance += 0 # Field does not exist in response..... try: route_leg_mode = leg['mode'] except: route_leg_mode = notavailablestring try: route_leg_from_lat = leg['from']['lat'] route_leg_from_lon = leg['from']['lon'] except: route_leg_from_lat = notavailableint route_leg_from_lon = notavailableint try: route_leg_from_stopid = leg['from']['stopId'] except: route_leg_from_stopid = notavailablestring try: route_leg_from_stopcode = leg['from']['stopCode'] except: route_leg_from_stopcode = notavailablestring try: route_leg_from_name = leg['from']['name'] except: route_leg_from_name = notavailablestring try: route_leg_from_departure = leg['from']['departure'] route_leg_from_departure = datetime.fromtimestamp( int(route_leg_from_departure) / 1000) route_leg_from_departure = QDateTime.fromString( str(route_leg_from_departure), 'yyyy-MM-dd hh:mm:ss') except: route_leg_from_departure = notavailableothers try: route_leg_to_lat = leg['to']['lat'] route_leg_to_lon = leg['to']['lon'] except: route_leg_to_lat = notavailableint route_leg_to_lon = notavailableint try: route_leg_to_stopid = leg['to']['stopId'] except: route_leg_to_stopid = notavailablestring try: route_leg_to_stopcode = leg['to']['stopCode'] except: route_leg_to_stopcode = notavailablestring try: route_leg_to_name = leg['to']['name'] except: route_leg_to_name = notavailablestring try: route_leg_to_arrival = leg['to']['arrival'] route_leg_to_arrival = datetime.fromtimestamp( int(route_leg_to_arrival) / 1000) route_leg_to_arrival = QDateTime.fromString( str(route_leg_to_arrival), 'yyyy-MM-dd hh:mm:ss') except: route_leg_to_arrival = notavailableothers try: route_leg_encodedpolylinestring = leg[ 'legGeometry']['points'] route_leg_decodedpolylinestring_aspointlist = self.decode_polyline( route_leg_encodedpolylinestring) new_feature.setGeometry( QgsGeometry.fromPolyline( route_leg_decodedpolylinestring_aspointlist )) except: new_feature.setGeometry( QgsGeometry.fromPolyline(errorlinegeom)) route_error = 'Error: Decoding route geometry failed' # Adding the attributes to resultlayer for key, value in fieldindexdict.items( ): # keys contain the fieldindex, values the variablename which is the same as the fieldname, just in lowercase fieldindex = key if key < n_source_fields: # Copy source attributes from source layer fieldvalue = source_feature[ fieldindex] # source_feature = sourcelayer-feature, new_feature = new feature else: # Get the leg attributes from variables fieldvalue = locals( )[value] # variables are named exactly as the fieldnames, just lowercase, we adjusted that before new_feature.setAttribute(fieldindex, fieldvalue) sink.addFeature(new_feature, QgsFeatureSink.FastInsert ) # add feature to the output route_leg_totaldistcounter += 1 # counting the number of legs of a route # END OF LOOP legs # Update total distance here since it is the sum of all legs and not available in response jsons #attr_totaldistance = { fieldindex_position_of_routetotaldistance : route_total_distance } # only change totaldistance field, we get its position while building the dict #last_featureid_totaldistance = new_feature.id() # the last featureid of a route = current feature #first_featureid_totaldistance = last_featureid_totaldistance - route_leg_totaldistcounter + 1 # the first featureid of a route #print('last: ' + str(last_featureid_totaldistance)) #print('first: ' + str(first_featureid_totaldistance)) #for features_before in range(first_featureid_totaldistance,last_featureid_totaldistance): # loop through all legs of the current route #new_feature.setAttribute(fieldindex_position_of_routetotaldistance,route_total_distance) #dings = new_feature.id(features_before) #dings.setAttribute(fieldindex_position_of_routetotaldistance,route_total_distance) #new_feature.id(features_before)[fieldindex_position_of_routetotaldistance] = route_total_distance #print(new_feature.id(features_before)) #routes_memorylayer_pr.changeAttributeValues({ features_before : attr_totaldistance }) # add the leg-sum of all legs of a route as totaldistance # END OF LOOP iterinaries # END OF if route_error_bool == False else: # Create error-dummyfeature if no route has been returned route_routeid += 1 route_legid += 1 new_feature = QgsFeature(fields) try: route_errorid = route_data['error']['id'] except: route_errorid = notavailableint try: route_errordescription = route_data['error']['msg'] except: route_errordescription = notavailablestring try: route_errormessage = route_data['error']['message'] except: route_errormessage = notavailablestring try: route_errornopath = route_data['error']['noPath'] except: route_errornopath = notavailablestring # Create dummy-geometry new_feature.setGeometry( QgsGeometry.fromPolyline(errorlinegeom)) # Adding the attributes to resultlayer for key, value in fieldindexdict.items( ): # keys contain the fieldindex, values the variablename which is the same as the fieldname, just in lowercase fieldindex = key if fieldindex < n_source_fields: # copy attributes from source layer fieldvalue = source_feature[fieldindex] new_feature[fieldindex] = fieldvalue elif fieldindex <= fieldindex_position_of_last_alwaysneededfield: # Only fill the first fields on error fieldvalue = locals()[value] new_feature[fieldindex] = fieldvalue else: # Leave the others empty as there is no data available fieldvalue = None new_feature[fieldindex] = fieldvalue sink.addFeature( new_feature, QgsFeatureSink.FastInsert) # add feature to the output # END OF errorroutecreation if feedback.isCanceled(): # Cancel algorithm if button is pressed break feedback.setProgress(int(current * total)) # Set Progress in Progressbar return {self.OUTPUT: dest_id} # Return result of algorithm
def draw_circle(self, circle): polygon = [QgsPointXY(*point) for point in circle.to_polygon()] print(circle) print(polygon) print(type(polygon)) #gPnt = QgsGeometry.fromPointXY(QgsPointXY(1,1)) #gLine = QgsGeometry.fromPolyline([QgsPoint(1, 1), QgsPoint(2, 2)]) #gPolygon = QgsGeometry.fromPolygonXY([[QgsPointXY(1, 1), QgsPointXY(2, 2), QgsPointXY(2, 1)]]) #geometry = QgsGeometry.fromPolygon([polygon]) geometry = QgsGeometry.fromPolygonXY([polygon]) feature = QgsFeature() feature.setGeometry(geometry) feature.setFields(self.layer.fields()) destination = self.layer.crs() source = self.layer.crs() xform = self.crs_transform(source, destination) #print circle.center.x, circle.center.y #print(circle.center.x, circle.center.y) #line = [ # QgsPointXY(circle.center.x, circle.center.y), # QgsPointXY(circle.center.x + circle.radius, circle.center.y), #] line = [ QgsPointXY(circle.a, circle.b), QgsPointXY(circle.a + circle.r, circle.b), ] transformed = [ self.transform_point(xform, line[0]), self.transform_point(xform, line[1]), ] print("****",transformed) #new_line_geometry = QgsGeometry.fromPolyline( [ QgsGeometry.fromPointXY(transformed[0]), QgsGeometry.fromPointXY(transformed[1]) ] ) new_line_geometry = QgsGeometry.fromPolyline([QgsPoint(transformed[0][0], transformed[0][1]), QgsPoint(transformed[1][0], transformed[1][1])]) distance_area = self.get_distance_area(self.layer) actual_line_distance = distance_area.measureLength(new_line_geometry) # Translate circle center to units of degrees center_in_degrees = xform.transform(circle.a, circle.b) # circle_feature.id() is NULL for .shp file # and assigned automaticly for .gpkg # order is id, diameter, lon, lat feature.setAttribute('diameter',circle.diameter) feature.setAttribute('center_lon',circle.a) feature.setAttribute('center_lat',circle.b) self.layer.startEditing() self.layer.dataProvider().addFeatures([feature]) #self.layer.addFeature(feature, True) self.layer.commitChanges() # update layer's extent when new features have been added # because change of extent in provider is not propagated to the layer self.layer.updateExtents()
def processAlgorithm(self, feedback): radius = self.getParameterValue(self.DISTANCE) horizontal = self.getParameterValue(self.HORIZONTAL) output = self.getOutputFromName(self.OUTPUT_LAYER) layer = dataobjects.getObjectFromUri( self.getParameterValue(self.INPUT_LAYER)) writer = output.getVectorWriter(layer.fields(), layer.wkbType(), layer.crs()) features = vector.features(layer) total = 100.0 / len(features) duplicates = dict() for current, f in enumerate(features): wkt = f.geometry().exportToWkt() if wkt not in duplicates: duplicates[wkt] = [f.id()] else: duplicates[wkt].extend([f.id()]) feedback.setProgress(int(current * total)) current = 0 total = 100.0 / len(duplicates) feedback.setProgress(0) fullPerimeter = 2 * math.pi for (geom, fids) in list(duplicates.items()): count = len(fids) if count == 1: f = next( layer.getFeatures(QgsFeatureRequest().setFilterFid( fids[0]))) writer.addFeature(f) else: angleStep = fullPerimeter / count if count == 2 and horizontal: currentAngle = math.pi / 2 else: currentAngle = 0 old_point = QgsGeometry.fromWkt(geom).asPoint() request = QgsFeatureRequest().setFilterFids(fids).setFlags( QgsFeatureRequest.NoGeometry) for f in layer.getFeatures(request): sinusCurrentAngle = math.sin(currentAngle) cosinusCurrentAngle = math.cos(currentAngle) dx = radius * sinusCurrentAngle dy = radius * cosinusCurrentAngle new_point = QgsPoint(old_point.x() + dx, old_point.y() + dy) out_feature = QgsFeature() out_feature.setGeometry(QgsGeometry.fromPoint(new_point)) out_feature.setAttributes(f.attributes()) writer.addFeature(out_feature) currentAngle += angleStep current += 1 feedback.setProgress(int(current * total)) del writer
def test_resetSnappingIndex(self): self.pointsLayer.setDependencies([]) self.linesLayer.setDependencies([]) self.pointsLayer2.setDependencies([]) ms = QgsMapSettings() ms.setOutputSize(QSize(100, 100)) ms.setExtent(QgsRectangle(0, 0, 1, 1)) self.assertTrue(ms.hasValidSettings()) u = QgsSnappingUtils() u.setMapSettings(ms) cfg = u.config() cfg.setEnabled(True) cfg.setMode(QgsSnappingConfig.AdvancedConfiguration) cfg.setIndividualLayerSettings( self.pointsLayer, QgsSnappingConfig.IndividualLayerSettings(True, QgsSnappingConfig.Vertex, 20, QgsTolerance.Pixels)) u.setConfig(cfg) m = u.snapToMap(QPoint(95, 100)) self.assertTrue(m.isValid()) self.assertTrue(m.hasVertex()) self.assertEqual(m.point(), QgsPoint(1, 0)) f = QgsFeature(self.linesLayer.fields()) f.setId(1) geom = QgsGeometry.fromWkt("LINESTRING(0 0,1 1)") f.setGeometry(geom) self.linesLayer.startEditing() self.linesLayer.addFeatures([f]) self.linesLayer.commitChanges() l1 = len([f for f in self.pointsLayer.getFeatures()]) self.assertEqual(l1, 4) m = u.snapToMap(QPoint(95, 0)) # snapping not updated self.pointsLayer.setDependencies([]) self.assertEqual(m.isValid(), False) # set layer dependencies self.pointsLayer.setDependencies( [QgsMapLayerDependency(self.linesLayer.id())]) # add another line f = QgsFeature(self.linesLayer.fields()) f.setId(2) geom = QgsGeometry.fromWkt("LINESTRING(0 0,0.5 0.5)") f.setGeometry(geom) self.linesLayer.startEditing() self.linesLayer.addFeatures([f]) self.linesLayer.commitChanges() # check the snapped point is ok m = u.snapToMap(QPoint(45, 50)) self.assertTrue(m.isValid()) self.assertTrue(m.hasVertex()) self.assertEqual(m.point(), QgsPoint(0.5, 0.5)) self.pointsLayer.setDependencies([]) # test chained layer dependencies A -> B -> C cfg.setIndividualLayerSettings( self.pointsLayer2, QgsSnappingConfig.IndividualLayerSettings(True, QgsSnappingConfig.Vertex, 20, QgsTolerance.Pixels)) u.setConfig(cfg) self.pointsLayer.setDependencies( [QgsMapLayerDependency(self.linesLayer.id())]) self.pointsLayer2.setDependencies( [QgsMapLayerDependency(self.pointsLayer.id())]) # add another line f = QgsFeature(self.linesLayer.fields()) f.setId(3) geom = QgsGeometry.fromWkt("LINESTRING(0 0.2,0.5 0.8)") f.setGeometry(geom) self.linesLayer.startEditing() self.linesLayer.addFeatures([f]) self.linesLayer.commitChanges() # check the second snapped point is ok m = u.snapToMap(QPoint(75, 100 - 80)) self.assertTrue(m.isValid()) self.assertTrue(m.hasVertex()) self.assertEqual(m.point(), QgsPoint(0.7, 0.8)) self.pointsLayer.setDependencies([]) self.pointsLayer2.setDependencies([])
def test_signalConnection(self): # remove all layers QgsProject.instance().removeAllMapLayers() # set dependencies and add back layers self.pointsLayer = QgsVectorLayer( "dbname='%s' table=\"node\" (geom) sql=" % self.fn, "points", "spatialite") assert (self.pointsLayer.isValid()) self.linesLayer = QgsVectorLayer( "dbname='%s' table=\"section\" (geom) sql=" % self.fn, "lines", "spatialite") assert (self.linesLayer.isValid()) self.pointsLayer2 = QgsVectorLayer( "dbname='%s' table=\"node2\" (geom) sql=" % self.fn, "_points2", "spatialite") assert (self.pointsLayer2.isValid()) self.pointsLayer.setDependencies( [QgsMapLayerDependency(self.linesLayer.id())]) self.pointsLayer2.setDependencies( [QgsMapLayerDependency(self.pointsLayer.id())]) # this should update connections between layers QgsProject.instance().addMapLayers([self.pointsLayer]) QgsProject.instance().addMapLayers([self.linesLayer]) QgsProject.instance().addMapLayers([self.pointsLayer2]) ms = QgsMapSettings() ms.setOutputSize(QSize(100, 100)) ms.setExtent(QgsRectangle(0, 0, 1, 1)) self.assertTrue(ms.hasValidSettings()) u = QgsSnappingUtils() u.setMapSettings(ms) cfg = u.config() cfg.setEnabled(True) cfg.setMode(QgsSnappingConfig.AdvancedConfiguration) cfg.setIndividualLayerSettings( self.pointsLayer, QgsSnappingConfig.IndividualLayerSettings(True, QgsSnappingConfig.Vertex, 20, QgsTolerance.Pixels)) cfg.setIndividualLayerSettings( self.pointsLayer2, QgsSnappingConfig.IndividualLayerSettings(True, QgsSnappingConfig.Vertex, 20, QgsTolerance.Pixels)) u.setConfig(cfg) # add another line f = QgsFeature(self.linesLayer.fields()) f.setId(4) geom = QgsGeometry.fromWkt("LINESTRING(0.5 0.2,0.6 0)") f.setGeometry(geom) self.linesLayer.startEditing() self.linesLayer.addFeatures([f]) self.linesLayer.commitChanges() # check the second snapped point is ok m = u.snapToMap(QPoint(75, 100 - 0)) self.assertTrue(m.isValid()) self.assertTrue(m.hasVertex()) self.assertEqual(m.point(), QgsPoint(0.8, 0.0)) self.pointsLayer.setDependencies([]) self.pointsLayer2.setDependencies([])
def importPhotos(self): if self.append: layer = self._openShapefile() else: layer = self._newShapefile() if layer is None: self.importError.emit(self.tr("Unable to open or create layer.")) return provider = layer.dataProvider() fields = layer.fields() photos = [] for root, dirs, files in os.walk(self.directory): photos.extend(os.path.join(root, fName) for fName in files if fName.lower().endswith((".jpg", ".jpeg"))) if not self.recurse: break if len(photos) == 0: self.importError.emit(self.tr("No images found in the directory.")) return total = 100.0 / len(photos) ft = QgsFeature() ft.setFields(fields) for count, fName in enumerate(photos): with open(fName, "rb") as imgFile: tags = exifread.process_file(imgFile, details=False) if not tags.keys() & {"GPS GPSLongitude", "GPS GPSLatitude"}: self.importMessage.emit( self.tr("Skipping file {}: " "there are no GPS tags in it.".format(fName))) self.photoProcessed.emit(int(count * total)) continue # Start processing tags longitude, latitude = self._extractCoordinates(tags) if longitude is None: self.importMessage.emit( self.tr("Skipping file {}: " "there are no GPS fix data.".format(fName))) self.photoProcessed.emit(int(count * total)) continue altitude = self._extractAltitude(tags) north, azimuth = self._extractDirection(tags) gpsDate = self._extracrGPSDateTime(tags) imgDate = self._extractImageDateTime(tags) del tags # Write feature to layer z = altitude if altitude is not None else 0.0 ft.setGeometry(QgsGeometry(QgsPoint(longitude, latitude, z))) ft["filepath"] = fName ft["longitude"] = longitude ft["latitude"] = latitude ft["altitude"] = altitude ft["north"] = north ft["azimuth"] = azimuth ft["gps_date"] = gpsDate ft["img_date"] = imgDate provider.addFeatures([ft]) self.photoProcessed.emit(int(count * total)) self.importFinished.emit()
def _lineGrid(self, sink, bbox, hSpacing, vSpacing, hOverlay, vOverlay, feedback): feat = QgsFeature() if hOverlay > 0: hSpace = [hSpacing - hOverlay, hOverlay] else: hSpace = [hSpacing, hSpacing] if vOverlay > 0: vSpace = [vSpacing - vOverlay, vOverlay] else: vSpace = [vSpacing, vSpacing] count = 0 id = 1 # latitude lines count_max = bbox.height() / vSpacing count_update = count_max * 0.10 y = bbox.yMaximum() while y >= bbox.yMinimum(): if feedback.isCanceled(): break pt1 = QgsPoint(bbox.xMinimum(), y) pt2 = QgsPoint(bbox.xMaximum(), y) line = QgsLineString([pt1, pt2]) feat.setGeometry(QgsGeometry(line)) feat.setAttributes([bbox.xMinimum(), y, bbox.xMaximum(), y, id, y]) sink.addFeature(feat, QgsFeatureSink.FastInsert) y = y - vSpace[count % 2] id += 1 count += 1 if int(math.fmod(count, count_update)) == 0: feedback.setProgress(int(count / count_max * 50)) feedback.setProgress(50) # longitude lines # counters for progressbar - update every 5% count = 0 count_max = bbox.width() / hSpacing count_update = count_max * 0.10 x = bbox.xMinimum() while x <= bbox.xMaximum(): if feedback.isCanceled(): break pt1 = QgsPoint(x, bbox.yMaximum()) pt2 = QgsPoint(x, bbox.yMinimum()) line = QgsLineString([pt1, pt2]) feat.setGeometry(QgsGeometry(line)) feat.setAttributes([x, bbox.yMaximum(), x, bbox.yMinimum(), id, x]) sink.addFeature(feat, QgsFeatureSink.FastInsert) x = x + hSpace[count % 2] id += 1 count += 1 if int(math.fmod(count, count_update)) == 0: feedback.setProgress(50 + int(count / count_max * 50))
def processAlgorithm(self, context, feedback): extent = str(self.getParameterValue(self.EXTENT)).split(',') spacing = float(self.getParameterValue(self.SPACING)) inset = float(self.getParameterValue(self.INSET)) randomize = self.getParameterValue(self.RANDOMIZE) isSpacing = self.getParameterValue(self.IS_SPACING) crsId = self.getParameterValue(self.CRS) crs = QgsCoordinateReferenceSystem() crs.createFromUserInput(crsId) extent = QgsRectangle(float(extent[0]), float(extent[2]), float(extent[1]), float(extent[3])) fields = QgsFields() fields.append(QgsField('id', QVariant.Int, '', 10, 0)) writer = self.getOutputFromName(self.OUTPUT).getVectorWriter( fields, QgsWkbTypes.Point, crs, context) if randomize: seed() area = extent.width() * extent.height() if isSpacing: pSpacing = spacing else: pSpacing = sqrt(area / spacing) f = QgsFeature() f.initAttributes(1) f.setFields(fields) count = 0 total = 100.0 / (area / pSpacing) y = extent.yMaximum() - inset extent_geom = QgsGeometry.fromRect(extent) extent_engine = QgsGeometry.createGeometryEngine( extent_geom.geometry()) extent_engine.prepareGeometry() while y >= extent.yMinimum(): x = extent.xMinimum() + inset while x <= extent.xMaximum(): if randomize: geom = QgsGeometry().fromPoint( QgsPoint( uniform(x - (pSpacing / 2.0), x + (pSpacing / 2.0)), uniform(y - (pSpacing / 2.0), y + (pSpacing / 2.0)))) else: geom = QgsGeometry().fromPoint(QgsPoint(x, y)) if extent_engine.intersects(geom.geometry()): f.setAttribute('id', count) f.setGeometry(geom) writer.addFeature(f) x += pSpacing count += 1 feedback.setProgress(int(count * total)) y = y - pSpacing del writer
def testQgsEllipseRepr(self): e = QgsEllipse(QgsPoint(1, 2), 2.0, 3.0) self.assertEqual(e.__repr__(), '<QgsEllipse: Ellipse (Center: Point (1 2), Semi-Major Axis: 3, Semi-Minor Axis: 2, Azimuth: 180)>')
def _process_row(self, row): """Process line in LOG file and create a new point feature based on this line. :param row: row to be processed """ # define internal functions first def coords_float(coord, ne): """Convert coordinates to DMS. :param coord: coordinates as a string :param ne: longitude/latitude indicator :return: coordinate value """ ddmm, s = coord.split('.', 1) val = int(ddmm[:-2]) + int(ddmm[-2:])/60. + float('0.'+s)/60. if ne in ('S', 'W'): val *= -1 return val def datetime2localtime(datetime_value): """Convert datetime value to local time. :datetime_value: date time value (eg. '2016-05-16T18:22:26Z') :return: local time as a string (eg. '20:22:26') """ from_zone = tz.tzutc() to_zone = tz.tzlocal() utc = datetime.strptime(datetime_value, '%Y-%m-%dT%H:%M:%SZ') utc = utc.replace(tzinfo=from_zone) local = utc.astimezone(to_zone) return local.strftime('%H:%M:%S') if len(row) != len(self._provider.fields()) - 3: # last four columns (ader_microSvh, time_local, hdop, checksum) are computed raise SafecastReaderError(self.tr("Failed to read input data. Line: {}").format(','.join(row))) # force to split last item (hdop & checksum) row[-1], newitem = row[-1].split('*', 1) row.append('*' + newitem) # compute ader_microSvh try: ader = int(row[3]) * 0.0028571429 except ValueError: ader = -1 row.insert(0, ader) # compute local time (from datetime) try: time_local = datetime2localtime(row[3]) except ValueError: time_local = self.tr("unknown") row.insert(1, time_local) # create new feature fet = QgsFeature() # set coordinates y = coords_float(row[9], row[10]) x = coords_float(row[11], row[12]) fet.setGeometry(QgsGeometry.fromPoint(QgsPoint(x, y))) # set attributes fet.setAttributes(row) # add new feature into layer self._provider.addFeatures([fet])
def testQgsLineStringRepr(self): ls = QgsLineString([QgsPoint(10, 2), QgsPoint(10, 1), QgsPoint(5, 1)]) self.assertEqual(ls.__repr__(), '<QgsLineString: LineString (10 2, 10 1, 5 1)>')
def processAlgorithm(self, progress): layer = dataobjects.getObjectFromUri(self.getParameterValue( self.INPUT)) fields = [ QgsField('POINTA', QVariant.Double, '', 24, 15), QgsField('POINTB', QVariant.Double, '', 24, 15), QgsField('POINTC', QVariant.Double, '', 24, 15) ] writer = self.getOutputFromName(self.OUTPUT).getVectorWriter( fields, QgsWkbTypes.Polygon, layer.crs()) pts = [] ptDict = {} ptNdx = -1 c = voronoi.Context() features = vector.features(layer) total = 100.0 / len(features) for current, inFeat in enumerate(features): geom = QgsGeometry(inFeat.geometry()) if geom.isEmpty(): continue if geom.isMultipart(): points = geom.asMultiPoint() else: points = [geom.asPoint()] for n, point in enumerate(points): x = point.x() y = point.y() pts.append((x, y)) ptNdx += 1 ptDict[ptNdx] = (inFeat.id(), n) progress.setPercentage(int(current * total)) if len(pts) < 3: raise GeoAlgorithmExecutionException( self.tr('Input file should contain at least 3 points. Choose ' 'another file and try again.')) uniqueSet = set(item for item in pts) ids = [pts.index(item) for item in uniqueSet] sl = voronoi.SiteList([voronoi.Site(*i) for i in uniqueSet]) c.triangulate = True voronoi.voronoi(sl, c) triangles = c.triangles feat = QgsFeature() total = 100.0 / len(triangles) for current, triangle in enumerate(triangles): indicies = list(triangle) indicies.append(indicies[0]) polygon = [] attrs = [] step = 0 for index in indicies: fid, n = ptDict[ids[index]] request = QgsFeatureRequest().setFilterFid(fid) inFeat = next(layer.getFeatures(request)) geom = QgsGeometry(inFeat.geometry()) if geom.isMultipart(): point = QgsPoint(geom.asMultiPoint()[n]) else: point = QgsPoint(geom.asPoint()) polygon.append(point) if step <= 3: attrs.append(ids[index]) step += 1 feat.setAttributes(attrs) geometry = QgsGeometry().fromPolygon([polygon]) feat.setGeometry(geometry) writer.addFeature(feat) progress.setPercentage(int(current * total)) del writer
def processAlgorithm(self, progress): extent = self.getParameterValue(self.EXTENT).split(',') xSpace = self.getParameterValue(self.STEP_X) ySpace = self.getParameterValue(self.STEP_Y) bbox = QgsRectangle(float(extent[0]), float(extent[2]), float(extent[1]), float(extent[3])) mapCRS = iface.mapCanvas().mapSettings().destinationCrs() fields = QgsFields() fields.append(QgsField('id', QVariant.Int, '', 10, 0)) fields.append(QgsField('coord', QVariant.Double, '', 24, 15)) fieldCount = 2 writer = self.getOutputFromName(self.OUTPUT).getVectorWriter( fields, QgsWkbTypes.LineString, mapCRS) feat = QgsFeature() feat.initAttributes(fieldCount) feat.setFields(fields) geom = QgsGeometry() idVar = 0 count = 0 count_max = (bbox.yMaximum() - bbox.yMinimum()) / ySpace count_update = count_max * 0.10 y = bbox.yMaximum() while y >= bbox.yMinimum(): pt1 = QgsPoint(bbox.xMinimum(), y) pt2 = QgsPoint(bbox.xMaximum(), y) line = [pt1, pt2] feat.setGeometry(geom.fromPolyline(line)) feat.setAttribute(0, idVar) feat.setAttribute(1, y) writer.addFeature(feat) y = y - ySpace idVar += 1 count += 1 if int(math.fmod(count, count_update)) == 0: progress.setPercentage(int(count / count_max * 50)) progress.setPercentage(50) # counters for progressbar - update every 5% count = 0 count_max = (bbox.xMaximum() - bbox.xMinimum()) / xSpace count_update = count_max * 0.10 x = bbox.xMinimum() while x <= bbox.xMaximum(): pt1 = QgsPoint(x, bbox.yMaximum()) pt2 = QgsPoint(x, bbox.yMinimum()) line = [pt1, pt2] feat.setGeometry(geom.fromPolyline(line)) feat.setAttribute(0, idVar) feat.setAttribute(1, x) writer.addFeature(feat) x = x + xSpace idVar += 1 count += 1 if int(math.fmod(count, count_update)) == 0: progress.setPercentage(50 + int(count / count_max * 50)) del writer
def testJSONExporter(self): """ test converting features to GeoJSON """ fields = QgsFields() fields.append(QgsField("name", QVariant.String)) fields.append(QgsField("cost", QVariant.Double)) fields.append(QgsField("population", QVariant.Int)) feature = QgsFeature(fields, 5) feature.setGeometry(QgsGeometry(QgsPoint(5, 6))) feature.setAttributes(['Valsier Peninsula', 6.8, 198]) exporter = QgsJsonExporter() expected = """{ "type":"Feature", "id":5, "geometry": {"type": "Point", "coordinates": [5, 6]}, "properties":{ "name":"Valsier Peninsula", "cost":6.8, "population":198 } }""" self.assertEqual(exporter.exportFeature(feature), expected) # test with linestring for bbox inclusion l = QgsLineString() l.setPoints([QgsPoint(5, 6), QgsPoint(15, 16)]) feature.setGeometry(QgsGeometry(QgsLineString(l))) expected = """{ "type":"Feature", "id":5, "bbox":[5, 6, 15, 16], "geometry": {"type": "LineString", "coordinates": [ [5, 6], [15, 16]]}, "properties":{ "name":"Valsier Peninsula", "cost":6.8, "population":198 } }""" self.assertEqual(exporter.exportFeature(feature), expected) # test that precision is respected feature.setGeometry(QgsGeometry(QgsPoint(5.444444444, 6.333333333))) exporter.setPrecision(3) self.assertEqual(exporter.precision(), 3) expected = """{ "type":"Feature", "id":5, "geometry": {"type": "Point", "coordinates": [5.444, 6.333]}, "properties":{ "name":"Valsier Peninsula", "cost":6.8, "population":198 } }""" self.assertEqual(exporter.exportFeature(feature), expected) feature.setGeometry(QgsGeometry(QgsPoint(5, 6))) exporter.setPrecision(17) # test that attribute subset is respected exporter.setAttributes([0, 2]) self.assertEqual(exporter.attributes(), [0, 2]) expected = """{ "type":"Feature", "id":5, "geometry": {"type": "Point", "coordinates": [5, 6]}, "properties":{ "name":"Valsier Peninsula", "population":198 } }""" self.assertEqual(exporter.exportFeature(feature), expected) exporter.setAttributes([1]) self.assertEqual(exporter.attributes(), [1]) expected = """{ "type":"Feature", "id":5, "geometry": {"type": "Point", "coordinates": [5, 6]}, "properties":{ "cost":6.8 } }""" self.assertEqual(exporter.exportFeature(feature), expected) exporter.setAttributes([]) # text excluding attributes exporter.setExcludedAttributes([1]) self.assertEqual(exporter.excludedAttributes(), [1]) expected = """{ "type":"Feature", "id":5, "geometry": {"type": "Point", "coordinates": [5, 6]}, "properties":{ "name":"Valsier Peninsula", "population":198 } }""" self.assertEqual(exporter.exportFeature(feature), expected) exporter.setExcludedAttributes([1, 2]) self.assertEqual(exporter.excludedAttributes(), [1, 2]) expected = """{ "type":"Feature", "id":5, "geometry": {"type": "Point", "coordinates": [5, 6]}, "properties":{ "name":"Valsier Peninsula" } }""" self.assertEqual(exporter.exportFeature(feature), expected) exporter.setExcludedAttributes([0, 1, 2]) self.assertEqual(exporter.excludedAttributes(), [0, 1, 2]) expected = """{ "type":"Feature", "id":5, "geometry": {"type": "Point", "coordinates": [5, 6]}, "properties":null }""" self.assertEqual(exporter.exportFeature(feature), expected) # test that excluded attributes take precedence over included exporter.setAttributes([1, 2]) exporter.setExcludedAttributes([0, 1]) expected = """{ "type":"Feature", "id":5, "geometry": {"type": "Point", "coordinates": [5, 6]}, "properties":{ "population":198 } }""" self.assertEqual(exporter.exportFeature(feature), expected) exporter.setAttributes([]) exporter.setExcludedAttributes([]) # test excluding geometry exporter.setIncludeGeometry(False) self.assertEqual(exporter.includeGeometry(), False) feature.setGeometry(QgsGeometry(QgsLineString(l))) expected = """{ "type":"Feature", "id":5, "geometry":null, "properties":{ "name":"Valsier Peninsula", "cost":6.8, "population":198 } }""" self.assertEqual(exporter.exportFeature(feature), expected) exporter.setIncludeGeometry(True) feature.setGeometry(QgsGeometry(QgsPoint(5, 6))) # test excluding attributes exporter.setIncludeAttributes(False) self.assertEqual(exporter.includeAttributes(), False) expected = """{ "type":"Feature", "id":5, "geometry": {"type": "Point", "coordinates": [5, 6]}, "properties":null }""" self.assertEqual(exporter.exportFeature(feature), expected) exporter.setIncludeGeometry(False) expected = """{ "type":"Feature", "id":5, "geometry":null, "properties":null }""" self.assertEqual(exporter.exportFeature(feature), expected) exporter.setIncludeAttributes(True) # test overriding ID expected = """{ "type":"Feature", "id":29, "geometry":null, "properties":{ "name":"Valsier Peninsula", "cost":6.8, "population":198 } }""" self.assertEqual(exporter.exportFeature(feature, id=29), expected) # test injecting extra attributes expected = """{ "type":"Feature", "id":5, "geometry":null, "properties":{ "name":"Valsier Peninsula", "cost":6.8, "population":198, "extra":"val1", "extra2":2 } }""" self.assertEqual( exporter.exportFeature(feature, extraProperties={ "extra": "val1", "extra2": 2 }), expected) exporter.setIncludeAttributes(False) expected = """{ "type":"Feature", "id":5, "geometry":null, "properties":{ "extra":"val1", "extra2":{"nested_map":5, "nested_map2":"val"}, "extra3":[1,2,3] } }""" expected2 = """{ "type":"Feature", "id":5, "geometry":null, "properties":{ "extra":"val1", "extra2":{"nested_map":5,"nested_map2":"val"}, "extra3":[1,2,3] } }""" exp_f = exporter.exportFeature(feature, extraProperties={ "extra": "val1", "extra2": { "nested_map": 5, "nested_map2": "val" }, "extra3": [1, 2, 3] }) self.assertTrue(exp_f == expected or exp_f == expected2) exporter.setIncludeGeometry(True)
def processAlgorithm(self, feedback): layer = dataobjects.getObjectFromUri( self.getParameterValue(self.INPUT_VECTOR)) startPoint = self.getParameterValue(self.START_POINT) strategy = self.getParameterValue(self.STRATEGY) travelCost = self.getParameterValue(self.TRAVEL_COST) directionFieldName = self.getParameterValue(self.DIRECTION_FIELD) forwardValue = self.getParameterValue(self.VALUE_FORWARD) backwardValue = self.getParameterValue(self.VALUE_BACKWARD) bothValue = self.getParameterValue(self.VALUE_BOTH) defaultDirection = self.getParameterValue(self.DEFAULT_DIRECTION) bothValue = self.getParameterValue(self.VALUE_BOTH) defaultDirection = self.getParameterValue(self.DEFAULT_DIRECTION) speedFieldName = self.getParameterValue(self.SPEED_FIELD) defaultSpeed = self.getParameterValue(self.DEFAULT_SPEED) tolerance = self.getParameterValue(self.TOLERANCE) tmp = startPoint.split(',') startPoint = QgsPoint(float(tmp[0]), float(tmp[1])) directionField = -1 if directionFieldName is not None: directionField = layer.fields().lookupField(directionFieldName) speedField = -1 if speedFieldName is not None: speedField = layer.fields().lookupField(speedFieldName) director = QgsVectorLayerDirector(layer, directionField, forwardValue, backwardValue, bothValue, defaultDirection) distUnit = iface.mapCanvas().mapSettings().destinationCrs().mapUnits() multiplier = QgsUnitTypes.fromUnitToUnitFactor( distUnit, QgsUnitTypes.DistanceMeters) if strategy == 0: strategy = QgsNetworkDistanceStrategy() else: strategy = QgsNetworkSpeedStrategy(speedField, defaultSpeed, multiplier * 1000.0 / 3600.0) director.addStrategy(strategy) builder = QgsGraphBuilder( iface.mapCanvas().mapSettings().destinationCrs(), True, tolerance) feedback.pushInfo(self.tr('Building graph...')) snappedPoints = director.makeGraph(builder, [startPoint]) feedback.pushInfo(self.tr('Calculating service area...')) graph = builder.graph() idxStart = graph.findVertex(snappedPoints[0]) tree, cost = QgsGraphAnalyzer.dijkstra(graph, idxStart, 0) vertices = [] for i, v in enumerate(cost): if v > travelCost and tree[i] != -1: vertexId = graph.edge(tree[i]).outVertex() if cost[vertexId] <= travelCost: vertices.append(i) upperBoundary = [] lowerBoundary = [] for i in vertices: upperBoundary.append( graph.vertex(graph.edge(tree[i]).inVertex()).point()) lowerBoundary.append( graph.vertex(graph.edge(tree[i]).outVertex()).point()) feedback.pushInfo(self.tr('Writing results...')) fields = QgsFields() fields.append(QgsField('type', QVariant.String, '', 254, 0)) fields.append(QgsField('start', QVariant.String, '', 254, 0)) feat = QgsFeature() feat.setFields(fields) geomUpper = QgsGeometry.fromMultiPoint(upperBoundary) geomLower = QgsGeometry.fromMultiPoint(lowerBoundary) writer = self.getOutputFromName(self.OUTPUT_POINTS).getVectorWriter( fields, QgsWkbTypes.MultiPoint, layer.crs()) feat.setGeometry(geomUpper) feat['type'] = 'upper' feat['start'] = startPoint.toString() writer.addFeature(feat) feat.setGeometry(geomLower) feat['type'] = 'lower' feat['start'] = startPoint.toString() writer.addFeature(feat) del writer upperBoundary.append(startPoint) lowerBoundary.append(startPoint) geomUpper = QgsGeometry.fromMultiPoint(upperBoundary) geomLower = QgsGeometry.fromMultiPoint(lowerBoundary) writer = self.getOutputFromName(self.OUTPUT_POLYGON).getVectorWriter( fields, QgsWkbTypes.Polygon, layer.crs()) geom = geomUpper.convexHull() feat.setGeometry(geom) feat['type'] = 'upper' feat['start'] = startPoint.toString() writer.addFeature(feat) geom = geomLower.convexHull() feat.setGeometry(geom) feat['type'] = 'lower' feat['start'] = startPoint.toString() writer.addFeature(feat) del writer
def testExportFeatures(self): """ Test exporting feature collections """ fields = QgsFields() fields.append(QgsField("name", QVariant.String)) fields.append(QgsField("cost", QVariant.Double)) fields.append(QgsField("population", QVariant.Int)) feature = QgsFeature(fields, 5) feature.setGeometry(QgsGeometry(QgsPoint(5, 6))) feature.setAttributes(['Valsier Peninsula', 6.8, 198]) exporter = QgsJsonExporter() # single feature expected = """{ "type": "FeatureCollection", "features":[ { "type":"Feature", "id":5, "geometry": {"type": "Point", "coordinates": [5, 6]}, "properties":{ "name":"Valsier Peninsula", "cost":6.8, "population":198 } } ]}""" self.assertEqual(exporter.exportFeatures([feature]), expected) # multiple features feature2 = QgsFeature(fields, 6) feature2.setGeometry(QgsGeometry(QgsPoint(7, 8))) feature2.setAttributes(['Henry Gale Island', 9.7, 38]) expected = """{ "type": "FeatureCollection", "features":[ { "type":"Feature", "id":5, "geometry": {"type": "Point", "coordinates": [5, 6]}, "properties":{ "name":"Valsier Peninsula", "cost":6.8, "population":198 } }, { "type":"Feature", "id":6, "geometry": {"type": "Point", "coordinates": [7, 8]}, "properties":{ "name":"Henry Gale Island", "cost":9.7, "population":38 } } ]}""" self.assertEqual(exporter.exportFeatures([feature, feature2]), expected)
def processAlgorithm(self, parameters, context, feedback): spacing = self.parameterAsDouble(parameters, self.SPACING, context) inset = self.parameterAsDouble(parameters, self.INSET, context) randomize = self.parameterAsBool(parameters, self.RANDOMIZE, context) isSpacing = self.parameterAsBool(parameters, self.IS_SPACING, context) crs = self.parameterAsCrs(parameters, self.CRS, context) extent = self.parameterAsExtent(parameters, self.EXTENT, context, crs) fields = QgsFields() fields.append(QgsField('id', QVariant.Int, '', 10, 0)) (sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context, fields, QgsWkbTypes.Point, crs) if sink is None: raise QgsProcessingException( self.invalidSinkError(parameters, self.OUTPUT)) if randomize: seed() area = extent.width() * extent.height() if isSpacing: pSpacing = spacing else: pSpacing = sqrt(area / spacing) f = QgsFeature() f.initAttributes(1) f.setFields(fields) count = 0 id = 0 total = 100.0 / (area / pSpacing) y = extent.yMaximum() - inset extent_geom = QgsGeometry.fromRect(extent) extent_engine = QgsGeometry.createGeometryEngine( extent_geom.constGet()) extent_engine.prepareGeometry() while y >= extent.yMinimum(): x = extent.xMinimum() + inset while x <= extent.xMaximum(): if feedback.isCanceled(): break if randomize: geom = QgsGeometry( QgsPoint( uniform(x - (pSpacing / 2.0), x + (pSpacing / 2.0)), uniform(y - (pSpacing / 2.0), y + (pSpacing / 2.0)))) else: geom = QgsGeometry(QgsPoint(x, y)) if extent_engine.intersects(geom.constGet()): f.setAttributes([id]) f.setGeometry(geom) sink.addFeature(f, QgsFeatureSink.FastInsert) x += pSpacing id += 1 count += 1 feedback.setProgress(int(count * total)) y = y - pSpacing return {self.OUTPUT: dest_id}
def _hexagonGrid(self, writer, width, height, originX, originY, hSpacing, vSpacing, hOverlay, vOverlay, feedback): ft = QgsFeature() # To preserve symmetry, hspacing is fixed relative to vspacing xVertexLo = 0.288675134594813 * vSpacing xVertexHi = 0.577350269189626 * vSpacing hSpacing = xVertexLo + xVertexHi hOverlay = hSpacing - hOverlay if hOverlay < 0: raise GeoAlgorithmExecutionException( self. tr('To preserve symmetry, hspacing is fixed relative to vspacing\n \ hspacing is fixed at: {0} and hoverlay is fixed at: {1}\n \ hoverlay cannot be negative. Increase hoverlay.' ).format(hSpacing, hOverlay)) halfVSpacing = vSpacing / 2.0 columns = int(math.ceil(float(width) / hOverlay)) rows = int(math.ceil(float(height) / (vSpacing - vOverlay))) cells = rows * columns count_update = cells * 0.05 id = 1 count = 0 for col in range(columns): # (column + 1) and (row + 1) calculation is used to maintain # topology between adjacent shapes and avoid overlaps/holes # due to rounding errors x1 = originX + (col * hOverlay) # far left x2 = x1 + (xVertexHi - xVertexLo) # left x3 = originX + (col * hOverlay) + hSpacing # right x4 = x3 + (xVertexHi - xVertexLo) # far right for row in range(rows): if (col % 2) == 0: y1 = originY + (row * vOverlay) - ( ((row * 2) + 0) * halfVSpacing) # hi y2 = originY + (row * vOverlay) - ( ((row * 2) + 1) * halfVSpacing) # mid y3 = originY + (row * vOverlay) - ( ((row * 2) + 2) * halfVSpacing) # lo else: y1 = originY + (row * vOverlay) - ( ((row * 2) + 1) * halfVSpacing) # hi y2 = originY + (row * vOverlay) - ( ((row * 2) + 2) * halfVSpacing) # mid y3 = originY + (row * vOverlay) - ( ((row * 2) + 3) * halfVSpacing) # lo polyline = [] polyline.append(QgsPoint(x1, y2)) polyline.append(QgsPoint(x2, y1)) polyline.append(QgsPoint(x3, y1)) polyline.append(QgsPoint(x4, y2)) polyline.append(QgsPoint(x3, y3)) polyline.append(QgsPoint(x2, y3)) polyline.append(QgsPoint(x1, y2)) ft.setGeometry(QgsGeometry.fromPolygon([polyline])) ft.setAttributes([x1, y1, x4, y3, id]) writer.addFeature(ft) id += 1 count += 1 if int(math.fmod(count, count_update)) == 0: feedback.setProgress(int(count / cells * 100))
def processAlgorithm(self, parameters, context, feedback): source = self.parameterAsSource(parameters, self.INPUT, context) if source is None: raise QgsProcessingException( self.invalidSourceError(parameters, self.INPUT)) fields = source.fields() x_field_index = fields.lookupField( self.parameterAsString(parameters, self.XFIELD, context)) y_field_index = fields.lookupField( self.parameterAsString(parameters, self.YFIELD, context)) z_field_index = -1 if self.parameterAsString(parameters, self.ZFIELD, context): z_field_index = fields.lookupField( self.parameterAsString(parameters, self.ZFIELD, context)) m_field_index = -1 if self.parameterAsString(parameters, self.MFIELD, context): m_field_index = fields.lookupField( self.parameterAsString(parameters, self.MFIELD, context)) wkb_type = QgsWkbTypes.Point if z_field_index >= 0: wkb_type = QgsWkbTypes.addZ(wkb_type) if m_field_index >= 0: wkb_type = QgsWkbTypes.addM(wkb_type) target_crs = self.parameterAsCrs(parameters, self.TARGET_CRS, context) (sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context, fields, wkb_type, target_crs) if sink is None: raise QgsProcessingException( self.invalidSinkError(parameters, self.OUTPUT)) request = QgsFeatureRequest().setFlags(QgsFeatureRequest.NoGeometry) features = source.getFeatures( QgsFeatureRequest(), QgsProcessingFeatureSource.FlagSkipGeometryValidityChecks) total = 100.0 / source.featureCount() if source.featureCount() else 0 for current, feature in enumerate(features): if feedback.isCanceled(): break feedback.setProgress(int(current * total)) attrs = feature.attributes() try: x = float(attrs[x_field_index]) y = float(attrs[y_field_index]) point = QgsPoint(x, y) if z_field_index >= 0: try: point.addZValue(float(attrs[z_field_index])) except: point.addZValue(0.0) if m_field_index >= 0: try: point.addMValue(float(attrs[m_field_index])) except: point.addMValue(0.0) feature.setGeometry(QgsGeometry(point)) except: pass # no geometry sink.addFeature(feature) return {self.OUTPUT: dest_id}
def setUp(self): self.mPoint = QgsPoint(10.0, 10.0)
def testQgsCircleRepr(self): c = QgsCircle(QgsPoint(1, 1), 2.0) self.assertEqual(c.__repr__(), '<QgsCircle: Circle (Center: Point (1 1), Radius: 2, Azimuth: 0)>')
def testQgsCurvepolygonRepr(self): cp = QgsCurvePolygon() cs = QgsCircularString(QgsPoint(1, 10), QgsPoint(2, 11), QgsPoint(1, 10)) cp.setExteriorRing(cs) self.assertEqual(cp.__repr__(), '<QgsCurvePolygon: CurvePolygon (CircularString (1 10, 2 11, 1 10))>')
def testQgsCompoundcurveRepr(self): cs = QgsCircularString(QgsPoint(1, 2), QgsPoint(2, 3), QgsPoint(3, 4)) cc = QgsCompoundCurve() cc.addCurve(cs) self.assertEqual(cc.__repr__(), '<QgsCompoundCurve: CompoundCurve (CircularString (1 2, 2 3, 3 4))>')
def testAreaMeasureAndUnits(self): """Test a variety of area measurements in different CRS and ellipsoid modes, to check that the calculated areas and units are always consistent """ da = QgsDistanceArea() da.setSourceCrs(3452) da.setEllipsoidalMode(False) da.setEllipsoid("NONE") polygon = QgsGeometry.fromPolygon([[ QgsPoint(0, 0), QgsPoint(1, 0), QgsPoint(1, 1), QgsPoint(2, 1), QgsPoint(2, 2), QgsPoint(0, 2), QgsPoint(0, 0), ]]) # We check both the measured area AND the units, in case the logic regarding # ellipsoids and units changes in future area = da.measureArea(polygon) units = da.areaUnits() print(("measured {} in {}".format(area, QgsUnitTypes.toString(units)))) assert ((abs(area - 3.0) < 0.00000001 and units == QgsUnitTypes.AreaSquareDegrees) or (abs(area - 37176087091.5) < 0.1 and units == QgsUnitTypes.AreaSquareMeters)) da.setEllipsoid("WGS84") area = da.measureArea(polygon) units = da.areaUnits() print(("measured {} in {}".format(area, QgsUnitTypes.toString(units)))) assert ((abs(area - 3.0) < 0.00000001 and units == QgsUnitTypes.AreaSquareDegrees) or (abs(area - 37176087091.5) < 0.1 and units == QgsUnitTypes.AreaSquareMeters)) da.setEllipsoidalMode(True) area = da.measureArea(polygon) units = da.areaUnits() print(("measured {} in {}".format(area, QgsUnitTypes.toString(units)))) # should always be in Meters Squared self.assertAlmostEqual(area, 37416879192.9, delta=0.1) self.assertEqual(units, QgsUnitTypes.AreaSquareMeters) # test converting the resultant area area = da.convertAreaMeasurement(area, QgsUnitTypes.AreaSquareMiles) self.assertAlmostEqual(area, 14446.7378, delta=0.001) # now try with a source CRS which is in feet polygon = QgsGeometry.fromPolygon([[ QgsPoint(1850000, 4423000), QgsPoint(1851000, 4423000), QgsPoint(1851000, 4424000), QgsPoint(1852000, 4424000), QgsPoint(1852000, 4425000), QgsPoint(1851000, 4425000), QgsPoint(1850000, 4423000) ]]) da.setSourceCrs(27469) da.setEllipsoidalMode(False) # measurement should be in square feet area = da.measureArea(polygon) units = da.areaUnits() print(("measured {} in {}".format(area, QgsUnitTypes.toString(units)))) self.assertAlmostEqual(area, 2000000, delta=0.001) self.assertEqual(units, QgsUnitTypes.AreaSquareFeet) # test converting the resultant area area = da.convertAreaMeasurement(area, QgsUnitTypes.AreaSquareYards) self.assertAlmostEqual(area, 222222.2222, delta=0.001) da.setEllipsoidalMode(True) # now should be in Square Meters again area = da.measureArea(polygon) units = da.areaUnits() print(("measured {} in {}".format(area, QgsUnitTypes.toString(units)))) self.assertAlmostEqual(area, 184149.37, delta=1.0) self.assertEqual(units, QgsUnitTypes.AreaSquareMeters) # test converting the resultant area area = da.convertAreaMeasurement(area, QgsUnitTypes.AreaSquareYards) self.assertAlmostEqual(area, 220240.8172549, delta=1.0)