When we use standard ST_Transform (e.g. PostGIS implementation), from a SRID to another that curves straight lines, the original straight lines represented by two points, that must be transformed into curves, will be transformed into straight lines. This is the central problem.
Illustrating below a real-life example (from an equal-area projection to WGS84), a grid transformation, where the large cell, after transform, loses compatibility with the small cells.
I don't know if the problem already had an appropriate name, but everyone knows the curve made by the line of a clothesline supported between two points, and they know that tightening it, it will be a straight line.
The set of original straight lines are like a tight clothesline: if the ST_Transform is made with more points (e.g. by ST_Segmentize) it results in a correct transformation, analog to a loose clothesline.
[Theorem] When not good, that is, when ST_Transform results are bad:
the central distance d (illustrated) between "correct line" and "bad line" is proportional to the length of the original line.
So, seems that a "good segmentization procedure" must use two reasonable assumptions:
- the optimal split is into the middle (where d is maximum);
- the length of the segments must be a fraction of the "characteristic diameter" (cdiam) of the geometry that will be transformed.
[The question] How to do "good segmentization"? If the hypotheses are correct, we have three problems:
more segments is more cost: more CPU time and more "pollution" (more points and geometrical complexity), we need a balance between quality and complexity.
segmentize is not necessary in some directions: in general a direction (for example lines parallel to longitude) not need to be segmentized.
aleatory segmentization is not good: the "split into segments" process must to use (the optimal) middle point.
... A naive solution is to use a fraction of cdiam as parameter in ST_Segmentize.
A clue but not the optimal solution
This example was expressed in PostGIS, but is only an illustration, the ideia is to segmentize by "characteristic diameter".
CREATE FUNCTION ST_Transform_resilient(
g geometry,
srid integer,
density float DEFAULT 0.05
) RETURNS geometry AS $f$
SELECT CASE
WHEN isnot_point THEN -- using the fraction of cdiam here:
ST_Transform( ST_Segmentize(g,density*(a+p)/2.0) ,srid)
ELSE ST_Transform(g,srid)
END
FROM (
SELECT CASE WHEN is_poly THEN SQRT(ST_Area(g))
ELSE 0 END,
CASE WHEN is_poly THEN ST_Perimeter(g)/3.5
WHEN isnot_point THEN 2.0*ST_Length(g) END,
isnot_point
FROM ( SELECT GeometryType(g) ) t1(geomtype), LATERAL (
SELECT
CASE WHEN geomtype='POLYGON' OR geomtype='MULTIPOLYGON' THEN true ELSE false END AS is_poly,
CASE WHEN geomtype='POINT' OR geomtype='MULTIPOINT' THEN false ELSE true END AS isnot_point
) t2
) t3(a,p,isnot_point)
$f$ LANGUAGE SQL IMMUTABLE;
PS: a final correction is possible by minimal ST_Simplify, to remove collinear points. I need an optimal solution, one that generates good geometries with less complexity, and uses less CPU time to do so... And, ideally, understands the directions that really need ST_Segmentize.