Skip to main content

Source data: Lines and points near to the line

 

I'm trying find the distance of each point to the line. I have tried using Nearest Neighbor but it doesn't work with 3D features.

So the distance between a point p0 and a line segment (p1, p2) is calculated via vectors.  p =  (x, y, z)

d = 0684Q00000ArJxFQAV.gif  substitute p for x in the image.

I would use the numpy.linalg norm function  in a python caller

d = norm(np.cross(p2-p1, p1-p0))/norm(p2-p1)

 

However if you have a polyline you would have to chop it into 2 vertex segments, calculate the distance to each segment, and get the minimum.

 

 

There may be ways to optimize checking only certain line segments, but I can't think of them off hand.


This can be more simply done perhaps by integrating SpatiaLite to the workspace. This avoids having to manually code up the calculus and having to manually test a whole bunch of conditions, as the general calculus formula presented is for where the line being tested against is of infinite length and where it is a straight line, whereas a general line has bounds on the X, Y, Z space it occupies so you need to test if the nearest point on the infinite line is within the X, Y, Z bounds of the actual line being tested against.

SpatiaLite, on the other hand, already embeds the LWGEOM library function "ST_3DDistance( g1 AS geometry, g2 as geometry)", which I've tested on 3D points and lines and works. Then it just becomes a matter of calling ST_3DDistance(points.geometry, lines.geometry) in a SQL statement to get the minimum distance between any 2 general point and line combination.

In theory, this is where SQLExecutor could do the heavy lifting, but unfortunately, at least in FME 2018, the GDAL library being used by a SpatiaLite SQLExecutor either doesn't use a later build of SpatiaLite or the build hasn't integrated the LWGEOM function library so although it works fine in my version of SpatiaLite, SQLExecutor returns "unrecognized function"

It gets a little tricky then, off the cuff if it was me I would:

  • Download the latest SpatiaLite.exe compiled binary which has the LWGEOM library automatically
  • Send the Lines and Points out in a SpatiaLite FeatureWriter. My testing shows that it writes 3D geometries into SpatiaLite in 3D coordinates......so all good
  • Use SystemCaller to call the SpatiaLite.exe command and pass to it the location of the SQLITE file generated by the FeatureWriter and pass it the SQL command "CREATE TABLE Results AS SELECT PointID, LineID, ST_3DDistance(points.geometry, lines.geometry) AS Min3DDistance FROM Points, Lines".............this will create the results table inside the file database
  • Read in the Results table that got generated back in using either a FeatureReader or an SQLExecutor

The pain in this method is that you would need to deploy the SpatiaLite.EXE executable to any other PC attempt to run this on, but on the other hand it may avoid a lot of hand coding of formulae to test for minimum 3D distance values.

Alternatively there are Python ways of getting access to the same library written in C, but then this still needs the DLL (and it appears later versions of ST_3DDistance have forked to the RTTOPO library of geospatial functions) and coding skills to use it perhaps like this:

https://gis.stackexchange.com/questions/278425/seeking-st-subdivide-implementation-in-python


This can be more simply done perhaps by integrating SpatiaLite to the workspace. This avoids having to manually code up the calculus and having to manually test a whole bunch of conditions, as the general calculus formula presented is for where the line being tested against is of infinite length and where it is a straight line, whereas a general line has bounds on the X, Y, Z space it occupies so you need to test if the nearest point on the infinite line is within the X, Y, Z bounds of the actual line being tested against.

SpatiaLite, on the other hand, already embeds the LWGEOM library function "ST_3DDistance( g1 AS geometry, g2 as geometry)", which I've tested on 3D points and lines and works. Then it just becomes a matter of calling ST_3DDistance(points.geometry, lines.geometry) in a SQL statement to get the minimum distance between any 2 general point and line combination.

In theory, this is where SQLExecutor could do the heavy lifting, but unfortunately, at least in FME 2018, the GDAL library being used by a SpatiaLite SQLExecutor either doesn't use a later build of SpatiaLite or the build hasn't integrated the LWGEOM function library so although it works fine in my version of SpatiaLite, SQLExecutor returns "unrecognized function"

It gets a little tricky then, off the cuff if it was me I would:

  • Download the latest SpatiaLite.exe compiled binary which has the LWGEOM library automatically
  • Send the Lines and Points out in a SpatiaLite FeatureWriter. My testing shows that it writes 3D geometries into SpatiaLite in 3D coordinates......so all good
  • Use SystemCaller to call the SpatiaLite.exe command and pass to it the location of the SQLITE file generated by the FeatureWriter and pass it the SQL command "CREATE TABLE Results AS SELECT PointID, LineID, ST_3DDistance(points.geometry, lines.geometry) AS Min3DDistance FROM Points, Lines".............this will create the results table inside the file database
  • Read in the Results table that got generated back in using either a FeatureReader or an SQLExecutor

The pain in this method is that you would need to deploy the SpatiaLite.EXE executable to any other PC attempt to run this on, but on the other hand it may avoid a lot of hand coding of formulae to test for minimum 3D distance values.

Alternatively there are Python ways of getting access to the same library written in C, but then this still needs the DLL (and it appears later versions of ST_3DDistance have forked to the RTTOPO library of geospatial functions) and coding skills to use it perhaps like this:

https://gis.stackexchange.com/questions/278425/seeking-st-subdivide-implementation-in-python

Thanks for sharing your experience on this matter. Great tips there!


Reply