In BigQuery assume I have a GEOPOINT Datatype. Say for eg ST_GEOGPOINT(-122, 37)
How can I find say 10 GEOGPOINTS that make the Outer Circle with the radius as 100 km.
The requirement is for a Looker Dashboard, where I have the GPS Data of Devices at the lowest level and we are tracking it's activity.
Now we will create an aggregated table at City Level as following data with
ST_CENTROID_AGG
function in BigQuerycity | Age Bucket | Central GEOGPOINT | # of Devices |
---|---|---|---|
Texas, USA | 1 Day | ST_GEOGPOINT(31, 99) | 100 |
Texas, USA | 1 Week | ST_GEOGPOINT(31, 99) | 10 |
Texas, USA | 1 Month | ST_GEOGPOINT(31, 99) | 10 |
Texas, USA | 2 Month | ST_GEOGPOINT(31, 99) | 10 |
Texas, USA | 4 Month | ST_GEOGPOINT(31, 99) | 10 |
Texas, USA | 6 Month | ST_GEOGPOINT(31, 99) | 10 |
Texas, USA | 10 Month | ST_GEOGPOINT(31, 99) | 100 |
Florida, USA | 1 Day | ST_GEOGPOINT(27, 81) | 100 |
Florida, USA | 2 Week | ST_GEOGPOINT(27, 81) | 10 |
Florida, USA | 3 Month | ST_GEOGPOINT(27, 81) | 10 |
Florida, USA | 5 Month | ST_GEOGPOINT(27, 81) | 10 |
Florida, USA | 6 Month | ST_GEOGPOINT(27, 81) | 10 |
Florida, USA | 9 Month | ST_GEOGPOINT(27, 81) | 10 |
Florida, USA | 10 Month | ST_GEOGPOINT(27, 81) | 100 |
Here while plotting, the I would like to see all Florida being plotted at the central point with concentric circles around it. For Texas, USA here it needs 6 points in the outside circle For Florida, USA here it needs 7 points in the outside circle
How can we have a BigQuery function where I can get these GEOGPOINTS (either pre-calcualted in agg table or as a runtime function) to plot in a better way
I tired to play around the following article
https://towardsdatascience.com/spatial-binning-with-google-bigquery-d118afba6273
And could get some approximate cirlces, which will be looking oval due to how Lat & Long is shown in Map and get skewed at either north or south poles
--
-- Table Function to Generate Circular Points for an input (Will be Oval in Shape)
--
CREATE OR REPLACE TABLE FUNCTION looker_iot_model.approx_circle_points(
latitude FLOAT64, longitude FLOAT64, circle FLOAT64, points INTEGER)
AS (
SELECT
seq,
ST_GEOGPOINT(longitude + ((SIN(ACOS(-1)*seq/points))*circle/9), latitude + ((COS(ACOS(-1)*seq/points))*circle/10)) AS geo_point
FROM UNNEST(GENERATE_ARRAY(-1*(points-1),(points-1),2)) as seq
);
Now If I run
select * FROM looker_iot_model.approx_circle_points(37.7749, -122.4194, 12, 12)
select * FROM looker_iot_model.approx_circle_points(71, 42, 12, 12)
ST_Buffer(central_point, 100*1000, 10/4)
builds a polygonized loop around the central point. The second argument is radius (in meters), the third one is number of points per quarter. It returns POLYGON with 10 vertices (that look like 11 due to first and last one repeated in POLYGON loop)
To convert it to list of points we would need ST_DumpPoints
that is not available in BigQuery, let's build poor-man version of it using text manipulation:
select st_geogfromtext(concat("POINT(", p, ")")) AS point
from unnest(split(
trim(
st_astext(st_buffer(ST_GEOGPOINT(-122, 37), 100e3,
num_seg_quarter_circle => 10/4)),
"POLYGON()"),
",")) p with offset o
where o <> 0;
This builds a buffer, converts it to text, strips "polygon((..))" wrappings, splits the remaining points, and converts them back to geographies omitting the first point (that is repeated at the end of polygon definition).