ok .. como está nas unidades do mapa, isso deve ser bastante direto, dentro de limitações. Você já sabe a altura do rótulo. Se estivesse em pontos, seria dependente da escala.
Isso pressupõe um tamanho fixo de etiqueta, portanto, o quão bem isso funciona depende de quão uniformes são suas etiquetas e se você usa ou não uma fonte proporcional ou de largura fixa (largura fixa é mais fácil - multiplique o comprimento da etiqueta pelo tamanho da etiqueta para obtenha a largura da etiqueta).
Infelizmente, isso não responde à sua pergunta sobre como encontrar os limites do rótulo como renderizados .
você tem 4 casos (NE, NW, SE, SW).
Presumo que sua tabela se parece com isso (desculpas, alguns nomes de campo são 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;
Em seguida, adicione 4 pontos (todos idênticos), mas com rótulos nos 4 quadrantes para representar os 4 principais casos de uso
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')
Usei o CRS 27700 (0,0 em unidades do mapa inferior esquerdo, em m). Assumi uma largura 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);
Transformações Afins
Outra possibilidade é reduzir todas as linhas principais, ou seja, 80%.
- Você pode usar ST_Translate (geom, -ST_X (geom), - ST_Y (geom)) para mover a linha para a origem e obter geom_o
- use ST_Scale (geom_o, 0.8,0.8) para obter geom_o_scaled
- retranslate usando ST_Translate (geom_o_scaled, ST_X (geom), ST_Y (geom)) de volta à posição original.
Isso pode funcionar melhor, embora eu não tenha tentado.