Як виконати згладжування лінії SIA або Bezier в PostGIS?


Відповіді:


6

Я створив невеликий, наївний сценарій, який перетворює вхідні LineStrings в CompoundCurves на основі певної евристики.

Що це робить:

  • Вирізає гострі кути, щоб створити більш візуально привабливіші результати, ніж вихідні дані.
  • Використовує plpgsql. Ніяких додаткових розширень не потрібно.
  • Приймає необов'язковий "коефіцієнт згладжування" від 0 до 100, крім геометрії.

Що не робить:

  • Процеси MultiLineStrings. Для будь-якого іншого типу геометрії він просто повертає вхід.
  • Використовує значення Z і M. Це просто їх скидає. Використовуйте це лише для двовимірних картографічних цілей.
  • Створює математично правильні результати. Результати далекі від правильних, а в деяких випадках можуть бути навіть неестетичними (наприклад, гострі кути). Я не перевіряв це ретельно. Завжди переглядайте результати!
  • Біжить швидко. Я впевнений, що це можна переписати на куди більш оптимальну форму.
  • Чи справжнє згладжування. Існують набагато кращі алгоритми (наприклад, Chaiken або ті, які згадуються у питанні), які використовуються для реального згладжування. Ця відповідь націлена на таких людей, як я, шукаючи чистий підхід до PostGIS, автоматично створюючи якісь вигнуті лінії з реальних даних.

Сценарій:

CREATE OR REPLACE FUNCTION CreateCurve(geom geometry, percent int DEFAULT 40)
    RETURNS geometry AS
$$
DECLARE
    result text;
    p0 geometry;
    p1 geometry;
    p2 geometry;
    intp geometry;
    tempp geometry;
    geomtype text := ST_GeometryType(geom);
    factor double precision := percent::double precision / 200;
    i integer;
BEGIN
    IF percent < 0 OR percent > 100 THEN
        RAISE EXCEPTION 'Smoothing factor must be between 0 and 100';
    END IF;
    IF geomtype != 'ST_LineString' OR factor = 0 THEN
        RETURN geom;
    END IF;
    result := 'COMPOUNDCURVE((';
    p0 := ST_PointN(geom, 1);
    IF ST_NPoints(geom) = 2 THEN
        p1:= ST_PointN(geom, 2);
        result := result || ST_X(p0) || ' ' || ST_Y(p0) || ',' || ST_X(p1) || ' ' || ST_Y(p1) || '))';
    ELSE
        FOR i IN 2..(ST_NPoints(geom) - 1) LOOP
            p1 := ST_PointN(geom, i);
            p2 := ST_PointN(geom, i + 1);
            result := result || ST_X(p0) || ' ' || ST_Y(p0) || ',';
            tempp := ST_Line_Interpolate_Point(ST_MakeLine(p1, p0), factor);
            p0 := ST_Line_Interpolate_Point(ST_MakeLine(p1, p2), factor);
            intp := ST_Line_Interpolate_Point(
                ST_MakeLine(
                    ST_Line_Interpolate_Point(ST_MakeLine(p0, p1), 0.5),
                    ST_Line_Interpolate_Point(ST_MakeLine(tempp, p1), 0.5)
                ), 0.5);
            result := result || ST_X(tempp) || ' ' || ST_Y(tempp) || '),CIRCULARSTRING(' || ST_X(tempp) || ' ' || ST_Y(tempp) || ',' || ST_X(intp) || ' ' ||
            ST_Y(intp) || ',' || ST_X(p0) || ' ' || ST_Y(p0) || '),(';
        END LOOP;
        result := result || ST_X(p0) || ' ' || ST_Y(p0) || ',' || ST_X(p2) || ' ' || ST_Y(p2) || '))';
    END IF;
    RETURN ST_SetSRID(result::geometry, ST_SRID(geom));
END;
$$
LANGUAGE 'plpgsql' IMMUTABLE;

Оскільки він повертає криві типу геометрії, якщо ви хочете використовувати його в ГІС, наприклад, QGIS, вам доведеться обернути їх у функції PostGIS, перетворюючи їх навколо. Синтаксис використання за призначенням:

SELECT ST_AsText(ST_CurveToLine(CreateCurve(geom))) AS geom FROM linestringtable;

Це був рятівник! Дякую за сценарій Здається, що згладжування Chaikin стане доступним як функція від postgis 2.5 і далі, що я з нетерпінням чекаю.
she_weeds

1

Це питання досі залишається відкритим у PostGIS (та інших інструментах ГІС), про що йдеться у книзі "PostGIS у дії" в розділі 2.2.6 "Вигнуті геометрії".

Ось кілька посилань на алгоритми та код:


Я додав посилання.17.x6 ... посилання
Мартін

0

Ви можете спробувати перетворити рядки рядків у криві за допомогою ST_LineToCurve, а потім повернутися до рядків рядків за допомогою ST_CurveToLine .

У ST_CurveToLine ви можете встановити кількість сегментів на квартальне коло, яке потрібно.


LineToCurve побудований для передачі виходів CurveToLine, а не для отримання кривих з довільного введення.
Пол Рамзі

@PaulRamsey буде більш приємним згладжуванням буде додано в наступних версіях Postgis? Я думав про що - то , як це, наприклад: webhelp.esri.com/arcgisdesktop/9.2 / ...
Джері
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.