добре .. як це в одиницях карт, це має бути досить прямо, в межах обмежень. Ви вже знаєте висоту етикетки. Якби це було в балах, це було б залежно від масштабу.
Це передбачає фіксований розмір мітки, тому від того, наскільки добре це працює, залежить від того, наскільки однакові ваші мітки, і від того, чи використовуєте ви шрифт пропорційної чи фіксованої ширини (фіксовану ширину простіше - помножте довжину мітки на розмір мітки на отримати ширину мітки).
На жаль, це не дає відповіді на ваше запитання про те, як насправді знайти межі викладених .
у вас 4 випадки (СЗ, СЗ, ЮЗ, ЮЗ).
я припускаю, що ваша таблиця виглядає так (вибачте, деякі назви полів різні)
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;
Далі додайте 4 бали (усі однакові), але з мітками у чотирьох квадрантах, щоб представити чотири основні випадки використання
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')
Я використав CRS 27700 (0,0 внизу ліворуч, одиниці карти в м). Я припустив ширину етикетки 50, висоту 30 одиниць карт.
-- 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);
Аффінні трансформації
Ще одна можливість - скоротити всі провідні лінії, скажімо, на 80%.
- Ви можете використовувати ST_Translate (geom, -ST_X (geom), - ST_Y (geom)) для переміщення лінії до початку, щоб отримати geom_o
- використовуйте ST_Scale (geom_o, 0.8,0.8), щоб отримати geom_o_scaled
- потім повторно перекладіть за допомогою ST_Translate (geom_o_scaled, ST_X (geom), ST_Y (geom)) назад у вихідне положення.
Це може працювати і краще, хоча я цього не пробував.