Рисование линии в PostGIS с использованием метода ближайшего соседа
-
16-09-2019 - |
Вопрос
Это перекрестный пост из электронного письма, которое я отправил в список рассылки PostGIS
До сих пор я пытался создать линию между точкой и ее проекцией поиск местоположения на линии занимал много времени, но я почти на месте.По состоянию на вчерашний день, и перед включением любого анализа ближайших соседей, я получил результаты, показанные на этом изображении:
Как вы можете видеть, каждая точка розового цвета соединяется со всеми проецируемыми точками, тогда как я хочу соединить каждый розовый x только с соответствующей проекцией.
В IRC было рекомендовано, чтобы я использовал Метод ближайшего соседа Бостонгиса.Я ввел функцию в PostgreSQL и безуспешно попробовал ее, как описано ниже.Я предполагаю, что моя ошибка связана с неправильным типом параметра.Я поиграл с этим, изменил тип некоторых столбцов на varchar, но все равно не могу заставить это работать.
Есть какие-нибудь идеи относительно того, что я делаю не так?есть какие-нибудь предложения о том, как это исправить?
Код:
-- this sql script creates a line table that connects points
-- convert multi lines into lines
CREATE TABLE exploded_roads AS
SELECT the_geom
FROM (
SELECT ST_GeometryN(
the_geom,
generate_series(1, ST_NumGeometries(the_geom)))
AS the_geom
FROM "StreetCenterLines"
)
AS foo;
-- Create line table that'll connect the centroids to the projected points on exploded lines
CREATE TABLE lines_from_centroids_to_roads (
the_geom geometry,
edge_id SERIAL
);
-- Populate Table
INSERT INTO lines_from_centroids_to_roads ( the_geom )
SELECT
ST_MakeLine(
centroids.the_geom,
(pgis_fn_nn(centroids.the_geom, 1000000, 1,1000, 'exploded_roads' ,'true', 'gid',
ST_Line_Interpolate_Point(
exploded_roads.the_geom,
ST_Line_Locate_Point(
exploded_roads.the_geom,
centroids.the_geom
)
)
)).*
)
FROM exploded_roads, fred_city_o6_da_centroids centroids;
DROP TABLE exploded_roads;
ОШИБКА
NOTICE: CREATE TABLE will create implicit sequence "lines_from_centroids_to_roads_edge_id_seq" for serial column "lines_from_centroids_to_roads.edge_id"
ERROR: function pgis_fn_nn(geometry, integer, integer, integer, unknown, unknown, unknown, geometry) does not exist
LINE 28: (pgis_fn_nn(centroids.the_geom, 1000000, 1,1000, 'exploded...
^
HINT: No function matches the given name and argument types. You might need to add explicit type casts.
********** Error **********
ERROR: function pgis_fn_nn(geometry, integer, integer, integer, unknown, unknown, unknown, geometry) does not exist
SQL state: 42883
Hint: No function matches the given name and argument types. You might need to add explicit type casts.
Character: 584
Решение 2
оказывается, мне все-таки не нужно использовать ближайшего соседа.Я присвоил идентификатор, идентичный центроидам, через которые я соединяю линии
-- this sql script creates a line table that connects points
-- delete existing tables if they exist
DROP TABLE exploded_roads;
DROP TABLE projected_points;
DROP TABLE lines_from_centroids_to_roads;
-- convert multi lines into lines
CREATE TABLE exploded_roads (
the_geom geometry,
edge_id serial
);
-- insert the linestring that don't need to be converted
INSERT INTO exploded_roads
SELECT the_geom
FROM "StreetCenterLines"
WHERE st_geometrytype(the_geom) = 'ST_LineString';
INSERT INTO exploded_roads
SELECT the_geom
FROM (
SELECT ST_GeometryN(
the_geom,
generate_series(1, ST_NumGeometries(the_geom)))
AS the_geom
FROM "StreetCenterLines"
)
AS foo;
-- create projected points table with ids matching centroid table
CREATE TABLE projected_points (
the_geom geometry,
pid serial,
dauid int
);
-- Populate Table
INSERT INTO projected_points(the_geom, dauid)
SELECT DISTINCT ON ("DAUID")
(
ST_Line_Interpolate_Point(
exploded_roads.the_geom,
ST_Line_Locate_Point(
exploded_roads.the_geom,
centroids.the_geom
)
)
),
(centroids."DAUID"::int)
FROM exploded_roads, fred_city_o6_da_centroids centroids;
-- Create Line tables
CREATE TABLE lines_from_centroids_to_roads (
the_geom geometry,
edge_id SERIAL
);
-- Populate Line Table
INSERT INTO lines_from_centroids_to_roads(
SELECT
ST_MakeLine( centroids.the_geom, projected_points.the_geom )
FROM projected_points, fred_city_o6_da_centroids centroids
WHERE projected_points.dauid = centroids."DAUID"::int
);
-- Delete temp tables
--DROP TABLE exploded_roads;
--DROP TABLE projected_points;
Другие советы
Проблема была бы в том, что я думаю, что функция ожидает второй аргумент (distguess) должен иметь двойную точность вместо целого числа.Попробуйте 1000000.0 или попробуйте выполнить приведение к явному значению float...