okay.. as it's in map units this should be fairly straight-forward, within limitations. You already know the height of the label. If it was in points it would be scale-dependant.
This assumes a fixed label size, so how well this works depends on how uniform your labels are, and whether or not you use a proportional or fixed-width font (fixed width is easier - multiply the length of the label by the label size to get the label width).
Sadly this doesn't answer your question on how to actually find the bounds of the label as rendered.
you have 4 cases (NE,NW,SE,SW).
i assume your table looks like this (apologies, some field names are different)
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;
Next, add 4 points (all identical) but with labels in the 4 quadrants to represent the 4 main use cases
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')
I used CRS 27700 (0,0 in lower-left, map units in m)
I've assumed a label width 50, height 30 map units.
-- 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);
Affine Transformations
Another possibility is to shorten all leading lines, to say 80%.
- You could use ST_Translate(geom,-ST_X(geom),-ST_Y(geom)) to move the line to the origin to get geom_o
- use ST_Scale(geom_o,0.8,0.8) to get geom_o_scaled
- then retranslate using ST_Translate(geom_o_scaled,ST_X(geom),ST_Y(geom)) back to the original position.
This might work better, although I haven't tried it.