Chcę wyciągnąć kształt wielokąta w postgisie, aby stworzyć efekt pseudo 3D. W tym celu napisałem prostą funkcję, aby to osiągnąć. Jest to bardzo testowy kod, który tworzy nowy wierzchołek Y dla każdego punktu na wielokącie, a następnie zamyka go, wracając do pierwotnego punktu: -
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
Działa z prostymi wielokątami, ale ma problemy z pierścieniami wewnętrznymi, ale głównym problemem jest to, że jest naprawdę wolny. Muszę wygenerować wynikowy kształt jako wielokąt, który można zacienić i renderować w serwerze map. Stąd operacje buforowania na końcu, co jest jedynym znanym mi sposobem zmniejszenia kształtu do jego obrysu.
Efektem końcowym będzie wytłoczony kształt reprezentujący oryginalny wielokąt. Następnie mogę przesunąć oryginalny wielokąt o tę samą odległość wyciągnięcia i umieścić go na górze, aby wykonać dach.
Rozważałem użycie funkcji ST_Extrude w postgis-2.1.1 ALE to tworzy typ ST_PolyhedralSurface i nie jestem w stanie wyrenderować jej w serwerze map. O ile mogę stwierdzić, nie ma możliwości stworzenia tego konturu, ponieważ ST_Buffer nie działa z ST_polyhedralsurfaces.
Moje pytanie brzmi: czy można poprawić moją funkcję? Czy jest lepsze podejście? Dane wyjściowe muszą wyglądać jak na schemacie, który utworzyłem, umieszczając przesunięty wielokąt na moim wyciągniętym kształcie.