def create_line(self, centroid, degree, radius): outer_ring = [] outer_ring.append(centroid) outer_ring.append(self.create_point(centroid, math.radians(degree), radius)) return QgsGeometry.fromPolylineXY(outer_ring)
def canvasReleaseEvent(self, event): if self.m2 and self.m1: self.reset() point = self.snappoint(event.pos()) if not self.m1: self.m1 = QgsVertexMarker(self.canvas()) self.m1.setIconType(1) self.m1.setColor(Qt.blue) self.m1.setIconSize(6) self.m1.setPenWidth(3) self.m1.setCenter(point) self.p1 = point return if not self.m2: self.m2 = QgsVertexMarker(self.canvas()) self.m2.setIconType(1) self.m2.setColor(Qt.red) self.m2.setIconSize(6) self.m2.setPenWidth(3) self.m2.setCenter(point) self.p2 = point if self.m2 and self.m1: geom = QgsGeometry.fromPolylineXY([self.p1, self.p2]) self.band.setToGeometry(geom, None) self.geometryComplete.emit(geom)
def __moved(self, position): if len(self.pointsToDraw) > 0: mapPos = self.canvas.getCoordinateTransform().toMapCoordinates(position["x"], position["y"]) self.rubberband.reset(self.polygon) newPnt = QgsPointXY(mapPos.x(), mapPos.y()) pnts = self.pointsToDraw + [newPnt] self.rubberband.setToGeometry(QgsGeometry.fromPolylineXY(pnts), None)
def __signal_pbCopyKml_clicked(self, cheked): # Extent Openlayers action = "map.getExtent().toGeometry().toString();" wkt = self.webViewMap.page().mainFrame().evaluateJavaScript(action) rect = QgsGeometry.fromWkt(wkt).boundingBox() srsGE = QgsCoordinateReferenceSystem( 4326, QgsCoordinateReferenceSystem.EpsgCrsId) coodTrans = QgsCoordinateTransform(self.__srsOL, srsGE, QgsProject.instance()) rect = coodTrans.transform( rect, QgsCoordinateTransform.ForwardTransform) line = QgsGeometry.fromRect(rect).asPolygon()[0] wkt = str(QgsGeometry.fromPolylineXY(line).asWkt()) # Kml proj4 = str(srsGE.toProj4()) kmlLine = bindogr.exportKml(wkt, proj4) kml = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"\ "<kml xmlns=\"http://www.opengis.net/kml/2.2\" " \ "xmlns:gx=\"http://www.google.com/kml/ext/2.2\" " \ "xmlns:kml=\"http://www.opengis.net/kml/2.2\" " \ "xmlns:atom=\"http://www.w3.org/2005/Atom\">" \ "<Placemark>" \ "<name>KML from Plugin Openlayers Overview for QGIS</name>" \ "<description>Extent of openlayers map from Plugin Openlayers \ Overview for QGIS</description>"\ "%s" \ "</Placemark></kml>" % kmlLine clipBoard = QApplication.clipboard() clipBoard.setText(kml)
def processAlgorithm(self, parameters, context, feedback): if parameters[self.INPUT] == parameters[self.HUBS]: raise QgsProcessingException( self.tr('Same layer given for both hubs and spokes')) point_source = self.parameterAsSource(parameters, self.INPUT, context) hub_source = self.parameterAsSource(parameters, self.HUBS, context) fieldName = self.parameterAsString(parameters, self.FIELD, context) units = self.UNITS[self.parameterAsEnum(parameters, self.UNIT, context)] fields = point_source.fields() fields.append(QgsField('HubName', QVariant.String)) fields.append(QgsField('HubDist', QVariant.Double)) (sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context, fields, QgsWkbTypes.LineString, point_source.sourceCrs()) index = QgsSpatialIndex(hub_source.getFeatures(QgsFeatureRequest().setSubsetOfAttributes([]).setDestinationCrs(point_source.sourceCrs(), context.transformContext()))) distance = QgsDistanceArea() distance.setSourceCrs(point_source.sourceCrs(), context.transformContext()) distance.setEllipsoid(context.project().ellipsoid()) # Scan source points, find nearest hub, and write to output file features = point_source.getFeatures() total = 100.0 / point_source.featureCount() if point_source.featureCount() else 0 for current, f in enumerate(features): if feedback.isCanceled(): break if not f.hasGeometry(): sink.addFeature(f, QgsFeatureSink.FastInsert) continue src = f.geometry().boundingBox().center() neighbors = index.nearestNeighbor(src, 1) ft = next(hub_source.getFeatures(QgsFeatureRequest().setFilterFid(neighbors[0]).setSubsetOfAttributes([fieldName], hub_source.fields()).setDestinationCrs(point_source.sourceCrs(), context.transformContext()))) closest = ft.geometry().boundingBox().center() hubDist = distance.measureLine(src, closest) if units != self.LAYER_UNITS: hub_dist_in_desired_units = distance.convertLengthMeasurement(hubDist, units) else: hub_dist_in_desired_units = hubDist attributes = f.attributes() attributes.append(ft[fieldName]) attributes.append(hub_dist_in_desired_units) feat = QgsFeature() feat.setAttributes(attributes) feat.setGeometry(QgsGeometry.fromPolylineXY([src, closest])) sink.addFeature(feat, QgsFeatureSink.FastInsert) feedback.setProgress(int(current * total)) return {self.OUTPUT: dest_id}
def createLayerWithOneLine(): # create a temporary layer # linelayer = iface.addVectorLayer("LineString?crs=epsg:4326&field=gid:int&field=name:string", "simple_line", "memory") linelayer = QgsVectorLayer("LineString?crs=epsg:4326&field=gid:int&field=name:string", "simple_line", "memory") one = QgsFeature(linelayer.dataProvider().fields(), 0) one.setAttributes([1, 'one']) one.setGeometry(QgsGeometry.fromPolylineXY([QgsPointXY(-7, 38), QgsPointXY(-8, 42)])) linelayer.dataProvider().addFeatures([one]) return linelayer
def _setRubberBandMarker(self, geom): m = QgsRubberBand(self.qgisIface.mapCanvas(), False) # not polygon if QgsWkbTypes.geometryType(geom.wkbType()) == QgsWkbTypes.LineGeometry: linegeom = geom elif QgsWkbTypes.geometryType(geom.wkbType()) == QgsWkbTypes.PolygonGeometry: linegeom = QgsGeometry.fromPolylineXY(geom.asPolygon()[0]) m.setToGeometry(linegeom, None) m.setColor(QColor(self.config['rubber_color'])) m.setWidth(self.config['rubber_width']) return m
def testMeasureLine(self): # +-+ # | | # +-+ + linestring = QgsGeometry.fromPolylineXY( [QgsPointXY(0, 0), QgsPointXY(1, 0), QgsPointXY(1, 1), QgsPointXY(2, 1), QgsPointXY(2, 0), ] ) da = QgsDistanceArea() length = da.measureLength(linestring) myMessage = ('Expected:\n%f\nGot:\n%f\n' % (4, length)) assert length == 4, myMessage
def testWFSLineStrings(self): """ Adds some lines, then check and clear all """ layer_name = 'test_linestring' layer = self._getLayer(layer_name) wfs_layer = self._getWFSLayer(layer_name) feat1 = QgsFeature(wfs_layer.pendingFields()) feat1['id'] = 11 feat1['name'] = 'name 11' feat1.setGeometry(QgsGeometry.fromPolylineXY([QgsPointXY(9, 45), QgsPointXY(10, 46)])) feat2 = QgsFeature(wfs_layer.pendingFields()) feat2.setGeometry(QgsGeometry.fromPolylineXY([QgsPointXY(9.5, 45.5), QgsPointXY(10.5, 46.5)])) feat2['id'] = 12 feat2['name'] = 'name 12' old_features = [feat1, feat2] # Change feat1 new_feat1 = QgsFeature(wfs_layer.pendingFields()) new_feat1['id'] = 121 new_feat1['name'] = 'name 121' new_feat1.setGeometry(QgsGeometry.fromPolylineXY([QgsPointXY(9.8, 45.8), QgsPointXY(10.8, 46.8)])) new_features = [new_feat1, feat2] self._testLayer(wfs_layer, layer, old_features, new_features)
def _swap_qgs_geometry(qgsgeom): if qgsgeom.wkbType() == QgsWkbTypes.Point: p = qgsgeom.asPoint() qgsgeom = QgsGeometry.fromPointXY(QgsPointXY(p[1], p[0])) elif qgsgeom.wkbType() == QgsWkbTypes.MultiPoint: mp = qgsgeom.asMultiPoint() qgsgeom = QgsGeometry.fromMultiPointXY([QgsPointXY(p[1], p[0]) for p in mp]) elif qgsgeom.wkbType() == QgsWkbTypes.LineString: pl = qgsgeom.asPolyline() qgsgeom = QgsGeometry.fromPolylineXY([QgsPointXY(p[1],p[0]) for p in pl]) elif qgsgeom.wkbType() == QgsWkbTypes.MultiLineString: mls = qgsgeom.asMultiPolyline() qgsgeom = QgsGeometry.fromMultiPolylineXY([[QgsPointXY(p[1],p[0]) for p in pl] for pl in mls]) elif qgsgeom.wkbType() == QgsWkbTypes.Polygon: pl = qgsgeom.asPolygon() qgsgeom = QgsGeometry.fromPolygonXY([[QgsPointXY(p[1],p[0]) for p in r] for r in pl]) elif qgsgeom.wkbType() == QgsWkbTypes.MultiPolygon: mp = qgsgeom.asMultiPolygon() qgsgeom = QgsGeometry.fromMultiPolygonXY([[[QgsPointXY(p[1],p[0]) for p in r] for r in pl] for pl in mp]) return qgsgeom
def canvasPressEvent(self, e): # find the side of the rectangle closest to the click and some data # necessary to compute the new cneter and scale topLeft, topRight, bottomRight, bottomLeft = \ self.layer.cornerCoordinates() top = [topLeft, topRight] right = [bottomRight, topRight] bottom = [bottomRight, bottomLeft] left = [bottomLeft, topLeft] click = QgsGeometry.fromPointXY(self.toMapCoordinates(e.pos())) # order is important (for referenceSide) sides = [top, right, bottom, left] distances = [click.distance( QgsGeometry.fromPolylineXY(side)) for side in sides] self.indexSide = self.minDistance(distances) self.side = sides[self.indexSide] self.sidePoint = self.center(self.side) self.vector = self.directionVector(self.side) # side that does not move (opposite of indexSide) self.referenceSide = sides[(self.indexSide + 2) % 4] self.referencePoint = self.center(self.referenceSide) self.referenceDistance = self.distance( self.sidePoint, self.referencePoint) self.isXScale = self.indexSide % 2 == 1 self.startPoint = click.asPoint() self.endPoint = self.startPoint self.isEmittingPoint = True self.isLayerVisible = isLayerVisible(self.iface, self.layer) setLayerVisible(self.iface, self.layer, False) adjustment = self.computeAdjustment() self.showAdjustment(*adjustment) self.layer.history.append( {"action": "adjust", "center": self.layer.center, "xScale": self.layer.xScale, "yScale": self.layer.yScale})
def processAlgorithm(self, parameters, context, feedback): network = self.parameterAsSource(parameters, self.INPUT, context) startPoints = self.parameterAsSource(parameters, self.START_POINTS, context) endPoint = self.parameterAsPoint(parameters, self.END_POINT, context, network.sourceCrs()) strategy = self.parameterAsEnum(parameters, self.STRATEGY, context) directionFieldName = self.parameterAsString(parameters, self.DIRECTION_FIELD, context) forwardValue = self.parameterAsString(parameters, self.VALUE_FORWARD, context) backwardValue = self.parameterAsString(parameters, self.VALUE_BACKWARD, context) bothValue = self.parameterAsString(parameters, self.VALUE_BOTH, context) defaultDirection = self.parameterAsEnum(parameters, self.DEFAULT_DIRECTION, context) speedFieldName = self.parameterAsString(parameters, self.SPEED_FIELD, context) defaultSpeed = self.parameterAsDouble(parameters, self.DEFAULT_SPEED, context) tolerance = self.parameterAsDouble(parameters, self.TOLERANCE, context) fields = startPoints.fields() fields.append(QgsField('start', QVariant.String, '', 254, 0)) fields.append(QgsField('end', QVariant.String, '', 254, 0)) fields.append(QgsField('cost', QVariant.Double, '', 20, 7)) feat = QgsFeature() feat.setFields(fields) (sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context, fields, QgsWkbTypes.LineString, network.sourceCrs()) directionField = -1 if directionFieldName: directionField = network.fields().lookupField(directionFieldName) speedField = -1 if speedFieldName: speedField = network.fields().lookupField(speedFieldName) director = QgsVectorLayerDirector(network, directionField, forwardValue, backwardValue, bothValue, defaultDirection) distUnit = context.project().crs().mapUnits() multiplier = QgsUnitTypes.fromUnitToUnitFactor( distUnit, QgsUnitTypes.DistanceMeters) if strategy == 0: strategy = QgsNetworkDistanceStrategy() else: strategy = QgsNetworkSpeedStrategy(speedField, defaultSpeed, multiplier * 1000.0 / 3600.0) multiplier = 3600 director.addStrategy(strategy) builder = QgsGraphBuilder(network.sourceCrs(), True, tolerance) feedback.pushInfo( QCoreApplication.translate('ShortestPathLayerToPoint', 'Loading start points…')) request = QgsFeatureRequest() request.setDestinationCrs(network.sourceCrs(), context.transformContext()) features = startPoints.getFeatures(request) total = 100.0 / startPoints.featureCount() if startPoints.featureCount( ) else 0 points = [endPoint] source_attributes = {} i = 1 for current, f in enumerate(features): if feedback.isCanceled(): break if not f.hasGeometry(): continue for p in f.geometry().vertices(): points.append(QgsPointXY(p)) source_attributes[i] = f.attributes() i += 1 feedback.setProgress(int(current * total)) feedback.pushInfo( QCoreApplication.translate('ShortestPathLayerToPoint', 'Building graph…')) snappedPoints = director.makeGraph(builder, points, feedback) feedback.pushInfo( QCoreApplication.translate('ShortestPathLayerToPoint', 'Calculating shortest paths…')) graph = builder.graph() idxEnd = graph.findVertex(snappedPoints[0]) nPoints = len(snappedPoints) total = 100.0 / nPoints if nPoints else 1 for i in range(1, nPoints): if feedback.isCanceled(): break idxStart = graph.findVertex(snappedPoints[i]) tree, costs = QgsGraphAnalyzer.dijkstra(graph, idxStart, 0) if tree[idxEnd] == -1: msg = self.tr( 'There is no route from start point ({}) to end point ({}).' .format(points[i].toString(), endPoint.toString())) feedback.reportError(msg) # add feature with no geometry feat.clearGeometry() attrs = source_attributes[i] attrs.append(points[i].toString()) feat.setAttributes(attrs) sink.addFeature(feat, QgsFeatureSink.FastInsert) continue route = [graph.vertex(idxEnd).point()] cost = costs[idxEnd] current = idxEnd while current != idxStart: current = graph.edge(tree[current]).fromVertex() route.append(graph.vertex(current).point()) route.reverse() geom = QgsGeometry.fromPolylineXY(route) feat.setGeometry(geom) attrs = source_attributes[i] attrs.extend( [points[i].toString(), endPoint.toString(), cost / multiplier]) feat.setAttributes(attrs) sink.addFeature(feat, QgsFeatureSink.FastInsert) feedback.setProgress(int(i * total)) return {self.OUTPUT: dest_id}
def updateRubberGeom(self): if self.pA is None: return self.zoneWidth = self.pA.distance(self.pB) self.zoneDepth = self.pA.distance(self.pD) self.pM = QgsPointXY((self.pC.x() + self.pD.x()) / 2, (self.pC.y() + self.pD.y()) / 2) self.d0 = self.pM.distance(self.pY) # self.widget.updateZ(self.pY) self.rb.setToGeometry( QgsGeometry.fromPolygonXY( [[self.pD, self.pA, self.pB, self.pC, self.pD]])) self.rbFoc.setToGeometry( QgsGeometry.fromPolylineXY([self.pD, self.pY, self.pC])) for p, rb in [ [self.pA, self.rbPA], [self.pB, self.rbPB], [self.pC, self.rbPC], [self.pD, self.rbPD], [self.pY, self.rbPY], [self.pH, self.rbPH], [self.pL, self.rbPL], ]: rb.setToGeometry(QgsGeometry.fromPointXY(p)) leftEdge = (QgsGeometry.fromPolylineXY([ self.pA, self.pD ]).densifyByCount(self.widget.rowCount.value() - 1).asPolyline()) rightEdge = (QgsGeometry.fromPolylineXY([ self.pB, self.pC ]).densifyByCount(self.widget.rowCount.value() - 1).asPolyline()) # Plot edges lines polyline = list(zip(leftEdge, rightEdge)) backSide = (QgsGeometry.fromPolylineXY([ self.pA, self.pB ]).densifyByCount(self.widget.columnCount.value() - 1).asPolyline()) frontSide = (QgsGeometry.fromPolylineXY([ self.pD, self.pC ]).densifyByCount(self.widget.columnCount.value() - 1).asPolyline()) polylineX = list(zip(frontSide[:], backSide[:])) self.finalWidth = self.zoneWidth self.rowLines = polyline self.columnLines = polylineX self.allLines = polyline + polylineX self.rbLines.setToGeometry( QgsGeometry.fromMultiPolylineXY( polylineX + polyline + polyline[::max(1, 1 + len(polyline))])) if self.widget.cbReverseRows.isChecked(): if self.widget.cbReverseColumns.isChecked(): self.rbPC.setColor(Qt.red) self.rbPD.setColor(Qt.red) self.rbPA.setColor(Qt.red) self.rbPB.setColor(QColor(0, 200, 150, 255)) else: self.rbPC.setColor(Qt.red) self.rbPD.setColor(Qt.red) self.rbPB.setColor(Qt.red) self.rbPA.setColor(QColor(0, 200, 150, 255)) else: if self.widget.cbReverseColumns.isChecked(): self.rbPA.setColor(Qt.red) self.rbPB.setColor(Qt.red) self.rbPD.setColor(Qt.red) self.rbPC.setColor(QColor(0, 200, 150, 255)) else: self.rbPA.setColor(Qt.red) self.rbPB.setColor(Qt.red) self.rbPC.setColor(Qt.red) self.rbPD.setColor(QColor(0, 200, 150, 255)) self.widget.alert.setText("Total plots: {}".format( self.widget.columnCount.value() * self.widget.rowCount.value()))
def processAlgorithm(self, parameters, context, feedback): source = self.parameterAsSource(parameters, self.PrmInputLayer, context) shapetype = self.parameterAsInt(parameters, self.PrmShapeType, context) lobescol = self.parameterAsString(parameters, self.PrmLobesField, context) startanglecol = self.parameterAsString(parameters, self.PrmStartingAngleField, context) radiuscol = self.parameterAsString(parameters, self.PrmRadiusField, context) radius = self.parameterAsDouble(parameters, self.PrmRadius, context) startAngle = self.parameterAsDouble(parameters, self.PrmStartingAngle, context) lobes = self.parameterAsInt(parameters, self.PrmLobes, context) segments = self.parameterAsInt(parameters, self.PrmDrawingSegments, context) units = self.parameterAsInt(parameters, self.PrmUnitsOfMeasure, context) export_geom = self.parameterAsBool(parameters, self.PrmExportInputGeometry, context) measureFactor = conversionToMeters(units) radius *= measureFactor r = radius / lobes srcCRS = source.sourceCrs() fields = source.fields() if export_geom: names = fields.names() name_x, name_y = settings.getGeomNames(names) fields.append(QgsField(name_x, QVariant.Double)) fields.append(QgsField(name_y, QVariant.Double)) if shapetype == 0: (sink, dest_id) = self.parameterAsSink(parameters, self.PrmOutputLayer, context, fields, QgsWkbTypes.Polygon, srcCRS) else: (sink, dest_id) = self.parameterAsSink(parameters, self.PrmOutputLayer, context, fields, QgsWkbTypes.LineString, srcCRS) if srcCRS != epsg4326: geomTo4326 = QgsCoordinateTransform(srcCRS, epsg4326, QgsProject.instance()) toSinkCrs = QgsCoordinateTransform(epsg4326, srcCRS, QgsProject.instance()) featureCount = source.featureCount() total = 100.0 / featureCount if featureCount else 0 step = 360.0 / segments numbad = 0 iterator = source.getFeatures() for index, feature in enumerate(iterator): if feedback.isCanceled(): break try: if startanglecol: sangle = float(feature[startanglecol]) else: sangle = startAngle if lobescol: lobes2 = int(feature[lobescol]) else: lobes2 = lobes if radiuscol: radius2 = float(feature[radiuscol]) * measureFactor else: radius2 = radius r = radius2 / lobes2 except: numbad += 1 continue pts = [] pt = feature.geometry().asPoint() pt_orig_x = pt.x() pt_orig_y = pt.y() # make sure the coordinates are in EPSG:4326 if srcCRS != epsg4326: pt = geomTo4326.transform(pt.x(), pt.y()) angle = 0.0 while angle <= 360.0: a = math.radians(angle - sangle) x = r * (lobes2 - 1.0) * math.cos(a) + r * math.cos( (lobes2 - 1.0) * a) y = r * (lobes2 - 1.0) * math.sin(a) - r * math.sin( (lobes2 - 1.0) * a) dist = math.sqrt(x * x + y * y) g = geod.Direct(pt.y(), pt.x(), angle, dist, Geodesic.LATITUDE | Geodesic.LONGITUDE) pts.append(QgsPointXY(g['lon2'], g['lat2'])) angle += step # If the Output crs is not 4326 transform the points to the proper crs if srcCRS != epsg4326: for x, ptout in enumerate(pts): pts[x] = toSinkCrs.transform(ptout) f = QgsFeature() if shapetype == 0: f.setGeometry(QgsGeometry.fromPolygonXY([pts])) else: f.setGeometry(QgsGeometry.fromPolylineXY(pts)) attr = feature.attributes() if export_geom: attr.append(pt_orig_x) attr.append(pt_orig_y) f.setAttributes(attr) sink.addFeature(f) if index % 100 == 0: feedback.setProgress(int(index * total)) return {self.PrmOutputLayer: dest_id}
def run(bar,layer1_path,layer2_path,obstacles_path,research_ray): output = {} #layer1 receiver layer1 = QgsVectorLayer(layer1_path,"layer1","ogr") #layer 2 source layer2 = QgsVectorLayer(layer2_path,"layer2","ogr") layer2_feat_all_dict = {} layer2_feat_all = layer2.dataProvider().getFeatures() layer2_spIndex = QgsSpatialIndex() for layer2_feat in layer2_feat_all: layer2_spIndex.insertFeature(layer2_feat) layer2_feat_all_dict[layer2_feat.id()] = layer2_feat if obstacles_path is not None: obstacles_layer = QgsVectorLayer(obstacles_path,"obstacles","ogr") obstacles_feat_all = obstacles_layer.dataProvider().getFeatures() obstacles_spIndex = QgsSpatialIndex() obstacles_feat_all_dict = {} for obstacles_feat in obstacles_feat_all: obstacles_spIndex.insertFeature(obstacles_feat) obstacles_feat_all_dict[obstacles_feat.id()] = obstacles_feat layer1_feat_all = layer1.dataProvider().getFeatures() layer1_feat_total = layer1.dataProvider().featureCount() layer1_feat_number = 0 for layer1_feat in layer1_feat_all: layer1_feat_number = layer1_feat_number + 1 barValue = layer1_feat_number/float(layer1_feat_total)*100 bar.setValue(barValue) # researches the layer2 points in a rectangle created by the research_ray # creates the search rectangle rect = QgsRectangle() rect.setXMinimum( layer1_feat.geometry().asPoint().x() - research_ray ) rect.setXMaximum( layer1_feat.geometry().asPoint().x() + research_ray ) rect.setYMinimum( layer1_feat.geometry().asPoint().y() - research_ray ) rect.setYMaximum( layer1_feat.geometry().asPoint().y() + research_ray ) layer2_request = layer2_spIndex.intersects(rect) layer2_points = [] for layer2_id in layer2_request: layer2_feat = layer2_feat_all_dict[layer2_id] ray_to_test_length = compute_distance(layer1_feat.geometry().asPoint(),layer2_feat.geometry().asPoint()) if ray_to_test_length <= research_ray: ray_to_test = QgsGeometry.fromPolylineXY( [ layer1_feat.geometry().asPoint() , layer2_feat.geometry().asPoint() ] ) intersect = 0 if obstacles_path is not None: obstacles_request = obstacles_spIndex.intersects(ray_to_test.boundingBox()) for obstacles_id in obstacles_request: if obstacles_feat_all_dict[obstacles_id].geometry().crosses(ray_to_test) == 1: intersect = 1 break if intersect == 0: layer2_points.append(layer2_feat.id()) output[layer1_feat.id()] = layer2_points return output
def processAlgorithm(self, parameters, context, feedback): if parameters[self.INPUT] == parameters[self.HUBS]: raise QgsProcessingException( self.tr('Same layer given for both hubs and spokes')) point_source = self.parameterAsSource(parameters, self.INPUT, context) if point_source is None: raise QgsProcessingException( self.invalidSourceError(parameters, self.INPUT)) hub_source = self.parameterAsSource(parameters, self.HUBS, context) if hub_source is None: raise QgsProcessingException( self.invalidSourceError(parameters, self.HUBS)) fieldName = self.parameterAsString(parameters, self.FIELD, context) units = self.UNITS[self.parameterAsEnum(parameters, self.UNIT, context)] fields = point_source.fields() fields.append(QgsField('HubName', QVariant.String)) fields.append(QgsField('HubDist', QVariant.Double)) (sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context, fields, QgsWkbTypes.LineString, point_source.sourceCrs()) if sink is None: raise QgsProcessingException( self.invalidSinkError(parameters, self.OUTPUT)) index = QgsSpatialIndex( hub_source.getFeatures(QgsFeatureRequest().setSubsetOfAttributes( []).setDestinationCrs(point_source.sourceCrs(), context.transformContext()))) distance = QgsDistanceArea() distance.setSourceCrs(point_source.sourceCrs(), context.transformContext()) distance.setEllipsoid(context.project().ellipsoid()) # Scan source points, find nearest hub, and write to output file features = point_source.getFeatures() total = 100.0 / point_source.featureCount( ) if point_source.featureCount() else 0 for current, f in enumerate(features): if feedback.isCanceled(): break if not f.hasGeometry(): sink.addFeature(f, QgsFeatureSink.FastInsert) continue src = f.geometry().boundingBox().center() neighbors = index.nearestNeighbor(src, 1) ft = next( hub_source.getFeatures(QgsFeatureRequest().setFilterFid( neighbors[0]).setSubsetOfAttributes( [fieldName], hub_source.fields()).setDestinationCrs( point_source.sourceCrs(), context.transformContext()))) closest = ft.geometry().boundingBox().center() hubDist = distance.measureLine(src, closest) if units != self.LAYER_UNITS: hub_dist_in_desired_units = distance.convertLengthMeasurement( hubDist, units) else: hub_dist_in_desired_units = hubDist attributes = f.attributes() attributes.append(ft[fieldName]) attributes.append(hub_dist_in_desired_units) feat = QgsFeature() feat.setAttributes(attributes) feat.setGeometry(QgsGeometry.fromPolylineXY([src, closest])) sink.addFeature(feat, QgsFeatureSink.FastInsert) feedback.setProgress(int(current * total)) return {self.OUTPUT: dest_id}
def processAlgorithm(self, parameters, context, feedback): source = self.parameterAsSource(parameters, self.INPUT, context) if source is None: raise QgsProcessingException(self.invalidSourceError(parameters, self.INPUT)) use_ring_count = False; fields_or_rings = self.parameterAsString(parameters, self.FIELDS_OR_RINGS, context) if (self.is_number(fields_or_rings)): ring_num = int(fields_or_rings) use_ring_count = True else: input_fields = fields_or_rings.strip().split(',') ring_num = len(input_fields) for idx in range(ring_num): input_fields[idx] = input_fields[idx].strip() if (ring_num == 0): raise QgsProcessingException('The count of Rings must be greater than zero') ring_value_field = self.parameterAsString(parameters, self.RING_VALUE_FIELD, context) self.GAPS = self.parameterAsInt(parameters, self.RING_GAP, context) if self.GAPS < 0 or self.GAPS > 10: raise QgsProcessingException('The Gap value must be between 0 and 10.') # calculate layer's extent & feature count feature_count = source.featureCount() extent = self.calculate_layer_extent(source) # create spatial index & convert to points (spatial_index, centroid_features) = self.create_spatial_index(source) center_point = extent.center(); # QgsPoint minx = extent.xMinimum() miny = extent.yMinimum() maxx = extent.xMaximum() maxy = extent.yMaximum() radius = (((maxx - minx)**2 + (maxy - miny)**2) **0.5) / 2.0 radius_interval = radius / ring_num ring_fields = source.fields() ring_fields.append(QgsField("ring_num", QVariant.Int)) ring_fields.append(QgsField(ring_value_field, QVariant.Double)) idx_fields = [] for idx in range(ring_num): if (use_ring_count): idx_fields.append(-1) else: idx_fields.append(ring_fields.lookupField(input_fields[idx])) (sink_ring, ring_id) = self.parameterAsSink(parameters, self.OUTPUT_RING, context, ring_fields, QgsWkbTypes.Polygon, source.sourceCrs()) (sink_anchor, anchor_id) = self.parameterAsSink(parameters, self.OUTPUT_ANCHOR, context, source.fields(), QgsWkbTypes.LineString, source.sourceCrs()) if sink_ring is None: raise QgsProcessingException(self.invalidSinkError(parameters, self.OUTPUT_RING)) if sink_anchor is None: raise QgsProcessingException(self.invalidSinkError(parameters, self.OUTPUT_ANCHOR)) step_angle = 360.0 / feature_count half_step = step_angle / 2.0 total = 100.0 / feature_count if feature_count else 0 for idx_side in range(feature_count): if feedback.isCanceled(): break from_deg = half_step + (idx_side * step_angle) to_deg = half_step + ((idx_side + 1) * step_angle) default_radius = radius for idx_radius in range(ring_num): cell = self.create_ring_cell(center_point, from_deg, to_deg, default_radius, default_radius + radius_interval) cell_centroid_point = cell.centroid().asPoint() # find nearest feature & create anchor line if (idx_radius == 0): fids = spatial_index.nearestNeighbor(cell_centroid_point, 1) for fid in fids: nearest_feature = centroid_features[fid] nearest_point = nearest_feature.geometry().asPoint() anchor_feature = QgsFeature() anchor_feature.setGeometry(QgsGeometry.fromPolylineXY([nearest_point, cell_centroid_point])) anchor_feature.setAttributes(nearest_feature.attributes()) # Add a new feature in the sink sink_anchor.addFeature(anchor_feature, QgsFeatureSink.FastInsert) spatial_index.deleteFeature(nearest_feature) # create and write ring feature ring_feature = QgsFeature(ring_fields) ring_feature.setGeometry(cell) ring_attributes = nearest_feature.attributes() ring_attributes.append(idx_radius + 1) # ring_num if (idx_fields[idx_radius] == -1): ring_attributes.append(0) # default value = 0 else: ring_attributes.append(ring_attributes[idx_fields[idx_radius]]) # ring_val ring_feature.setAttributes(ring_attributes) # Add a new feature in the sink sink_ring.addFeature(ring_feature, QgsFeatureSink.FastInsert) default_radius += radius_interval # Update the progress bar feedback.setProgress(int(idx_side * total)) # cleanup del centroid_features return {self.OUTPUT_RING: ring_id, self.OUTPUT_ANCHOR: anchor_id}
def canvasMoveEvent(self, event): if len(self.pointsToDraw) > 0: self.rubberband.reset() line = [self.pointsToDraw[0], event.mapPoint()] self.rubberband.setToGeometry(QgsGeometry.fromPolylineXY(line), None)
def epa2gis(inpname): plugin_path = os.path.dirname(__file__) file_extension = os.path.dirname(inpname) inpname = os.path.basename(inpname) inp = file_extension + '/' + inpname if len(file_extension) == 0: inp = inpname newpath = file_extension + '/_shapefiles_' if not os.path.exists(newpath): os.makedirs(newpath) iface = qgis.utils.iface d.LoadFile(inp) d.BinUpdateClass() nlinkCount = d.getBinLinkCount() res = newpath + '\\' saveFile = res + inpname[:len(inpname) - 4] # Get all Sections mixing = d.getMixingSection() reactions = d.getReactionsSection() sources = d.getSourcesSection() rules = d.getRulesSection() quality = d.getQualitySection() curves = d.getCurvesSection() patterns = d.getPatternsSection() controls = d.getControlsSection() emitters = d.getEmittersSection() status = d.getStatusSection() demands = d.getDemandsSection() energy = d.getEnergySection() optReactions = d.getReactionsOptionsSection() times = d.getTimesSection() report = d.getReportSection() options = d.getOptionsSection() # Get all Section lengths allSections = [len(energy), len(optReactions), len(demands), len(status), len(emitters), len(controls), len(patterns), len(curves[0]), len(quality), len(rules), len(sources), len(reactions), len(mixing), len(times), len(report), len(options), d.getBinNodeCount(), d.getBinLinkCount()] ss = max(allSections) root = QgsProject.instance().layerTreeRoot() idx = root.insertGroup(0, inpname[:len(inpname) - 4]) xy = d.getBinNodeCoordinates() x = xy[0] y = xy[1] vertx = xy[2] verty = xy[3] vertxyFinal = [] for i in range(len(vertx)): vertxy = [] for u in range(len(vertx[i])): vertxy.append([float(vertx[i][u]), float(verty[i][u])]) if vertxy: vertxyFinal.append(vertxy) otherDemads = d.getBinNodeBaseDemandsDemSection() ndID = d.getBinNodeNameID() ndBaseD = d.getBinNodeBaseDemands() ndPatID = d.getBinNodeDemandPatternID() otherDemadsIndex = [] otherDemadsPatterns = [] for i, p in enumerate(otherDemads[1]): otherDemadsIndex.append(ndID.index(p)) otherDemadsPatterns.append(otherDemads[2][i]) counter = collections.Counter(otherDemadsIndex) maxCategories = 1 if counter: maxCategories = max(counter.values()) if not ndBaseD: ndBaseD = otherDemads[0] # Get data of Junctions if d.getBinNodeJunctionCount() > 0: ndBaseTmp = np.empty((len(ndBaseD), maxCategories,)) ndPatTmp = [] for t in range(0, maxCategories): for u in range(0, len(ndBaseD)): ndBaseTmp[u][t] = 0 ndPatTmp.append(['None'] * 2) for uu in range(0, len(ndBaseD)): if d.getBinNodeBaseDemands(): ndBaseTmp[uu][0] = ndBaseD[uu] ndPatTmp[uu][0] = ndPatID[uu] t = 0 for i, p in enumerate(otherDemadsIndex): if d.getBinNodeBaseDemands(): ndBaseTmp[p][t] = ndBaseD[otherDemadsIndex[i]] ndPatTmp[p][t] = ndPatID[otherDemadsIndex[i]] else: ndBaseTmp[p][t] = otherDemads[0][i] ndPatTmp[p][t] = otherDemads[2][i] t = t + 1 if t > max(counter.values()) - 1: t = max(counter.values()) - 1 if i > 0: if otherDemadsIndex[i - 1] == p: ndBaseTmp[p][t] = otherDemads[0][i] ndPatTmp[p][t] = otherDemads[2][i] t = t - 1 # Write Junction Shapefile fields = ["ID", "Elevation"] # , "pattern", "demand"] fieldsCode = [0, 1] for u in range(0, maxCategories): fields.append('Demand' + str(u + 1)) fields.append('Pattern' + str(u + 1)) fieldsCode.append(1) fieldsCode.append(0) posJunction = QgsVectorLayer("point?crs=EPSG:4326", "Junctions", "memory") prJunction = posJunction.dataProvider() ndBaseTmp = ndBaseTmp.tolist() createColumnsAttrb(prJunction, fields, fieldsCode) posJunction.startEditing() ndEle = d.getBinNodeJunctionElevations() # Get data of Pipes # Write shapefile pipe if nlinkCount > 0: posPipe = QgsVectorLayer("LineString?crs=EPSG:4326", "Pipes", "memory") prPipe = posPipe.dataProvider() fields = ["ID", "NodeFrom", "NodeTo", "Status", "Length", "Diameter", "Roughness", "MinorLoss"] fieldsCode = [0, 0, 0, 0, 1, 1, 1, 1] createColumnsAttrb(prPipe, fields, fieldsCode) posPipe.startEditing() pIndex = d.getBinLinkPumpIndex() vIndex = d.getBinLinkValveIndex() ndlConn = d.getBinNodesConnectingLinksID() x1 = [] x2 = [] y1 = [] y2 = [] stat = d.getBinLinkInitialStatus() kk = 0 ch = 0 linkID = d.getBinLinkNameID() linkLengths = d.getBinLinkLength() linkDiameters = d.getBinLinkDiameter() linkRough = d.getBinLinkRoughnessCoeff() linkMinorloss = d.getBinLinkMinorLossCoeff() # Write Tank Shapefile and get tank data posTank = QgsVectorLayer("point?crs=EPSG:4326", "Tanks", "memory") prTank = posTank.dataProvider() fields = ["ID", "Elevation", "InitLevel", "MinLevel", "MaxLevel", "Diameter", "MinVolume", "VolumeCurve"] fieldsCode = [0, 1, 1, 1, 1, 1, 1, 0] createColumnsAttrb(prTank, fields, fieldsCode) posTank.startEditing() if d.getBinNodeTankCount() > 0: ndTankelevation = d.getBinNodeTankElevations() initiallev = d.getBinNodeTankInitialLevel() minimumlev = d.getBinNodeTankMinimumWaterLevel() maximumlev = d.getBinNodeTankMaximumWaterLevel() diameter = d.getBinNodeTankDiameter() minimumvol = d.getBinNodeTankMinimumWaterVolume() volumecurv = d.getBinNodeTankVolumeCurveID() ndTankID = d.getBinNodeTankNameID() # Write Reservoir Shapefile posReservoirs = QgsVectorLayer("point?crs=EPSG:4326", "Reservoirs", "memory") prReservoirs = posReservoirs.dataProvider() fields = ["ID", "Head"] fieldsCode = [0, 1] createColumnsAttrb(prReservoirs, fields, fieldsCode) head = d.getBinNodeReservoirElevations() posReservoirs.startEditing() if times: posTimes = QgsVectorLayer("point?crs=EPSG:4326", "Times", "memory") prTimes = posTimes.dataProvider() if energy: posE = QgsVectorLayer("point?crs=EPSG:4326", "Energy", "memory") prE = posE.dataProvider() if report: posRep = QgsVectorLayer("point?crs=EPSG:4326", "Report", "memory") prRep = posRep.dataProvider() if options: posOpt = QgsVectorLayer("point?crs=EPSG:4326", "Options", "memory") prOpt = posOpt.dataProvider() if optReactions: posO = QgsVectorLayer("point?crs=EPSG:4326", "Reactions", "memory") prO = posO.dataProvider() ppE = [] ppO = [] ppTimes = [] ppRep = [] ppOpt = [] ppMix = [] ppReactions = [] ppSourc = [] ppRul = [] ppPat = [] ppQual = [] ppDem = [] ppStat = [] ppEmit = [] ppCont = [] ppCurv = [] for i in range(ss): if i < d.getBinNodeJunctionCount(): featJ = QgsFeature() point = QgsPointXY(float(x[i]), float(y[i])) featJ.initAttributes(2 + len(ndBaseTmp[0]) * 2) featJ.setGeometry(QgsGeometry.fromPointXY(point)) featJ.setAttribute(0, ndID[i]) featJ.setAttribute(1, ndEle[i]) w = 2 for j in range(0, len(ndBaseTmp[0])): featJ.setAttribute(w, ndBaseTmp[i][j]) featJ.setAttribute(w + 1, ndPatTmp[i][j]) w = w + 2 prJunction.addFeatures([featJ]) if i < nlinkCount: if len(stat) == i: ch = 1 if ch == 1: stat.append('OPEN') x1.append(x[ndID.index(d.getBinLinkFromNode()[i])]) y1.append(y[ndID.index(d.getBinLinkFromNode()[i])]) x2.append(x[ndID.index(d.getBinLinkToNode()[i])]) y2.append(y[ndID.index(d.getBinLinkToNode()[i])]) if i in pIndex: pass elif i in vIndex: pass else: point1 = QgsPointXY(float(x1[i]), float(y1[i])) point2 = QgsPointXY(float(x2[i]), float(y2[i])) featPipe = QgsFeature() if vertx[i]: parts = [] parts.append(point1) for mm in range(len(vertxyFinal[kk])): a = vertxyFinal[kk][mm] parts.append(QgsPointXY(a[0], a[1])) parts.append(point2) featPipe.setGeometry((QgsGeometry.fromPolylineXY(parts))) kk = kk + 1 else: featPipe.setGeometry(QgsGeometry.fromPolylineXY([point1, point2])) featPipe.setAttributes( [linkID[i], ndlConn[0][i], ndlConn[1][i], stat[i], linkLengths[i], linkDiameters[i], linkRough[i], linkMinorloss[i]]) prPipe.addFeatures([featPipe]) if i < d.getBinNodeTankCount(): p = d.getBinNodeTankIndex()[i] - 1 featTank = QgsFeature() point = QgsPointXY(float(x[p]), float(y[p])) featTank.setGeometry(QgsGeometry.fromPointXY(point)) featTank.setAttributes( [ndTankID[i], ndTankelevation[i], initiallev[i], minimumlev[i], maximumlev[i], diameter[i], minimumvol[i], volumecurv[i]]) prTank.addFeatures([featTank]) if i < d.getBinNodeReservoirCount(): p = d.getBinNodeReservoirIndex()[i] - 1 feature = QgsFeature() point = QgsPointXY(float(x[p]), float(y[p])) feature.setGeometry(QgsGeometry.fromPointXY(point)) feature.setAttributes([ndID[p], head[i]]) prReservoirs.addFeatures([feature]) if i < allSections[12]: if len(mixing[i]) == 3: ppMix.append([mixing[i][0], mixing[i][1], mixing[i][2]]) else: ppMix.append([mixing[i][0], mixing[i][1]]) if i < allSections[11]: ppReactions.append([reactions[i][0], reactions[i][1], reactions[i][2]]) if i < allSections[10]: if len(sources[i]) == 4: ppSourc.append([sources[i][0], sources[i][1], sources[i][2], sources[i][3]]) elif len(sources[i]) == 3: ppSourc.append([sources[i][0], sources[i][1], sources[i][2]]) else: ppSourc.append([sources[i][0], sources[i][1]]) if i < allSections[9]: if len(rules[i]) > 2: ppRul.append([rules[i][0][1][1], rules[i][1][0] + rules[i][2][0] + rules[i][3][0]]) if i < allSections[8]: ppQual.append([quality[i][0], quality[i][1]]) if i < allSections[7]: ppCurv.append([str(curves[0][i][0]), str(curves[0][i][1]), str(curves[0][i][2]), str(curves[1][i])]) if i < allSections[6]: ppPat.append([patterns[i][0], str(patterns[i][1])]) if i < allSections[5]: ppCont.append([controls[i]]) if i < allSections[4]: ppEmit.append([emitters[i][0], emitters[i][1]]) if i < allSections[3]: ppStat.append([status[i][0], status[i][1]]) if i < allSections[2]: if len(demands[i]) > 2: ppDem.append([demands[i][0], demands[i][1], demands[i][2]]) if i < allSections[0]: mm = energy[i][0] if mm.upper() == "GLOBAL": prE.addAttributes([QgsField("Global" + energy[i][1], QVariant.String)]) if len(energy[i]) > 2: ppE.append(energy[i][2]) else: ppE.append('') if mm.upper() == "PUMP": prE.addAttributes([QgsField("Pump", QVariant.String)]) if len(energy[i]) > 2: ppE.append(energy[i][1] + ' ' + energy[i][2]) else: ppE.append(energy[i][1]) elif mm.upper() == "DEMAND": if energy[i][1].upper() == "CHARGE": prE.addAttributes([QgsField("DemCharge", QVariant.String)]) if len(energy[i]) > 2: ppE.append(energy[i][2]) if i < allSections[1]: mm = optReactions[i][0] if mm.upper() == "ORDER": prO.addAttributes([QgsField("Order" + optReactions[i][1], QVariant.String)]) if len(optReactions[i]) > 2: ppO.append(optReactions[i][2]) else: ppO.append('') elif mm.upper() == "GLOBAL": prO.addAttributes([QgsField("Global" + optReactions[i][1], QVariant.String)]) if len(optReactions[i]) > 2: ppO.append(optReactions[i][2]) else: ppO.append('') elif mm.upper() == "BULK": prO.addAttributes([QgsField("Bulk", QVariant.String)]) if len(optReactions[i]) > 2: ppO.append(optReactions[i][1] + ' ' + optReactions[i][2]) else: ppO.append(optReactions[i][1]) elif mm.upper() == "WALL": prO.addAttributes([QgsField("Wall", QVariant.String)]) if len(optReactions[i]) > 2: ppO.append(optReactions[i][1] + ' ' + optReactions[i][2]) else: ppO.append(optReactions[i][1]) elif mm.upper() == "TANK": prO.addAttributes([QgsField("Tank", QVariant.String)]) if len(optReactions[i]) > 2: ppO.append(optReactions[i][1] + ' ' + optReactions[i][2]) else: ppO.append(optReactions[i][1]) elif mm.upper() == "LIMITING": if optReactions[i][1].upper() == "POTENTIAL": prO.addAttributes([QgsField("LimPotent", QVariant.String)]) if len(optReactions[i]) > 2: ppO.append(optReactions[i][2]) elif mm.upper() == "ROUGHNESS": if optReactions[i][1].upper() == "CORRELATION": prO.addAttributes([QgsField("RoughCorr", QVariant.String)]) if len(optReactions[i]) > 2: ppO.append(optReactions[i][2]) if i < allSections[13]: mm = times[i][0] if mm.upper() == "DURATION": prTimes.addAttributes([QgsField("Duration", QVariant.String)]) ppTimes.append(times[i][1]) if mm.upper() == "HYDRAULIC": prTimes.addAttributes([QgsField("HydStep", QVariant.String)]) ppTimes.append(times[i][2]) elif mm.upper() == "QUALITY": prTimes.addAttributes([QgsField("QualStep", QVariant.String)]) ppTimes.append(times[i][2]) elif mm.upper() == "RULE": prTimes.addAttributes([QgsField("RuleStep", QVariant.String)]) ppTimes.append(times[i][2]) elif mm.upper() == "PATTERN": if times[i][1].upper() == "TIMESTEP": prTimes.addAttributes([QgsField("PatStep", QVariant.String)]) ppTimes.append(times[i][2]) if times[i][1].upper() == "START": prTimes.addAttributes([QgsField("PatStart", QVariant.String)]) ppTimes.append(times[i][2]) elif mm.upper() == "REPORT": if times[i][1].upper() == "TIMESTEP": prTimes.addAttributes([QgsField("RepStep", QVariant.String)]) ppTimes.append(times[i][2]) if times[i][1].upper() == "START": prTimes.addAttributes([QgsField("RepStart", QVariant.String)]) ppTimes.append(times[i][2]) elif mm.upper() == "START": if times[i][1].upper() == "CLOCKTIME": prTimes.addAttributes([QgsField("StartClock", QVariant.String)]) if len(times[i]) > 3: ppTimes.append(times[i][2] + ' ' + times[i][3]) else: ppTimes.append(times[i][2]) elif mm.upper() == "STATISTIC": prTimes.addAttributes([QgsField("Statistic", QVariant.String)]) if times[i][1].upper() == 'NONE' or times[i][1].upper() == 'AVERAGE' or times[i][1].upper() \ == 'MINIMUM' or times[i][1].upper() == 'MAXIMUM' or times[i][1].upper() == 'RANGE': ppTimes.append(times[i][1]) if i < allSections[14]: mm = report[i][0] if mm.upper() == "PAGESIZE": prRep.addAttributes([QgsField("PageSize", QVariant.String)]) ppRep.append(report[i][1]) if mm.upper() == "FILE": prRep.addAttributes([QgsField("FileName", QVariant.String)]) ppRep.append(report[i][1]) elif mm.upper() == "STATUS": prRep.addAttributes([QgsField("Status", QVariant.String)]) ppRep.append(report[i][1]) elif mm.upper() == "SUMMARY": prRep.addAttributes([QgsField("Summary", QVariant.String)]) ppRep.append(report[i][1]) elif mm.upper() == "ENERGY": prRep.addAttributes([QgsField("Energy", QVariant.String)]) ppRep.append(report[i][1]) elif mm.upper() == "NODES": prRep.addAttributes([QgsField("Nodes", QVariant.String)]) if len(report[i]) > 2: ppRep.append(report[i][1] + ' ' + report[i][2]) else: ppRep.append(report[i][1]) elif mm.upper() == "LINKS": prRep.addAttributes([QgsField("Links", QVariant.String)]) if len(report[i]) > 2: ppRep.append(report[i][1] + ' ' + report[i][2]) else: ppRep.append(report[i][1]) else: prRep.addAttributes([QgsField(mm, QVariant.String)]) if len(report[i]) > 2: ppRep.append(report[i][1] + ' ' + report[i][2]) else: ppRep.append(report[i][1]) if i < allSections[15]: mm = options[i][0] if mm.upper() == "UNITS": prOpt.addAttributes([QgsField("Units", QVariant.String)]) ppOpt.append(options[i][1]) if mm.upper() == "HYDRAULICS": prOpt.addAttributes([QgsField("Hydraulics", QVariant.String)]) if len(options[i]) > 2: ppOpt.append(options[i][1] + ' ' + options[i][2]) else: ppOpt.append(options[i][1]) elif mm.upper() == "QUALITY": prOpt.addAttributes([QgsField("Quality", QVariant.String)]) if len(options[i]) > 2: ppOpt.append(options[i][1] + ' ' + options[i][2]) elif len(options[i]) > 3: ppOpt.append(options[i][1] + ' ' + options[i][2] + ' ' + options[i][3]) else: ppOpt.append(options[i][1]) elif mm.upper() == "VISCOSITY": prOpt.addAttributes([QgsField("Viscosity", QVariant.String)]) ppOpt.append(options[i][1]) elif mm.upper() == "DIFFUSIVITY": prOpt.addAttributes([QgsField("Diffusivity", QVariant.String)]) ppOpt.append(options[i][1]) elif mm.upper() == "SPECIFIC": if options[i][1].upper() == "GRAVITY": prOpt.addAttributes([QgsField("SpecGrav", QVariant.String)]) ppOpt.append(options[i][2]) elif mm.upper() == "TRIALS": prOpt.addAttributes([QgsField("Trials", QVariant.String)]) ppOpt.append(options[i][1]) elif mm.upper() == "HEADLOSS": prOpt.addAttributes([QgsField("Headloss", QVariant.String)]) ppOpt.append(options[i][1]) elif mm.upper() == "ACCURACY": prOpt.addAttributes([QgsField("Accuracy", QVariant.String)]) ppOpt.append(options[i][1]) elif mm.upper() == "UNBALANCED": prOpt.addAttributes([QgsField("Unbalanced", QVariant.String)]) if len(options[i]) > 2: ppOpt.append(options[i][1] + ' ' + options[i][2]) else: ppOpt.append(options[i][1]) elif mm.upper() == "PATTERN": prOpt.addAttributes([QgsField("PatID", QVariant.String)]) ppOpt.append(options[i][1]) elif mm.upper() == "TOLERANCE": prOpt.addAttributes([QgsField("Tolerance", QVariant.String)]) ppOpt.append(options[i][1]) elif mm.upper() == "MAP": prOpt.addAttributes([QgsField("Map", QVariant.String)]) ppOpt.append(options[i][1]) elif mm.upper() == "DEMAND": if options[i][1].upper() == "MULTIPLIER": prOpt.addAttributes([QgsField("DemMult", QVariant.String)]) ppOpt.append(options[i][2]) elif mm.upper() == "EMITTER": if options[i][1].upper() == "EXPONENT": prOpt.addAttributes([QgsField("EmitExp", QVariant.String)]) ppOpt.append(options[i][2]) elif mm.upper() == "CHECKFREQ": prOpt.addAttributes([QgsField("CheckFreq", QVariant.String)]) ppOpt.append(options[i][1]) elif mm.upper() == "MAXCHECK": prOpt.addAttributes([QgsField("MaxCheck", QVariant.String)]) ppOpt.append(options[i][1]) elif mm.upper() == "DAMPLIMIT": prOpt.addAttributes([QgsField("DampLimit", QVariant.String)]) ppOpt.append(options[i][1]) writeDBF(posOpt, [ppOpt], prOpt, saveFile, inpname, "_OPTIONS", idx) writeDBF(posRep, [ppRep], prRep, saveFile, inpname, "_REPORT", idx) #if times: writeDBF(posTimes, [ppTimes], prTimes, saveFile, inpname, "_TIMES", idx) #if energy: writeDBF(posE, [ppE], prE, saveFile, inpname, "_ENERGY", idx) #if optReactions: writeDBF(posO, [ppO], prO, saveFile, inpname, "_REACTIONS", idx) posMix = QgsVectorLayer("point?crs=EPSG:4326", "Mixing", "memory") prMix = posMix.dataProvider() fields = ["Tank_ID", "Model", "Fraction"] fieldsCode = [0, 0, 1] # 0 String, 1 Double createColumnsAttrb(prMix, fields, fieldsCode) writeDBF(posMix, ppMix, prMix, saveFile, inpname, "_MIXING", idx) posReact = QgsVectorLayer("point?crs=EPSG:4326", "ReactionsI", "memory") prReact = posReact.dataProvider() fields = ["Type", "Pipe/Tank", "Coeff."] fieldsCode = [0, 0, 1] createColumnsAttrb(prReact, fields, fieldsCode) writeDBF(posReact, ppReactions, prReact, saveFile, inpname, "_REACTIONS_I", idx) posSourc = QgsVectorLayer("point?crs=EPSG:4326", "Sources", "memory") prSourc = posSourc.dataProvider() fields = ["Node_ID", "Type", "Strength", "Pattern"] fieldsCode = [0, 0, 1, 0] createColumnsAttrb(prSourc, fields, fieldsCode) writeDBF(posSourc, ppSourc, prSourc, saveFile, inpname, "_SOURCES", idx) posRul = QgsVectorLayer("point?crs=EPSG:4326", "Rules", "memory") prRul = posRul.dataProvider() fields = ["Rule_ID", "Rule"] fieldsCode = [0, 0] createColumnsAttrb(prRul, fields, fieldsCode) writeDBF(posRul, ppRul, prRul, saveFile, inpname, "_RULES", idx) posQual = QgsVectorLayer("point?crs=EPSG:4326", "Sources", "memory") prQual = posQual.dataProvider() fields = ["Node_ID", "Init_Qual"] fieldsCode = [0, 1] createColumnsAttrb(prQual, fields, fieldsCode) writeDBF(posQual, ppQual, prQual, saveFile, inpname, "_QUALITY", idx) posStat = QgsVectorLayer("point?crs=EPSG:4326", "Status", "memory") prStat = posStat.dataProvider() fields = ["Link_ID", "Status/Setting"] fieldsCode = [0, 0] createColumnsAttrb(prStat, fields, fieldsCode) writeDBF(posStat, ppStat, prStat, saveFile, inpname, "_STATUS", idx) posEmit = QgsVectorLayer("point?crs=EPSG:4326", "Emitters", "memory") prEmit = posEmit.dataProvider() fields = ["Junc_ID", "Coeff."] fieldsCode = [0, 1] createColumnsAttrb(prEmit, fields, fieldsCode) writeDBF(posEmit, ppEmit, prEmit, saveFile, inpname, "_EMITTERS", idx) posCont = QgsVectorLayer("point?crs=EPSG:4326", "Controls", "memory") prCont = posCont.dataProvider() fields = ["Controls"] fieldsCode = [0] createColumnsAttrb(prCont, fields, fieldsCode) writeDBF(posCont, ppCont, prCont, saveFile, inpname, "_CONTROLS", idx) posPat = QgsVectorLayer("point?crs=EPSG:4326", "Patterns", "memory") prPat = posPat.dataProvider() fields = ["Pattern_ID", "Multipliers"] fieldsCode = [0, 0] createColumnsAttrb(prPat, fields, fieldsCode) writeDBF(posPat, ppPat, prPat, saveFile, inpname, "_PATTERNS", idx) posCurv = QgsVectorLayer("point?crs=EPSG:4326", "Curves", "memory") prCurv = posCurv.dataProvider() fields = ["Curve_ID", "X-Value", "Y-Value", "Type"] fieldsCode = [0, 0, 0, 0] createColumnsAttrb(prCurv, fields, fieldsCode) writeDBF(posCurv, ppCurv, prCurv, saveFile, inpname, "_CURVES", idx) # Write Valve Shapefile posValve = QgsVectorLayer("LineString?crs=EPSG:4326", "Valve", "memory") prValve = posValve.dataProvider() fields = ["ID", "NodeFrom", "NodeTo", "Diameter", "Type", "Setting", "MinorLoss"] fieldsCode = [0, 0, 0, 1, 0, 1, 1] createColumnsAttrb(prValve, fields, fieldsCode) posValve.startEditing() if d.getBinLinkValveCount() > 0: linkID = d.getBinLinkValveNameID() linkType = d.getBinLinkValveType() # valve type linkDiameter = d.getBinLinkValveDiameters() linkInitSett = d.getBinLinkValveSetting() # BinLinkValveSetting linkMinorloss = d.getBinLinkValveMinorLoss() for i, p in enumerate(d.getBinLinkValveIndex()): point1 = QgsPointXY(float(x[ndID.index(d.getBinLinkFromNode()[p])]), float(y[ndID.index(d.getBinLinkFromNode()[p])])) point2 = QgsPointXY(float(x[ndID.index(d.getBinLinkToNode()[p])]), float(y[ndID.index(d.getBinLinkToNode()[p])])) feature = QgsFeature() feature.setGeometry(QgsGeometry.fromPolylineXY([point1, point2])) feature.setAttributes( [linkID[i], ndlConn[0][p], ndlConn[1][p], linkDiameter[i], linkType[i], linkInitSett[i], linkMinorloss[i]]) prValve.addFeatures([feature]) QgsVectorFileWriter.writeAsVectorFormat(posValve, saveFile + "_valves" + '.shp', "utf-8", QgsCoordinateReferenceSystem(posValve.crs().authid()), "ESRI Shapefile") ll = QgsVectorLayer(saveFile + "_valves" + '.shp', inpname[:len(inpname) - 4] + "_valves", "ogr") QgsProject.instance().addMapLayer(ll, False) nvalves = QgsLayerTreeLayer(ll) idx.insertChildNode(0, nvalves) nvalves.setCustomProperty("showFeatureCount", True) ll.loadNamedStyle(plugin_path + "/qmls/" + 'valvesline' + ".qml") ll.triggerRepaint() # Write Pump Shapefile posPump = QgsVectorLayer("LineString?crs=EPSG:4326", "Pump", "memory") prPump = posPump.dataProvider() fields = ["ID", "NodeFrom", "NodeTo", "Power", "Pattern", "Curve"] fieldsCode = [0, 0, 0, 0, 0, 0] createColumnsAttrb(prPump, fields, fieldsCode) posPump.startEditing() if d.getBinLinkPumpCount() > 0: curveXY = d.getBinCurvesXY() curvesID = d.getBinCurvesNameID() a = curvesID b = [] for l in a: if l not in b: b.append(l) curvesIDunique = b CurvesTmpIndices = [] for p in range(0, len(curvesIDunique)): CurvesTmpIndices.append(curvesID.count(curvesIDunique[p])) curveIndices = [] Curve = d.getBinLinkPumpCurveNameID() for i in range(len(Curve)): curveIndices.append(curvesIDunique.index(Curve[i])) if d.getBinCurveCount(): CurvesTmpIndicesFinal = [] CurvesTmpIndicesFinal.append([CurvesTmpIndices[index] for index in curveIndices]) CurvesTmp = [] i = 0 for u in range(max(CurvesTmpIndicesFinal[0])): fields.append('Head' + str(u + 1)) fields.append('Flow' + str(u + 1)) fieldsCode.append(1) fieldsCode.append(1) if u < d.getBinCurveCount(): tmp1 = [] for p in range(CurvesTmpIndices[u]): tmp1.append([curveXY[i][0], curveXY[i][1]]) i = i + 1 CurvesTmp.append(tmp1) createColumnsAttrb(prPump, fields, fieldsCode) chPowerPump = d.getBinLinkPumpPower() pumpID = d.getBinLinkPumpNameID() patternsIDs = d.getBinLinkPumpPatterns() ppatt = d.getBinLinkPumpPatternsPumpID() linkID = d.getBinLinkNameID() for i, p in enumerate(d.getBinLinkPumpIndex()): Curve = [] power = [] pattern = [] pumpNameIDPower = d.getBinLinkPumpNameIDPower() if len(pumpNameIDPower) > 0: for uu in range(0, len(pumpNameIDPower)): if pumpNameIDPower[uu] == pumpID[i]: power = chPowerPump[uu] if len(patternsIDs) > 0: for uu in range(0, len(ppatt)): if ppatt[uu] == pumpID[i]: pattern = patternsIDs[uu] point1 = QgsPointXY(float(x[ndID.index(d.getBinLinkFromNode()[p])]), float(y[ndID.index(d.getBinLinkFromNode()[p])])) point2 = QgsPointXY(float(x[ndID.index(d.getBinLinkToNode()[p])]), float(y[ndID.index(d.getBinLinkToNode()[p])])) feature = QgsFeature() feature.setGeometry(QgsGeometry.fromPolylineXY([point1, point2])) if not Curve: Curve = 'NULL' if not power: power = 'NULL' if not pattern: pattern = 'NULL' if d.getBinCurveCount() > 0 and len(pumpNameIDPower) == 0: Curve = d.getBinLinkPumpCurveNameID()[i] curveIndex = curvesIDunique.index(Curve) feature.initAttributes(6 + sum(CurvesTmpIndices) * 2 + 1) feature.setAttribute(0, linkID[p]) feature.setAttribute(1, ndlConn[0][p]) feature.setAttribute(2, ndlConn[1][p]) feature.setAttribute(3, power) feature.setAttribute(4, pattern) feature.setAttribute(5, Curve) if d.getBinCurveCount() == 1: w = 6 for p in range(CurvesTmpIndices[curveIndex]): feature.setAttribute(w, CurvesTmp[curveIndex][p][0]) feature.setAttribute(w + 1, CurvesTmp[curveIndex][p][1]) w = w + 2 for j in range(d.getBinCurveCount() - 1): w = 6 for p in range(CurvesTmpIndices[curveIndex]): feature.setAttribute(w, CurvesTmp[curveIndex][p][0]) feature.setAttribute(w + 1, CurvesTmp[curveIndex][p][1]) w = w + 2 prPump.addFeatures([feature]) QgsVectorFileWriter.writeAsVectorFormat(posPump,saveFile+"_pumps"+'.shp', "utf-8", QgsCoordinateReferenceSystem(posPump.crs().authid()), "ESRI Shapefile") ll = QgsVectorLayer(saveFile + "_pumps" + '.shp', inpname[:len(inpname) - 4] + "_pumps", "ogr") QgsProject.instance().addMapLayer(ll, False) npump = QgsLayerTreeLayer(ll) idx.insertChildNode(0, npump) npump.setCustomProperty("showFeatureCount", True) ll.loadNamedStyle(plugin_path + "/qmls/" + 'pumpsline' + ".qml") ll.triggerRepaint() QgsVectorFileWriter.writeAsVectorFormat(posPipe,saveFile+"_pipes"+'.shp', "utf-8", QgsCoordinateReferenceSystem(posPipe.crs().authid()), "ESRI Shapefile") ll = QgsVectorLayer(saveFile + "_pipes" + '.shp', inpname[:len(inpname) - 4] + "_pipes", "ogr") QgsProject.instance().addMapLayer(ll, False) npipe = QgsLayerTreeLayer(ll) idx.insertChildNode(0, npipe) npipe.setCustomProperty("showFeatureCount", True) ll.loadNamedStyle(plugin_path + "/qmls/" + 'pipes' + ".qml") ll.triggerRepaint() iface.mapCanvas().setExtent(ll.extent()) QgsVectorFileWriter.writeAsVectorFormat(posJunction,saveFile+"_junctions"+'.shp', "utf-8", QgsCoordinateReferenceSystem(posJunction.crs().authid()), "ESRI Shapefile") ll = QgsVectorLayer(saveFile + "_junctions" + '.shp', inpname[:len(inpname) - 4] + "_junctions", "ogr") QgsProject.instance().addMapLayer(ll, False) njunc = QgsLayerTreeLayer(ll) idx.insertChildNode(0, njunc) njunc.setCustomProperty("showFeatureCount", True) ll.loadNamedStyle(plugin_path + "/qmls/" + 'junctions' + ".qml") ll.triggerRepaint() QgsVectorFileWriter.writeAsVectorFormat(posTank, saveFile + "_tanks" + '.shp', "utf-8", QgsCoordinateReferenceSystem(posTank.crs().authid()), "ESRI Shapefile") ll = QgsVectorLayer(saveFile + "_tanks" + '.shp', inpname[:len(inpname) - 4] + "_tanks", "ogr") QgsProject.instance().addMapLayer(ll, False) ntanks = QgsLayerTreeLayer(ll) idx.insertChildNode(0, ntanks) ntanks.setCustomProperty("showFeatureCount", True) ll.loadNamedStyle(plugin_path + "/qmls/" + 'tanks' + ".qml") ll.triggerRepaint() QgsVectorFileWriter.writeAsVectorFormat(posReservoirs, saveFile + "_reservoirs" + '.shp', "utf-8", QgsCoordinateReferenceSystem(posReservoirs.crs().authid()), "ESRI Shapefile") ll = QgsVectorLayer(saveFile + "_reservoirs" + '.shp', inpname[:len(inpname) - 4] + "_reservoirs", "ogr") QgsProject.instance().addMapLayer(ll, False) nres = QgsLayerTreeLayer(ll) idx.insertChildNode(0, nres) nres.setCustomProperty("showFeatureCount", True) ll.loadNamedStyle(plugin_path + "/qmls/" + 'reservoirs' + ".qml") ll.triggerRepaint()
def processAlgorithm(self, parameters, context, feedback): source = self.parameterAsSource(parameters, self.PrmInputLayer, context) shapetype = self.parameterAsInt(parameters, self.PrmShapeType, context) sidescol = self.parameterAsString(parameters, self.PrmNumberOfSidesField, context) anglecol = self.parameterAsString(parameters, self.PrmStartingAngleField, context) distcol = self.parameterAsString(parameters, self.PrmRadiusField, context) sides = self.parameterAsInt(parameters, self.PrmDefaultNumberOfSides, context) angle = self.parameterAsDouble(parameters, self.PrmDefaultStartingAngle, context) defaultDist = self.parameterAsInt(parameters, self.PrmDefaultRadius, context) unitOfDist = self.parameterAsInt(parameters, self.PrmUnitsOfMeasure, context) export_geom = self.parameterAsBool(parameters, self.PrmExportInputGeometry, context) measureFactor = conversionToMeters(unitOfDist) defaultDist *= measureFactor srcCRS = source.sourceCrs() fields = source.fields() if export_geom: names = fields.names() name_x, name_y = settings.getGeomNames(names) fields.append(QgsField(name_x, QVariant.Double)) fields.append(QgsField(name_y, QVariant.Double)) if shapetype == 0: (sink, dest_id) = self.parameterAsSink(parameters, self.PrmOutputLayer, context, fields, QgsWkbTypes.Polygon, srcCRS) else: (sink, dest_id) = self.parameterAsSink(parameters, self.PrmOutputLayer, context, fields, QgsWkbTypes.LineString, srcCRS) if srcCRS != epsg4326: geomTo4326 = QgsCoordinateTransform(srcCRS, epsg4326, QgsProject.instance()) toSinkCrs = QgsCoordinateTransform(epsg4326, srcCRS, QgsProject.instance()) featureCount = source.featureCount() total = 100.0 / featureCount if featureCount else 0 iterator = source.getFeatures() numbad = 0 for cnt, feature in enumerate(iterator): if feedback.isCanceled(): break try: pt = feature.geometry().asPoint() pt_orig_x = pt.x() pt_orig_y = pt.y() if srcCRS != epsg4326: pt = geomTo4326.transform(pt.x(), pt.y()) if sidescol: s = int(feature[sidescol]) else: s = sides if anglecol: startangle = float(feature[anglecol]) else: startangle = angle if distcol: d = float(feature[distcol]) * measureFactor else: d = defaultDist pts = [] i = s while i >= 0: a = (i * 360.0 / s) + startangle i -= 1 g = geod.Direct(pt.y(), pt.x(), a, d, Geodesic.LATITUDE | Geodesic.LONGITUDE) pts.append(QgsPointXY(g['lon2'], g['lat2'])) # If the Output crs is not 4326 transform the points to the proper crs if srcCRS != epsg4326: for x, ptout in enumerate(pts): pts[x] = toSinkCrs.transform(ptout) f = QgsFeature() if shapetype == 0: f.setGeometry(QgsGeometry.fromPolygonXY([pts])) else: f.setGeometry(QgsGeometry.fromPolylineXY(pts)) attr = feature.attributes() if export_geom: attr.append(pt_orig_x) attr.append(pt_orig_y) f.setAttributes(attr) sink.addFeature(f) except: numbad += 1 if cnt % 100 == 0: feedback.setProgress(int(cnt * total)) if numbad > 0: feedback.pushInfo( tr("{} out of {} features had invalid parameters and were ignored." .format(numbad, featureCount))) return {self.PrmOutputLayer: dest_id}
def processAlgorithm(self, parameters, context, feedback): """ Here is where the processing itself takes place. """ # Retrieve the feature source and sink. The 'dest_id' variable is used # to uniquely identify the feature sink, and must be included in the # dictionary returned by the processAlgorithm function. rep_GTFS = self.parameterAsFile(parameters, self.REP_GTFS, context) debut_periode=self.parameterAsString(parameters,self.DEBUT_PERIODE,context) fin_periode=self.parameterAsString(parameters,self.FIN_PERIODE,context) t1=self.parameterAsString(parameters,self.T1,context) t2=self.parameterAsString(parameters,self.T2,context) prefixe=self.parameterAsString(parameters,self.PREFIXE,context) proj=self.parameterAsCrs(parameters,self.PROJ,context) rep_sortie = self.parameterAsFile(parameters, self.REP_SORTIE, context) encodage = self.parameterAsString(parameters, self.ENCODAGE, context) debut_periode=QDate.fromString(debut_periode, "d/M/yyyy").toPyDate() fin_periode=QDate.fromString(fin_periode, "d/M/yyyy").toPyDate() t1=QTime.fromString(t1,"h:m:s") t2=QTime.fromString(t2,"h:m:s") nom_rep=rep_GTFS lname=prefixe isnodes=True islines=True if "stops.txt" in os.listdir(nom_rep) : fich_noeuds=io.open(nom_rep+"/stops.txt","r",encoding=encodage) t_noeuds=QgsFields() t_noeuds.append(QgsField(self.tr("ident"),QVariant.String,len=15)) t_noeuds.append(QgsField(self.tr("name"),QVariant.String,len=40)) t_noeuds.append(QgsField(self.tr("arrivals"),QVariant.Double)) t_noeuds.append(QgsField(self.tr("departures"),QVariant.Double)) t_links=QgsFields() t_links.append(QgsField(self.tr("line_num"),QVariant.String,len=15)) t_links.append(QgsField(self.tr("ligne_name"),QVariant.String,len=50)) t_links.append(QgsField("i",QVariant.String,len=15)) t_links.append(QgsField("j",QVariant.String,len=15)) t_links.append(QgsField(self.tr("lines_count"),QVariant.Int)) t_links.append(QgsField(self.tr("services_count"),QVariant.Int)) t_links.append(QgsField("delta1",QVariant.Int)) t_links.append(QgsField("delta2",QVariant.Int)) src=QgsCoordinateReferenceSystem("EPSG:4326") dest=QgsCoordinateReferenceSystem(proj) xtr=QgsCoordinateTransform(src,dest,QgsProject.instance()) t_arcs=QgsFields() t_arcs.append(QgsField("i",QVariant.String,len=15)) t_arcs.append(QgsField("j",QVariant.String,len=15)) t_arcs.append(QgsField("ij",QVariant.String,len=40)) l_noeuds=QgsVectorFileWriter(rep_sortie+"/"+lname+"_stops.shp","UTF-8",t_noeuds,QgsWkbTypes.Point,dest,"ESRI Shapefile") l_arcs=QgsVectorFileWriter(rep_sortie+"/"+lname+"_arcs.shp","UTF-8",t_arcs,QgsWkbTypes.MultiLineString,dest,"ESRI Shapefile") l_links=QgsVectorFileWriter(rep_sortie+"/"+lname+"_lines.shp","UTF-8",t_links,QgsWkbTypes.MultiLineString,dest,"ESRI Shapefile") arrets={} feedback.setProgressText("Lecture des stops") for i,ligne in enumerate(fich_noeuds): if i==0: entete=re.split(",(?=(?:[^\"]*\"[^\"]*\")*[^\"]*$)",ligne[:-1]) for e1,e in enumerate(entete): entete[e1]=entete[e1].strip("\"") idx=entete.index('stop_lon') idy=entete.index('stop_lat') iid=entete.index('stop_id') iname=entete.index('stop_name') else: elements=re.split(",(?=(?:[^\"]*\"[^\"]*\")*[^\"]*$)",ligne[:-1]) arrets[elements[iid]]=[elements[iid],elements[iname].strip("\""),elements[idx].strip("\""),elements[idy].strip("\""),0.0,0.0] calendar={} if ("calendar.txt" in os.listdir(nom_rep)): fich_calendar=io.open(nom_rep+"/calendar.txt","r",encoding=encodage) feedback.setProgressText(self.tr("Reading calendars...")) for i,cal in enumerate(fich_calendar): if i==0: entete=cal.strip().split(',') iid=entete.index('service_id') idato=entete.index('start_date') idatd=entete.index('end_date') i1=entete.index('monday') i2=entete.index('tuesday') i3=entete.index('wednesday') i4=entete.index('thursday') i5=entete.index('friday') i6=entete.index('saturday') i7=entete.index('sunday') else: elements=cal.strip().split(",") dato=elements[idato] dato=datetime.date(int(dato[0:4]),int(dato[4:6]),int(dato[6:8])) datd=elements[idatd] datd=datetime.date(int(datd[0:4]),int(datd[4:6]),int(datd[6:8])) calendar[elements[iid]]=[elements[iid],dato,datd,elements[i1],elements[i2],elements [i3],elements[i4],elements[i5],elements[i6],elements[i7]] calendar_dates={} calendar_dates2={} if ("calendar_dates.txt" in os.listdir(nom_rep)): fich_calendar_dates=io.open(nom_rep+"/calendar_dates.txt","r",encoding=encodage) feedback.setProgressText(self.tr("reading calendar dates...")) for i,calendar_date in enumerate(fich_calendar_dates): if i==0: entete=calendar_date.strip().split(',') for i1,i2 in enumerate(entete): entete[i1]=i2.strip('"') iid=entete.index('service_id') idate=entete.index('date') iex=entete.index('exception_type') else: elements=calendar_date.strip().split(",") vdate=elements[idate].strip('"') vdate=datetime.date(int(vdate[0:4]),int(vdate[4:6]),int(vdate[6:8])) calendar_dates[(elements[iid],vdate,elements[iex])]=[elements[iid],vdate,elements[iex]] if elements[iex]=="1": if elements[iid] not in calendar_dates2: calendar_dates2[elements[iid]]=[] calendar_dates2[elements[iid]].append([elements[iid],vdate]) routes={} test_l=int(("routes.txt" in os.listdir(nom_rep))*("trips.txt" in os.listdir(nom_rep))* ("stop_times.txt" in os.listdir(nom_rep))) if test_l==1 and islines: fich_routes=io.open(nom_rep+"/routes.txt","r",encoding=encodage) feedback.setProgressText(self.tr("Reading routes...")) for i,route in enumerate(fich_routes): if i==0: entete=route.strip().split(',') for i1,i2 in enumerate(entete): entete[i1]=i2.strip('"') iid=entete.index('route_id') if 'route_short_name' not in entete: iname=entete.index('route_long_name') else: iname=entete.index('route_short_name') if 'route_long_name' not in entete: ilong=entete.index('route_desc') else: ilong=entete.index('route_long_name') else: elements=route.strip().split(",") if elements[iname]=="": elements[iname]=u' ' if elements[ilong]=="": elements[ilong]=u' ' routes[elements[iid]]=[elements[iid],elements[iname],elements[ilong]] trips={} fich_trips=io.open(nom_rep+"/trips.txt","r",encoding=encodage) feedback.setProgressText(self.tr("Reading trips...")) for i,trip in enumerate(fich_trips): if i==0: entete=trip.strip(" ").split(',') for i1,i2 in enumerate(entete): entete[i1]=i2.strip('"') entete[i1]=i2.strip('\n').strip('\r') iid=entete.index('route_id') itrip=entete.index('trip_id') iservice=entete.index('service_id') if 'shape_id' in entete: ishape=entete.index('shape_id') else: elements=trip.strip(" ").strip('\n').strip('\r').split(",") trips[elements[itrip]]=[elements[itrip],elements[iid],elements[iservice]] stop_times={} fich_stop_times=io.open(nom_rep+"/stop_times.txt","r",encoding=encodage) id_trip=None id_stop=None hi2=None segments={} links={} feedback.setProgressText(self.tr("Reading stop times...")) nb=float(os.stat(nom_rep+"/stop_times.txt").st_size) for i,stop_time in enumerate(fich_stop_times): if i==0: entete=stop_time.strip().split(",") iid=entete.index('trip_id') iharr=entete.index('arrival_time') ihdep=entete.index('departure_time') istop=entete.index('stop_id') iseq=entete.index('stop_sequence') else: #progress.setPercentage(float(fich_stop_times.tell())*100/nb) elements=stop_time.strip().split(',') #print((istop,iid,elements[istop],elements[iid])) if elements[istop] in arrets and trips[elements[iid]][1] in routes: id_stop2=elements[istop] id_trip2=elements[iid] ligne=trips[elements[iid]][1] num_ligne=routes[ligne][1].strip() descr=routes[ligne][2].strip() hi1=QTime(int(elements[ihdep][0:2]),int(elements[ihdep][3:5]),int(elements[ihdep][6:8])) hj=QTime(int(elements[iharr][0:2]),int(elements[iharr][3:5]),int(elements[iharr][6:8])) if (id_trip2==id_trip): nbservices=0 nbs1=0 nbs2=0 if ("calendar.txt" in os.listdir(nom_rep)): if trips[elements[iid]][2] in calendar: dp=calendar[trips[elements[iid]][2]][1] fp=calendar[trips[elements[iid]][2]][2] nb_jours=(fin_periode-debut_periode).days for k in range(nb_jours+1): date_offre=debut_periode+datetime.timedelta(days=k) if dp<=date_offre<=fp: jour=date_offre.isoweekday() if int(calendar[trips[id_trip][2]][2+jour])==1: nbservices+=1 if (trips[id_trip][2],date_offre,'1') in calendar_dates: nbservices+=1 if (trips[id_trip][2],date_offre,'2') in calendar_dates: nbservices+=-1 elif trips[elements[iid]][2] in calendar_dates2: for k in calendar_dates2[trips[elements[iid]][2]]: nbservices+=1 segment_id=(num_ligne, id_stop,id_stop2) if (t1<=hi2<=t2): nbs1=nbservices if (t1<=hj<=t2): nbs2=nbservices if (id_stop,id_stop2) not in links: links[(id_stop,id_stop2)]={} if num_ligne not in links[(id_stop,id_stop2)]: links[(id_stop,id_stop2)][num_ligne]=(1,nbs1,descr) else: seg= links[(id_stop,id_stop2)][num_ligne] links[(id_stop,id_stop2)][num_ligne]=(1,seg[1]+nbs1,descr) arrets[id_stop][5]+=nbs1 arrets[id_stop2][4]+=nbs2 hi2=hi1 id_stop=id_stop2 id_trip=id_trip2 feedback.setProgressText(self.tr("Generating arcs and lines...")) for i,s in enumerate(links): i1=0 i2=0 g_links=QgsFeature() g_arcs=QgsFeature() #print([unicode(s[0]),unicode(s[1]),unicode(s[0])+"-"+unicode(s[1])]) g_links.setGeometry(QgsGeometry.fromPolylineXY([(xtr.transform(QgsPointXY(float(arrets[s[0]][2]),float(arrets[s[0]][3])))),xtr.transform(QgsPointXY(float(arrets[s[1]][2]),float(arrets[s[1]][3])))])) g_arcs.setAttributes([unicode(s[0]),unicode(s[1]),unicode(s[0])+"-"+unicode(s[1])]) g_arcs.setGeometry(g_links.geometry()) if g_arcs.geometry().length()<1600000: l_arcs.addFeature(g_arcs) for t in links[s]: if t=="" or t==None: tt= " " else: tt=t #print([tt.decode("cp1252"),links[s][t][2].decode("cp1252"),unicode(s[0]),unicode(s[1]),links[s][t][0],links[s][t][1],i1,i2]) try: g_links.setAttributes([unicode(t),unicode(links[s][t][2]),unicode(s[0]),unicode(s[1]),links[s][t][0],links[s][t][1],i1,i2]) except: print(t,links[s][t][2]) i1+=1 i2+=links[s][t][1] if g_links.geometry().length()<1600000: l_links.addFeature(g_links) del(stop_times) del(trips) del(routes) del(calendar) del(calendar_dates) if (isnodes): for s in arrets: g_noeuds=QgsFeature() g_noeuds.setGeometry(QgsGeometry.fromPointXY(xtr.transform(QgsPointXY(float(arrets[s][2]),float(arrets[s][3]))))) #print([unicode(arrets[s][0]),arrets[s][1].decode('cp1252'),arrets[s][4],arrets[s][5]]) try: g_noeuds.setAttributes([unicode(arrets[s][0]),unicode(arrets[s][1]),arrets[s][4],arrets[s][5]]) except: print(arrets[s][1]) l_noeuds.addFeature(g_noeuds) del(arrets) del(l_noeuds) del(l_links) del(l_arcs) return {self.REP_GTFS: self.REP_GTFS}
def processAlgorithm(self, parameters, context, feedback): """ Here is where the processing itself takes place. """ # Retrieve the feature source and sink. The 'dest_id' variable is used # to uniquely identify the feature sink, and must be included in the # dictionary returned by the processAlgorithm function. reseau = self.parameterAsVectorLayer(parameters, self.RESEAU, context) fenetre=self.parameterAsExtent(parameters,self.FENETRE,context) cout_i=QgsExpression(self.parameterAsExpression(parameters,self.COUT_I,context)) cout_j=QgsExpression(self.parameterAsExpression(parameters,self.COUT_J,context)) sens=QgsExpression(self.parameterAsExpression(parameters,self.SENS,context)) diffusion=QgsExpression(self.parameterAsExpression(parameters,self.DIFFUSION,context)) traversabilite=QgsExpression(self.parameterAsExpression(parameters,self.TRAVERSABILITE,context)) nb_pixels_x=self.parameterAsInt(parameters,self.NB_PIXELS_X,context) nb_pixels_y=self.parameterAsInt(parameters,self.NB_PIXELS_Y,context) taille_pixel_x=self.parameterAsDouble(parameters,self.TAILLE_PIXEL_X,context) taille_pixel_y=self.parameterAsDouble(parameters,self.TAILLE_PIXEL_Y,context) decimales=self.parameterAsInt(parameters,self.DECIMALES,context) rayon=self.parameterAsDouble(parameters,self.RAYON,context) vitesse_diffusion=QgsExpression(self.parameterAsExpression(parameters,self.VITESSE_DIFFUSION,context)) intraversable = self.parameterAsBool(parameters, self.INTRAVERSABLE, context) resultat = self.parameterAsFileOutput(parameters, self.RESULTAT,context) # Compute the number of steps to display within the progress bar and formule_cout_i=self.createExpressionContext(parameters,context) cout_i.prepare(formule_cout_i) formule_cout_j=self.createExpressionContext(parameters,context) cout_j.prepare(formule_cout_j) formule_sens=self.createExpressionContext(parameters,context) sens.prepare(formule_sens) formule_diffusion=self.createExpressionContext(parameters,context) diffusion.prepare(formule_diffusion) formule_traversabilite=self.createExpressionContext(parameters,context) traversabilite.prepare(formule_traversabilite) formule_vitesse_diffusion=self.createExpressionContext(parameters,context) vitesse_diffusion.prepare(formule_vitesse_diffusion) grille=numpy.array([[-9999.0]*nb_pixels_y]*nb_pixels_x) grille_distance=numpy.array([[1e38]*nb_pixels_y]*nb_pixels_x) rep=os.path.dirname(resultat) a=fenetre.asWktCoordinates().split(',') fenetre2=fenetre#QgsRectangle(float(a[0]),float(a[2]),float(a[1]),float(a[3])) p1=a[0].split() p2=a[1].split() ll=(float(p1[0]),float(p1[1])) hauteur=float(p2[1])-float(p1[1]) largeur=float(p2[0])-float(p1[0]) if not(taille_pixel_x<=0): nb_pixels_x=int(largeur/taille_pixel_x) else: taille_pixel_x=float(largeur/nb_pixels_x) if not(taille_pixel_y<=0): nb_pixels_y=int(hauteur/taille_pixel_y) else: taille_pixel_y=float(hauteur/nb_pixels_y) layer=reseau if layer.type()==QgsMapLayer.VectorLayer: if not layer==None: if layer.geometryType()==1: simple=QgsSimplifyMethod() simple.setMethodType(QgsSimplifyMethod.PreserveTopology) simple.setTolerance(min(taille_pixel_x,taille_pixel_y)/2) texte=diffusion.dump()+' in (\'1\',\'2\',\'3\') and ('+cout_j.dump()+' IS NOT NULL and '+sens.dump()+' in (\'1\',\'3\')) ' request=(QgsFeatureRequest().setFilterRect(fenetre2)).setFilterExpression(texte).setSimplifyMethod(simple).setFlags(QgsFeatureRequest.ExactIntersect) req_intra=(QgsFeatureRequest().setFilterRect(fenetre2)).setFilterExpression(traversabilite.dump()+' in (\'1\',\'2\',\'3\')').setSimplifyMethod(simple).setFlags(QgsFeatureRequest.ExactIntersect) features=[f for f in layer.getFeatures(request)] if intraversable: features_intra=[f for f in layer.getFeatures(req_intra)] else: features_intra=[] for k,i in enumerate(features): formule_sens.setFeature(i) formule_cout_i.setFeature(i) formule_cout_j.setFeature(i) formule_vitesse_diffusion.setFeature(i) formule_diffusion.setFeature(i) formule_traversabilite.setFeature(i) var_diffusion=diffusion.evaluate(formule_diffusion) var_sens=sens.evaluate(formule_sens) var_traversabilite=traversabilite.evaluate(formule_traversabilite) ti=cout_i.evaluate(formule_cout_i) tj=cout_j.evaluate(formule_cout_j) var_vitesse_diffusion=vitesse_diffusion.evaluate(formule_vitesse_diffusion) speed=60/(1000*var_vitesse_diffusion) if var_sens in ['1','2','3'] : geom=i.geometry() zone=geom.buffer(rayon,12).boundingBox() deltax=int((zone.xMinimum()-ll[0])/taille_pixel_x) deltay=int((zone.yMinimum()-ll[1])/taille_pixel_y) dx=int(zone.width()/taille_pixel_x) dy=int(zone.height()/taille_pixel_y) l1=geom.length() if geom.wkbType()==QgsWkbTypes.MultiLineString: geom_l=geom.asMultiPolyline() else: geom_l=geom.asPolyline() for p in range(dx): d2x=deltax+p for q in range(dy): d2y=deltay+q if 0<=d2x<nb_pixels_x and 0<=d2y<nb_pixels_y: pt1=QgsGeometry.fromPointXY(QgsPointXY(ll[0]+(d2x+0.5)*taille_pixel_x,ll[1]+(d2y+0.5)*taille_pixel_y)) res=geom.closestSegmentWithContext(pt1.asPoint()) d=round(res[0],decimales) if d<=grille_distance[d2x,d2y] and d<rayon*rayon: if d>0 and l1>0: pt2=res[1] #feedback.setProgressText(geom.asWkt()) if geom.wkbType()==QgsWkbTypes.MultiLineString: num_poly=-1 npts=0 for k,id_poly in enumerate(geom_l): if res[2]<npts+len(id_poly): infos_poly=(k,res[2]) else: npts+=len(id_poly) #feedback.setProgressText(str(infos_poly[0])+"-"+str(infos_poly[1])+"-"+str(npts)) geoma=geom_l[infos_poly[0]][:(infos_poly[1]-npts)]+[pt2] else: geoma=geom_l[:res[2]]+[pt2] #geoma=QgsGeometry(geom) #geoma.insertVertex(pt2[0],pt2[1],res[2]) l2=QgsGeometry.fromPolylineXY(geoma).length() if res[2]==0: pt3=geom.vertexAt(res[2]) pt4=geom.vertexAt(res[2]+1) else: try: pt3=geom.vertexAt(res[2]-1) pt4=geom.vertexAt(res[2]) except: print(res,geom_l) pt3=geom_l[res[2]-1] pt4=geom_l[res[2]] p1=pt1.asPoint() test_sens=(pt4.x()-pt3.x())*(p1.y()-pt2.y())-(p1.x()-pt2.x())*(pt4.y()-pt3.y()) if var_sens in ['1','3'] and not tj==None: if (var_diffusion in ['1','3'] and test_sens<=0) or (var_diffusion in ['2','3'] and test_sens>=0): if not tj==None: if not ti==None: t=tj*(l2/l1)+ti*(1-(l2/l1))+math.sqrt(d)*speed l3=QgsGeometry.fromPolylineXY([pt1.asPoint(),QgsPointXY(pt2)]) result_test=False if l3!=None: if len(features_intra)>0: for intra in features_intra: if intra.geometry().intersects(l3): result_test=True break if result_test==False: if (t<grille[d2x,d2y] and d==grille_distance[d2x,d2y]) or d<grille_distance[d2x,d2y]: grille_distance[d2x,d2y] =d grille[d2x,d2y] =t sortie=os.path.splitext(resultat) fichier_grille=open(sortie[0]+sortie[1],'w') fichier_grille.write("NCOLS {0:d}\nNROWS {1:d}\nXLLCORNER {2}\nYLLCORNER {3}\nDX {4}\nDY {5}\nNODATA_VALUE -9999\n".format(nb_pixels_x,nb_pixels_y,ll[0],ll[1],taille_pixel_x,taille_pixel_y)) fichier_grille2=open(sortie[0]+"_dist"+sortie[1],'w') fichier_grille2.write("NCOLS {0:d}\nNROWS {1:d}\nXLLCORNER {2}\nYLLCORNER {3}\nDX {4}\nDY {5}\nNODATA_VALUE -9999\n".format(nb_pixels_x,nb_pixels_y,ll[0],ll[1],taille_pixel_x,taille_pixel_y)) g1=numpy.rot90(grille,1) #g1=numpy.flipud(g1) g2=numpy.rot90(grille_distance,1) #g2=numpy.flipud(g2) for i in g1: fichier_grille.write(" ".join([str(ii) for ii in i])+"\n") fichier_grille.close() for i in g2: fichier_grille2.write(" ".join([str(math.sqrt(ii)) for ii in i])+"\n") fichier_grille2.close() fichier_prj=open(sortie[0]+".prj",'w') fichier2_prj=open(sortie[0]+"_dist.prj",'w') fichier_prj.write(layer.crs().toWkt()) fichier2_prj.write(layer.crs().toWkt()) fichier_prj.close() fichier2_prj.close() nom_sortie=os.path.basename(sortie[0]) rlayer=QgsRasterLayer(resultat,nom_sortie) return {self.RESULTAT: fichier_grille}
def processFeature(self, feature, feedback): if feature.hasGeometry(): geom = feature.geometry() geomType = QgsWkbTypes.flatType(geom.wkbType()) newGeom = None if geomType == QgsWkbTypes.Point: points = self._gridify([geom.asPoint()], self.h_spacing, self.v_spacing) newGeom = QgsGeometry.fromPoint(points[0]) elif geomType == QgsWkbTypes.MultiPoint: points = self._gridify(geom.asMultiPoint(), self.h_spacing, self.v_spacing) newGeom = QgsGeometry.fromMultiPoint(points) elif geomType == QgsWkbTypes.LineString: points = self._gridify(geom.asPolyline(), self.h_spacing, self.v_spacing) if len(points) < 2: feedback.reportError(self.tr('Failed to gridify feature with FID {0}').format(feature.id())) newGeom = None else: newGeom = QgsGeometry.fromPolylineXY(points) elif geomType == QgsWkbTypes.MultiLineString: polyline = [] for line in geom.asMultiPolyline(): points = self._gridify(line, self.h_spacing, self.v_spacing) if len(points) > 1: polyline.append(points) if len(polyline) <= 0: feedback.reportError(self.tr('Failed to gridify feature with FID {0}').format(feature.id())) newGeom = None else: newGeom = QgsGeometry.fromMultiPolyline(polyline) elif geomType == QgsWkbTypes.Polygon: polygon = [] for line in geom.asPolygon(): points = self._gridify(line, self.h_spacing, self.v_spacing) if len(points) > 1: polygon.append(points) if len(polygon) <= 0: feedback.reportError(self.tr('Failed to gridify feature with FID {0}').format(feature.id())) newGeom = None else: newGeom = QgsGeometry.fromPolygon(polygon) elif geomType == QgsWkbTypes.MultiPolygon: multipolygon = [] for polygon in geom.asMultiPolygon(): newPolygon = [] for line in polygon: points = self._gridify(line, self.h_spacing, self.v_spacing) if len(points) > 2: newPolygon.append(points) if len(newPolygon) > 0: multipolygon.append(newPolygon) if len(multipolygon) <= 0: feedback.reportError(self.tr('Failed to gridify feature with FID {0}').format(feature.id())) newGeom = None else: newGeom = QgsGeometry.fromMultiPolygon(multipolygon) if newGeom is not None: feature.setGeometry(newGeom) else: feature.clearGeometry() return feature
def createQgLineFeature(self, vertices): line = QgsGeometry.fromPolylineXY(vertices) qgFeat = QgsFeature() qgFeat.setGeometry(line) return qgFeat
def updateLine(self, points): self.rubberband.setToGeometry(QgsGeometry.fromPolylineXY(points), None) self.drawnLine = self.createDigiFeature(points) self.drawStueMarker(points[0]) self.drawStueMarker(points[1])
def getShape(self, shpExtent=None, AzimuthToCentreLine=None, offset=None): TOMsMessageLog.logMessage("In getShape ... ", level=Qgis.Info) feature = self.currFeature restGeomType = self.currRestGeomType orientation = self.currBayOrientation if shpExtent is None: shpExtent = self.BayWidth if AzimuthToCentreLine is None: AzimuthToCentreLine = self.currAzimuthToCentreLine if offset is None: offset = self.BayOffsetFromKerb """ Logic is : For vertex 0, Move for defined distance (typically 0.25m) in direction "AzimuthToCentreLine" and create point 1 Move for bay width (typically 2.0m) in direction "AzimuthToCentreLine and create point 2 Calculate Azimuth for line between vertex 0 and vertex 1 Calc difference in Azimuths and decide < or > 180 (to indicate which side of kerb line to generate bay) For each vertex (starting at 1) Calculate Azimuth for current vertex and previous Calculate perpendicular to centre of road (using knowledge of which side of kerb line generated above) Move for bay width (typically 2.0m) along perpendicular and create point For last vertex Move for defined distance (typically 0.25m) along perpendicular and create last point """ line = generateGeometryUtils.getLineForAz(feature) # TOMsMessageLog.logMessage("In getDisplayGeometry: nr of pts = " + str(len(line)), level=Qgis.Info) if len(line) == 0: return 0 # Now have a valid set of points ptsList = [] parallelPtsList = [] nextAz = 0 diffEchelonAz = 0 # now loop through each of the vertices and process as required. New geometry points are added to ptsList for i in range(len(line) - 1): # TOMsMessageLog.logMessage("In getDisplayGeometry: i = " + str(i), level=Qgis.Info) Az = generateGeometryUtils.checkDegrees(line[i].azimuth(line[i + 1])) # TOMsMessageLog.logMessage("In getShape: geometry: " + str(line[i].x()) + ":" + str(line[i].y()) + " " + str(line[i+1].x()) + ":" + str(line[i+1].y()) + " " + str(Az), level=Qgis.Info) # if this is the first point if i == 0: # determine which way to turn towards CL # TOMsMessageLog.logMessage("In generate_display_geometry: considering first point", level=Qgis.Info) Turn = generateGeometryUtils.turnToCL(Az, AzimuthToCentreLine) newAz = generateGeometryUtils.checkDegrees(Az + Turn) # TOMsMessageLog.logMessage("In getShape: newAz: " + str(newAz) + "; turn is " + str(Turn), level=Qgis.Info) cosa, cosb = generateGeometryUtils.cosdir_azim(newAz) # TOMsMessageLog.logMessage("In generate_display_geometry: cosa : " + str(cosa) + " " + str(cosb), level=Qgis.Info) # dx = float(offset) * cosa # dy = float(offset) * cosb # TOMsMessageLog.logMessage("In generate_display_geometry: dx: " + str(dx) + " dy: " + str(dy), level=Qgis.Info) ptsList.append( QgsPointXY(line[i].x() + (float(offset) * cosa), line[i].y() + (float(offset) * cosb))) parallelPtsList.append( QgsPointXY(line[i].x() + (float(offset) * cosa), line[i].y() + (float(offset) * cosb))) # TOMsMessageLog.logMessage("In geomType: added point 1 ", level=Qgis.Info) # Now add the point at the extent. If it is an echelon bay: # a. calculate the difference between the first Az and the echelon Az (??), and # b. adjust the angle # c. *** also need to adjust the length *** Not yet implemented # if restGeomType == 5 or restGeomType == 25: # echelon if restGeomType in [5, 25]: # echelon # TOMsMessageLog.logMessage("In getShape: orientation: " + str(orientation), level=Qgis.Info) if self.is_float(orientation) == False: orientation = AzimuthToCentreLine # TOMsMessageLog.logMessage("In getShape: orientation: " + str(float(orientation)), level=Qgis.Info) diffEchelonAz1 = float(orientation) - newAz # TOMsMessageLog.logMessage("In getShape: diffEchelonAz1: " + str(diffEchelonAz1), level=Qgis.Info) diffEchelonAz = generateGeometryUtils.checkDegrees(diffEchelonAz1) #TOMsMessageLog.logMessage("In getShape: newAz: " + str(newAz) + " diffEchelonAz1: " + str(diffEchelonAz1) + " diffEchelonAz: " + str(diffEchelonAz), # level=Qgis.Info) newAz = generateGeometryUtils.checkDegrees(newAz + diffEchelonAz) #TOMsMessageLog.logMessage("In getShape: newAz: " + str(newAz) + " diffEchelonAz: " + str(diffEchelonAz), # level=Qgis.Info) cosa, cosb = generateGeometryUtils.cosdir_azim(newAz) ptsList.append( QgsPointXY(line[i].x() + (float(shpExtent) * cosa), line[i].y() + (float(shpExtent) * cosb))) # TOMsMessageLog.logMessage("In geomType: added point 2 ", level=Qgis.Info) # ptsList.append(newPoint) # TOMsMessageLog.logMessage("In geomType: after append ", level=Qgis.Info) # ptsList.append(QgsPoint(line[i].x()+(float(bayWidth)*cosa), line[i].y()+(float(bayWidth)*cosb))) else: # now pass along the feature # TOMsMessageLog.logMessage("In generate_display_geometry: considering point: " + str(i), level=Qgis.Info) # need to work out half of bisected angle # TOMsMessageLog.logMessage("In generate_display_geometry: prevAz: " + str(prevAz) + " currAz: " + str(Az), level=Qgis.Info) newAz, distWidth = generateGeometryUtils.calcBisector(prevAz, Az, Turn, shpExtent) # TOMsMessageLog.logMessage("In generate_display_geometry: newAz: " + str(newAz), level=Qgis.Info) cosa, cosb = generateGeometryUtils.cosdir_azim(newAz + diffEchelonAz) ptsList.append( QgsPointXY(line[i].x() + (float(distWidth) * cosa), line[i].y() + (float(distWidth) * cosb))) parallelPtsList.append( QgsPointXY(line[i].x() + (float(offset) * cosa), line[i].y() + (float(offset) * cosb))) # TOMsMessageLog.logMessage("In generate_display_geometry: point appended", level=Qgis.Info) prevAz = Az # TOMsMessageLog.logMessage("In generate_display_geometry: newPoint 1: " + str(ptsList[1].x()) + " " + str(ptsList[1].y()), level=Qgis.Info) # have reached the end of the feature. Now need to deal with last point. # Use Azimuth from last segment but change the points # TOMsMessageLog.logMessage("In generate_display_geometry: feature processed. Now at last point ", level=Qgis.Info) # standard bay newAz = generateGeometryUtils.checkDegrees(Az + Turn + diffEchelonAz) # TOMsMessageLog.logMessage("In generate_display_geometry: newAz: " + str(newAz), level=Qgis.Info) cosa, cosb = generateGeometryUtils.cosdir_azim(newAz) ptsList.append(QgsPointXY(line[len(line) - 1].x() + (float(shpExtent) * cosa), line[len(line) - 1].y() + (float(shpExtent) * cosb))) # add end point (without any consideration of Echelon) newAz = Az + Turn cosa, cosb = generateGeometryUtils.cosdir_azim(newAz) ptsList.append(QgsPointXY(line[len(line) - 1].x() + (float(offset) * cosa), line[len(line) - 1].y() + (float(offset) * cosb))) parallelPtsList.append(QgsPointXY(line[len(line) - 1].x() + (float(offset) * cosa), line[len(line) - 1].y() + (float(offset) * cosb))) newLine = QgsGeometry.fromPolylineXY(ptsList) #parallelPtsList.reverse() parallelLine = QgsGeometry.fromPolylineXY(parallelPtsList) # TOMsMessageLog.logMessage("In getDisplayGeometry: newLine ********: " + newLine.asWkt(), level=Qgis.Info) # TOMsMessageLog.logMessage("In getDisplayGeometry: parallelLine ********: " + parallelLine.asWkt(), level=Qgis.Info) return newLine, parallelLine
def computeOnePath(self, point, index, start, baseRaster, destinations, lcps, logMessageFile): # compute cost map for the entire area startCost = timeit.default_timer() logMessage = "%.2f" % (timeit.default_timer( ) - start) + " - id " + self._id + " thread: " + current_thread( ).name + " computing cost map from source point: " + str( index + 1) + " at position: " + format( point.x(), ".2f") + "/" + format(point.y(), ".2f") QgsMessageLog.logMessage(logMessage, tag="LCPNetwork", level=Qgis.Info) logMessageFile.write(logMessage + "\n") distances = self.computeCost(point, baseRaster, logMessageFile) logMessage = "\t%.2f" % (timeit.default_timer( ) - start) + " - Done! seconds to compute cost map: " + str( "%.2f" % (timeit.default_timer() - startCost)) QgsMessageLog.logMessage(logMessage, tag="LCPNetwork", level=Qgis.Info) logMessageFile.write(logMessage + "\n") if distances is None: QMessageBox.information( None, "ERROR!", "Cost map could not be computed for point: " + str(index), tag="LCPNetwork", level=Qgis.Warning) return "error" self.storeCostMap(distances, baseRaster, index) name = os.path.dirname(__file__) + "/distances" + self._id + "_" + str( index) + ".tif" distanceBase = gdal.Open(name) distances = np.array(distanceBase.GetRasterBand(1).ReadAsArray()) logMessage = "\t%.2f" % ( timeit.default_timer() - start) + " thread: " + current_thread( ).name + " - cost map stored; estimating least-cost paths..." QgsMessageLog.logMessage(logMessage, tag="LCPNetwork", level=Qgis.Info) logMessageFile.write(logMessage + "\n") destIndex = 1 for destination in destinations: if destination == point: continue logMessage = "\t\t%.2f" % ( timeit.default_timer() - start ) + " - estimating path to dest: " + str(destIndex) + "/" + str( len(destinations)) + " at pos:" + format( destination.x(), ".2f") + "/" + format( destination.y(), ".2f") QgsMessageLog.logMessage(logMessage, tag="LCPNetwork", level=Qgis.Info) logMessageFile.write(logMessage + "\n") pathLine = self.getGlobalPath(point, destination, baseRaster, distances, logMessageFile) if pathLine is None: QMessageBox.information( None, "ERROR!", "Route could not be found for destination: " + str(destIndex), tag="LCPNetwork", level=Qgis.Warning) return lcp = QgsFeature() ## set geometry from the list of QgsPointXY's to the feature lcp.setGeometry(QgsGeometry.fromPolylineXY(pathLine)) lcps.append(lcp) destIndex = destIndex + 1 logMessage = "%.2f" % ( timeit.default_timer() - start) + " thread: " + current_thread( ).name + " - computation finished for source point: " + str(index + 1) QgsMessageLog.logMessage(logMessage, tag="LCPNetwork", level=Qgis.Info) logMessageFile.write(logMessage + "\n") return "%.2f" % (timeit.default_timer( ) - start) + " - id " + self._id + " thread: " + current_thread( ).name + " finished for index: " + str(index)
def processAlgorithm(self, parameters, context, feedback): """ Here is where the processing itself takes place. """ # Retrieve the feature source and sink. The 'dest_id' variable is used # to uniquely identify the feature sink, and must be included in the # dictionary returned by the processAlgorithm function. arrets = self.parameterAsSource(parameters, self.STOPS, context) stop_id=self.parameterAsFields(parameters,self.STOP_ID,context)[0] noeuds = self.parameterAsSource(parameters, self.NOEUDS, context) node_id=self.parameterAsFields(parameters,self.NODE_ID,context)[0] mode_i=self.parameterAsString(parameters,self.MODE_ORI,context) mode_j=self.parameterAsString(parameters,self.MODE_DES,context) texte_i=self.parameterAsString(parameters,self.TEXTE_ORI,context) texte_j=self.parameterAsString(parameters,self.TEXTE_DES,context) rayon=self.parameterAsDouble(parameters,self.RAYON,context) vitesse=self.parameterAsDouble(parameters,self.VITESSE,context) nb_max=self.parameterAsInt(parameters,self.MAX_NB,context) # Compute the number of steps to display within the progress bar and # get features from source ##a=fenetre.split(",") ##fenetre2=QgsRectangle(float(a[0]),float(a[2]),float(a[1]),float(a[3])) arr=[a for a in arrets.getFeatures()] nb=len(arr) index=QgsSpatialIndex(noeuds.getFeatures()) champs=QgsFields() champs.append(QgsField('i',QVariant.String,len=15)) champs.append(QgsField('j',QVariant.String,len=15)) champs.append(QgsField(self.tr('length'),QVariant.Double)) champs.append(QgsField(self.tr('time'),QVariant.Double)) champs.append(QgsField(self.tr('mode'),QVariant.String,len=10)) (table_connecteurs,dest_id) = self.parameterAsSink(parameters, self.CONNECTEURS,context,champs, QgsWkbTypes.LineString, noeuds.sourceCrs()) nom_fichier=dest_id fichier_connecteurs=os.path.splitext(nom_fichier)[0]+".txt" sortie=codecs.open(fichier_connecteurs,"w",encoding="utf-8") nbc=0 for i,n in enumerate(arr): near=index.nearestNeighbor(n.geometry().centroid().asPoint(),nb_max) feedback.setProgress(i*100/nb) if len(near)>0: for k,nearest in enumerate(near): if k<nb_max: f=noeuds.getFeatures(request=QgsFeatureRequest(nearest)) for j, g in enumerate(f): if j==0: l=n.geometry().distance(g.geometry()) id_node=unicode(g.attribute(node_id)) id_stop=unicode(n.attribute(stop_id)) if l<rayon: nbc+=1 gline=QgsGeometry.fromPolylineXY([QgsPointXY(n.geometry().centroid().asPoint()),QgsPointXY(g.geometry().centroid().asPoint())]) hline=QgsGeometry.fromPolylineXY([QgsPointXY(g.geometry().centroid().asPoint()),QgsPointXY(n.geometry().centroid().asPoint())]) fline=QgsFeature() fline.setGeometry(gline) ll=gline.length() moda=unicode(mode_i)+unicode(mode_j) if vitesse<=0: fline.setAttributes([id_stop,id_node, ll/1000,0.0,moda]) else: fline.setAttributes([id_stop,id_node, ll/1000,ll*60/(vitesse*1000),moda]) fline2=QgsFeature() fline2.setGeometry(hline) modb=unicode(mode_j)+unicode(mode_i) if vitesse<=0: fline2.setAttributes([id_node,id_stop, ll/1000,0,modb]) else: fline2.setAttributes([id_node,id_stop, ll/1000,ll*60/(vitesse*1000),modb]) table_connecteurs.addFeature(fline) table_connecteurs.addFeature(fline2) if vitesse>0: sortie.write(id_node+';'+id_stop+';'+str((60/vitesse)*(ll/1000.0))+';'+str(ll/1000.0)+';-1;-1;-1;-1;-1;'+modb+';'+modb+'\n') sortie.write(id_stop+';'+id_node+';'+str((60/vitesse)*(ll/1000.0))+';'+str(ll/1000.0)+';-1;-1;-1;-1;-1;'+moda+';'+moda+'\n') else: sortie.write(id_node+';'+id_stop+';'+str(0.0)+';'+str(ll/1000.0)+';-1;-1;-1;-1;-1;'+modb +';'+modb+'\n') sortie.write(id_stop+';'+id_node+';'+str(0.0)+';'+str(ll/1000.0)+';-1;-1;-1;-1;-1;'+moda+';'+moda+'\n') feedback.setProgressText(unicode(nbc)+"/"+unicode(nb)+self.tr(" connected nodes")) sortie.close() return {self.OUTPUT: dest_id}
def processAlgorithm(self, parameters, context, feedback): """ Here is where the processing itself takes place. """ # Retrieve the feature source and sink. The 'dest_id' variable is used # to uniquely identify the feature sink, and must be included in the # dictionary returned by the processAlgorithm function. couche_lines = self.parameterAsVectorLayer(parameters, self.LINES, context) couche_points = self.parameterAsVectorLayer(parameters, self.NODES, context) radius=self.parameterAsDouble(parameters,self.RAYON,context) # Compute the number of steps to display within the progress bar and # get features from source delta=float(radius) index=QgsSpatialIndex() lines=couche_lines.getFeatures() for i in lines: if i.geometry().isMultipart(): i.setGeometry(QgsGeometry.fromPolylineXY(i.geometry().asMultiPolyline()[0])) index.insertFeature(i) couche_lines.startEditing() couche_lines.beginEditCommand(self.tr("Split polylines at connections")) points=couche_points.getFeatures() nb=couche_points.featureCount() feedback.setProgressText(self.tr("Connecting points to lines...")) for pos,pt in enumerate(points): feedback.setProgress(pos*100.0/nb) ptg=pt.geometry() if ptg.isMultipart(): ptg=QgsGeometry.fromPoint(ptg.asMultiPoint()[0]) coor=ptg.asPoint() nearest=index.intersects(QgsRectangle(coor.x()-delta,coor.y()-delta,coor.x()+delta,coor.y()+delta)) dmin=1e38 if len(nearest)>0: for n in nearest: f=couche_lines.getFeatures(request=QgsFeatureRequest(n)) for g in f: d=g.geometry().distance(pt.geometry()) if d<=dmin: dmin=d gmin=g gid=g.id() g=gmin if g.geometry().distance(pt.geometry())<delta: a=g.geometry().closestSegmentWithContext(ptg.asPoint()) if not(a[2]==0): geom=g.geometry() geom.convertToSingleType() geom_id=g.id() att=g.attributes() connexion=QgsFeature() connexion.setGeometry(QgsGeometry.fromPolylineXY([ptg.asPoint(),a[1]])) connexion.setAttributes(att) couche_lines.addFeature(connexion) geom.insertVertex(a[1][0],a[1][1],a[2]) geoma=geom.asPolyline()[:a[2]+1] geomb=geom.asPolyline()[a[2]:] feedback.setProgressText(unicode(geomb)) fa=QgsFeature() fa.setGeometry(QgsGeometry.fromPolylineXY(geoma)) fa.setAttributes(att) couche_lines.addFeature(fa) index.insertFeature(fa) fb=QgsFeature() fb.setGeometry(QgsGeometry.fromPolylineXY(geomb)) fb.setAttributes(att) couche_lines.addFeature(fb) index.insertFeature(fb) couche_lines.deleteFeature(g.id()) index.deleteFeature(g) couche_lines.endEditCommand() return {self.LINES: 'OK'}
def run(self): try: inputlayer = self.inputvectorlayer if inputlayer is None: self.error.emit(self.tr('No input layer defined')) self.finished.emit(False, None) return # Get and check the geometry type of the input layer geometryType = self.inputvectorlayer.geometryType() if not (geometryType == QgsWkbTypes.LineGeometry or geometryType == QgsWkbTypes.PolygonGeometry): self.error.emit('Only line and polygon layers are supported!') self.finished.emit(False, None) return self.processed = 0 self.percentage = 0 if self.selectedfeaturesonly: self.feature_count = inputlayer.selectedFeatureCount() else: self.feature_count = inputlayer.featureCount() if self.feature_count == 0: self.error.emit("No features in layer") self.finished.emit(False, None) return self.increment = self.feature_count // 1000 # Initialise the result list statistics = [] # Initialise the bins for the over all result mybins = [] for i in range(self.bins): mybins.append([0.0, 0]) # Add the over all bins statistics.append(mybins) # Get the features (iterator) if self.selectedfeaturesonly: features = inputlayer.getSelectedFeatures() # features = inputlayer.selectedFeaturesIterator() else: features = inputlayer.getFeatures() # Create a list for the (possible) tile (Polygon) # geometries tilegeoms = [] if self.tilelayer is not None: self.status.emit("Using tiles!") for tilefeat in self.tilelayer.getFeatures(): tilegeoms.append(tilefeat.geometry()) # Initialise and add bins for all the tiles for i in range(len(tilegeoms)): mybins = [] for j in range(self.bins): mybins.append([0.0, 0]) statistics.append(mybins) # Go through the features for feat in features: # Allow user abort if self.abort is True: break # Prepare for the histogram creation by extracting # line geometries (QgsGeometry) from the input layer # First we do all the lines of the layer. Later we # will do the lines per tile # We use a list of line geometries to be able to # handle MultiPolylines and Polygons inputlines = [] geom = feat.geometry() # QgsGeometry if geometryType == QgsWkbTypes.LineGeometry: # Lines! if geom.isMultipart(): theparts = geom.constParts() # QgsGeometryConstPartIterator # Go through the parts of the multigeometry for part in theparts: # QgsAbstractGeometry - QgsLineString partgeom = QgsGeometry.fromPolyline(part) inputlines.append(partgeom) # QgsGeometry else: inputlines.append(geom) # There are only two possibilites for geometry type, so # this elif: could be replaced with an else: elif geometryType == QgsWkbTypes.PolygonGeometry: # Polygons! # We use a list of polygon geometries to be able to # handle MultiPolygons inputpolygons = [] if geom.isMultipart(): # Multi polygon multipoly = geom.asMultiPolygon() for geompoly in multipoly: # list of list of QgsPointXY # abstract geometry -> QgsGeometry polygon polygeometry = QgsGeometry.fromPolygonXY(geompoly) inputpolygons.append(polygeometry) else: # Non-multi polygon # Make sure it is a QgsGeometry polygon singlegeom = geom.asPolygon() polygeometry = QgsGeometry.fromPolygonXY(singlegeom) inputpolygons.append(polygeometry) # QgsGeometry # Add the polygon rings for polygon in inputpolygons: # create a list of list of QgsPointXY poly = polygon.asPolygon() for ring in poly: # list of QgsPointXY # Create a QgsGeometry line geometryring = QgsGeometry.fromPolylineXY(ring) inputlines.append(geometryring) # QgsGeometry else: # We should never end up here self.status.emit("Unexpected geometry type!") # We introduce a list of line geometries for the tiling tilelinecoll = [None] * (len(tilegeoms) + 1) # Use the first element to store all the input lines # (for the over all histogram) tilelinecoll[0] = inputlines # Clip the lines based on the tile layer if self.tilelayer is not None: i = 1 # The first one is used for the complete dataset for tile in tilegeoms: # Go through the tiles # Create a list for the lines in the tile newlines = [] for linegeom in inputlines: # QgsGeometry # Clip clipres = linegeom.intersection(tile) if clipres.isEmpty(): continue if clipres.isMultipart(): # MultiLineString clipresparts = clipres.constParts() for clipline in clipresparts: # Create a QgsGeometry line linegeom = QgsGeometry.fromPolyline(clipline) newlines.append(linegeom) # QgsGeometry else: # ? newlines.append(clipres) tilelinecoll[i] = newlines i = i + 1 # Do calculations (line length and directions) j = 0 # Counter for the tiles for tilelines in tilelinecoll: # Handling the tiles for inputlinegeom in tilelines: # Handling the lines # QgsGeometry line - wkbType 2 if inputlinegeom is None: continue numvert = 0 for v in inputlinegeom.vertices(): numvert = numvert + 1 if numvert == 0: continue if numvert < 2: self.status.emit("Less than two vertices!") continue # Go through all the segments of this line thispoint = inputlinegeom.vertexAt(0) # QgsPoint first = True for v in inputlinegeom.vertices(): if first: first = False continue nextpoint = v linelength = sqrt(thispoint.distanceSquared(nextpoint)) # Find the angle of the line segment lineangle = thispoint.azimuth(nextpoint) if lineangle < 0: lineangle = 360 + lineangle if self.directionneutral: if lineangle >= 180.0: lineangle = lineangle - 180 # Find the bin if lineangle > self.offsetangle: fitbin = (int((lineangle - self.offsetangle) / self.binsize) % self.bins) else: fitbin = (int((360 + lineangle - self.offsetangle) / self.binsize) % self.bins) # Have to handle special case to keep index in range? if fitbin == self.bins: self.status.emit("fitbin == self.bins") fitbin = 0 # Add to the length of the bin of this tile (j) statistics[j][fitbin][0] = (statistics[j][fitbin][0] + linelength) # Add to the number of line segments in the bin statistics[j][fitbin][1] = (statistics[j][fitbin][1] + 1) thispoint = nextpoint # advance to the next point j = j + 1 # Next tile self.calculate_progress() except Exception as e: self.status.emit("Exception occurred - " + str()) self.error.emit(str(e)) self.finished.emit(False, None) else: if self.abort: self.status.emit("Aborted") self.finished.emit(False, None) else: self.status.emit("Completed") self.finished.emit(True, statistics)
def test_isThisTOMsLayer(self): #self.testData() testLayerA = QgsVectorLayer(('LineString?crs=epsg:27700&index=yes'), 'test1', 'memory') testProviderA = testLayerA.dataProvider() testLineString1 = QgsGeometry.fromPolylineXY( [QgsPointXY(0, 0), QgsPointXY(1, 0)]) testLineString2 = QgsGeometry.fromPolylineXY( [QgsPointXY(1, 0), QgsPointXY(1, 1)]) testLineString3 = QgsGeometry.fromPolylineXY( [QgsPointXY(0, 0), QgsPointXY(-1, 1)]) testLineString4 = QgsGeometry.fromPolylineXY( [QgsPointXY(1, 1), QgsPointXY(2, 1)]) testProviderA.addAttributes([ QgsField("GeometryID", QVariant.String), QgsField("age", QVariant.Int), QgsField("size", QVariant.Double), QgsField("size2", QVariant.Double) ]) testFieldsA = testProviderA.fields() """for field in testFields: print ('** {}'.format(field.name()))""" testFeature1 = QgsFeature(testFieldsA) testFeature1.setGeometry(testLineString1) testFeature1.setAttributes(["Smith", 20, 0.3]) testProviderA.addFeatures([testFeature1]) testFeature2 = QgsFeature(testFieldsA) testFeature2.setGeometry(testLineString2) testFeature2.setAttributes(["Blogs", 20, 0.3]) testProviderA.addFeatures([testFeature2]) # check field called "OpenDate" does not exist result = self.testClass.isThisTOMsLayerUsingCurrentFeatures(testLayerA) self.assertFalse(result) # check field called "OpenDate" does exist but is NULL testLayerB = QgsVectorLayer(('LineString?crs=epsg:27700&index=yes'), 'test2', 'memory') testProviderB = testLayerB.dataProvider() testProviderB.addAttributes([QgsField("OpenDate", QVariant.String)]) testFieldsB = testProviderB.fields() testFeature3 = QgsFeature(testFieldsB) testFeature3.setGeometry(testLineString2) testProviderB.addFeatures([testFeature3]) result = self.testClass.isThisTOMsLayerUsingCurrentFeatures(testLayerB) self.assertFalse(result) # check field called "OpenDate" does exist but is not NULL testFeature3.setAttribute("OpenDate", 'Test') testProviderB.addFeatures([testFeature3]) #print ('*************************** Count: {}'.format(testLayerB.featureCount())) testLayerB.reload() for field in testLayerB.fields(): print('+++ field: {}'.format(field.name())) result = self.testClass.isThisTOMsLayerUsingCurrentFeatures(testLayerB) self.assertTrue(result)
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
def densify_poly(in_layer, pr): bad_geom = 0 iterator = in_layer.getFeatures() # create empty feature to write to for feature in iterator: try: if feature.geometry().wkbType( ) == QgsWkbTypes.LineString: line_geom = feature.geometry().asPolyline() geom_type = "LineString" elif feature.geometry().wkbType( ) == QgsWkbTypes.MultiLineString: multiline_geom = feature.geometry( ).asMultiPolyline() geom_type = "MultiLineString" elif feature.geometry().wkbType( ) == QgsWkbTypes.Polygon: poly_geom = feature.geometry().asPolygon() geom_type = "Polygon" elif feature.geometry().wkbType( ) == QgsWkbTypes.MultiPolygon: multipoly_geom = feature.geometry().asMultiPolygon( ) geom_type = "MultiPolygon" else: bad_geom += 1 except: bad_geom += 1 if geom_type == "LineString": dense_points = [] point_count = len(line_geom) start_pt = QgsPointXY(line_geom[0][0], line_geom[0][1]) dense_points.append(start_pt) if self.inLayer.crs() != wgs84crs: start_pt = transtowgs84.transform(start_pt) for j in range(1, point_count): end_pt = QgsPointXY(line_geom[j][0], line_geom[j][1]) if self.inLayer.crs() != wgs84crs: end_pt = transtowgs84.transform(end_pt) # create a geographiclib line object line_object = self.geod.InverseLine( start_pt.y(), start_pt.x(), end_pt.y(), end_pt.x()) # determine how many densified segments there will be if self.segmentMethod == 'count': n = self.segmentCount else: n = int( math.ceil(line_object.s13 / self.spacing)) if line_object.s13 > self.spacing: seglen = line_object.s13 / n for k in range(1, n): s = seglen * k g = line_object.Position( s, Geodesic.LATITUDE | Geodesic.LONGITUDE | Geodesic.LONG_UNROLL) waypoint = QgsPointXY(g['lon2'], g['lat2']) if self.inLayer.crs() != wgs84crs: waypoint = transfromwgs84.transform( waypoint) dense_points.append(waypoint) if self.inLayer.crs() != wgs84crs: end_pt = transfromwgs84.transform(end_pt) dense_points.append(end_pt) start_pt = end_pt elif geom_type == "MultiLineString": dense_features = [] for i in range(len(multiline_geom)): dense_points = [] line = multiline_geom[i] point_count = len(line) start_pt = QgsPointXY(line[0][0], line[0][1]) dense_points.append(start_pt) for j in range(1, point_count): end_pt = QgsPointXY(line[j][0], line[j][1]) if self.inLayer.crs() != wgs84crs: start_pt = transtowgs84.transform(start_pt) end_pt = transtowgs84.transform(end_pt) # create a geographiclib line object line_object = self.geod.InverseLine( start_pt.y(), start_pt.x(), end_pt.y(), end_pt.x()) # determine how many densified segments there will be if self.segmentMethod == 'count': n = self.segmentCount else: n = int( math.ceil(line_object.s13 / self.spacing)) if line_object.s13 > self.spacing: seglen = line_object.s13 / n for k in range(1, n): s = seglen * k g = line_object.Position( s, Geodesic.LATITUDE | Geodesic.LONGITUDE | Geodesic.LONG_UNROLL) waypoint = QgsPointXY( g['lon2'], g['lat2']) if self.inLayer.crs() != wgs84crs: waypoint = transfromwgs84.transform( waypoint) dense_points.append(waypoint) if self.inLayer.crs() != wgs84crs: end_pt = transfromwgs84.transform( end_pt) dense_points.append(end_pt) start_pt = end_pt dense_features.append(dense_points) elif geom_type == "Polygon": for poly in poly_geom: dense_points = [] point_count = len(poly) start_pt = QgsPointXY(poly[0][0], poly[0][1]) dense_points.append(start_pt) for j in range(1, point_count): end_pt = QgsPointXY(poly[j][0], poly[j][1]) if self.inLayer.crs() != wgs84crs: end_pt = transtowgs84.transform(end_pt) start_pt = transtowgs84.transform(start_pt) # create a geographiclib line object line_object = self.geod.InverseLine( start_pt.y(), start_pt.x(), end_pt.y(), end_pt.x()) # determine how many densified segments there will be if self.segmentMethod == 'count': n = self.segmentCount else: n = int( math.ceil(line_object.s13 / self.spacing)) if line_object.s13 > self.spacing: seglen = line_object.s13 / n for k in range(1, n): s = seglen * k g = line_object.Position( s, Geodesic.LATITUDE | Geodesic.LONGITUDE | Geodesic.LONG_UNROLL) waypoint = QgsPointXY( g['lon2'], g['lat2']) if self.inLayer.crs() != wgs84crs: waypoint = transfromwgs84.transform( waypoint) dense_points.append(waypoint) if self.inLayer.crs() != wgs84crs: end_pt = transfromwgs84.transform( end_pt) dense_points.append(end_pt) start_pt = end_pt if geom_type == "MultiPolygon": dense_features = [] for i in range(len(multipoly_geom)): dense_points = [] poly = multipoly_geom[i][0] point_count = len(poly) start_pt = QgsPointXY(poly[0][0], poly[0][1]) dense_points.append(start_pt) for j in range(1, point_count): end_pt = QgsPointXY(poly[j][0], poly[j][1]) if self.inLayer.crs() != wgs84crs: start_pt = transtowgs84.transform(start_pt) end_pt = transtowgs84.transform(end_pt) # create a geographiclib line object line_object = self.geod.InverseLine( start_pt.y(), start_pt.x(), end_pt.y(), end_pt.x()) # determine how many densified segments there will be if self.segmentMethod == 'count': n = self.segmentCount else: n = int( math.ceil(line_object.s13 / self.spacing)) if line_object.s13 > self.spacing: seglen = line_object.s13 / n for k in range(1, n): s = seglen * k g = line_object.Position( s, Geodesic.LATITUDE | Geodesic.LONGITUDE | Geodesic.LONG_UNROLL) waypoint = QgsPointXY( g['lon2'], g['lat2']) if self.inLayer.crs() != wgs84crs: waypoint = transfromwgs84.transform( waypoint) dense_points.append(waypoint) if self.inLayer.crs() != wgs84crs: end_pt = transfromwgs84.transform( end_pt) dense_points.append(end_pt) start_pt = end_pt dense_features.append(dense_points) new_poly = QgsFeature() if geom_type == "LineString": new_poly.setGeometry( QgsGeometry.fromPolylineXY(dense_points)) elif geom_type == "MultiLineString": new_poly.setGeometry( QgsGeometry.fromMultiPolylineXY(dense_features)) elif geom_type == "Polygon": new_poly.setGeometry( QgsGeometry.fromPolygonXY([dense_points])) elif geom_type == "MultiPolygon": new_poly.setGeometry( QgsGeometry.fromMultiPolygonXY([dense_features])) new_poly.setAttributes(feature.attributes()) pr.addFeatures([new_poly]) if bad_geom > 0: self.iface.messageBar().pushWarning( "", "{} features failed".format(bad_geom))
def processAlgorithm(self, parameters, context, feedback): """ Here is where the processing itself takes place. """ # Retrieve the feature source and sink. The 'dest_id' variable is used # to uniquely identify the feature sink, and must be included in the # dictionary returned by the processAlgorithm function. arrets = self.parameterAsSource(parameters, self.STOPS, context) stop_id = self.parameterAsFields(parameters, self.STOP_ID, context)[0] noeuds = self.parameterAsSource(parameters, self.NOEUDS, context) node_id = self.parameterAsFields(parameters, self.NODE_ID, context)[0] mode_i = self.parameterAsString(parameters, self.MODE_ORI, context) mode_j = self.parameterAsString(parameters, self.MODE_DES, context) texte_i = self.parameterAsString(parameters, self.TEXTE_ORI, context) texte_j = self.parameterAsString(parameters, self.TEXTE_DES, context) rayon = self.parameterAsDouble(parameters, self.RAYON, context) vitesse = self.parameterAsDouble(parameters, self.VITESSE, context) nb_max = self.parameterAsInt(parameters, self.MAX_NB, context) l0 = self.parameterAsBool(parameters, self.LONG_0, context) # Compute the number of steps to display within the progress bar and # get features from source ##a=fenetre.split(",") ##fenetre2=QgsRectangle(float(a[0]),float(a[2]),float(a[1]),float(a[3])) arr = [a for a in arrets.getFeatures()] nb = len(arr) index = QgsSpatialIndex(noeuds.getFeatures()) champs = QgsFields() champs.append(QgsField('i', QVariant.String, len=15)) champs.append(QgsField('j', QVariant.String, len=15)) champs.append(QgsField(self.tr('length'), QVariant.Double)) champs.append(QgsField(self.tr('time'), QVariant.Double)) champs.append(QgsField(self.tr('mode'), QVariant.String, len=10)) (table_connecteurs, dest_id) = self.parameterAsSink(parameters, self.CONNECTEURS, context, champs, QgsWkbTypes.LineString, noeuds.sourceCrs()) nom_fichier = dest_id fichier_connecteurs = os.path.splitext(nom_fichier)[0] + ".txt" sortie = codecs.open(fichier_connecteurs, "w", encoding="utf-8") nbc = 0 for i, n in enumerate(arr): near = index.nearestNeighbor(n.geometry().centroid().asPoint(), nb_max) feedback.setProgress(i * 100 / nb) if len(near) > 0: for k, nearest in enumerate(near): if k < nb_max: f = noeuds.getFeatures( request=QgsFeatureRequest(nearest)) for j, g in enumerate(f): if j == 0: l = n.geometry().distance(g.geometry()) id_node = unicode(g.attribute(node_id)) id_stop = unicode(n.attribute(stop_id)) if l < rayon: nbc += 1 gline = QgsGeometry.fromPolylineXY([ QgsPointXY( n.geometry().centroid().asPoint()), QgsPointXY( g.geometry().centroid().asPoint()) ]) hline = QgsGeometry.fromPolylineXY([ QgsPointXY( g.geometry().centroid().asPoint()), QgsPointXY( n.geometry().centroid().asPoint()) ]) fline = QgsFeature() fline.setGeometry(gline) if l0 == 0: ll = 0 else: ll = gline.length() moda = unicode(mode_i) + unicode(mode_j) if vitesse <= 0: fline.setAttributes([ id_stop, id_node, ll / 1000, 0.0, moda ]) else: fline.setAttributes([ id_stop, id_node, ll / 1000, ll * 60 / (vitesse * 1000), moda ]) fline2 = QgsFeature() fline2.setGeometry(hline) modb = unicode(mode_j) + unicode(mode_i) if vitesse <= 0: fline2.setAttributes([ id_node, id_stop, ll / 1000, 0, modb ]) else: fline2.setAttributes([ id_node, id_stop, ll / 1000, ll * 60 / (vitesse * 1000), modb ]) table_connecteurs.addFeature(fline) table_connecteurs.addFeature(fline2) if vitesse > 0: sortie.write(id_node + ';' + id_stop + ';' + str((60 / vitesse) * (ll / 1000.0)) + ';' + str(ll / 1000.0) + ';-1;-1;-1;-1;-1;' + modb + ';' + modb + '\n') sortie.write(id_stop + ';' + id_node + ';' + str((60 / vitesse) * (ll / 1000.0)) + ';' + str(ll / 1000.0) + ';-1;-1;-1;-1;-1;' + moda + ';' + moda + '\n') else: sortie.write(id_node + ';' + id_stop + ';' + str(0.0) + ';' + str(ll / 1000.0) + ';-1;-1;-1;-1;-1;' + modb + ';' + modb + '\n') sortie.write(id_stop + ';' + id_node + ';' + str(0.0) + ';' + str(ll / 1000.0) + ';-1;-1;-1;-1;-1;' + moda + ';' + moda + '\n') feedback.setProgressText( unicode(nbc) + "/" + unicode(nb) + self.tr(" connected nodes")) sortie.close() return {self.OUTPUT: dest_id}
def getZigZag(self, wavelength=None, shpExtent=None): TOMsMessageLog.logMessage("In getZigZag ... ", level=Qgis.Info) if not wavelength: wavelength = 3.0 if not shpExtent: shpExtent = self.BayWidth / 2 offset = self.BayOffsetFromKerb line = generateGeometryUtils.getLineForAz(self.currFeature) if len(line) == 0: return 0 ptsList = [] length = self.currFeature.geometry().length() NrSegments = int(length / wavelength) # e.g., length = 33, wavelength = 4 interval = int(length/float(NrSegments) * 10000) / 10000 TOMsMessageLog.logMessage("In getZigZag. LengthLine: " + str(length) + " NrSegments = " + str(NrSegments) + "; interval: " + str(interval), level=Qgis.Info) Az = line[0].azimuth(line[1]) # TOMsMessageLog.logMessage("In getZigZag. Az = " + str(Az) + "; AzCL = " + str(self.currAzimuthToCentreLine) + "; line[0]: " + line[0].asWkt() + "; line[1]: " + line[1].asWkt(), level=Qgis.Info) Turn = generateGeometryUtils.turnToCL(Az, self.currAzimuthToCentreLine) newAz = Az + Turn # TOMsMessageLog.logMessage("In generate_display_geometry: newAz: " + str(newAz), level=Qgis.Info) cosa, cosb = generateGeometryUtils.cosdir_azim(newAz) # deal with two points ptsList.append( QgsPointXY(line[0].x() + (float(offset) * cosa), line[0].y() + (float(offset) * cosb))) ptsList.append( QgsPointXY(line[0].x() + (float(shpExtent) * cosa), line[0].y() + (float(shpExtent) * cosb))) distanceAlongLine = 0.0 countSegments = 0 while countSegments < (NrSegments): countSegments = countSegments + 1 distanceAlongLine = distanceAlongLine + interval / 2 interpolatedPointC = self.currFeature.geometry().interpolate(distanceAlongLine).asPoint() TOMsMessageLog.logMessage("In getZigZag. PtC = " + str(interpolatedPointC.x()) + ": " + str(interpolatedPointC.y()) + "; distanceAlongLine = " + str(distanceAlongLine), level=Qgis.Info) # TOMsMessageLog.logMessage("In getZigZag. offset = " + str(float(offset)) + "; cosa = " + str(cosa) + "; cosb = " + str(cosb), level=Qgis.Info) TOMsMessageLog.logMessage("In getZigZag. newC x = " + str(interpolatedPointC.x() + (float(offset) * cosa)) + "; y = " + str(interpolatedPointC.y() + (float(offset) * cosb)), level=Qgis.Info) ptsList.append(QgsPointXY(interpolatedPointC.x() + (float(offset) * cosa), interpolatedPointC.y() + (float(offset) * cosb))) distanceAlongLine = distanceAlongLine+interval/2 interpolatedPointD = self.currFeature.geometry().interpolate(distanceAlongLine).asPoint() # TOMsMessageLog.logMessage("In getZigZag. PtD = " + interpolatedPointD.asWkt() + "; distanceAlongLine = " + str(distanceAlongLine), level=Qgis.Info) ptsList.append(QgsPointXY(interpolatedPointD.x() + (float(shpExtent) * cosa), interpolatedPointD.y() + (float(shpExtent) * cosb))) # deal with last point ptsList.append( QgsPointXY(line[len(line) - 1].x() + (float(offset) * cosa), line[len(line) - 1].y() + (float(offset) * cosb))) newLine = QgsGeometry.fromPolylineXY(ptsList) return newLine
def accept(self): try: distance = float(self.distLineEdit.text()) azimuth = float(self.azimuthLineEdit.text()) units = self.unitsComboBox.currentIndex( ) # 0 km, 1 m, 2 nm, 3 miles, 4 yards, 5 ft, 6 inches, 7 cm start = self.checkBox.isChecked() except Exception: self.iface.messageBar().pushMessage( "", tr("Either distance or azimuth were invalid"), level=Qgis.Warning, duration=4) return layer = self.iface.activeLayer() if layer is None: self.iface.messageBar().pushMessage( "", tr("No point or line layer selected"), level=Qgis.Warning, duration=4) return measureFactor = conversionToMeters(units) distance = distance * measureFactor pt = self.pt destCRS = layer.crs() transform = QgsCoordinateTransform(epsg4326, destCRS, QgsProject.instance()) if layer.wkbType() == QgsWkbTypes.Point: g = geod.Direct(pt.y(), pt.x(), azimuth, distance, Geodesic.LATITUDE | Geodesic.LONGITUDE) if start: ptStart = transform.transform(self.pt.x(), self.pt.y()) feat = QgsFeature(layer.fields()) feat.setGeometry(QgsGeometry.fromPointXY(ptStart)) layer.addFeature(feat) pt = transform.transform(g['lon2'], g['lat2']) feat = QgsFeature(layer.fields()) feat.setGeometry(QgsGeometry.fromPointXY(pt)) layer.addFeature(feat) else: # It will either be a LineString or MultiLineString maxseglen = settings.maxSegLength * 1000.0 # Needs to be in meters maxSegments = settings.maxSegments gline = geod.Line(pt.y(), pt.x(), azimuth) n = int(math.ceil(distance / maxseglen)) if n > maxSegments: n = maxSegments seglen = distance / n pts = [] for i in range(0, n + 1): s = seglen * i g = gline.Position( s, Geodesic.LATITUDE | Geodesic.LONGITUDE | Geodesic.LONG_UNROLL) ptc = transform.transform(g['lon2'], g['lat2']) pts.append(ptc) feat = QgsFeature(layer.fields()) if layer.wkbType() == QgsWkbTypes.LineString: feat.setGeometry(QgsGeometry.fromPolylineXY(pts)) else: feat.setGeometry(QgsGeometry.fromMultiPolylineXY([pts])) layer.addFeatures([feat]) layer.updateExtents() self.iface.mapCanvas().refresh() self.close()
def processAlgorithm(self, parameters, context, feedback): t_regard = self.parameterAsSource(parameters, self.MANHOLES_TABLE, context) g_regard = self.parameterAsSource(parameters, self.GEOM_MANHOLES, context) t_troncon = self.parameterAsVectorLayer(parameters, self.SEGMENTS_TABLE, context) g_troncon = self.parameterAsVectorLayer(parameters, self.GEOM_SEGMENTS, context) exp_context = QgsExpressionContext() exp_context.appendScope(QgsExpressionContextUtils.globalScope()) exp_context.appendScope( QgsExpressionContextUtils.projectScope(context.project())) exp_context.appendScope( QgsExpressionContextUtils.layerScope(t_troncon)) exp_str = '"id_geom_troncon" IS NULL' exp = QgsExpression(exp_str) exp.prepare(exp_context) if exp.hasEvalError(): raise QgsProcessingException( tr('* ERROR: Expression {} has eval error: {}').format( exp.expression(), exp.evalErrorString())) request = QgsFeatureRequest(exp, exp_context) r_ids = [] # identifiant des regards l_t_f = {} # lien troncon fichier l_f_t = {} # lien fichier troncons troncons = {} sorties = {} entrees = {} for tro in t_troncon.getFeatures(request): # Stop the algorithm if cancel button has been clicked if feedback.isCanceled(): return {self.SEGMENT_CREATED: None} segment_number = tro['id'] r1 = tro['id_regard1'] r2 = tro['id_regard2'] if r1 not in r_ids: r_ids.append(r1) if r2 not in r_ids: r_ids.append(r2) fid = tro['id_file'] l_t_f[segment_number] = fid if fid in l_f_t: l_f_t[fid] = l_f_t[fid] + [segment_number] else: l_f_t[fid] = [segment_number] troncons[segment_number] = (r1, r2) if r1 in sorties: sorties[r1] = sorties[r1] + [segment_number] else: sorties[r1] = [segment_number] if r2 in entrees: entrees[r2] = entrees[r2] + [segment_number] else: entrees[r2] = [segment_number] exp_context = QgsExpressionContext() exp_context.appendScope(QgsExpressionContextUtils.globalScope()) exp_context.appendScope( QgsExpressionContextUtils.projectScope(context.project())) exp_context.appendScope(t_regard.createExpressionContextScope()) exp_str = ('"id_geom_regard" IS NOT NULL ' 'AND ' '"id" IN ({})').format(','.join([str(i) for i in r_ids] + ['-1'])) exp = QgsExpression(exp_str) exp.prepare(exp_context) if exp.hasEvalError(): raise QgsProcessingException( tr('* ERROR: Expression {} has eval error: {}').format( exp.expression(), exp.evalErrorString())) request = QgsFeatureRequest(exp, exp_context) g_ids = [] # identifiants des géométrie de regards l_r_g = {} # lien regard geometrie l_g_r = {} # lien geometrie regards for reg in t_regard.getFeatures(request): # Stop the algorithm if cancel button has been clicked if feedback.isCanceled(): return {self.SEGMENT_CREATED: None} segment_number = reg['id'] fid = reg['id_file'] if segment_number in sorties: sorties[segment_number] = [ trid for trid in sorties[segment_number] if l_t_f[trid] == fid ] if segment_number in entrees: entrees[segment_number] = [ trid for trid in entrees[segment_number] if l_t_f[trid] == fid ] gid = reg['id_geom_regard'] l_r_g[segment_number] = gid if gid not in g_ids: g_ids.append(gid) if gid in l_g_r: l_g_r[gid] = l_g_r[gid] + [segment_number] else: l_g_r[gid] = [segment_number] exp_context = QgsExpressionContext() exp_context.appendScope(QgsExpressionContextUtils.globalScope()) exp_context.appendScope( QgsExpressionContextUtils.projectScope(context.project())) exp_context.appendScope(g_regard.createExpressionContextScope()) exp_str = '"id" IN ({})'.format(','.join([str(i) for i in g_ids] + ['-1'])) exp = QgsExpression(exp_str) exp.prepare(exp_context) if exp.hasEvalError(): raise QgsProcessingException( tr('* ERROR: Expression {} has eval error: {}').format( exp.expression(), exp.evalErrorString())) request = QgsFeatureRequest(exp, exp_context) points = {} pt_labels = {} for reg in g_regard.getFeatures(request): # Stop the algorithm if cancel button has been clicked if feedback.isCanceled(): return {self.SEGMENT_CREATED: None} segment_number = reg['id'] points[segment_number] = reg.geometry().asPoint() pt_labels[segment_number] = reg['label'] lines = {} for gid in points: # Stop the algorithm if cancel button has been clicked if feedback.isCanceled(): return {self.SEGMENT_CREATED: None} if gid not in l_g_r: continue for rid in l_g_r[gid]: # Stop the algorithm if cancel button has been clicked if feedback.isCanceled(): return {self.SEGMENT_CREATED: None} if rid in sorties: for tid in sorties[rid]: # Stop the algorithm if cancel button has been clicked if feedback.isCanceled(): return {self.SEGMENT_CREATED: None} if tid in lines: continue if tid not in troncons: continue r2 = troncons[tid][1] if r2 not in l_r_g: continue g2 = l_r_g[r2] if g2 not in points: continue lines[tid] = (gid, g2) if rid in entrees: for tid in entrees[rid]: # Stop the algorithm if cancel button has been clicked if feedback.isCanceled(): return {self.SEGMENT_CREATED: None} if tid in lines: continue if tid not in troncons: continue r1 = troncons[tid][0] if r1 not in l_r_g: continue g1 = l_r_g[r1] if g1 not in points: continue lines[tid] = (g1, gid) # Creation des troncons l_t_g = {} # lien troncon et geometrie troncon l_pts_t = {} # lien points troncons features = [] # les objets de geometrie de troncon geom_point_keys = [] # liste des clés des points troncons for tid, pts in lines.items(): # Stop the algorithm if cancel button has been clicked if feedback.isCanceled(): return {self.SEGMENT_CREATED: None} exp_context = QgsExpressionContext() exp_context.appendScope(QgsExpressionContextUtils.globalScope()) exp_context.appendScope( QgsExpressionContextUtils.projectScope(context.project())) exp_context.appendScope( QgsExpressionContextUtils.layerScope(g_troncon)) exp_str = ('"id_geom_regard_amont" = {} AND ' '"id_geom_regard_aval" = {}').format(pts[0], pts[1]) exp = QgsExpression(exp_str) exp.prepare(exp_context) if exp.hasEvalError(): raise QgsProcessingException( tr('* ERROR: Expression {} has eval error: {}').format( exp.expression(), exp.evalErrorString())) request = QgsFeatureRequest(exp, exp_context) request.setLimit(1) for tro in g_troncon.getFeatures(request): l_t_g[tid] = tro['id'] continue if (pts[0], pts[1]) in geom_point_keys: l_pts_t[(pts[0], pts[1])].append(tid) continue else: l_pts_t[(pts[0], pts[1])] = [tid] geom_point_keys.append((pts[0], pts[1])) feat_t = QgsVectorLayerUtils.createFeature(g_troncon) feat_t.setAttribute( 'label', '{}-{}'.format(pt_labels[pts[0]], pt_labels[pts[1]])) feat_t.setAttribute('id_geom_regard_amont', pts[0]) feat_t.setAttribute('id_geom_regard_aval', pts[1]) feat_t.setGeometry( QgsGeometry.fromPolylineXY([points[pts[0]], points[pts[1]]])) features.append(feat_t) # Ajout des objets troncons if features: g_troncon.startEditing() (res, outFeats) = g_troncon.dataProvider().addFeatures(features) if not res or not outFeats: raise QgsProcessingException( tr('* ERREUR: lors de l\'enregistrement ' 'des regards {}').format(', '.join( g_troncon.dataProvider().errors()))) if not g_troncon.commitChanges(): raise QgsProcessingException( tr('* ERROR: Commit {}.').format(g_troncon.commitErrors())) for tro in outFeats: # Stop the algorithm if cancel button has been clicked if feedback.isCanceled(): return {self.SEGMENT_CREATED: None} if not tro['id']: continue key = (tro['id_geom_regard_amont'], tro['id_geom_regard_aval']) if key not in geom_point_keys: continue for tid in l_pts_t[(pts[0], pts[1])]: l_t_g[tid] = tro['id'] # Stop the algorithm if cancel button has been clicked if feedback.isCanceled(): return {self.SEGMENT_CREATED: None} for tid, pts in lines.items(): # Stop the algorithm if cancel button has been clicked if feedback.isCanceled(): return {self.SEGMENT_CREATED: None} if tid in l_t_g: continue exp_context = QgsExpressionContext() exp_context.appendScope(QgsExpressionContextUtils.globalScope()) exp_context.appendScope( QgsExpressionContextUtils.projectScope(context.project())) exp_context.appendScope( QgsExpressionContextUtils.layerScope(g_troncon)) exp_str = ('"id_geom_regard_amont" = {} AND ' '"id_geom_regard_aval" = {}').format(pts[0], pts[1]) exp = QgsExpression(exp_str) exp.prepare(exp_context) if exp.hasEvalError(): raise QgsProcessingException( tr('* ERROR: Expression {} has eval error: {}').format( exp.expression(), exp.evalErrorString())) request = QgsFeatureRequest(exp, exp_context) request.setLimit(1) for tro in g_troncon.getFeatures(request): l_t_g[tid] = tro['id'] # Stop the algorithm if cancel button has been clicked if feedback.isCanceled(): return {self.SEGMENT_CREATED: None} if not l_t_g.keys(): raise QgsProcessingException( tr('* ERREUR: Aucune géométrie de tronçon')) # Mise a jour de la table troncon exp_context = QgsExpressionContext() exp_context.appendScope(QgsExpressionContextUtils.globalScope()) exp_context.appendScope( QgsExpressionContextUtils.projectScope(context.project())) exp_context.appendScope( QgsExpressionContextUtils.layerScope(t_troncon)) exp_str = ('"id_geom_troncon" IS NULL AND ' 'id IN ({})').format(','.join( [str(i) for i in l_t_g.keys()])) exp = QgsExpression(exp_str) exp.prepare(exp_context) if exp.hasEvalError(): raise QgsProcessingException( tr('* ERROR: Expression %s has eval error: %s').format( exp.expression(), exp.evalErrorString())) # Mise a jour de la table de tronçon request = QgsFeatureRequest(exp, exp_context) t_troncon.startEditing() segment_number = 0 for tro in t_troncon.getFeatures(request): tro.setAttribute('id_geom_troncon', l_t_g[tro['id']]) t_troncon.updateFeature(tro) # Stop the algorithm if cancel button has been clicked if feedback.isCanceled(): return {self.SEGMENT_CREATED: None} segment_number += 1 if not t_troncon.commitChanges(): raise QgsProcessingException( tr('* ERROR: Commit %s.') % t_troncon.commitErrors()) # Returns empty dict if no outputs return {self.SEGMENT_CREATED: segment_number}
def processAlgorithm(self, parameters, context, feedback): feedback.pushInfo( self.tr( "[QNEAT3Algorithm] This is a QNEAT3 Algorithm: '{}'".format( self.displayName()))) network = self.parameterAsSource(parameters, self.INPUT, context) #QgsProcessingFeatureSource points = self.parameterAsSource(parameters, self.POINTS, context) #QgsProcessingFeatureSource id_field = self.parameterAsString(parameters, self.ID_FIELD, context) #str strategy = self.parameterAsEnum(parameters, self.STRATEGY, context) #int directionFieldName = self.parameterAsString( parameters, self.DIRECTION_FIELD, context) #str (empty if no field given) forwardValue = self.parameterAsString(parameters, self.VALUE_FORWARD, context) #str backwardValue = self.parameterAsString(parameters, self.VALUE_BACKWARD, context) #str bothValue = self.parameterAsString(parameters, self.VALUE_BOTH, context) #str defaultDirection = self.parameterAsEnum(parameters, self.DEFAULT_DIRECTION, context) #int speedFieldName = self.parameterAsString(parameters, self.SPEED_FIELD, context) #str defaultSpeed = self.parameterAsDouble(parameters, self.DEFAULT_SPEED, context) #float tolerance = self.parameterAsDouble(parameters, self.TOLERANCE, context) #float analysisCrs = network.sourceCrs() if analysisCrs.isGeographic(): raise QgsProcessingException( 'QNEAT3 algorithms are designed to work with projected coordinate systems. Please use a projected coordinate system (eg. UTM zones) instead of geographic coordinate systems (eg. WGS84)!' ) if analysisCrs != points.sourceCrs(): raise QgsProcessingException( 'QNEAT3 algorithms require that all inputs to be the same projected coordinate reference system (including project coordinate system).' ) feedback.pushInfo("[QNEAT3Algorithm] Building Graph...") net = Qneat3Network(network, points, strategy, directionFieldName, forwardValue, backwardValue, bothValue, defaultDirection, analysisCrs, speedFieldName, defaultSpeed, tolerance, feedback) list_analysis_points = [ Qneat3AnalysisPoint("point", feature, id_field, net, net.list_tiedPoints[i], feedback) for i, feature in enumerate( getFeaturesFromQgsIterable(net.input_points)) ] feat = QgsFeature() fields = QgsFields() output_id_field_data_type = getFieldDatatype(points, id_field) fields.append( QgsField('InputID', output_id_field_data_type, '', 254, 0)) fields.append( QgsField('TargetID', output_id_field_data_type, '', 254, 0)) fields.append(QgsField('entry_cost', QVariant.Double, '', 20, 7)) fields.append(QgsField('network_cost', QVariant.Double, '', 20, 7)) fields.append(QgsField('exit_cost', QVariant.Double, '', 20, 7)) fields.append(QgsField('total_cost', QVariant.Double, '', 20, 7)) feat.setFields(fields) (sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context, fields, QgsWkbTypes.LineString, network.sourceCrs()) total_workload = float(pow(len(list_analysis_points), 2)) feedback.pushInfo( "[QNEAT3Algorithm] Expecting total workload of {} iterations". format(int(total_workload))) current_workstep_number = 0 for start_point in list_analysis_points: #optimize in case of undirected (not necessary to call calcDijkstra as it has already been calculated - can be replaced by reading from list) dijkstra_query = net.calcDijkstra(start_point.network_vertex_id, 0) for query_point in list_analysis_points: if (current_workstep_number % 1000) == 0: feedback.pushInfo( "[QNEAT3Algorithm] {} OD-pairs processed...".format( current_workstep_number)) if query_point.point_id == start_point.point_id: feat['InputID'] = start_point.point_id feat['TargetID'] = query_point.point_id feat['entry_cost'] = 0.0 feat['network_cost'] = 0.0 feat['exit_cost'] = 0.0 feat['total_cost'] = 0.0 sink.addFeature(feat, QgsFeatureSink.FastInsert) elif dijkstra_query[0][query_point.network_vertex_id] == -1: feat['InputID'] = start_point.point_id feat['TargetID'] = query_point.point_id #do not populate cost field so that it defaults to null sink.addFeature(feat, QgsFeatureSink.FastInsert) else: network_cost = dijkstra_query[1][ query_point.network_vertex_id] feat.setGeometry( QgsGeometry.fromPolylineXY( [start_point.point_geom, query_point.point_geom])) feat['InputID'] = start_point.point_id feat['TargetID'] = query_point.point_id feat['entry_cost'] = start_point.entry_cost feat['network_cost'] = network_cost feat['exit_cost'] = query_point.entry_cost feat[ 'total_cost'] = network_cost + start_point.entry_cost + query_point.entry_cost sink.addFeature(feat, QgsFeatureSink.FastInsert) current_workstep_number = current_workstep_number + 1 feedback.setProgress( (current_workstep_number / total_workload) * 100) feedback.pushInfo( "[QNEAT3Algorithm] Total number of OD-pairs processed: {}".format( current_workstep_number)) feedback.pushInfo("[QNEAT3Algorithm] Ending Algorithm") results = {} results[self.OUTPUT] = dest_id return results
def processAlgorithm(self, parameters, context, feedback): source = self.parameterAsSource(parameters, self.PrmInputLayer, context) shapetype = self.parameterAsInt(parameters, self.PrmShapeType, context) anglecol = self.parameterAsString(parameters, self.PrmStartingAngleField, context) radiuscol = self.parameterAsString(parameters, self.PrmRadiusField, context) radius = self.parameterAsDouble(parameters, self.PrmRadius, context) startAngle = self.parameterAsDouble(parameters, self.PrmStartingAngle, context) segments = self.parameterAsInt(parameters, self.PrmDrawingSegments, context) units = self.parameterAsInt(parameters, self.PrmUnitsOfMeasure, context) export_geom = self.parameterAsBool(parameters, self.PrmExportInputGeometry, context) # The algorithm creates the heart on its side so this rotates # it so that it is upright. startAngle -= 90.0 measureFactor = conversionToMeters(units) radius *= measureFactor srcCRS = source.sourceCrs() fields = source.fields() if export_geom: names = fields.names() name_x, name_y = settings.getGeomNames(names) fields.append(QgsField(name_x, QVariant.Double)) fields.append(QgsField(name_y, QVariant.Double)) if shapetype == 0: (sink, dest_id) = self.parameterAsSink(parameters, self.PrmOutputLayer, context, fields, QgsWkbTypes.Polygon, srcCRS) else: (sink, dest_id) = self.parameterAsSink(parameters, self.PrmOutputLayer, context, fields, QgsWkbTypes.LineString, srcCRS) if srcCRS != epsg4326: geomTo4326 = QgsCoordinateTransform(srcCRS, epsg4326, QgsProject.instance()) toSinkCrs = QgsCoordinateTransform(epsg4326, srcCRS, QgsProject.instance()) featureCount = source.featureCount() total = 100.0 / featureCount if featureCount else 0 step = 360.0 / segments numbad = 0 iterator = source.getFeatures() for index, feature in enumerate(iterator): if feedback.isCanceled(): break try: if anglecol: sangle = float(feature[anglecol]) - 90 else: sangle = startAngle if radiuscol: radius2 = float(feature[radiuscol]) * measureFactor else: radius2 = radius except Exception: numbad += 1 continue pts = [] pt = feature.geometry().asPoint() pt_orig_x = pt.x() pt_orig_y = pt.y() # make sure the coordinates are in EPSG:4326 if srcCRS != epsg4326: pt = geomTo4326.transform(pt.x(), pt.y()) angle = 0.0 while angle <= 360.0: a = math.radians(angle) sina = math.sin(a) x = 16 * sina * sina * sina y = 13 * math.cos(a) - 5 * math.cos(2 * a) - 2 * math.cos( 3 * a) - math.cos(4 * a) dist = math.sqrt(x * x + y * y) * radius2 / 17.0 a2 = math.degrees(math.atan2(y, x)) + sangle g = geod.Direct(pt.y(), pt.x(), a2, dist, Geodesic.LATITUDE | Geodesic.LONGITUDE) pts.append(QgsPointXY(g['lon2'], g['lat2'])) angle += step # If the Output crs is not 4326 transform the points to the proper crs if srcCRS != epsg4326: for x, ptout in enumerate(pts): pts[x] = toSinkCrs.transform(ptout) f = QgsFeature() if shapetype == 0: f.setGeometry(QgsGeometry.fromPolygonXY([pts])) else: f.setGeometry(QgsGeometry.fromPolylineXY(pts)) attr = feature.attributes() if export_geom: attr.append(pt_orig_x) attr.append(pt_orig_y) f.setAttributes(attr) sink.addFeature(f) if index % 100 == 0: feedback.setProgress(int(index * total)) if numbad > 0: feedback.pushInfo( tr("{} out of {} features had invalid parameters and were ignored." .format(numbad, featureCount))) return {self.PrmOutputLayer: dest_id}
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 calcEntryLinestring(self): return QgsGeometry.fromPolylineXY( [self.point_geom, self.network_vertex.point()])
def path_in_sea_xy(self, y1, x1, y2, x2): return self.in_sea( QgsGeometry.fromPolylineXY( [QgsPointXY(x1, y1), QgsPointXY(x2, y2)]))
def on_btnSave_released(self): layer = QgsVectorLayer( "MultiLineString?crs={}".format( QgsProject.instance().crs().authid()), "Lines", "memory", ) #QgsProject.instance().addMapLayer(layer) layer.startEditing() layer.dataProvider().addAttributes([QgsField("num", QVariant.Int)]) layer.dataProvider().addAttributes([QgsField("row", QVariant.Int)]) layer.dataProvider().addAttributes([QgsField("column", QVariant.Int)]) layer.updateFields() feats = [] columnGap = self.columnGap.value() rowGap = self.rowGap.value() fid = 0 lin = QgsGeometry.fromMultiPolylineXY(self.mt.rowLines) feature = QgsFeature(fid) feature.setAttributes([str(fid)]) feature.setGeometry(lin) feats.append(feature) g = feature.geometry() rowBuffer = g.buffer(rowGap / 2, 5) fid = 1 lin = QgsGeometry.fromMultiPolylineXY(self.mt.columnLines) feature = QgsFeature(fid) feature.setAttributes([str(fid)]) feature.setGeometry(lin) feats.append(feature) columnBuffer = lin.buffer(columnGap / 2, 5) layer.dataProvider().addFeatures(feats) # layer.loadNamedStyle(self.plugin_dir + "/lines.qml") layer.commitChanges() # Generate index lines if self.cbReverseRows.isChecked(): leftEdge = (QgsGeometry.fromPolylineXY([ self.mt.pA, self.mt.pD ]).densifyByCount(self.rowCount.value() * 2 - 1).asPolyline()) rightEdge = (QgsGeometry.fromPolylineXY([ self.mt.pB, self.mt.pC ]).densifyByCount(self.rowCount.value() * 2 - 1).asPolyline()) else: leftEdge = (QgsGeometry.fromPolylineXY([ self.mt.pD, self.mt.pA ]).densifyByCount(self.rowCount.value() * 2 - 1).asPolyline()) rightEdge = (QgsGeometry.fromPolylineXY([ self.mt.pC, self.mt.pB ]).densifyByCount(self.rowCount.value() * 2 - 1).asPolyline()) # Plot edges lines polyline_rows = list(zip(leftEdge[1::2], rightEdge[1::2])) if self.cbReverseColumns.isChecked(): backSide = (QgsGeometry.fromPolylineXY([ self.mt.pB, self.mt.pA ]).densifyByCount(self.columnCount.value() * 2 - 1).asPolyline()) frontSide = (QgsGeometry.fromPolylineXY([ self.mt.pC, self.mt.pD ]).densifyByCount(self.columnCount.value() * 2 - 1).asPolyline()) else: backSide = (QgsGeometry.fromPolylineXY([ self.mt.pA, self.mt.pB ]).densifyByCount(self.columnCount.value() * 2 - 1).asPolyline()) frontSide = (QgsGeometry.fromPolylineXY([ self.mt.pD, self.mt.pC ]).densifyByCount(self.columnCount.value() * 2 - 1).asPolyline()) polyline_columns = list(zip(backSide[1::2], frontSide[1::2])) # Generate Row lines iRowLayer = QgsVectorLayer( "MultiLineString?crs={}".format( QgsProject.instance().crs().authid()), "Index Rows", "memory", ) #QgsProject.instance().addMapLayer(iRowLayer) iRowLayer.startEditing() iRowLayer.dataProvider().addAttributes([QgsField("row", QVariant.Int)]) iRowLayer.updateFields() feats = [] row = 1 lines_rows = QgsGeometry.fromMultiPolylineXY(polyline_rows) for p in lines_rows.asGeometryCollection(): feature = QgsFeature(fid) feature.setAttributes([row]) feature.setGeometry(p) feats.append(feature) row += 1 iRowLayer.dataProvider().addFeatures(feats) iRowLayer.commitChanges() # Generate Column lines iColLayer = QgsVectorLayer( "MultiLineString?crs={}".format( QgsProject.instance().crs().authid()), "Index Columns", "memory", ) #QgsProject.instance().addMapLayer(iColLayer) iColLayer.startEditing() iColLayer.dataProvider().addAttributes( [QgsField("column", QVariant.Int)]) iColLayer.updateFields() feats = [] column = 1 lines_columns = QgsGeometry.fromMultiPolylineXY(polyline_columns) for p in lines_columns.asGeometryCollection(): feature = QgsFeature(fid) feature.setAttributes([column]) feature.setGeometry(p) feats.append(feature) column += 1 iColLayer.dataProvider().addFeatures(feats) iColLayer.commitChanges() pLayer = QgsVectorLayer( "Polygon?crs={}".format(QgsProject.instance().crs().authid()), "Polygons", "memory", ) #QgsProject.instance().addMapLayer(pLayer) pLayer.dataProvider().addAttributes([QgsField("num", QVariant.Int)]) pLayer.dataProvider().addAttributes([QgsField("row", QVariant.Int)]) pLayer.dataProvider().addAttributes([QgsField("column", QVariant.Int)]) pLayer.startEditing() pLayer.updateFields() feats = [] feature = QgsFeature(0) feature.setAttributes([str(fid), 0, 0]) line_list = [f.geometry() for f in layer.getFeatures()] lines = QgsGeometry.unaryUnion(line_list) polygons = QgsGeometry.polygonize([lines]) fid = 0 for p in polygons.asGeometryCollection(): feature = QgsFeature(fid) feature.setAttributes([str(fid), 0, 0]) feature.setGeometry(p) feats.append(feature) fid += 1 pLayer.dataProvider().addFeatures(feats) pLayer.commitChanges() pcLayer = QgsVectorLayer( "Polygon?crs={}".format(QgsProject.instance().crs().authid()), "Plots", "memory", ) QgsProject.instance().addMapLayer(pcLayer) pcLayer.dataProvider().addAttributes(pLayer.fields()) pcLayer.startEditing() pcLayer.updateFields() pcLayer.dataProvider().addFeatures( self.clip_polygons(pLayer, rowBuffer, columnBuffer, iRowLayer, iColLayer)) pcLayer.commitChanges() ptLayer = QgsVectorLayer( "Point?crs={}".format(QgsProject.instance().crs().authid()), "Points", "memory") QgsProject.instance().addMapLayer(ptLayer) ptLayer.startEditing() ptLayer.dataProvider().addAttributes([QgsField("num", QVariant.Int)]) ptLayer.updateFields() feats = [] fid = 0 lin = QgsGeometry.fromMultiPolylineXY(self.mt.rowLines) for line in lin.asGeometryCollection(): poly = line.densifyByCount(self.rowCount.value() * 2).asPolyline() for part in poly: feature = QgsFeature(fid) feature.setAttributes([str(fid)]) feature.setGeometry(QgsPoint(part)) feats.append(feature) fid += 1 # ptLayer.dataProvider().addFeatures(sorted(feats, key=lambda f: f['num'])) ptLayer.dataProvider().addFeatures(feats) ptLayer.commitChanges()
def algorithm_wrapper(start_point, end_point, node_layer, input_data_path, output_file, algorithm, node_id_attribute='nodeID'): """ `start_point` : the starting point as QgsPointXY `end_point` : the end point as QgsPointXY `node_layer` : a point vector layer that contains the node. Naturally it's located in input_data_path `input_data_path` : a path to directory with nodes and edges layer. `output_file` : a path to the output shape file. """ # Get the nearest node from start and end start_node = get_nearest_feature(node_layer, start_point) print('start nodeID:', start_node['nodeID']) end_node = get_nearest_feature(node_layer, end_point) print('end nodeID:', end_node['nodeID']) # generate path with the `algorithm` start_node_id = (node_id_attribute, start_node['nodeID']) end_node_id = (node_id_attribute, end_node['nodeID']) path = algorithm(start_node_id, end_node_id, input_data_path, output_file) # Sort the path coordinates = [start_point] G = nx.Graph(nx.read_shp(input_data_path, strict=False, geom_attrs=True)) # Read and convert to Graph for i in range(len(path) - 1): node1 = path[i] node2 = path[i + 1] edge_key = [node1, node2] # print('edge key: ', edge_key) points = get_points(G, edge_key) # print(points) if i == 0: for p in points: coordinates.append(QgsPointXY(p[0], p[1])) else: start_point_path = QgsPointXY(points[0][0], points[0][1]) if start_point_path == coordinates[-1]: # Same end point, add a usual for p in points[1:]: coordinates.append(QgsPointXY(p[0], p[1])) else: # Different endpoint, reverse for p in points[::-1][1:]: coordinates.append(QgsPointXY(p[0], p[1])) # Append end point coordinates.append(end_point) # Spatial reference spatial_reference = get_spatial_reference(input_data_path) # Write result to a shapefile (TODO: put it in a function) # Create geometry for the whole line line_geometry = QgsGeometry.fromPolylineXY(coordinates) # Convert to Wkt for ogr line_wkt = line_geometry.asWkt() # set up the shapefile driver driver = ogr.GetDriverByName("ESRI Shapefile") # create the data source data_source = driver.CreateDataSource(output_file) # create the layer layer = data_source.CreateLayer("A Star Shortest Path", spatial_reference, ogr.wkbLineString) feature = ogr.Feature(layer.GetLayerDefn()) geom = ogr.CreateGeometryFromWkt(line_wkt) # Set the feature geometry using the geom feature.SetGeometry(geom) # Create the feature in the layer (shapefile) layer.CreateFeature(feature) # Dereference the feature feature = None data_source = None print(output_file)
def processAlgorithm(self, parameters, context, feedback): network = self.parameterAsSource(parameters, self.INPUT, context) if network is None: raise QgsProcessingException( self.invalidSourceError(parameters, self.INPUT)) startPoint = self.parameterAsPoint(parameters, self.START_POINT, context, network.sourceCrs()) endPoint = self.parameterAsPoint(parameters, self.END_POINT, context, network.sourceCrs()) strategy = self.parameterAsEnum(parameters, self.STRATEGY, context) directionFieldName = self.parameterAsString(parameters, self.DIRECTION_FIELD, context) forwardValue = self.parameterAsString(parameters, self.VALUE_FORWARD, context) backwardValue = self.parameterAsString(parameters, self.VALUE_BACKWARD, context) bothValue = self.parameterAsString(parameters, self.VALUE_BOTH, context) defaultDirection = self.parameterAsEnum(parameters, self.DEFAULT_DIRECTION, context) speedFieldName = self.parameterAsString(parameters, self.SPEED_FIELD, context) defaultSpeed = self.parameterAsDouble(parameters, self.DEFAULT_SPEED, context) tolerance = self.parameterAsDouble(parameters, self.TOLERANCE, context) fields = QgsFields() fields.append(QgsField('start', QVariant.String, '', 254, 0)) fields.append(QgsField('end', QVariant.String, '', 254, 0)) fields.append(QgsField('cost', QVariant.Double, '', 20, 7)) (sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context, fields, QgsWkbTypes.LineString, network.sourceCrs()) if sink is None: raise QgsProcessingException( self.invalidSinkError(parameters, self.OUTPUT)) directionField = -1 if directionField: directionField = network.fields().lookupField(directionFieldName) speedField = -1 if speedFieldName: speedField = network.fields().lookupField(speedFieldName) director = QgsVectorLayerDirector(network, directionField, forwardValue, backwardValue, bothValue, defaultDirection) distUnit = context.project().crs().mapUnits() multiplier = QgsUnitTypes.fromUnitToUnitFactor( distUnit, QgsUnitTypes.DistanceMeters) if strategy == 0: strategy = QgsNetworkDistanceStrategy() else: strategy = QgsNetworkSpeedStrategy(speedField, defaultSpeed, multiplier * 1000.0 / 3600.0) multiplier = 3600 director.addStrategy(strategy) builder = QgsGraphBuilder(network.sourceCrs(), True, tolerance) feedback.pushInfo( QCoreApplication.translate('ShortestPathPointToPoint', 'Building graph…')) snappedPoints = director.makeGraph(builder, [startPoint, endPoint], feedback) feedback.pushInfo( QCoreApplication.translate('ShortestPathPointToPoint', 'Calculating shortest path…')) graph = builder.graph() idxStart = graph.findVertex(snappedPoints[0]) idxEnd = graph.findVertex(snappedPoints[1]) tree, costs = QgsGraphAnalyzer.dijkstra(graph, idxStart, 0) if tree[idxEnd] == -1: raise QgsProcessingException( self.tr('There is no route from start point to end point.')) route = [graph.vertex(idxEnd).point()] cost = costs[idxEnd] current = idxEnd while current != idxStart: current = graph.edge(tree[current]).fromVertex() route.append(graph.vertex(current).point()) route.reverse() feedback.pushInfo( QCoreApplication.translate('ShortestPathPointToPoint', 'Writing results…')) geom = QgsGeometry.fromPolylineXY(route) feat = QgsFeature() feat.setFields(fields) feat['start'] = startPoint.toString() feat['end'] = endPoint.toString() feat['cost'] = cost / multiplier feat.setGeometry(geom) sink.addFeature(feat, QgsFeatureSink.FastInsert) results = {} results[self.TRAVEL_COST] = cost / multiplier results[self.OUTPUT] = dest_id return results
def setBBOXInQuery(self): sourceCrs = None if self.layerExtentOrBBOX: xMax = self.mts_layer.extent().xMaximum() xMin = self.mts_layer.extent().xMinimum() yMin = self.mts_layer.extent().yMinimum() yMax = self.mts_layer.extent().yMaximum() pointt1 = QgsGeometry.fromPointXY(QgsPointXY(xMax, yMin)) pointt2 = QgsGeometry.fromPointXY(QgsPointXY(xMin, yMin)) pointt3 = QgsGeometry.fromPointXY(QgsPointXY(xMin, yMax)) pointt4 = QgsGeometry.fromPointXY(QgsPointXY(xMax, yMax)) sourceCrs = QgsCoordinateReferenceSystem(self.mts_layer.crs()) else: sourceCrs = QgsCoordinateReferenceSystem(self.mts_layer.crs()) destCrs = self.crsdialog.crs() if self.polygon: polygon = self.poly_tool.rb.asGeometry() tr = QgsCoordinateTransform(sourceCrs, destCrs, QgsProject.instance()) polygon.transform(tr) elif self.circle: pointt1 = QgsGeometry.fromWkt(self.circ_tool.point1.asWkt()) pointt2 = QgsGeometry.fromWkt(self.circ_tool.point2.asWkt()) pointt3 = QgsGeometry.fromWkt(self.circ_tool.point3.asWkt()) pointt4 = QgsGeometry.fromWkt(self.circ_tool.point4.asWkt()) else: pointt1 = QgsGeometry.fromWkt(self.rect_tool.point1.asWkt()) pointt2 = QgsGeometry.fromWkt(self.rect_tool.point2.asWkt()) pointt3 = QgsGeometry.fromWkt(self.rect_tool.point3.asWkt()) pointt4 = QgsGeometry.fromWkt(self.rect_tool.point4.asWkt()) if sourceCrs != None: tr = QgsCoordinateTransform(sourceCrs, destCrs, QgsProject.instance()) pointt1.transform(tr) pointt2.transform(tr) pointt3.transform(tr) pointt4.transform(tr) polygon = QgsGeometry.fromPolylineXY([ pointt1.asPoint(), pointt2.asPoint(), pointt3.asPoint(), pointt4.asPoint() ]) center = polygon.centroid() #distance = QgsDistanceArea() #distance.setSourceCrs(destCrs) #distance.setEllipsoidalMode(True) #distance.setEllipsoid('WGS84') curquery = self.inp_sparql.toPlainText() if self.rectangle or self.circle: widthm = 100 #distance.measureLine(pointt1, pointt2) self.curbbox = [] self.curbbox.append(pointt1) self.curbbox.append(pointt2) self.curbbox.append(pointt3) self.curbbox.append(pointt4) self.close() if "bboxquery" in self.triplestoreconf[ self.endpointIndex] and self.triplestoreconf[ self. endpointIndex]["bboxquery"]["type"] == "geosparql": curquery = curquery[ 0:curquery.rfind('}')] + self.triplestoreconf[ self.endpointIndex]["bboxquery"]["query"].replace( "%%x1%%", str(pointt1.asPoint().x())).replace( "%%x2%%", str(pointt3.asPoint().x())).replace( "%%y1%%", str(pointt1.asPoint().y())).replace( "%%y2%%", str(pointt3.asPoint().y()) ) + "}\n" + curquery[curquery.rfind('}') + 1:] elif "bboxquery" in self.triplestoreconf[ self.endpointIndex] and self.triplestoreconf[ self.endpointIndex]["bboxquery"]["type"] == "minmax": curquery = curquery[ 0:curquery.rfind('}')] + self.triplestoreconf[ self.endpointIndex]["bboxquery"]["query"].replace( "%%minPoint%%", pointt2.asWkt()).replace( "%%maxPoint%%", pointt4.asWkt() ) + curquery[curquery.rfind('}') + 1:] elif "bboxquery" in self.triplestoreconf[ self.endpointIndex] and self.triplestoreconf[ self. endpointIndex]["bboxquery"]["type"] == "pointdistance": curquery = curquery[ 0:curquery.rfind('}')] + self.triplestoreconf[ self.endpointIndex]["bboxquery"]["query"].replace( "%%lat%%", str(center.asPoint().y())).replace( "%%lon%%", str(center.asPoint().x())).replace( "%%distance%%", str(widthm / 1000) ) + curquery[curquery.rfind('}') + 1:] elif polygon: widthm = 100 if "bboxquery" in self.triplestoreconf[ self.endpointIndex] and self.triplestoreconf[ self. endpointIndex]["bboxquery"]["type"] == "geosparql": curquery = curquery[0:curquery.rfind( '}')] + "FILTER(geof:sfIntersects(?geo,\"" + polygon.asWkt( ) + "\"^^geo:wktLiteral))" elif "bboxquery" in self.triplestoreconf[ self.endpointIndex] and self.triplestoreconf[ self.endpointIndex]["bboxquery"]["type"] == "minmax": curquery = curquery[ 0:curquery.rfind('}')] + self.triplestoreconf[ self.endpointIndex]["bboxquery"]["query"].replace( "%%minPoint%%", "POINT(" + str(polygon.boundingBox().yMinimum()) + " " + str(polygon.boundingBox().xMinimum()) + ")").replace( "%%maxPoint%%", "POINT(" + str(polygon.boundingBox().yMaximum()) + " " + str(polygon.boundingBox().xMaximum()) + ")") + curquery[curquery.rfind('}') + 1:] elif "bboxquery" in self.triplestoreconf[ self.endpointIndex] and self.triplestoreconf[ self. endpointIndex]["bboxquery"]["type"] == "pointdistance": curquery = curquery[ 0:curquery.rfind('}')] + self.triplestoreconf[ self.endpointIndex]["bboxquery"]["query"].replace( "%%lat%%", str(polygon.boundingBox().center().asPoint().y( ))).replace( "%%lon%%", str(polygon.boundingBox().center().asPoint().x( ))).replace("%%distance%%", str( widthm / 1000)) + curquery[curquery.rfind('}') + 1:] self.inp_sparql.setPlainText(curquery) self.close()
def getRecordGeometry(self, record): polylineXY = polylineXYSegmentXY(self.polyline, record.partFrom, record.partTo) geo = QgsGeometry.fromPolylineXY(polylineXY) return geo
def run(bar, layer1_path, layer2_path, obstacles_path, research_ray): output = {} #layer1 receiver layer1 = QgsVectorLayer(layer1_path, "layer1", "ogr") #layer 2 source layer2 = QgsVectorLayer(layer2_path, "layer2", "ogr") layer2_feat_all_dict = {} layer2_feat_all = layer2.dataProvider().getFeatures() layer2_spIndex = QgsSpatialIndex() for layer2_feat in layer2_feat_all: layer2_spIndex.insertFeature(layer2_feat) layer2_feat_all_dict[layer2_feat.id()] = layer2_feat if obstacles_path is not None: obstacles_layer = QgsVectorLayer(obstacles_path, "obstacles", "ogr") obstacles_feat_all = obstacles_layer.dataProvider().getFeatures() obstacles_spIndex = QgsSpatialIndex() obstacles_feat_all_dict = {} for obstacles_feat in obstacles_feat_all: obstacles_spIndex.insertFeature(obstacles_feat) obstacles_feat_all_dict[obstacles_feat.id()] = obstacles_feat layer1_feat_all = layer1.dataProvider().getFeatures() layer1_feat_total = layer1.dataProvider().featureCount() layer1_feat_number = 0 for layer1_feat in layer1_feat_all: layer1_feat_number = layer1_feat_number + 1 barValue = layer1_feat_number / float(layer1_feat_total) * 100 bar.setValue(barValue) # researches the layer2 points in a rectangle created by the research_ray # creates the search rectangle rect = QgsRectangle() rect.setXMinimum(layer1_feat.geometry().asPoint().x() - research_ray) rect.setXMaximum(layer1_feat.geometry().asPoint().x() + research_ray) rect.setYMinimum(layer1_feat.geometry().asPoint().y() - research_ray) rect.setYMaximum(layer1_feat.geometry().asPoint().y() + research_ray) layer2_request = layer2_spIndex.intersects(rect) layer2_points = [] for layer2_id in layer2_request: layer2_feat = layer2_feat_all_dict[layer2_id] ray_to_test_length = compute_distance( layer1_feat.geometry().asPoint(), layer2_feat.geometry().asPoint()) if ray_to_test_length <= research_ray: ray_to_test = QgsGeometry.fromPolylineXY([ layer1_feat.geometry().asPoint(), layer2_feat.geometry().asPoint() ]) intersect = 0 if obstacles_path is not None: obstacles_request = obstacles_spIndex.intersects( ray_to_test.boundingBox()) for obstacles_id in obstacles_request: if obstacles_feat_all_dict[obstacles_id].geometry( ).crosses(ray_to_test) == 1: intersect = 1 break if intersect == 0: layer2_points.append(layer2_feat.id()) output[layer1_feat.id()] = layer2_points return output
def processAlgorithm(self, parameters, context, feedback): network = self.parameterAsSource(parameters, self.INPUT, context) if network is None: raise QgsProcessingException(self.invalidSourceError(parameters, self.INPUT)) startPoint = self.parameterAsPoint(parameters, self.START_POINT, context, network.sourceCrs()) endPoint = self.parameterAsPoint(parameters, self.END_POINT, context, network.sourceCrs()) strategy = self.parameterAsEnum(parameters, self.STRATEGY, context) directionFieldName = self.parameterAsString(parameters, self.DIRECTION_FIELD, context) forwardValue = self.parameterAsString(parameters, self.VALUE_FORWARD, context) backwardValue = self.parameterAsString(parameters, self.VALUE_BACKWARD, context) bothValue = self.parameterAsString(parameters, self.VALUE_BOTH, context) defaultDirection = self.parameterAsEnum(parameters, self.DEFAULT_DIRECTION, context) speedFieldName = self.parameterAsString(parameters, self.SPEED_FIELD, context) defaultSpeed = self.parameterAsDouble(parameters, self.DEFAULT_SPEED, context) tolerance = self.parameterAsDouble(parameters, self.TOLERANCE, context) fields = QgsFields() fields.append(QgsField('start', QVariant.String, '', 254, 0)) fields.append(QgsField('end', QVariant.String, '', 254, 0)) fields.append(QgsField('cost', QVariant.Double, '', 20, 7)) (sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context, fields, QgsWkbTypes.LineString, network.sourceCrs()) if sink is None: raise QgsProcessingException(self.invalidSinkError(parameters, self.OUTPUT)) directionField = -1 if directionField: directionField = network.fields().lookupField(directionFieldName) speedField = -1 if speedFieldName: speedField = network.fields().lookupField(speedFieldName) director = QgsVectorLayerDirector(network, directionField, forwardValue, backwardValue, bothValue, defaultDirection) distUnit = context.project().crs().mapUnits() multiplier = QgsUnitTypes.fromUnitToUnitFactor(distUnit, QgsUnitTypes.DistanceMeters) if strategy == 0: strategy = QgsNetworkDistanceStrategy() else: strategy = QgsNetworkSpeedStrategy(speedField, defaultSpeed, multiplier * 1000.0 / 3600.0) multiplier = 3600 director.addStrategy(strategy) builder = QgsGraphBuilder(network.sourceCrs(), True, tolerance) feedback.pushInfo(QCoreApplication.translate('ShortestPathPointToPoint', 'Building graph…')) snappedPoints = director.makeGraph(builder, [startPoint, endPoint], feedback) feedback.pushInfo(QCoreApplication.translate('ShortestPathPointToPoint', 'Calculating shortest path…')) graph = builder.graph() idxStart = graph.findVertex(snappedPoints[0]) idxEnd = graph.findVertex(snappedPoints[1]) tree, costs = QgsGraphAnalyzer.dijkstra(graph, idxStart, 0) if tree[idxEnd] == -1: raise QgsProcessingException( self.tr('There is no route from start point to end point.')) route = [graph.vertex(idxEnd).point()] cost = costs[idxEnd] current = idxEnd while current != idxStart: current = graph.edge(tree[current]).fromVertex() route.append(graph.vertex(current).point()) route.reverse() feedback.pushInfo(QCoreApplication.translate('ShortestPathPointToPoint', 'Writing results…')) geom = QgsGeometry.fromPolylineXY(route) feat = QgsFeature() feat.setFields(fields) feat['start'] = startPoint.toString() feat['end'] = endPoint.toString() feat['cost'] = cost / multiplier feat.setGeometry(geom) sink.addFeature(feat, QgsFeatureSink.FastInsert) results = {} results[self.TRAVEL_COST] = cost / multiplier results[self.OUTPUT] = dest_id return results
def processAlgorithm(self, parameters, context, feedback): source = self.parameterAsSource(parameters, self.INPUT, context) if source is None: raise QgsProcessingException( self.invalidSourceError(parameters, self.INPUT)) use_ring_count = False fields_or_rings = self.parameterAsString(parameters, self.FIELDS_OR_RINGS, context) if (self.is_number(fields_or_rings)): ring_num = int(fields_or_rings) use_ring_count = True else: input_fields = fields_or_rings.strip().split(',') ring_num = len(input_fields) for idx in range(ring_num): input_fields[idx] = input_fields[idx].strip() if (ring_num == 0): raise QgsProcessingException( 'The count of Rings must be greater than zero') ring_value_field = self.parameterAsString(parameters, self.RING_VALUE_FIELD, context) self.GAPS = self.parameterAsInt(parameters, self.RING_GAP, context) if self.GAPS < 0 or self.GAPS > 10: raise QgsProcessingException( 'The Gap value must be between 0 and 10.') # calculate layer's extent & feature count feature_count = source.featureCount() extent = self.calculate_layer_extent(source) # create spatial index & convert to points (spatial_index, centroid_features) = self.create_spatial_index(source) center_point = extent.center() # QgsPoint minx = extent.xMinimum() miny = extent.yMinimum() maxx = extent.xMaximum() maxy = extent.yMaximum() radius = (((maxx - minx)**2 + (maxy - miny)**2)**0.5) / 2.0 radius_interval = radius / ring_num ring_fields = source.fields() ring_fields.append(QgsField("ring_num", QVariant.Int)) ring_fields.append(QgsField(ring_value_field, QVariant.Double)) idx_fields = [] for idx in range(ring_num): if (use_ring_count): idx_fields.append(-1) else: idx_fields.append(ring_fields.lookupField(input_fields[idx])) (sink_ring, ring_id) = self.parameterAsSink(parameters, self.OUTPUT_RING, context, ring_fields, QgsWkbTypes.Polygon, source.sourceCrs()) (sink_anchor, anchor_id) = self.parameterAsSink(parameters, self.OUTPUT_ANCHOR, context, source.fields(), QgsWkbTypes.LineString, source.sourceCrs()) if sink_ring is None: raise QgsProcessingException( self.invalidSinkError(parameters, self.OUTPUT_RING)) if sink_anchor is None: raise QgsProcessingException( self.invalidSinkError(parameters, self.OUTPUT_ANCHOR)) step_angle = 360.0 / feature_count half_step = step_angle / 2.0 total = 100.0 / feature_count if feature_count else 0 for idx_side in range(feature_count): if feedback.isCanceled(): break from_deg = half_step + (idx_side * step_angle) to_deg = half_step + ((idx_side + 1) * step_angle) default_radius = radius for idx_radius in range(ring_num): cell = self.create_ring_cell(center_point, from_deg, to_deg, default_radius, default_radius + radius_interval) cell_centroid_point = cell.centroid().asPoint() # find nearest feature & create anchor line if (idx_radius == 0): fids = spatial_index.nearestNeighbor( cell_centroid_point, 1) for fid in fids: nearest_feature = centroid_features[fid] nearest_point = nearest_feature.geometry().asPoint() anchor_feature = QgsFeature() anchor_feature.setGeometry( QgsGeometry.fromPolylineXY( [nearest_point, cell_centroid_point])) anchor_feature.setAttributes( nearest_feature.attributes()) # Add a new feature in the sink sink_anchor.addFeature(anchor_feature, QgsFeatureSink.FastInsert) spatial_index.deleteFeature(nearest_feature) # create and write ring feature ring_feature = QgsFeature(ring_fields) ring_feature.setGeometry(cell) ring_attributes = nearest_feature.attributes() ring_attributes.append(idx_radius + 1) # ring_num if (idx_fields[idx_radius] == -1): ring_attributes.append(0) # default value = 0 else: ring_attributes.append( ring_attributes[idx_fields[idx_radius]]) # ring_val ring_feature.setAttributes(ring_attributes) # Add a new feature in the sink sink_ring.addFeature(ring_feature, QgsFeatureSink.FastInsert) default_radius += radius_interval # Update the progress bar feedback.setProgress(int(idx_side * total)) # cleanup del centroid_features return {self.OUTPUT_RING: ring_id, self.OUTPUT_ANCHOR: anchor_id}
def createDigiFeature(pnts): line = QgsGeometry.fromPolylineXY(pnts) qgFeat = QgsFeature() qgFeat.setGeometry(line) return qgFeat
def processAlgorithm(self, parameters, context, feedback): """ Here is where the processing itself takes place. """ # Retrieve the feature source and sink. The 'dest_id' variable is used # to uniquely identify the feature sink, and must be included in the # dictionary returned by the processAlgorithm function. reseau = self.parameterAsVectorLayer(parameters, self.RESEAU, context) fenetre = self.parameterAsExtent(parameters, self.FENETRE, context) cout_i = QgsExpression( self.parameterAsExpression(parameters, self.COUT_I, context)) cout_j = QgsExpression( self.parameterAsExpression(parameters, self.COUT_J, context)) sens = QgsExpression( self.parameterAsExpression(parameters, self.SENS, context)) diffusion = QgsExpression( self.parameterAsExpression(parameters, self.DIFFUSION, context)) traversabilite = QgsExpression( self.parameterAsExpression(parameters, self.TRAVERSABILITE, context)) nb_pixels_x = self.parameterAsInt(parameters, self.NB_PIXELS_X, context) nb_pixels_y = self.parameterAsInt(parameters, self.NB_PIXELS_Y, context) taille_pixel_x = self.parameterAsDouble(parameters, self.TAILLE_PIXEL_X, context) taille_pixel_y = self.parameterAsDouble(parameters, self.TAILLE_PIXEL_Y, context) decimales = self.parameterAsInt(parameters, self.DECIMALES, context) rayon = self.parameterAsDouble(parameters, self.RAYON, context) vitesse_diffusion = QgsExpression( self.parameterAsExpression(parameters, self.VITESSE_DIFFUSION, context)) intraversable = self.parameterAsBool(parameters, self.INTRAVERSABLE, context) valeurs_individuelles = QgsExpression( self.parameterAsExpression(parameters, self.IND_VALUES, context)) resultat = self.parameterAsOutputLayer( parameters, self.RESULTAT, context ) # Compute the number of steps to display within the progress bar and poles = {} formule_cout_i = self.createExpressionContext(parameters, context) cout_i.prepare(formule_cout_i) formule_cout_j = self.createExpressionContext(parameters, context) cout_j.prepare(formule_cout_j) formule_sens = self.createExpressionContext(parameters, context) sens.prepare(formule_sens) formule_diffusion = self.createExpressionContext(parameters, context) diffusion.prepare(formule_diffusion) formule_traversabilite = self.createExpressionContext( parameters, context) traversabilite.prepare(formule_traversabilite) formule_vitesse_diffusion = self.createExpressionContext( parameters, context) vitesse_diffusion.prepare(formule_vitesse_diffusion) formule_valeurs_individuelles = self.createExpressionContext( parameters, context) valeurs_individuelles.prepare(formule_valeurs_individuelles) crsSrc = QgsCoordinateReferenceSystem('EPSG:' + str(reseau.crs().postgisSrid())) dist_unit = QgsUnitTypes.fromUnitToUnitFactor( crsSrc.mapUnits(), QgsUnitTypes.DistanceMeters) rayon = rayon / dist_unit grille = numpy.array([[-9999.0] * nb_pixels_y] * nb_pixels_x) grille_distance = numpy.array([[1e38] * nb_pixels_y] * nb_pixels_x) grille_ind = numpy.array([['0'] * nb_pixels_y] * nb_pixels_x, dtype='<U25') rep = os.path.dirname(resultat) a = fenetre.asWktCoordinates().split(',') fenetre2 = fenetre #QgsRectangle(float(a[0]),float(a[2]),float(a[1]),float(a[3])) p1 = a[0].split() p2 = a[1].split() ll = (float(p1[0]), float(p1[1])) hauteur = float(p2[1]) - float(p1[1]) largeur = float(p2[0]) - float(p1[0]) if not (taille_pixel_x <= 0): nb_pixels_x = int(largeur / taille_pixel_x) else: taille_pixel_x = float(largeur / nb_pixels_x) if not (taille_pixel_y <= 0): nb_pixels_y = int(hauteur / taille_pixel_y) else: taille_pixel_y = float(hauteur / nb_pixels_y) layer = reseau if layer.type() == QgsMapLayer.VectorLayer: if not layer == None: if layer.geometryType() == 1: simple = QgsSimplifyMethod() simple.setMethodType(QgsSimplifyMethod.PreserveTopology) simple.setTolerance( min(taille_pixel_x, taille_pixel_y) / 2) texte = diffusion.dump( ) + ' in (\'1\',\'2\',\'3\') and (' + cout_j.dump( ) + ' IS NOT NULL and ' + sens.dump( ) + ' in (\'1\',\'3\')) ' #request=(QgsFeatureRequest().setFilterRect(fenetre2)).setFilterExpression(texte).setSimplifyMethod(simple).setFlags(QgsFeatureRequest.ExactIntersect) request = (QgsFeatureRequest().setFilterRect(fenetre2) ).setFilterExpression(texte) #req_intra=(QgsFeatureRequest().setFilterRect(fenetre2)).setFilterExpression(traversabilite.dump()+' in (\'1\',\'2\',\'3\')').setSimplifyMethod(simple).setFlags(QgsFeatureRequest.ExactIntersect) req_intra = ( QgsFeatureRequest().setFilterRect(fenetre2) ).setFilterExpression(traversabilite.dump() + ' in (\'1\',\'2\',\'3\')') features = [f for f in layer.getFeatures(request)] if intraversable: features_intra = [ f for f in layer.getFeatures(req_intra) ] else: features_intra = [] for k, i in enumerate(features): formule_sens.setFeature(i) formule_cout_i.setFeature(i) formule_cout_j.setFeature(i) formule_vitesse_diffusion.setFeature(i) formule_diffusion.setFeature(i) formule_traversabilite.setFeature(i) formule_valeurs_individuelles.setFeature(i) var_diffusion = diffusion.evaluate(formule_diffusion) var_sens = sens.evaluate(formule_sens) var_traversabilite = traversabilite.evaluate( formule_traversabilite) ti = cout_i.evaluate(formule_cout_i) tj = cout_j.evaluate(formule_cout_j) var_ind = valeurs_individuelles.evaluate( formule_valeurs_individuelles) var_vitesse_diffusion = vitesse_diffusion.evaluate( formule_vitesse_diffusion) speed = 60 / (1000 * var_vitesse_diffusion) if var_sens in ['1', '2', '3']: geom = i.geometry() zone = geom.buffer(rayon, 12).boundingBox() deltax = int( (zone.xMinimum() - ll[0]) / taille_pixel_x) deltay = int( (zone.yMinimum() - ll[1]) / taille_pixel_y) dx = int(zone.width() / taille_pixel_x) dy = int(zone.height() / taille_pixel_y) l1 = geom.length() if geom.wkbType() == QgsWkbTypes.MultiLineString: geom_l = geom.asMultiPolyline() else: geom_l = geom.asPolyline() for p in range(dx): d2x = deltax + p for q in range(dy): d2y = deltay + q if 0 <= d2x < nb_pixels_x and 0 <= d2y < nb_pixels_y: pt1 = QgsGeometry.fromPointXY( QgsPointXY( ll[0] + (d2x + 0.5) * taille_pixel_x, ll[1] + (d2y + 0.5) * taille_pixel_y)) res = geom.closestSegmentWithContext( pt1.asPoint()) d = round(res[0], decimales) if d <= grille_distance[ d2x, d2y] and d < rayon * rayon: if d > 0 and l1 > 0: pt2 = res[1] #feedback.setProgressText(geom.asWkt()) if geom.wkbType( ) == QgsWkbTypes.MultiLineString: num_poly = -1 npts = 0 for k, id_poly in enumerate( geom_l): if res[2] < npts + len( id_poly): infos_poly = ( k, res[2]) else: npts += len( id_poly) #feedback.setProgressText(str(infos_poly[0])+"-"+str(infos_poly[1])+"-"+str(npts)) geoma = geom_l[infos_poly[ 0]][:(infos_poly[1] - npts)] + [pt2] else: geoma = geom_l[:res[2]] + [ pt2 ] #geoma=QgsGeometry(geom) #geoma.insertVertex(pt2[0],pt2[1],res[2]) l2 = QgsGeometry.fromPolylineXY( geoma).length() if res[2] == 0: pt3 = geom.vertexAt(res[2]) pt4 = geom.vertexAt( res[2] + 1) else: try: pt3 = geom.vertexAt( res[2] - 1) pt4 = geom.vertexAt( res[2]) except: print(res, geom_l) pt3 = geom_l[res[2] - 1] pt4 = geom_l[res[2]] p1 = pt1.asPoint() test_sens = (pt4.x() - pt3.x( )) * (p1.y() - pt2.y()) - ( p1.x() - pt2.x()) * ( pt4.y() - pt3.y()) if var_sens in [ '1', '3' ] and not tj == None: if (var_diffusion in ['1', '3'] and test_sens <= 0 ) or (var_diffusion in ['2', '3'] and test_sens >= 0): if not tj == None: if not ti == None: t = tj * ( l2 / l1 ) + ti * ( 1 - (l2 / l1) ) + math.sqrt( d ) * speed / dist_unit l3 = QgsGeometry.fromPolylineXY( [ pt1. asPoint( ), QgsPointXY( pt2 ) ]) result_test = False if l3 != None: if len(features_intra ) > 0: for intra in features_intra: if intra.geometry( ).intersects( l3 ): result_test = True break if result_test == False: if ( t < grille[d2x, d2y] and d == grille_distance[ d2x, d2y] ) or d < grille_distance[ d2x, d2y]: grille_distance[ d2x, d2y] = d grille[d2x, d2y] = t if var_ind not in poles: poles[ var_ind] = len( poles ) + 1 grille_ind[ d2x, d2y] = poles[ var_ind] sortie = os.path.splitext(resultat) fichier_grille = open(sortie[0] + sortie[1], 'w') fichier_grille.write( "NCOLS {0:d}\nNROWS {1:d}\nXLLCORNER {2}\nYLLCORNER {3}\nDX {4}\nDY {5}\nNODATA_VALUE -9999\n" .format(nb_pixels_x, nb_pixels_y, ll[0], ll[1], taille_pixel_x, taille_pixel_y)) fichier_grille2 = open(sortie[0] + "_dist" + sortie[1], 'w') fichier_grille2.write( "NCOLS {0:d}\nNROWS {1:d}\nXLLCORNER {2}\nYLLCORNER {3}\nDX {4}\nDY {5}\nNODATA_VALUE -9999\n" .format(nb_pixels_x, nb_pixels_y, ll[0], ll[1], taille_pixel_x, taille_pixel_y)) g1 = numpy.rot90(grille, 1) #g1=numpy.flipud(g1) g2 = numpy.rot90(grille_ind, 1) #g2=numpy.flipud(g2) for i in g1: fichier_grille.write(" ".join([str(ii) for ii in i]) + "\n") fichier_grille.close() for i in g2: fichier_grille2.write(" ".join([str(ii) for ii in i]) + "\n") fichier_grille2.close() fichier_prj = open(sortie[0] + ".prj", 'w') fichier2_prj = open(sortie[0] + "_dist.prj", 'w') fichier2_dict = open(sortie[0] + "_dist.dic", 'w') fichier_prj.write(layer.crs().toWkt()) fichier2_prj.write(layer.crs().toWkt()) fichier2_dict.write( json.dumps(dict(map(reversed, poles.items())))) fichier_prj.close() fichier2_prj.close() fichier2_dict.close() nom_sortie = os.path.basename(sortie[0]) rlayer = QgsRasterLayer(resultat, nom_sortie) return {self.RESULTAT: resultat}
def processAlgorithm(self, parameters, context, feedback): network = self.parameterAsSource(parameters, self.INPUT, context) startPoints = self.parameterAsSource(parameters, self.START_POINTS, context) endPoint = self.parameterAsPoint(parameters, self.END_POINT, context, network.sourceCrs()) strategy = self.parameterAsEnum(parameters, self.STRATEGY, context) directionFieldName = self.parameterAsString(parameters, self.DIRECTION_FIELD, context) forwardValue = self.parameterAsString(parameters, self.VALUE_FORWARD, context) backwardValue = self.parameterAsString(parameters, self.VALUE_BACKWARD, context) bothValue = self.parameterAsString(parameters, self.VALUE_BOTH, context) defaultDirection = self.parameterAsEnum(parameters, self.DEFAULT_DIRECTION, context) speedFieldName = self.parameterAsString(parameters, self.SPEED_FIELD, context) defaultSpeed = self.parameterAsDouble(parameters, self.DEFAULT_SPEED, context) tolerance = self.parameterAsDouble(parameters, self.TOLERANCE, context) fields = startPoints.fields() fields.append(QgsField('start', QVariant.String, '', 254, 0)) fields.append(QgsField('end', QVariant.String, '', 254, 0)) fields.append(QgsField('cost', QVariant.Double, '', 20, 7)) feat = QgsFeature() feat.setFields(fields) (sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context, fields, QgsWkbTypes.LineString, network.sourceCrs()) directionField = -1 if directionFieldName: directionField = network.fields().lookupField(directionFieldName) speedField = -1 if speedFieldName: speedField = network.fields().lookupField(speedFieldName) director = QgsVectorLayerDirector(network, directionField, forwardValue, backwardValue, bothValue, defaultDirection) distUnit = context.project().crs().mapUnits() multiplier = QgsUnitTypes.fromUnitToUnitFactor(distUnit, QgsUnitTypes.DistanceMeters) if strategy == 0: strategy = QgsNetworkDistanceStrategy() else: strategy = QgsNetworkSpeedStrategy(speedField, defaultSpeed, multiplier * 1000.0 / 3600.0) multiplier = 3600 director.addStrategy(strategy) builder = QgsGraphBuilder(network.sourceCrs(), True, tolerance) feedback.pushInfo(self.tr('Loading start points...')) request = QgsFeatureRequest() request.setDestinationCrs(network.sourceCrs()) features = startPoints.getFeatures(request) total = 100.0 / startPoints.featureCount() if startPoints.featureCount() else 0 points = [endPoint] source_attributes = {} i = 1 for current, f in enumerate(features): if feedback.isCanceled(): break if not f.hasGeometry(): continue for p in f.geometry().vertices(): points.append(QgsPointXY(p)) source_attributes[i] = f.attributes() i += 1 feedback.setProgress(int(current * total)) feedback.pushInfo(self.tr('Building graph...')) snappedPoints = director.makeGraph(builder, points, feedback) feedback.pushInfo(self.tr('Calculating shortest paths...')) graph = builder.graph() idxEnd = graph.findVertex(snappedPoints[0]) nPoints = len(snappedPoints) total = 100.0 / nPoints if nPoints else 1 for i in range(1, nPoints): if feedback.isCanceled(): break idxStart = graph.findVertex(snappedPoints[i]) tree, costs = QgsGraphAnalyzer.dijkstra(graph, idxStart, 0) if tree[idxEnd] == -1: msg = self.tr('There is no route from start point ({}) to end point ({}).'.format(points[i].toString(), endPoint.toString())) feedback.reportError(msg) # add feature with no geometry feat.clearGeometry() attrs = source_attributes[i] attrs.append(points[i].toString()) feat.setAttributes(attrs) sink.addFeature(feat, QgsFeatureSink.FastInsert) continue route = [graph.vertex(idxEnd).point()] cost = costs[idxEnd] current = idxEnd while current != idxStart: current = graph.edge(tree[current]).fromVertex() route.append(graph.vertex(current).point()) route.reverse() geom = QgsGeometry.fromPolylineXY(route) feat.setGeometry(geom) attrs = source_attributes[i] attrs.extend([points[i].toString(), endPoint.toString(), cost / multiplier]) feat.setAttributes(attrs) sink.addFeature(feat, QgsFeatureSink.FastInsert) feedback.setProgress(int(i * total)) return {self.OUTPUT: dest_id}
def processAlgorithm(self, parameters, context, feedback): source = self.parameterAsSource(parameters, self.PrmInputLayer, context) shapetype = self.parameterAsInt(parameters, self.PrmShapeType, context) cuspscol = self.parameterAsString(parameters, self.PrmCuspsField, context) startanglecol = self.parameterAsString(parameters, self.PrmStartingAngleField, context) radiuscol = self.parameterAsString(parameters, self.PrmRadiusField, context) radius = self.parameterAsDouble(parameters, self.PrmRadius, context) startAngle = self.parameterAsDouble(parameters, self.PrmStartingAngle, context) cusps = self.parameterAsInt(parameters, self.PrmCusps, context) segments = self.parameterAsInt(parameters, self.PrmDrawingSegments, context) units = self.parameterAsInt(parameters, self.PrmUnitsOfMeasure, context) measureFactor = conversionToMeters(units) radius *= measureFactor srcCRS = source.sourceCrs() if shapetype == 0: (sink, dest_id) = self.parameterAsSink(parameters, self.PrmOutputLayer, context, source.fields(), QgsWkbTypes.Polygon, srcCRS) else: (sink, dest_id) = self.parameterAsSink(parameters, self.PrmOutputLayer, context, source.fields(), QgsWkbTypes.LineString, srcCRS) if srcCRS != epsg4326: geomTo4326 = QgsCoordinateTransform(srcCRS, epsg4326, QgsProject.instance()) toSinkCrs = QgsCoordinateTransform(epsg4326, srcCRS, QgsProject.instance()) featureCount = source.featureCount() total = 100.0 / featureCount if featureCount else 0 step = 360.0 / segments numbad = 0 iterator = source.getFeatures() for index, feature in enumerate(iterator): if feedback.isCanceled(): break try: if startanglecol: sangle = float(feature[startanglecol]) else: sangle = startAngle if cuspscol: cusps2 = int(feature[cuspscol]) else: cusps2 = cusps if radiuscol: radius2 = float(feature[radiuscol]) * measureFactor else: radius2 = radius r = radius2 / cusps2 except: numbad += 1 continue pts = [] pt = feature.geometry().asPoint() # make sure the coordinates are in EPSG:4326 if srcCRS != epsg4326: pt = geomTo4326.transform(pt.x(), pt.y()) angle = 0.0 while angle <= 360.0: a = math.radians(angle) x = r * (cusps2 - 1.0)*math.cos(a) + r * math.cos((cusps2 - 1.0) * a) y = r * (cusps2 - 1.0)*math.sin(a) - r * math.sin((cusps2 - 1.0) * a) a2 = math.degrees(math.atan2(y,x))+sangle dist = math.sqrt(x*x + y*y) g = geod.Direct(pt.y(), pt.x(), a2, dist, Geodesic.LATITUDE | Geodesic.LONGITUDE) pts.append(QgsPointXY(g['lon2'], g['lat2'])) angle += step # If the Output crs is not 4326 transform the points to the proper crs if srcCRS != epsg4326: for x, ptout in enumerate(pts): pts[x] = toSinkCrs.transform(ptout) f = QgsFeature() if shapetype == 0: f.setGeometry(QgsGeometry.fromPolygonXY([pts])) else: f.setGeometry(QgsGeometry.fromPolylineXY(pts)) f.setAttributes(feature.attributes()) sink.addFeature(f) if index % 100 == 0: feedback.setProgress(int(index * total)) if numbad > 0: feedback.pushInfo(tr("{} out of {} features had invalid parameters and were ignored.".format(numbad, featureCount))) return {self.PrmOutputLayer: dest_id}
def processAlgorithm(self, parameters, context, feedback): source = self.parameterAsSource(parameters, self.PrmInputLayer, context) shapetype = self.parameterAsInt(parameters, self.PrmShapeType, context) azimuthmode = self.parameterAsInt(parameters, self.PrmAzimuthMode, context) startanglecol = self.parameterAsString(parameters, self.PrmAzimuth1Field, context) endanglecol = self.parameterAsString(parameters, self.PrmAzimuth2Field, context) radiusCol = self.parameterAsString(parameters, self.PrmRadiusField, context) startangle = self.parameterAsDouble(parameters, self.PrmDefaultAzimuth1, context) endangle = self.parameterAsDouble(parameters, self.PrmDefaultAzimuth2, context) radius = self.parameterAsDouble(parameters, self.PrmDefaultRadius, context) segments = self.parameterAsInt(parameters, self.PrmDrawingSegments, context) units = self.parameterAsInt(parameters, self.PrmUnitsOfMeasure, context) export_geom = self.parameterAsBool(parameters, self.PrmExportInputGeometry, context) measureFactor = conversionToMeters(units) radius *= measureFactor ptSpacing = 360.0 / segments srcCRS = source.sourceCrs() fields = source.fields() if export_geom: names = fields.names() name_x, name_y = settings.getGeomNames(names) fields.append(QgsField(name_x, QVariant.Double)) fields.append(QgsField(name_y, QVariant.Double)) if shapetype == 0: (sink, dest_id) = self.parameterAsSink(parameters, self.PrmOutputLayer, context, fields, QgsWkbTypes.Polygon, srcCRS) else: (sink, dest_id) = self.parameterAsSink(parameters, self.PrmOutputLayer, context, fields, QgsWkbTypes.LineString, srcCRS) if srcCRS != epsg4326: geomTo4326 = QgsCoordinateTransform(srcCRS, epsg4326, QgsProject.instance()) toSinkCrs = QgsCoordinateTransform(epsg4326, srcCRS, QgsProject.instance()) featureCount = source.featureCount() total = 100.0 / featureCount if featureCount else 0 numbad = 0 iterator = source.getFeatures() for cnt, feature in enumerate(iterator): if feedback.isCanceled(): break try: pts = [] pt = feature.geometry().asPoint() pt_orig_x = pt.x() pt_orig_y = pt.y() # make sure the coordinates are in EPSG:4326 if srcCRS != epsg4326: pt = geomTo4326.transform(pt.x(), pt.y()) pts.append(pt) if startanglecol: sangle = float(feature[startanglecol]) else: sangle = startangle if endanglecol: eangle = float(feature[endanglecol]) else: eangle = endangle if azimuthmode == 1: width = abs(eangle) / 2.0 eangle = sangle + width sangle -= width if radiusCol: dist = float(feature[radiusCol]) * measureFactor else: dist = radius sangle = sangle % 360 eangle = eangle % 360 if sangle > eangle: # We are crossing the 0 boundry so lets just subtract # 360 from it. sangle -= 360.0 while sangle < eangle: g = geod.Direct(pt.y(), pt.x(), sangle, dist, Geodesic.LATITUDE | Geodesic.LONGITUDE) pts.append(QgsPointXY(g['lon2'], g['lat2'])) sangle += ptSpacing # add this number of degrees to the angle g = geod.Direct(pt.y(), pt.x(), eangle, dist, Geodesic.LATITUDE | Geodesic.LONGITUDE) pts.append(QgsPointXY(g['lon2'], g['lat2'])) pts.append(pt) # If the Output crs is not 4326 transform the points to the proper crs if srcCRS != epsg4326: for x, ptout in enumerate(pts): pts[x] = toSinkCrs.transform(ptout) f = QgsFeature() if shapetype == 0: f.setGeometry(QgsGeometry.fromPolygonXY([pts])) else: f.setGeometry(QgsGeometry.fromPolylineXY(pts)) attr = feature.attributes() if export_geom: attr.append(pt_orig_x) attr.append(pt_orig_y) f.setAttributes(attr) sink.addFeature(f) except: numbad += 1 if cnt % 100 == 0: feedback.setProgress(int(cnt * total)) if numbad > 0: feedback.pushInfo(tr("{} out of {} features had invalid parameters and were ignored.".format(numbad, featureCount))) return {self.PrmOutputLayer: dest_id}
def processAlgorithm(self, parameters, context, feedback): """ Here is where the processing itself takes place. """ # Retrieve the feature source and sink. The 'dest_id' variable is used # to uniquely identify the feature sink, and must be included in the # dictionary returned by the processAlgorithm function. couche_lines = self.parameterAsVectorLayer(parameters, self.LINES, context) couche_points = self.parameterAsVectorLayer(parameters, self.NODES, context) radius=self.parameterAsDouble(parameters,self.RAYON,context) # Compute the number of steps to display within the progress bar and # get features from source delta=float(radius) index=QgsSpatialIndex() lines=couche_lines.getFeatures() for i in lines: if i.geometry().isMultipart(): i.setGeometry(QgsGeometry.fromPolylineXY(i.geometry().asMultiPolyline()[0])) index.insertFeature(i) couche_lines.startEditing() couche_lines.beginEditCommand(self.tr("Split polylines at connections")) points=couche_points.getFeatures() nb=couche_points.featureCount() feedback.setProgressText(self.tr("Connecting points to lines...")) for pos,pt in enumerate(points): feedback.setProgress(pos*100.0/nb) ptg=pt.geometry() if ptg.isMultipart(): ptg=QgsGeometry.fromPoint(ptg.asMultiPoint()[0]) coor=ptg.asPoint() nearest=index.intersects(QgsRectangle(coor.x()-delta,coor.y()-delta,coor.x()+delta,coor.y()+delta)) dmin=1e38 if len(nearest)>0: for n in nearest: f=couche_lines.getFeatures(request=QgsFeatureRequest(n)) for g in f: d=g.geometry().distance(pt.geometry()) if d<=dmin: dmin=d gmin=g gid=g.id() g=gmin if g.geometry().distance(pt.geometry())<delta: a=g.geometry().closestSegmentWithContext(ptg.asPoint()) if not(a[2]==0): geom=g.geometry() geom.convertToSingleType() geom_id=g.id() att=g.attributes() connexion=QgsFeature() connexion.setGeometry(QgsGeometry.fromPolylineXY([ptg.asPoint(),a[1]])) connexion.setAttributes(att) couche_lines.addFeature(connexion) geom.insertVertex(a[1][0],a[1][1],a[2]) geoma=geom.asPolyline()[:a[2]+1] geomb=geom.asPolyline()[a[2]:] feedback.setProgressText(unicode(geomb)) fa=QgsFeature() fa.setGeometry(QgsGeometry.fromPolylineXY(geoma)) fa.setAttributes(att) couche_lines.addFeature(fa) index.insertFeature(fa) fb=QgsFeature() fb.setGeometry(QgsGeometry.fromPolylineXY(geomb)) fb.setAttributes(att) couche_lines.addFeature(fb) index.insertFeature(fb) couche_lines.deleteFeature(g.id()) index.deleteFeature(g) couche_lines.commitChanges() couche_lines.endEditCommand() return {self.LINES: 'OK'}