Interesujące pytanie! Chciałem spróbować, więc spróbowałem.
Możesz to zrobić w PostGRES / POSTGIS za pomocą funkcji, która generuje zestaw wielokątów.
W moim przypadku mam tabelę z jedną funkcją (MULTILINESTRING), która reprezentuje linię kolejową. Musi używać CRS w metrach, używam osgb (27700). Zrobiłem 4 strony x 2 km „stron”.
Tutaj możesz zobaczyć wynik ... zielony jest siecią drogową, przyciętą do 1 km bufora wokół linii kolejowej, co ładnie odpowiada wysokości wielokątów.
Oto funkcja ...
CREATE OR REPLACE FUNCTION getAllPages(wid float, hite float, srid integer, overlap float) RETURNS SETOF geometry AS
$BODY$
DECLARE
page geometry; -- holds each page as it is generated
myline geometry; -- holds the line geometry
startpoint geometry;
endpoint geometry;
azimuth float; -- angle of rotation
curs float := 0.0 ; -- how far along line left edge is
step float;
stepnudge float;
currpoly geometry; -- used to make pages
currline geometry;
currangle float;
numpages float;
BEGIN
-- drop ST_LineMerge call if using LineString
-- replace this with your table.
SELECT ST_LineMerge(geom) INTO myline from traced_osgb;
numpages := ST_Length(myline)/wid;
step := 1.0/numpages;
stepnudge := (1.0-overlap) * step;
FOR r in 1..cast (numpages as integer)
LOOP
-- work out current line segment
startpoint := ST_SetSRID(ST_Line_Interpolate_Point(myline,curs),srid);
endpoint := ST_SetSRID(ST_Line_Interpolate_Point(myline,curs+step),srid);
currline := ST_SetSRID(ST_MakeLine(startpoint,endpoint),srid);
-- make a polygon of appropriate size at origin of CRS
currpoly := ST_SetSRID(ST_Extent(ST_MakeLine(ST_MakePoint(0.0,0.0),ST_MakePoint(wid,hite))),srid);
-- then nudge downwards so the midline matches the current line segment
currpoly := ST_Translate(currpoly,0.0,-hite/2.0);
-- Rotate to match angle
-- I have absolutely no idea how this bit works.
currangle := -ST_Azimuth(startpoint,endpoint) - (PI()/2.0) + PI();
currpoly := ST_Rotate(currpoly, currangle);
-- then move to start of current segment
currpoly := ST_Translate(currpoly,ST_X(startpoint),ST_Y(startpoint));
page := currpoly;
RETURN NEXT page as geom; -- yield next result
curs := curs + stepnudge;
END LOOP;
RETURN;
END
$BODY$
LANGUAGE 'plpgsql' ;
Korzystanie z tej funkcji
Oto przykład; Strony 4 km x 2 km, epsg: 27700 i 10% nakładania się
select st_asEwkt(getallpages) from getAllPages(4000.0, 2000.0, 27700, 0.1);
Po uruchomieniu możesz następnie wyeksportować z PgAdminIII do pliku csv. Możesz zaimportować to do QGIS, ale może być konieczne ręczne ustawienie CRS dla warstwy - QGIS nie używa SRID w EWKT, aby ustawić dla ciebie CRS warstwy: /
Dodanie atrybutu namiaru
Prawdopodobnie łatwiej to zrobić w postgis, można to zrobić za pomocą wyrażeń QGIS, ale trzeba będzie napisać trochę kodu. Coś takiego...
create table pages as (
select getallpages from getAllPages(4000.0, 2000.0, 27700, 0.1)
);
alter table pages add column bearing float;
update pages set bearing=ST_Azimuth(ST_PointN(getallpages,1),ST_PointN(getallpages,2));
Ostrzeżenia
Jest trochę zhakowany i miał okazję przetestować tylko jeden zestaw danych.
Nie jestem w 100% pewien, które dwa wierzchołki musisz wybrać w tej aktualizacji atrybutu namiaru query
. Może być konieczne eksperymentowanie.
Muszę wyznać, że nie mam pojęcia, dlaczego muszę wykonać tak skomplikowaną formułę, aby obrócić wielokąt w celu dopasowania do bieżącego segmentu linii. Myślałem, że mogę użyć danych wyjściowych z ST_Azimuth () w ST_Rotate (), ale najwyraźniej nie.