bien ... como está en unidades de mapa, esto debería ser bastante sencillo, dentro de las limitaciones. Ya sabes la altura de la etiqueta. Si estuviera en puntos, dependería de la escala.
Esto supone un tamaño de etiqueta fijo, por lo que su funcionamiento depende de cuán uniformes sean sus etiquetas y de si usa o no una fuente proporcional o de ancho fijo (el ancho fijo es más fácil: multiplique la longitud de la etiqueta por el tamaño de la etiqueta para obtener el ancho de la etiqueta).
Lamentablemente, esto no responde a su pregunta sobre cómo encontrar realmente los límites de la etiqueta tal como se representa .
Tiene 4 casos (NE, NW, SE, SW).
Supongo que su tabla se ve así (disculpas, algunos nombres de campo son diferentes)
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;
Luego, agregue 4 puntos (todos idénticos) pero con etiquetas en los 4 cuadrantes para representar los 4 casos de uso principales
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')
Utilicé CRS 27700 (0,0 en la parte inferior izquierda, unidades de mapa en m). Asumí un ancho de etiqueta 50, altura 30 unidades de mapa.
-- 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);
Transformaciones afines
Otra posibilidad es acortar todas las líneas principales, por ejemplo, el 80%.
- Puede usar ST_Translate (geom, -ST_X (geom), - ST_Y (geom)) para mover la línea al origen para obtener geom_o
- use ST_Scale (geom_o, 0.8,0.8) para obtener geom_o_scaled
- luego vuelva a traducir usando ST_Translate (geom_o_scaled, ST_X (geom), ST_Y (geom)) de vuelta a la posición original.
Esto podría funcionar mejor, aunque no lo he probado.