ok .. ponieważ jest to w jednostkach mapy, powinno to być dość proste, w granicach ograniczeń. Znasz już wysokość etykiety. Gdyby był w punktach, byłby zależny od skali.
Zakłada się stały rozmiar etykiety, więc to, jak to działa, zależy od tego, jak jednolite są twoje etykiety, oraz od tego, czy używasz czcionki proporcjonalnej lub stałej szerokości (stała szerokość jest łatwiejsza - pomnóż długość etykiety przez rozmiar etykiety do pobierz szerokość etykiety).
Niestety nie odpowiada to na pytanie, jak znaleźć granice etykiety jako renderowane .
masz 4 przypadki (NE, NW, SE, SW).
zakładam, że twoja tabela wygląda tak (przepraszam, niektóre nazwy pól są różne)
CREATE TABLE points
(
uniq int PRIMARY KEY,
geom geometry(Point,27700),
label_x int,
label_y int,
labeltext character varying(100)
);
ALTER TABLE points
OWNER TO user;
GRANT ALL ON TABLE points TO user;
GRANT SELECT ON TABLE points TO public;
Następnie dodaj 4 punkty (wszystkie identyczne), ale z etykietami w 4 ćwiartkach, aby przedstawić 4 główne przypadki użycia
insert into points values
(1,ST_SetSRID(ST_Point(1000,1000),27700),750,750,'123');
insert into points values(2,ST_SetSRID(ST_Point(1000,1000),27700),1250,1250,'456')
insert into points values
(3,ST_SetSRID(ST_Point(1000,1000),27700),750,1250,'456')
insert into points values
(4,ST_SetSRID(ST_Point(1000,1000),27700),1250,750,'789')
Użyłem CRS 27700 (0,0 w lewym dolnym rogu, jednostki mapy w metrach). Przyjąłem szerokość etykiety 50, wysokość 30 jednostek mapy.
-- SW use case
CREATE OR REPLACE VIEW leader_line_sw AS
SELECT
uniq,
ST_MakeLine(geom, ST_SetSRID(ST_MakePoint(label_x+50, label_y+30), 27700))::geometry(linestring, 27700) AS geom
FROM points
WHERE label_x IS NOT NULL AND
label_y<=ST_Y(geom) and label_x<=ST_X(geom);
-- SE use case
CREATE OR REPLACE VIEW leader_line_se AS
SELECT
uniq,
ST_MakeLine(geom, ST_SetSRID(ST_MakePoint(label_x, label_y-30), 27700))::geometry(linestring, 27700) AS geom
FROM points
WHERE label_x IS NOT NULL AND
label_y<=ST_Y(geom) and label_x>ST_X(geom);
-- NE use case
CREATE OR REPLACE VIEW leader_line_ne AS
SELECT
uniq,
ST_MakeLine(geom, ST_SetSRID(ST_MakePoint(label_x, label_y), 27700))::geometry(linestring, 27700) AS geom
FROM points
WHERE label_x IS NOT NULL AND
label_y>ST_Y(geom) and label_x>ST_X(geom);
-- NW use case
CREATE OR REPLACE VIEW leader_line_nw2 AS
SELECT
uniq,
ST_MakeLine(geom, ST_SetSRID(ST_MakePoint(label_x+50, label_y), 27700))::geometry(linestring, 27700) AS geom
FROM points
WHERE label_x IS NOT NULL AND
label_y>ST_Y(geom) and label_x<=ST_X(geom);
Transformacje afiniczne
Inną możliwością jest skrócenie wszystkich wiodących linii, na przykład 80%.
- Możesz użyć ST_Translate (geom, -ST_X (geom), - ST_Y (geom)), aby przesunąć linię do początku, aby uzyskać geom_o
- użyj ST_Scale (geom_o, 0.8,0.8), aby uzyskać geom_o_scaled
- następnie ponownie przetłumacz za pomocą ST_Translate (geom_o_scaled, ST_X (geom), ST_Y (geom)) z powrotem do pierwotnej pozycji.
To może działać lepiej, chociaż tego nie próbowałem.