def currentHistoryChanged(self, current, previous): self.new_geometry.reset() self.old_geometry.reset() self.tblChanges.model().removeRows() if not current.isValid(): return item = current.data(Qt.UserRole) if item is None: data = {} else: data = current.data(Qt.UserRole).getDetails() with SetLocale_CtxDec(): extent = None if data.get('new_geometry'): wkt = CreateGeometryFromJson( json.dumps(data['new_geometry']) ).ExportToWkt() geom = QgsGeometry.fromWkt( wkt ) l = QgsVectorLayer('Point?crs=epsg:4326', 'asd', 'memory') self.new_geometry.setToGeometry( geom, l ) extent = QgsRectangle(geom.boundingBox()) if data.get('old_geometry'): wkt = CreateGeometryFromJson( json.dumps(data['old_geometry']) ).ExportToWkt() geom = QgsGeometry.fromWkt( wkt ) l = QgsVectorLayer('Point?crs=epsg:4326', 'asd', 'memory') self.old_geometry.setToGeometry( geom, l ) if extent is None: extent = QgsRectangle(geom.boundingBox()) else: extent.combineExtentWith( geom.boundingBox() ) if extent is not None: extent.grow(0.01) self.mapCanvas.setExtent( extent ) self.mapCanvas.refresh() if data.get('what_attributes', []): self.tblChanges.model().insertRows( 0, data.get('what_attributes', []) )
def testRasterBlock(self): """Test raster block with extent""" path = os.path.join(unitTestDataPath(), 'landsat_4326.tif') raster_layer = QgsRasterLayer(path, 'test') self.assertTrue(raster_layer.isValid()) extent = QgsRectangle(17.94284482577178252, 30.23021770271909503, 17.94407867909909626, 30.23154272264058307) block = raster_layer.dataProvider().block(1, extent, 2, 3) self.checkBlockContents(block, [ 125.0, 125.0, 125.0, 125.0, 125.0, 124.0, ]) full_content = [ 125.0, 125.0, 125.0, 125.0, 125.0, 125.0, 125.0, 124.0, 125.0, 126.0, 127.0, 127.0, ] extent = raster_layer.extent() block = raster_layer.dataProvider().block(1, extent, 3, 4) self.checkBlockContents(block, full_content) extent = raster_layer.extent() extent.grow(-0.0001) block = raster_layer.dataProvider().block(1, extent, 3, 4) self.checkBlockContents(block, full_content) row_height = raster_layer.extent().height() / raster_layer.height() for row in range(raster_layer.height()): extent = raster_layer.extent() extent.setYMaximum(extent.yMaximum() - row_height * row) extent.setYMinimum(extent.yMaximum() - row_height) block = raster_layer.dataProvider().block(1, extent, 3, 1) self.checkBlockContents(block, full_content[row * 3:row * 3 + 3])
def jump_to(self, item): data = item.data(32) if not data: return layername, fid = data[0], data[1] layer = roam.api.utils.layer_by_name(layername) feature = layer.getFeatures(QgsFeatureRequest(fid)).next() box = feature.geometry().boundingBox() xmin, xmax, ymin, ymax = box.xMinimum(), box.xMaximum(), box.yMinimum(), box.yMaximum() xmin -= 5 xmax += 5 ymin -= 5 ymax += 5 box = QgsRectangle(xmin, ymin, xmax, ymax) box.grow(20) self.api.mainwindow.canvas.setExtent(box) self.api.mainwindow.canvas.refresh() self.api.mainwindow.showmap() RoamEvents.selectionchanged.emit({layer: [feature]})
def jump_to(self, item): data = item.data(32) if not data: return layername, fid = data[0], data[1] layer = roam.api.utils.layer_by_name(layername) feature = layer.getFeatures(QgsFeatureRequest(fid)).next() box = feature.geometry().boundingBox() xmin, xmax, ymin, ymax = box.xMinimum(), box.xMaximum(), box.yMinimum( ), box.yMaximum() xmin -= 5 xmax += 5 ymin -= 5 ymax += 5 box = QgsRectangle(xmin, ymin, xmax, ymax) box.grow(20) self.api.mainwindow.canvas.setExtent(box) self.api.mainwindow.canvas.refresh() self.api.mainwindow.showmap() RoamEvents.selectionchanged.emit({layer: [feature]})
def processAlgorithm(self, parameters, context, feedback): """ Here is where the processing itself takes place. """ grib_layerfile = self.parameterAsFile(parameters, self.GRIB, context) grib_layer = self.parameterAsLayer(parameters, self.GRIB, context) wind_ds = self.parameterAsInt(parameters, self.WIND_DATASET_INDEX, context) polar_filename = self.polar_names[self.parameterAsEnum( parameters, self.POLAR, context)] polar = Polar( os.path.join(self.polars_dir, self.polars[polar_filename])) start = self.parameterAsDateTime(parameters, self.START_TIME, context) start_point = self.parameterAsPoint(parameters, self.START_POINT, context, crs=grib_layer.crs()) end_point = self.parameterAsPoint(parameters, self.END_POINT, context, crs=grib_layer.crs()) print("grib_layerfile", grib_layerfile) print("grib_layer", grib_layer) print("wind_ds", wind_ds) print("polar", polar) track = ((start_point.y(), start_point.x()), (end_point.y(), end_point.x())) geo_context = QgsRectangle(start_point.x(), start_point.y(), end_point.x(), end_point.y()) track_dist = QgsPointXY(start_point.x(), start_point.y()).sqrDist( end_point.x(), end_point.y()) geo_context.grow( (track_dist / 2) if track_dist < 1 else 0.5) #limit grow to 0.5 degree checkValidity = in_sea_checker(geo_context) grib_reader = grib_sampler(grib_layer, wind_ds) #test #print ("TESTGRIB",grib_reader.getWindAt(datetime.strptime("02/02/21 18:00", "%d/%m/%y %H:%M"),39.31064,5.06086)) print("track", track) route_process = Routing( LinearBestIsoRouter, polar, track, grib_reader, start.toPyDateTime(), lineValidity=checkValidity.path_in_sea_xy, ) step = 1 execution = "ok" while not route_process.end: if feedback.isCanceled(): break try: res = route_process.step() step += 1 feedback.pushInfo("step %d: %s" % (step, str(res.time))) if feedback.isCanceled(): return {"result": "terminated by user"} if res.time > grib_reader.end_time: execution = "terminated: out of grib temporal scope" except Exception as e: feedback.pushInfo("Error: %s" % e.message) if res.path: waypfields = QgsFields() waypfields.append(QgsField("wayp_id", QVariant.Int)) waypfields.append(QgsField("timestamp", QVariant.String, len=25)) waypfields.append(QgsField("time", QVariant.DateTime)) waypfields.append(QgsField("twd", QVariant.Double, len=10, prec=3)) waypfields.append(QgsField("tws", QVariant.Double, len=10, prec=3)) waypfields.append( QgsField("knots", QVariant.Double, len=10, prec=3)) waypfields.append( QgsField("heading", QVariant.Double, len=10, prec=3)) routefields = QgsFields() routefields.append( QgsField("start_tracking", QVariant.String, len=25)) routefields.append( QgsField("end_tracking", QVariant.String, len=25)) (sink_waypoints, dest_waypoints_id) = self.parameterAsSink( parameters, self.OUTPUT_WAYPOINTS, context, waypfields, QgsWkbTypes.Point, QgsCoordinateReferenceSystem(4326)) (sink_route, dest_route_id) = self.parameterAsSink( parameters, self.OUTPUT_ROUTE, context, routefields, QgsWkbTypes.LineString, QgsCoordinateReferenceSystem(4326)) # Compute the number of steps to display within the progress bar and # get features from source tr = [] for wp in res.path: if len(wp) == 3: tr.append((wp[0], wp[1], str(wp[2]), 0, 0, 0, 0)) else: tr.append( (wp[0], wp[1], str(wp[4]), wp[5], wp[6], wp[7], wp[8])) if execution == "ok": tr.append((*track[-1], dateutil.parser.parse(tr[-1][2]) + timedelta(hours=1), 0, 0, 0, 0)) print(tr) route_polyline = [] for order, wayp in enumerate(tr): # Stop the algorithm if cancel button has been clicked print(wayp[1], wayp[0], wayp[2]) if feedback.isCanceled(): break print(wayp[2], type(wayp[2])) new_feat = QgsFeature(waypfields) new_feat.setAttribute('wayp_id', order) new_feat.setAttribute( 'timestamp', str(wayp[2])[:25]) #.isoformat(timespec='minutes') new_feat.setAttribute('time', str(wayp[2])) new_feat.setAttribute('twd', math.degrees(wayp[3])) new_feat.setAttribute('tws', wayp[4]) new_feat.setAttribute('knots', wayp[5]) new_feat.setAttribute('heading', wayp[6]) waypoint = QgsPointXY(wayp[1], wayp[0]) route_polyline.append(waypoint) new_geom = QgsGeometry.fromPointXY(waypoint) new_feat.setGeometry(new_geom) sink_waypoints.addFeature(new_feat, QgsFeatureSink.FastInsert) new_route_feat = QgsFeature(routefields) new_route_feat.setAttribute('start_tracking', tr[0][2][:25]) new_route_feat.setAttribute('end_tracking', tr[-2][2][:25]) new_route_feat.setGeometry( QgsGeometry.fromPolylineXY(route_polyline)) sink_route.addFeature(new_route_feat, QgsFeatureSink.FastInsert) return { self.OUTPUT_WAYPOINTS: dest_waypoints_id, self.OUTPUT_ROUTE: dest_route_id, "result": execution } else: return {"result", "no_path"}
def doStart(self): # first see if we can pull data from the predictions layer startTime = self.datetime endTime = self.datetime.addDays(1) featureRequest = QgsFeatureRequest() stationPt = QgsPointXY(self.stationFeature.geometry().vertexAt(0)) searchRect = QgsRectangle(stationPt, stationPt) searchRect.grow( 0.01 / 60 ) # in the neighborhood of .01 nm as 1/60 = 1 arc minute in this proj. featureRequest.setFilterRect(searchRect) # Create a time based query ctx = featureRequest.expressionContext() scope = QgsExpressionContextScope() scope.setVariable('startTime', startTime) scope.setVariable('endTime', endTime) scope.setVariable('station', self.stationFeature['station']) ctx.appendScope(scope) featureRequest.setFilterExpression( "station = @station and time >= @startTime and time < @endTime") featureRequest.addOrderBy('time') savedFeatureIterator = self.manager.predictionsLayer.getFeatures( featureRequest) savedFeatures = list(savedFeatureIterator) if len(savedFeatures) > 0: # We have some features, so go ahead and stash them in the layer and resolve this promise print('{}: retrieved {} features from layer'.format( self.stationFeature['station'], len(savedFeatures))) self.predictions = savedFeatures self.resolve() else: # The layer didn't have what we wanted, so we must request the data we need. # At this point, the situation falls into several possible cases. # Case 1: A Harmonic station with known flood/ebb directions. Here # we need two requests which can simply be combined and sorted: # 1a: EventType, i.e. slack, flood and ebb # 1b: SpeedDirType, as velocity can be calculated by projecting along flood/ebb # # Case 2: A Harmonic station with unknown flood and/or ebb. # We actually need to combine 3 requests: # 2a: EventType # 2b: SpeedDirType, which only provides vector magnitude/angle # 2c: VelocityMajorType, which only provides current velocity (but for same times as 2b) # Here we set up requests for cases 1 and 2 if self.stationFeature['type'] == 'H': self.speedDirRequest = CurrentPredictionRequest( self.manager, self.stationFeature, startTime, endTime, CurrentPredictionRequest.SpeedDirectionType) self.addDependency(self.speedDirRequest) self.eventRequest = CurrentPredictionRequest( self.manager, self.stationFeature, startTime, endTime, CurrentPredictionRequest.EventType) self.addDependency(self.eventRequest) floodDir = self.stationFeature['meanFloodDir'] ebbDir = self.stationFeature['meanEbbDir'] if floodDir == NULL or ebbDir == NULL: self.velocityRequest = CurrentPredictionRequest( self.manager, self.stationFeature, startTime, endTime, CurrentPredictionRequest.VelocityMajorType) self.addDependency(self.velocityRequest) else: self.velocityRequest = None # Case 3: A Subordinate station which only knows its events. Here we need the following: # 3a: PredictionEventPromises for this station in a 3-day window surrounding the date of interest # 3b: PredictionDataPromises for the reference station in the same 3-day window. else: self.eventPromises = [] self.refPromises = [] refStation = self.manager.getStation( self.stationFeature['refStation']) if refStation is None: print("Could not find ref station {} for {}".format( self.stationFeature['refStation'], self.stationFeature['station'])) else: for dayOffset in [-1, 0, 1]: windowDate = self.localDate.addDays(dayOffset) dataPromise = self.manager.getDataPromise( refStation, windowDate) self.refPromises.append(dataPromise) self.addDependency(dataPromise) eventPromise = self.manager.getEventPromise( self.stationFeature, windowDate) self.eventPromises.append(eventPromise) self.addDependency(eventPromise)