如何在PostGIS中执行SIA或Bezier线平滑?


Answers:


6

我创建了一个小巧的天真脚本,该脚本基于一些启发式将输入LineStrings转换为CompoundCurves。

它能做什么:

  • 减少尖角以创建比原始数据更具视觉吸引力的结果。
  • 使用plpgsql。无需其他扩展名。
  • 除几何图形外,还接受介于0和100之间的可选“平滑因子”。

它不起作用:

  • 处理MultiLineStrings。对于任何其他几何类型,它仅返回输入。
  • 使用Z和M值。它只是将它们丢弃。仅将其用于2D制图目的。
  • 创建数学上正确的结果。结果远非正确,在某些情况下(例如尖角)甚至可能在视觉上不美观。我没有彻底测试。始终查看结果!
  • 运行快。我相信它可以重写为更好的形式。
  • 进行真正的平滑处理。有更好的算法(例如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之类的GIS中使用它,则必须将其包装到PostGIS函数中以对其进行转换。预期的使用语法为:

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

这是救命稻草!谢谢您的脚本。似乎Chaikin平滑功能将从postgis 2.5开始可用,我很期待。
she_weeds

1

如第2.2.6章“弯曲的几何图形”中的“ PostGIS in Action”一书中所述,这仍然是PostGIS(和其他GIS工具)中的未解决问题。

以下是有关算法和代码的一些参考:


我添加了postgis.17.x6 ...链接
Martin F

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.