When working with geospatial data in BigQuery, you’ll often encounter LineString geometries representing routes, boundaries, or trajectories. Sometimes, you need to access the individual points that make up these LineStrings for detailed analysis or visualization.
In this tutorial, we’ll explore a powerful technique to extract all vertex points from a LineString using BigQuery’s spatial functions and array operations.
The Challenge
LineStrings in BigQuery are stored as single geometry objects, but for many analyses, you need access to the individual vertices. For example, you might want to:
- Calculate the distance between consecutive points
- Identify sharp turns or unusual segments
- Sample points along a route for time-series analysis
- Create a heatmap from trajectory density
The Solution: Combining ST_PointN with Array Generation
BigQuery provides the ST_PointN function to extract a specific point from a LineString, but it requires an index. By combining this with array generation, we can extract all points in a single query.
Here’s the technique:
WITH linestring AS (
SELECT ST_GeogFromText('LINESTRING(1 1, 2 1, 3 2, 3 3)') AS g
)
SELECT
idx,
ST_PointN(g, idx) AS point,
ST_X(ST_PointN(g, idx)) AS longitude,
ST_Y(ST_PointN(g, idx)) AS latitude
FROM linestring,
UNNEST(GENERATE_ARRAY(1, ST_NumPoints(g))) AS idx
Breaking Down the Solution
Let’s analyze how this works:
- We create a sample LineString using
ST_GeogFromText ST_NumPoints(g)tells us how many points are in the LineStringGENERATE_ARRAY(1, ST_NumPoints(g))creates an array of indices from 1 to the number of pointsUNNESTexpands this array into individual rowsST_PointN(g, idx)extracts each point by its index- We also extract the longitude and latitude using
ST_XandST_Y
Practical Application: Analyzing Point-to-Point Distances
Once you have individual points, you can analyze the distances between consecutive points:
WITH linestring AS (
SELECT ST_GeogFromText('LINESTRING(1 1, 2 1, 3 2, 3 3)') AS g
),
points AS (
SELECT
idx,
ST_PointN(g, idx) AS point
FROM linestring,
UNNEST(GENERATE_ARRAY(1, ST_NumPoints(g))) AS idx
)
SELECT
a.idx AS point_idx,
b.idx AS next_point_idx,
ST_Distance(a.point, b.point) AS distance_meters
FROM points a
JOIN points b ON a.idx = b.idx - 1
ORDER BY a.idx
This query calculates the distance between each consecutive pair of points in the LineString, which can be useful for identifying segments with unusual distances.
Advanced Example: Creating Equidistant Points Along a LineString
Sometimes you need points sampled at regular distance intervals rather than the original vertices. Here’s how to generate points every 100 meters along a LineString:
WITH linestring AS (
SELECT ST_GeogFromText('LINESTRING(1 1, 2 1, 3 2, 3 3)') AS g
),
line_length AS (
SELECT ST_Length(g) AS total_length
FROM linestring
),
sample_points AS (
SELECT
GENERATE_ARRAY(0, CAST(FLOOR(total_length/100) AS INT64)) AS point_indices
FROM line_length
)
SELECT
idx AS sample_idx,
idx*100 AS distance_along_line_meters,
ST_LineInterpolatePoint(linestring.g, idx*100/line_length.total_length) AS point
FROM linestring, line_length, sample_points,
UNNEST(sample_points.point_indices) AS idx
Performance Considerations
When working with very large LineStrings or many LineStrings in a table:
- Ensure your table is properly partitioned and clustered
- Consider materializing the extracted points if you query them frequently
- Use column-level partitioning if you’re storing LineStrings with timestamps
Conclusion
Extracting points from LineStrings in BigQuery opens up powerful analytical possibilities. By combining spatial functions with array operations, you can transform complex geospatial data into more accessible formats for analysis and visualization.
This technique is particularly valuable for transportation analysis, movement tracking, and any application where routes or trajectories need to be analyzed at the point level.
Further Resources
Visualizing Geospatial Data from BigQuery in Looker Studio

