ok .. car il est en unités de carte, cela devrait être assez simple, dans les limites. Vous connaissez déjà la hauteur de l'étiquette. Si c'était en points, cela dépendrait de l'échelle.
Cela suppose une taille d'étiquette fixe, donc la façon dont cela fonctionne dépend de l'uniformité de vos étiquettes et de l'utilisation ou non d'une police proportionnelle ou à largeur fixe (la largeur fixe est plus facile - multipliez la longueur de l'étiquette par la taille de l'étiquette à obtenir la largeur de l'étiquette).
Malheureusement, cela ne répond pas à votre question sur la façon de trouver réellement les limites de l'étiquette telles qu'elles sont rendues .
vous avez 4 cas (NE, NW, SE, SW).
je suppose que votre table ressemble à ceci (excuses, certains noms de champs sont différents)
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;
Ensuite, ajoutez 4 points (tous identiques) mais avec des étiquettes dans les 4 quadrants pour représenter les 4 principaux cas d'utilisation
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')
J'ai utilisé CRS 27700 (0,0 en bas à gauche, unités de carte en m) J'ai supposé une largeur d'étiquette de 50, une hauteur de 30 unités de carte.
-- 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);
Transformations affines
Une autre possibilité est de raccourcir toutes les lignes de tête, soit 80%.
- Vous pouvez utiliser ST_Translate (geom, -ST_X (geom), - ST_Y (geom)) pour déplacer la ligne vers l'origine pour obtenir geom_o
- utilisez ST_Scale (geom_o, 0.8,0.8) pour obtenir geom_o_scaled
- puis retraduisez en utilisant ST_Translate (geom_o_scaled, ST_X (geom), ST_Y (geom)) à la position d'origine.
Cela pourrait mieux fonctionner, même si je ne l'ai pas essayé.