Solution for three and more point layers using PyQGIS
Let's assume there are three point layers 'start'
(pink), 'end'
(dark green) and 'pois'
(dark blue), with its corresponding attribute tables accordingly, see image below.
Proceed with Plugins > Python Console > Show Editor
and paste the script below
# imports
import processing
# a list that defines all point layers for which connections have to be created
point_layers_names = ['start', 'end', 'pois'] # here a user has to specify names of point layers!
# creating a list of layers with points
point_layers = []
for point_layer_name in point_layers_names:
point_layers.append(QgsProject.instance().mapLayersByName(point_layer_name)[0])
# merging point layers into one layer with 'qgis:mergevectorlayers' geoalgorithm
points_merged = processing.run("qgis:mergevectorlayers",{
'CRS' : point_layers[0].crs().authid(),
'LAYERS' : point_layers,
'OUTPUT' : 'memory:'
})['OUTPUT']
# getting indexes of fields in the merged layer
points_merged_id_index = points_merged.fields().indexFromName('id')
points_merged_layer_index = points_merged.fields().indexFromName('layer')
# creating a virtual output layer with line strings
line_layer = QgsVectorLayer("LineString?crs={}&index=yes".format(point_layers[0].crs().authid()), "Connections", "memory")
# adding new fields
provider = line_layer.dataProvider()
provider.addAttributes([QgsField(points_merged.fields()[points_merged_index].name() + '_from', points_merged.fields()[points_merged_index].type()),\
QgsField(points_merged.fields()[points_merged_layer_index].name() + '_from', points_merged.fields()[points_merged_layer_index].type()),\
QgsField(points_merged.fields()[points_merged_index].name() + '_to', points_merged.fields()[points_merged_index].type()),\
QgsField(points_merged.fields()[points_merged_layer_index].name() + '_to', points_merged.fields()[points_merged_layer_index].type()),\
])
line_layer.updateFields()
# looping over each feature from the merged layer and making all possible connections between them
for f1 in points_merged.getFeatures():
for f2 in points_merged.getFeatures():
if f1.geometry().asPoint() != f2.geometry().asPoint(): # avoiding connections between same features
connect = [f1.geometry().asPoint(), f2.geometry().asPoint()] # connection between two points
line = QgsGeometry.fromPolylineXY(connect) # creating a line string from connection
f = QgsFeature() # creating Qgs feature
f.setGeometry(line) # setting new geometry as a line string
f.setAttributes([f1.attribute(points_merged_index), f1.attribute(points_merged_layer_index), f2.attribute(points_merged_index), f2.attribute(points_merged_layer_index)]) # setting new attributes as from and to
provider.addFeature(f) # adding Qgis feature to the output layer
# adding a new feature to the map
QgsProject.instance().addMapLayer(line_layer)
Press Run script
and get the output that will look like
Mind that in the example above duplicate geometries will appear because of the connection in two directions. If this component has to be avoided, please run this script
# imports
import processing
# a list that defines all point layers for which connections have to be created
point_layers_names = ['start', 'end', 'pois'] # here a user has to specify names of point layers!
# creating a list of layers with points
point_layers = []
for point_layer_name in point_layers_names:
point_layers.append(QgsProject.instance().mapLayersByName(point_layer_name)[0])
# merging point layers into one layer with 'qgis:mergevectorlayers' geoalgorithm
points_merged = processing.run("qgis:mergevectorlayers", {
'CRS' : point_layers[0].crs().authid(),
'LAYERS' : point_layers,
'OUTPUT' : 'memory:'
})['OUTPUT']
# getting indexes of fields in the merged layer
points_merged_id_index = points_merged.fields().indexFromName('id')
points_merged_layer_index = points_merged.fields().indexFromName('layer')
# creating a virtual output layer with line strings
line_layer = QgsVectorLayer("LineString?crs={}&index=yes".format(point_layers[0].crs().authid()), "Connections", "memory")
# adding new fields
provider = line_layer.dataProvider()
provider.addAttributes([QgsField(points_merged.fields()[points_merged_index].name() + '_from', points_merged.fields()[points_merged_index].type()),\
QgsField(points_merged.fields()[points_merged_layer_index].name() + '_from', points_merged.fields()[points_merged_layer_index].type()),\
QgsField(points_merged.fields()[points_merged_index].name() + '_to', points_merged.fields()[points_merged_index].type()),\
QgsField(points_merged.fields()[points_merged_layer_index].name() + '_to', points_merged.fields()[points_merged_layer_index].type()),\
])
line_layer.updateFields()
# looping over each feature from the merged layer and making all possible connections between them
for f1 in points_merged.getFeatures():
for f2 in points_merged.getFeatures():
if f1.geometry().asPoint() != f2.geometry().asPoint(): # avoiding connections between same features
connect = [f1.geometry().asPoint(), f2.geometry().asPoint()] # connection between two points
line = QgsGeometry.fromPolylineXY(connect) # creating a line string from connection
f = QgsFeature() # creating Qgs feature
f.setGeometry(line) # setting new geometry as a line string
f.setAttributes([f1.attribute(points_merged_index), f1.attribute(points_merged_layer_index), f2.attribute(points_merged_index), f2.attribute(points_merged_layer_index)]) # setting new attributes as from and to
provider.addFeature(f) # adding Qgis feature to the output layer
# removing duplicated geometries
line_layer_unique = processing.run("qgis:deleteduplicategeometries", {'INPUT': line_layer, 'OUTPUT': 'memory:'})['OUTPUT']
# adding a new feature to the map
QgsProject.instance().addMapLayer(line_layer_unique)
Press Run script
and get new output
References: