Quiero extruir una forma poligonal en Postgis para crear un efecto pseudo 3D. Para ello he escrito una función rudimentaria para lograrlo. Se trata en gran medida de código de prueba y crea un nuevo vértice Y para cada punto del polígono y luego lo cierra volviendo al punto original:-.
CREATE OR REPLACE FUNCTION public.extrude_polygon(wkb_geometry_param geometry, height integer, simplify boolean DEFAULT false)
RETURNS geometry AS
$BODY$
DECLARE
f int;
ret_geom geometry;
wkb_geometry geometry;
BEGIN
--convert polygon to linestring
IF ST_GeometryType(wkb_geometry_param) != 'ST_Polygon' THEN
RETURN NULL;
END IF;
IF simplify THEN
wkb_geometry = ST_Simplify(ST_Transform(ST_Exteriorring(wkb_geometry_param), 27700), 0.5);
ELSE
wkb_geometry = ST_Transform(ST_Exteriorring(wkb_geometry_param), 27700);
END IF;
--initialise output geometry
ret_geom =ST_MakeLine(ST_PointN(wkb_geometry,1),ST_PointN(wkb_geometry,1));
--Move first point to up
SELECT ST_AddPoint(ret_geom,
ST_MakePoint(ST_X(ST_PointN(wkb_geometry, 1)),
ST_Y(ST_PointN(wkb_geometry, 1)) + height)
) into ret_geom;
FOR f IN 1..ST_NPoints(wkb_geometry) LOOP
IF f < ST_NPoints(wkb_geometry) THEN
--across to next high point
SELECT ST_AddPoint(ret_geom,
ST_MakePoint(ST_X(ST_PointN(wkb_geometry, f + 1)),
ST_Y(ST_PointN(wkb_geometry, f + 1)) + height)
) into ret_geom;
--down to next point
SELECT ST_AddPoint(ret_geom, ST_PointN(wkb_geometry,f + 1)) into ret_geom;
--back to last point
SELECT ST_AddPoint(ret_geom, ST_PointN(wkb_geometry,f)) into ret_geom;
--back then up again
SELECT ST_AddPoint(ret_geom, ST_PointN(wkb_geometry,f + 1)) into ret_geom;
SELECT ST_AddPoint(ret_geom,
ST_MakePoint(ST_X(ST_PointN(wkb_geometry, f + 1)),
ST_Y(ST_PointN(wkb_geometry, f + 1)) + height)
) into ret_geom;
ELSE
--across to first high point
SELECT ST_AddPoint(ret_geom,
ST_MakePoint(ST_X(ST_PointN(wkb_geometry, 1)),
ST_Y(ST_PointN(wkb_geometry, 1)) + height)
) into ret_geom;
SELECT ST_AddPoint(ret_geom, ST_PointN(wkb_geometry,1)) into ret_geom;
END IF;
END LOOP;
RETURN ST_Buffer(ST_Buffer(ST_MakePolygon(ret_geom),10), -10);
END;
$BODY$
LANGUAGE plpgsql
Funciona con polígonos simples pero tiene problemas con anillos interiores, pero el problema principal es que es realmente lento. Necesito obtener la forma resultante como un polígono que pueda ser sombreado y renderizado en mapserver. De ahí las operaciones de búfer al final, que es la única manera que conozco de reducir la forma a su contorno.
El resultado final será una forma extruida que representa el polígono original. A continuación, puedo desplazar el polígono original por la misma distancia de extrusión y colocarlo en la parte superior para hacer el techo.
He considerado usar la función ST_Extrude en postgis-2.1.1 PERO esto crea un tipo ST_PolyhedralSurface y no soy capaz de renderizarlo en mapserver. Por lo que puedo ver no hay manera de crear un contorno de esto tampoco como ST_Buffer no funciona con ST_polyhedralsurfaces.
Entonces, mi pregunta es, ¿se puede mejorar mi función? O hay un enfoque mejor. La salida tiene que ser como en el diagrama que he creado mediante la colocación del polígono de desplazamiento en mi forma extruida.