J'ai créé un petit script naïf qui convertit les LineStrings d'entrée en CompoundCurves en fonction de certaines heuristiques.
Ce qu'il fait:
- Réduit les angles vifs pour créer des résultats visuellement plus attrayants que les données d'origine.
- Utilise plpgsql. Aucune extension supplémentaire requise.
- Accepte un "facteur de lissage" optionnel entre 0 et 100 en plus d'une géométrie.
Ce qu'il ne fait pas:
- Traite MultiLineStrings. Pour tout autre type de géométrie, il renvoie simplement l'entrée.
- Utilise les valeurs Z et M. Il les laisse simplement tomber. Utilisez-le uniquement à des fins cartographiques 2D.
- Crée des résultats mathématiquement corrects. Les résultats sont loin d'être corrects et peuvent même être visuellement inesthétiques dans certains cas (par exemple, les angles vifs). Je ne l'ai pas testé à fond. Examinez toujours les résultats!
- Court vite. Je suis sûr qu'il peut être réécrit sous une forme beaucoup plus optimale.
- Fait un vrai lissage. Il existe de bien meilleurs algorithmes (par exemple Chaiken ou ceux mentionnés dans la question) à utiliser pour un véritable lissage. Cette réponse cible les gens comme moi qui recherchent une approche PostGIS pure créant automatiquement une sorte de lignes courbes à partir de données réelles.
Le scénario:
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;
Comme il renvoie des courbes dans un type de géométrie, si vous souhaitez l'utiliser dans un SIG tel que QGIS, vous devez l'encapsuler dans des fonctions PostGIS en les convertissant. La syntaxe d'utilisation prévue est:
SELECT ST_AsText(ST_CurveToLine(CreateCurve(geom))) AS geom FROM linestringtable;
Il s'agit toujours d'un problème ouvert dans PostGIS (et dans d'autres outils SIG), comme indiqué dans le livre "PostGIS in Action" du chapitre 2.2.6 "Géométries courbes".
Voici quelques références aux algorithmes et au code:
la source
Vous pouvez essayer de convertir vos linestrings en courbes avec ST_LineToCurve , puis de nouveau en linestrings avec ST_CurveToLine .
Vous pouvez définir le nombre de segments par quart de cercle souhaité dans ST_CurveToLine.
la source