如何为来自 BigQuery JavaScript UDF 的字符串化几何集合中的每个特征创建几何?
How to create a geometry for each feature in a stringified geometry collection from a BigQuery JavaScript UDF?
我是 UDF 函数的新手,我创建了一个 BigQuery UDF,它采用多边形几何图形并用它创建点。我正在尝试绘制点密度图(将多边形+人口数量转换为点)。我改编了 this blog post. Because bigQuery doesn't have a way to log variables, I've been testing things out in this codepen.
中的代码
我正处于该功能似乎正常工作的地步。输出是点的几何集合。它在 bigquery 文档中说 st_geogfromgeojson
可以接受几何集合。
我的 UDF return 是一个字符串化的几何集合。
但我不明白为什么 st_geogfromgeojson
不起作用。我不知道我是否只是没有取消嵌套或什么。
CREATE TEMP FUNCTION myFunc(feature string, ethnicity_column FLOAT64, year INT64)
RETURNS string
LANGUAGE js
OPTIONS (
library=["https://storage.googleapis.com.../d3.js","https://storage.googleapis.com/.../turf.min.js","https://storage.googleapis.com/.../wellknown.js"]
)
AS
"""
if (feature === undefined || feature === null) return;
var feature_parsed = wellknown.parse(feature)
const bounds = turf.bbox(feature_parsed);
const populationData = Math.round(ethnicity_column / 10);
if (!populationData) return;
const x_min = bounds[0];
const y_min = bounds[1];
const x_max = bounds[2];
const y_max = bounds[3];
let hits = 0;
let count = 0;
const limit = populationData * 10; // limit test to 10x the population.
let points = [];
while (hits < populationData - 1 && count < limit) {
const lat = y_min + Math.random() * (y_max - y_min);
const lng = x_min + Math.random() * (x_max - x_min);
const randomPoint = turf.point([lng, lat]);
if (turf.booleanPointInPolygon(randomPoint, feature_parsed)) {
points.push(randomPoint);
hits++;
}
count++;
}
return JSON.stringify((turf.geometryCollection(points)));
// return JSON.stringify(points)
""";
SELECT ST_GEOGFROMGEOJSON(JSON_EXTRACT((myFunc(st_astext(geom), white_pop, 2018)),'$')) FROM `myteam.kyle_data.blockgroups_with_acs`
但我一直遇到随机错误,比如我没有正确使用函数
我乐于接受所有建议。为了简单起见,我 return 一个字符串,但也许我需要使用一个 STRUCT。也许我应该从创造点中切出草皮?我一定是漏掉了什么。
GeoJson 有两种不同的集合类型:
- 一个是
GeometryCollection
- 这是描述几何集合的几何图形,例如点和多边形的联合将是一个 GeometryCollection。
- 另一个是
FeatureCollection
- 特征集合,具有各种属性的对象,包括 geometry
(可以是几何集合或任何其他几何)和其他 user-defined 属性。
turf.geometryCollection 似乎 return a Feature
: https://www.npmjs.com/package/turf-geometrycollection (这就是它也接受 properties
参数的原因)。
ST_GEOGFROMGEOJSON
构造一个几何体,它确实支持GeometryCollection
,但不支持FeatureCollection
或单数Feature
returned by turf.
你可以做的是从这个特征中提取一个geometry
,并将它传递给ST_GEOGFROMGEOJSON
。我认为只使用 JSON 选择器 $.geometry
而不是 $
就足够了。
修复它的两件事:
- 返回
array<String>
而不是字符串
select
中的 CROSS JOIN UNNEST
CREATE TEMP FUNCTION myFunc(feature string, ethnicity_column FLOAT64)
RETURNS array<String>
LANGUAGE js
OPTIONS (
library=["https://storage.googleapis.com/../d3.js","https://storage.googleapis.com/.../turf.min.js","https://storage.googleapis.com/.../wellknown.js"]
)
AS
"""
geopath = d3.geoPath()
if (feature === undefined || feature === null) return;
var feature_parsed = wellknown.parse(feature)
const bounds = turf.bbox(feature_parsed);
const populationData = Math.round(ethnicity_column / 10);
if (!populationData) return;
const x_min = bounds[0];
const y_min = bounds[1];
const x_max = bounds[2];
const y_max = bounds[3];
let hits = 0;
let count = 0;
const limit = populationData; // limit test to 10x the population.
let points = [];
while (hits < populationData - 1 && count < limit) {
const lat = y_min + Math.random() * (y_max - y_min);
const lng = x_min + Math.random() * (x_max - x_min);
const randomPoint = turf.point([lng, lat]);
if (turf.booleanPointInPolygon(randomPoint, feature_parsed)) {
points.push('POINT ('+lng+' '+lat+')');
hits++;
}
count++;
}
return points;
""";
SELECT st_geogfromtext(points) as the_geom, 'white' as ethnicity from (SELECT (myFunc(st_astext(geom), white_pop)) as points FROM `tableonmybq`) CROSS JOIN UNNEST(points) as points
我是 UDF 函数的新手,我创建了一个 BigQuery UDF,它采用多边形几何图形并用它创建点。我正在尝试绘制点密度图(将多边形+人口数量转换为点)。我改编了 this blog post. Because bigQuery doesn't have a way to log variables, I've been testing things out in this codepen.
中的代码我正处于该功能似乎正常工作的地步。输出是点的几何集合。它在 bigquery 文档中说 st_geogfromgeojson
可以接受几何集合。
我的 UDF return 是一个字符串化的几何集合。
但我不明白为什么 st_geogfromgeojson
不起作用。我不知道我是否只是没有取消嵌套或什么。
CREATE TEMP FUNCTION myFunc(feature string, ethnicity_column FLOAT64, year INT64)
RETURNS string
LANGUAGE js
OPTIONS (
library=["https://storage.googleapis.com.../d3.js","https://storage.googleapis.com/.../turf.min.js","https://storage.googleapis.com/.../wellknown.js"]
)
AS
"""
if (feature === undefined || feature === null) return;
var feature_parsed = wellknown.parse(feature)
const bounds = turf.bbox(feature_parsed);
const populationData = Math.round(ethnicity_column / 10);
if (!populationData) return;
const x_min = bounds[0];
const y_min = bounds[1];
const x_max = bounds[2];
const y_max = bounds[3];
let hits = 0;
let count = 0;
const limit = populationData * 10; // limit test to 10x the population.
let points = [];
while (hits < populationData - 1 && count < limit) {
const lat = y_min + Math.random() * (y_max - y_min);
const lng = x_min + Math.random() * (x_max - x_min);
const randomPoint = turf.point([lng, lat]);
if (turf.booleanPointInPolygon(randomPoint, feature_parsed)) {
points.push(randomPoint);
hits++;
}
count++;
}
return JSON.stringify((turf.geometryCollection(points)));
// return JSON.stringify(points)
""";
SELECT ST_GEOGFROMGEOJSON(JSON_EXTRACT((myFunc(st_astext(geom), white_pop, 2018)),'$')) FROM `myteam.kyle_data.blockgroups_with_acs`
但我一直遇到随机错误,比如我没有正确使用函数
我乐于接受所有建议。为了简单起见,我 return 一个字符串,但也许我需要使用一个 STRUCT。也许我应该从创造点中切出草皮?我一定是漏掉了什么。
GeoJson 有两种不同的集合类型:
- 一个是
GeometryCollection
- 这是描述几何集合的几何图形,例如点和多边形的联合将是一个 GeometryCollection。 - 另一个是
FeatureCollection
- 特征集合,具有各种属性的对象,包括geometry
(可以是几何集合或任何其他几何)和其他 user-defined 属性。
turf.geometryCollection 似乎 return a Feature
: https://www.npmjs.com/package/turf-geometrycollection (这就是它也接受 properties
参数的原因)。
ST_GEOGFROMGEOJSON
构造一个几何体,它确实支持GeometryCollection
,但不支持FeatureCollection
或单数Feature
returned by turf.
你可以做的是从这个特征中提取一个geometry
,并将它传递给ST_GEOGFROMGEOJSON
。我认为只使用 JSON 选择器 $.geometry
而不是 $
就足够了。
修复它的两件事:
- 返回
array<String>
而不是字符串 select
中的 CROSS JOIN UNNEST
CREATE TEMP FUNCTION myFunc(feature string, ethnicity_column FLOAT64)
RETURNS array<String>
LANGUAGE js
OPTIONS (
library=["https://storage.googleapis.com/../d3.js","https://storage.googleapis.com/.../turf.min.js","https://storage.googleapis.com/.../wellknown.js"]
)
AS
"""
geopath = d3.geoPath()
if (feature === undefined || feature === null) return;
var feature_parsed = wellknown.parse(feature)
const bounds = turf.bbox(feature_parsed);
const populationData = Math.round(ethnicity_column / 10);
if (!populationData) return;
const x_min = bounds[0];
const y_min = bounds[1];
const x_max = bounds[2];
const y_max = bounds[3];
let hits = 0;
let count = 0;
const limit = populationData; // limit test to 10x the population.
let points = [];
while (hits < populationData - 1 && count < limit) {
const lat = y_min + Math.random() * (y_max - y_min);
const lng = x_min + Math.random() * (x_max - x_min);
const randomPoint = turf.point([lng, lat]);
if (turf.booleanPointInPolygon(randomPoint, feature_parsed)) {
points.push('POINT ('+lng+' '+lat+')');
hits++;
}
count++;
}
return points;
""";
SELECT st_geogfromtext(points) as the_geom, 'white' as ethnicity from (SELECT (myFunc(st_astext(geom), white_pop)) as points FROM `tableonmybq`) CROSS JOIN UNNEST(points) as points