6

I have a point shapefile where I want to connect all points (25 points that make 600 pairs).

As a result, I need a line shapefile with an attribute table that contains points lying on the line.

e.g.

lineID    pointID1    pointID2
  1          25          16

I've tried a few plugins including points2one, MMQGIS, etc., but none of them worked.

0

3 Answers 3

4

You can get this result using a python script that loops twice through the point layer, fetch the two points and construct a line. The solution below removes duplicates (that it, line A -> B is consider the same as B -> A).

The output has the same CRS as the input. Make sure to edit the constant with the proper point ID column name

Point connector output

from PyQt4.QtCore import QVariant

#Purpose: using the selected point layer, create a new scratch layer
#         containing a line between each pair of points and record the point ID

#***********Constants
#
SOURCEID = 'ID'

LINEID = 'lineID'
POINTID1 = 'pointID1'
POINTID2 = 'pointID2'
#
#***********

srclayer = iface.activeLayer()
crs = srclayer.crs().toWkt()

# Create the output layer
outLayer = QgsVectorLayer('Linestring?crs='+ crs, 'connector_lines' , 'memory')
outdp = outLayer.dataProvider()

#add the two point ID field
outdp.addAttributes([QgsField(LINEID, QVariant.Int),
                     QgsField(POINTID1, QVariant.Int),
                     QgsField(POINTID2, QVariant.Int)])
outLayer.updateFields()


#get the field index
srcIDfldidx = srclayer.dataProvider().fieldNameIndex(SOURCEID)
outLineIDfldidx = outdp.fieldNameIndex(LINEID)
outID1fldidx = outdp.fieldNameIndex(POINTID1)
outID2fldidx = outdp.fieldNameIndex(POINTID2)

lineIDcnt = 0

#loop through the points (1st point)
for feat1 in srclayer.getFeatures():
    geom1 = feat1.geometry()

    #statement for selecting the 2nd points with a greater ID to avoid duplicates
    # to keep them, change the expresion to ' <> '
    exp = QgsExpression(SOURCEID + ' > ' + str(feat1.attributes()[srcIDfldidx]))
    request = QgsFeatureRequest(exp)
    #Select only the points having the specified value
    feat2lst=srclayer.getFeatures(request)

    #loop through the points (2nd point)
    for feat2 in feat2lst:
        lineIDcnt +=  1
        geom2 = feat2.geometry()

        #create the line
        connector = QgsFeature(outLayer.pendingFields())
        connector.setGeometry(QgsGeometry.fromPolyline([geom1.asPoint(),
                                                        geom2.asPoint()]))

        #record the IDs
        res = connector.setAttribute(outLineIDfldidx, lineIDcnt)
        res = connector.setAttribute(outID1fldidx, feat1[srcIDfldidx])
        res = connector.setAttribute(outID2fldidx, feat2[srcIDfldidx])

        #add the feature to the layer
        res = outdp.addFeatures([connector])

# Add the layer to the Layers panel
QgsMapLayerRegistry.instance().addMapLayer(outLayer)

print "Done .. "
2

Another simple way is to:

  • Create a virtual layer with a self cross join
  • Save the virtual layer as a shapefile
  • Use the field calculator to add the lineid:
SELECT 
   p1.pointid p1id, 
   p2.pointid p2id,
   MakeLine(p1.geometry, p2.geometry) geometry 
FROM mypoint p1 CROSS JOIN mypoint p2  
WHERE p1.pointid > p2.pointid

Here is how it looks like in QGIS Virtual Layers dialog.

enter image description here

Save the virtual layer to a shapefile. Then add the lineid column to the shapefile:

enter image description here

You could generate the lineid in the sql code skipping the last two steps. I could not get it working. Perhaps someone else can.

enter image description here

1

WKT FIELD BASED SOLUTION

  • In Excel for example, create a table witht the Point start and end coordinates as below :

Excel

  • Create a new colum named WKT

  • Populate this column with a formula : use CONCATENATE command to create the following syntax for each line from your previous columns :

    LineString(POINT_START_X POINT_START_Y,POINT_END_X, POINT_END_Y)

  • The CONCATENATE command should be like this:

    =CONCATENATE("Linestring(";D2;" ";E2;",";F2;" ";G2;")")

  • You should obtain something like this in the last column :

    LineString(408963.1289 6708565.47,409267.9769 6708383.844)

  • Save as Excel to keep your formula, then save as CSV file

  • In QGIS, add a CSV layer like below - don't forget to check if QGIS has found that you put a WKT field :

Import CSV

There you go :

Ending

  • As it's a csv file, you can still regenerate it any time you need.

GEOMETRY CREATOR BASED SOLUTION (less good)

The following solution allows you to manage your lines creation from Excel. The downside is that is mainly visual : you can't label your layer with the line ID on the line as the label is based on the start point.

  • in your line list in excel (for example), add point 1 and point 2 coordinates (join it if necessary and use VLOOKUP in Excel) to get a table like below, with a point start coordinates and point end coordinates :

Link Points table

  • In QGIS add your CSV file (or install the Spreadcheet plugin and add directly the data from Excel)

  • Choose Point 1 columns coordinates to create a point layer

  • You will get a point table with all start points

  • Choose a Geometry generator style

  • Choose Linestring Geometry type

  • Enter this formula that will interactively create your lines from your Excel sheet or CSV file (just need to change thye name of field accordingly to your needs)

    make_line(make_point("Pt1_xcoord","Pt1_ycoord"), make_point("Pt2_xcoord","Pt2_ycoord"))

Link lines generator

And there you go :

Link  point lines

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.