def _calc_north(self): extent = self.canvas.extent() if self.canvas.layerCount() == 0 or extent.isEmpty(): print "No layers or extent" return 0 outcrs = self.canvas.mapSettings().destinationCrs() if outcrs.isValid() and not outcrs.geographicFlag(): crs = QgsCoordinateReferenceSystem() crs.createFromOgcWmsCrs("EPSG:4326") transform = QgsCoordinateTransform(outcrs, crs) p1 = QgsPoint(extent.center()) p2 = QgsPoint(p1.x(), p1.y() + extent.height() * 0.25) try: pp1 = transform.transform(p1) pp2 = transform.transform(p2) except QgsCsException: roam.utils.warning("North arrow. Error transforming.") return None area = QgsDistanceArea() area.setEllipsoid(crs.ellipsoidAcronym()) area.setEllipsoidalMode(True) area.setSourceCrs(crs) distance, angle, _ = area.computeDistanceBearing(pp1, pp2) angle = math.degrees(angle) return angle else: return 0
def _calc_north(self): extent = self.canvas.extent() if self.canvas.layerCount() == 0 or extent.isEmpty(): return 0 outcrs = self.canvas.mapSettings().destinationCrs() if outcrs.isValid() and not outcrs.geographicFlag(): crs = QgsCoordinateReferenceSystem() crs.createFromOgcWmsCrs("EPSG:4326") transform = QgsCoordinateTransform(outcrs, crs) p1 = QgsPoint(extent.center()) p2 = QgsPoint(p1.x(), p1.y() + extent.height() * 0.25) try: pp1 = transform.transform(p1) pp2 = transform.transform(p2) except QgsCsException: roam.utils.warning("North arrow. Error transforming.") return None area = QgsDistanceArea() area.setEllipsoid(crs.ellipsoidAcronym()) area.setEllipsoidalMode(True) area.setSourceCrs(crs) distance, angle, _ = area.computeDistanceBearing(pp1, pp2) angle = math.degrees(angle) return angle else: return 0
""" from qgis.core import QgsCoordinateReferenceSystem from osgeo import osr if __name__ == '__console__': print("-----------------------------------------------\n\n") # PostGIS SRID 4326 is allocated for WGS84 # If not specified otherwise in second parameter, PostGIS SRID is used by default. crs = QgsCoordinateReferenceSystem(4326, QgsCoordinateReferenceSystem.PostgisCrsId) print("Valid: ", crs.isValid()) print("QGIS CRS ID:", crs.srsid()) print("EPSG ID:", crs.authid()) print("Description:", crs.description()) print("Projection Acronym:", crs.projectionAcronym()) print("Ellipsoid Acronym:", crs.ellipsoidAcronym()) print("Proj4 String:", crs.toProj4()) # check whether it's geographic or projected coordinate system print("Is geographic:", crs.geographicFlag()) # check type of map units in this CRS (values defined in QGis::units enum) print("Map units:", crs.mapUnits()) print("-----------------------------------------------\n\n") wkt = '''GEOGCS["WGS84", DATUM["WGS84", SPHEROID["WGS84", 6378137.0, 298.257223563]], PRIMEM["Greenwich", 0.0], UNIT["degree", 0.017453292519943295], AXIS["Longitude", EAST], AXIS["Latitude", NORTH]]''' crs = QgsCoordinateReferenceSystem(wkt) print("Valid: ", crs.isValid()) print("QGIS CRS ID:", crs.srsid()) print("EPSG ID:", crs.authid())
def processAlgorithm(self, parameters, context, feedback): # get input variables source = self.parameterAsSource(parameters, self.INPUT_LINE, context) swath_angle_field = self.parameterAsString(parameters, self.SWATH_ANGLE_FIELD, context) swath_angle_fallback = self.parameterAsInt(parameters, self.SWATH_ANGLE, context) raster_layer = self.parameterAsRasterLayer(parameters, self.INPUT_RASTER, context) band_number = self.parameterAsInt(parameters, self.BAND, context) # copy of the field name for later swath_angle_field_name = swath_angle_field # set new default values in config feedback.pushConsoleInfo( self.tr(f'Storing new default settings in config...')) self.config.set(self.module, 'swath_angle', swath_angle_fallback) # get crs's crs_line = source.sourceCrs() crs_raster = raster_layer.crs() # get project transform_context transform_context = context.transformContext() # CRS transformation to "WGS84/World Mercator" for MBES coverage operations crs_mercator = QgsCoordinateReferenceSystem('EPSG:3395') trans_line2merc = QgsCoordinateTransform(crs_line, crs_mercator, transform_context) # CRS transformation to raster layer CRS for depth sampling trans_merc2raster = QgsCoordinateTransform(crs_mercator, crs_raster, transform_context) trans_line2raster = QgsCoordinateTransform(crs_line, crs_raster, transform_context) crs_geo = QgsCoordinateReferenceSystem('EPSG:4326') trans_line2geo = QgsCoordinateTransform(crs_line, crs_geo, transform_context) # initialize distance tool da = QgsDistanceArea() da.setSourceCrs(crs_mercator, transform_context) da.setEllipsoid(crs_mercator.ellipsoidAcronym()) # empty lists for unioned buffers buffer_union_list = [] # get (selected) features features = source.getFeatures() # feedback total = 100.0 / source.featureCount() if source.featureCount() else 0 # loop through features feedback.pushConsoleInfo(self.tr(f'Densifying line features...')) feedback.pushConsoleInfo(self.tr(f'Extracting vertices...')) feedback.pushConsoleInfo(self.tr(f'Sampling values...')) feedback.pushConsoleInfo( self.tr(f'Computing depth dependent buffers...')) feedback.pushConsoleInfo(self.tr(f'Unionizing output features...')) for feature_id, feature in enumerate(features): # get feature geometry feature_geom = feature.geometry() # check for LineString geometry if QgsWkbTypes.isSingleType(feature_geom.wkbType()): # get list of vertices vertices_list = feature_geom.asPolyline() vertices_list = [vertices_list] # check for MultiLineString geometry elif QgsWkbTypes.isMultiType(feature_geom.wkbType()): # get list of list of vertices per multiline part vertices_list = feature_geom.asMultiPolyline() for part_id, vertices in enumerate(vertices_list): # transform vertices CRS to "WGS 84 / World Mercator" vertices_t = [] for vertex in vertices: vertex_trans = trans_line2merc.transform(vertex) vertices_t.append(vertex_trans) # get centroid as point for UTM zone selection centroid = feature_geom.centroid() centroid_point = centroid.asPoint() # check if centroid needs to be transformed to get x/y in lon/lat if not crs_line.isGeographic(): centroid_point = trans_line2geo.transform(centroid_point) # get UTM zone of feature for buffering lat, lon = centroid_point.y(), centroid_point.x() crs_utm = self.get_UTM_zone(lat, lon) # create back and forth transformations for later trans_merc2utm = QgsCoordinateTransform( crs_mercator, crs_utm, transform_context) trans_utm2line = QgsCoordinateTransform( crs_utm, crs_line, transform_context) # split line into segments for segment_id in range(len(vertices_t) - 1): # ===== (1) DENSIFY LINE VERTICES ===== # create new Polyline geometry for line segment segment_geom = QgsGeometry.fromPolylineXY( [vertices_t[segment_id], vertices_t[segment_id + 1]]) # measure ellipsoidal distance between start and end vertex segment_length = da.measureLength(segment_geom) # calculate number of extra vertices to insert extra_vertices = int(segment_length // self.vertex_distance) # create additional vertices along line segment segment_geom_dense = segment_geom.densifyByCount( extra_vertices - 1) # initialize additional fields feature_id_field = QgsField('feature_id', QVariant.Int, 'Integer', len=5, prec=0) part_id_field = QgsField('part_id', QVariant.Int, 'Integer', len=5, prec=0) segment_id_field = QgsField('segment_id', QVariant.Int, 'Integer', len=5, prec=0) # list for segment buffers buffer_list = [] # loop over all vertices of line segment for i, vertex in enumerate(segment_geom_dense.vertices()): # === CREATE POINT FEATURE === # initialize feature and set geometry fpoint = QgsFeature() fpoint.setGeometry(vertex) # sample bathymetry grid # get point geometry (as QgsPointXY) fpoint_geom = fpoint.geometry() pointXY = fpoint_geom.asPoint() # transform point to raster CRS pointXY_raster = trans_merc2raster.transform( pointXY) #trans_line2raster.transform(pointXY) # sample raster at point location pointXY_depth, error_check = raster_layer.dataProvider( ).sample(pointXY_raster, 1) # check if valid depth was sampled, otherwise skip point if error_check == False: continue # create depth-dependant buffer: # check if swath_angle field is selected if swath_angle_field != '': # get value from field swath_angle_field_value = feature.attribute( swath_angle_field) # check if value is set (not NOLL) if swath_angle_field_value == None: # if NULL, set fallback swath_angle = swath_angle_fallback else: # othervise take value from field swath_angle = swath_angle_field_value # or if no field was selected use fallback value right away else: swath_angle = swath_angle_fallback # calculate buffer radius (swath width from depth and swath angle) buffer_radius = round( tan(radians(swath_angle / 2)) * abs(pointXY_depth), 0) # transform point from mercator zu UTM fpoint_geom.transform(trans_merc2utm) # create buffer buffer = fpoint_geom.buffer(buffer_radius, 10) # transform buffer back to initial input CRS buffer.transform(trans_utm2line) # store buffer in list buffer_list.append(buffer) # check if any points in this segment have been sampled if buffer_list == []: continue # dissolve point buffers of line segment: # dissolve all polygons based on line vertices into single feature buffer_union = QgsGeometry().unaryUnion(buffer_list) # set fields and attributes: # empty fields buffer_fields = QgsFields() # loop through line feature fields for field in feature.fields(): # and append all but the 'fid' field (if it exists) if field.name() != 'fid': buffer_fields.append(field) # append extra buffer fields (intial feature id, part id and segment id for buffer_field in [ feature_id_field, part_id_field, segment_id_field ]: buffer_fields.append(buffer_field) # if no input swath_angle field was selected on input, create one if swath_angle_field == '': swath_angle_field_name = 'mbes_swath_angle' buffer_fields.append( QgsField(swath_angle_field_name, QVariant.Int, 'Integer', len=5, prec=0)) # initialize polygon feature fpoly = QgsFeature(buffer_fields) # set attributes for polygon feature for field in feature.fields(): # ignore 'fid' again if field.name() != 'fid': # set attribute from feature to buffer fpoly.setAttribute(field.name(), feature.attribute(field.name())) # set addtional buffer fields fpoly.setAttribute('feature_id', feature_id) fpoly.setAttribute('part_id', part_id) fpoly.setAttribute('segment_id', segment_id) fpoly.setAttribute(swath_angle_field_name, swath_angle) # set geometry fpoly.setGeometry(buffer_union) # store segment coverage polygon if fpoly.hasGeometry() and fpoly.isValid(): buffer_union_list.append(fpoly) # set progess feedback.setProgress(int(feature_id * total)) # if buffer_union_list is empty, no buffer features where created if buffer_union_list == []: raise Exception( 'No depth values could be sampled from the input raster!') # creating feature sink feedback.pushConsoleInfo(self.tr(f'Creating feature sink...')) (sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context, buffer_fields, QgsWkbTypes.MultiPolygon, source.sourceCrs()) if sink is None: raise QgsProcessingException( self.invalidSinkError(parameters, self.OUTPUT)) # write coverage features to sink feedback.pushConsoleInfo(self.tr(f'Writing features...')) sink.addFeatures(buffer_union_list, QgsFeatureSink.FastInsert) # make variables accessible for post processing self.output = dest_id result = {self.OUTPUT: self.output} return result