কীভাবে ডায়নামিক লিডার লাইন তৈরি করবেন?


10

আমি কিউজিআইএস "সরান লেবেল" সরঞ্জাম ছাড়াও একটি পোস্টজিআইএস ভিউ ব্যবহার করে গতিশীল লিডার লাইন তৈরি করার চেষ্টা করছি।

CREATE VIEW leader_line AS
SELECT
gid,
ST_MakeLine(geom, ST_SetSRID(ST_MakePoint(xcord_label, ycord_label), SRID))::geometry(linestring, SRID) AS geom
FROM point
WHERE xcord_label IS NOT NULL;

এটি সমস্ত লেবেলের জন্য সূক্ষ্মভাবে কাজ WHERE ST_X(geom) < xcord_labelকরে তবে লেবেলগুলির জন্য ভুল দেখাচ্ছে এমন লিডার লাইন তৈরি করে WHERE ST_X(geom) > xcord_label

এখানে চিত্র বর্ণনা লিখুন এখানে চিত্র বর্ণনা লিখুন

লেবেলগুলির জন্য সঠিকভাবে স্থাপন করা লিডার লাইনগুলি কীভাবে পাওয়া যায় কেউ জানেন WHERE ST_X(geom) > xcord_label? লেবেলের xmax স্থানাঙ্ককে বোঝার কোনও উপায় আছে কি?

এখানে চিত্র বর্ণনা লিখুন


1
আপনার লেবেলগুলি পয়েন্ট বা মানচিত্রের ইউনিটগুলিতে রয়েছে? যদি এটি মানচিত্রের একক হয় তবে উচ্চতা অনুমান করা মোটামুটি সহজ হওয়া উচিত এবং এর মাধ্যমে ক্ষতিপূরণ দেওয়ার জন্য আপনার নেতার লাইনটি সংক্ষিপ্ত করা উচিত)
স্টিভেন কে

লেবেল আকার মানচিত্র ইউনিট হয়।
চন্দ্র সমুদ্র

উত্তর:


9

আপনি আরও ভাল লেবেল রাখার জন্য লাইনের আজিমুথ থেকে নির্ধারিত কিউজিআইএসের কোয়াড্রেন্ট প্লেসমেন্ট সুনির্দিষ্ট ব্যবহার করতে পারেন । কোয়াড্র্যান্ট একটি বিন্দুতে 8 টি অবস্থান নির্দিষ্ট করে:

[ 0=Above Left | 1=Above | 2=Above Right |
  3=Left       | 4=Over  | 5=Right       |
  6=Below Left | 7=Below | 8=Below Right ]

এখানে নাল দ্বীপের চারপাশের একটি উদাহরণ রয়েছে , একটি সারণী এবং দুটি মতামত তৈরি করা হয়েছে।

CREATE TABLE points (
  gid serial PRIMARY KEY,
  geom geometry(Point, 4326),
  label_geom geometry(Point, 4326),
  label text
);

INSERT INTO points(geom, label_geom, label)
SELECT origin, pt, round(degrees(ST_Azimuth(origin, pt))) || ' degrees'
FROM (
  SELECT
    ST_SetSRID(ST_MakePoint(0, 0), 4326) AS origin,
    ST_SetSRID(ST_MakePoint(cos(radians(x)), sin(radians(x))), 4326) AS pt
  FROM generate_series(0, 350, 15) AS x
) AS f;

CREATE OR REPLACE VIEW point_labels AS
  SELECT gid, label_geom AS geom,
  CASE
    WHEN ST_Azimuth(geom, label_geom) ISNULL THEN 2 -- default if azimuth cannot be determined
    WHEN degrees(ST_Azimuth(geom, label_geom)) < 22.5 THEN 1 -- Above
    WHEN degrees(ST_Azimuth(geom, label_geom)) < 67.5 THEN 2 -- Above Right
    WHEN degrees(ST_Azimuth(geom, label_geom)) < 112.5 THEN 5 -- Right
    WHEN degrees(ST_Azimuth(geom, label_geom)) < 157.5 THEN 8 -- Below Right
    WHEN degrees(ST_Azimuth(geom, label_geom)) < 202.5 THEN 7 -- Below
    WHEN degrees(ST_Azimuth(geom, label_geom)) < 247.5 THEN 6 -- Below Left
    WHEN degrees(ST_Azimuth(geom, label_geom)) < 292.5 THEN 3 -- Left
    WHEN degrees(ST_Azimuth(geom, label_geom)) < 337.5 THEN 0 -- Above Left
    ELSE 1 -- >= 337.5 Above
  END AS quadrant, label
  FROM points;

CREATE OR REPLACE VIEW leader_line AS
  SELECT gid, ST_MakeLine(geom, label_geom)::geometry(LineString, 4326) AS geom, label
  FROM points;

তারপরে কিউজিআইএস-এ যোগ করুন:

  • points - geom
  • leader_line- geom- প্রাথমিক কী হওয়া দরকারgid
  • point_labels- geom- প্রাথমিক কী হওয়া দরকারgid

QGIS

এখন এর জন্য স্তর বৈশিষ্ট্যগুলি কনফিগার করুন point_labels:

  • স্টাইল পরিবর্তন করুন যাতে বিন্দুটি টানা না যায়, যেমন, আকার পরিবর্তন করুন 0.0 এ
  • এই স্তরটি দিয়ে লেবেল করুন labelএবং বৈশিষ্ট্য ক্ষেত্রটি ব্যবহার করতে "চতুষ্কোণ" পরিবর্তন করে "পয়েন্ট থেকে অফসেট" এ স্থান পরিবর্তন করুনquadrant

পাদ

বিঙ্গো!

লোটোখেলা

দ্রষ্টব্য যে geographyপ্রকারগুলির জন্য কিছুটা ভিন্ন পদ্ধতির প্রয়োজন , যেহেতু ST_Azimuth ভিন্নভাবে আচরণ করে।


আপডেট:points স্তরে নতুন পয়েন্ট যুক্ত করার সময় geomক্ষেত্রটি যথারীতি আপডেট হয় তবে তা label_geomহয় না। label_geomনতুন পয়েন্টগুলির সাথে একটি ডিফল্ট মানকে জনিত করতে , একটি ট্রিগার তৈরি করা দরকার । তবে যদি একটি ট্রিগার ফাংশন ব্যবহৃত হয় তবে quadrantনির্দিষ্টকরণকারীটি pointsটেবিলের মধ্যে সংরক্ষণ করা যেতে পারে এবং point_labelsভিউ উপেক্ষা করা যায়:

উদাহরণস্বরূপ, আসুন একটি টেবিল এবং একটি দর্শন দিয়ে কিছুটা আলাদা উদাহরণ দিয়ে আবার শুরু করুন:

-- DROP TABLE points CASCADE;
CREATE TABLE points (
  gid serial PRIMARY KEY,
  geom geometry(Point, 4326),
  label_geom geometry(Point, 4326),
  quadrant integer,
  label text
);

CREATE FUNCTION label_geom_tg_fn() RETURNS trigger AS
$BODY$
DECLARE
  azimuth float8;
BEGIN
  -- Set a default label_geom
  IF NEW.label_geom ISNULL THEN
    NEW.label_geom := NEW.geom;
  END IF;
  -- Determine quadrant
  azimuth := degrees(ST_Azimuth(NEW.geom, NEW.label_geom));
  NEW.quadrant := CASE
    WHEN azimuth ISNULL THEN 2 -- azimuth cannot be determined, so put Above Right
    WHEN azimuth < 22.5 THEN 1 -- Above
    WHEN azimuth < 67.5 THEN 2 -- Above Right
    WHEN azimuth < 112.5 THEN 5 -- Right
    WHEN azimuth < 157.5 THEN 8 -- Below Right
    WHEN azimuth < 202.5 THEN 7 -- Below
    WHEN azimuth < 247.5 THEN 6 -- Below Left
    WHEN azimuth < 292.5 THEN 3 -- Left
    WHEN azimuth < 337.5 THEN 0 -- Above Left
    ELSE 1 END;-- >= 337.5 Above
  RETURN NEW;
END;$BODY$ LANGUAGE plpgsql;

CREATE TRIGGER label_geom_tg BEFORE INSERT OR UPDATE
   ON points FOR EACH ROW
   EXECUTE PROCEDURE label_geom_tg_fn();

প্রথম উদাহরণ থেকে, INSERT INTO pointsএবং CREATE OR REPLACE VIEW leader_lineবিবৃতিগুলি আবার করুন, কারণ এগুলিতে কোনও সংশোধন প্রয়োজন হয় না। তবে leader_lineভিউ উপেক্ষা করুন ।

তারপরে কিউজিআইএস-এ যোগ করুন:

  • points - geom
  • points - label_geom
  • leader_line- geom- প্রাথমিক কী হওয়া দরকারgid

এখন জন্য স্তরের বৈশিষ্ট্য কনফিগার pointsসঙ্গে label_geomপ্রথম উদাহরণস্বরূপ করেনি point_labelsquadrantসুনির্দিষ্টভাবে উল্লেখ করা নতুন এবং সরানো পয়েন্ট জন্য স্বয়ংক্রিয়ভাবে পরিবর্তন করা হবে, কিন্তু আপনি শুধুমাত্র এই প্রতিটি সময় আপনি আপনার সম্পাদনাগুলি সংরক্ষণ পরিবর্তন লক্ষ্য করবেন।


দুর্দান্ত কাজ, তবে কিউজিআইএস-এ একটি নতুন পয়েন্ট বৈশিষ্ট্য কীভাবে একটি পোস্টজিআইএস সারণীতে দুটি জ্যামিতি কলাম রয়েছে?
চন্দ্র সমুদ্র

@ লুনার সি - আকর্ষণীয়, আপনি কি টেবিলের জন্য দুটি ভুক্তি পান, প্রতি জ্যামিতিতে একটি, কিন্তু কিগিস আপনাকে কম্বো থেকে জ্যামিতির ক্ষেত্র সেট করতে দেয় না? আপনি কি আমদানি ডায়ালগ বক্সে একটি ম্যানুয়াল স্কয়ার কোয়েরি ব্যবহার করার চেষ্টা করেছেন (এটি সবচেয়ে ডান কলাম, এবং প্রায়শই দৃষ্টির বাইরে লুকানো থাকে ...)?
স্টিভেন কে

আমি QGIS ( gid | label_geom | labelএবং gid, geom, label) এর দুটি 'পয়েন্ট' স্তর রেখেছি ।
চন্দ্র সমুদ্র

@ লুনারসিএ আমি একটি দ্বিতীয় উদাহরণ পুনর্নির্মাণ করেছি যার একটি টেবিল এবং একটি ভিউ রয়েছে। এর জন্য একটি ডিফল্ট মান নির্ধারণ করতে সারণীতে ট্রিগার ফাংশন রয়েছে label_geomএবং quadrantমানটিও খুব বেশি আপডেট করে , সুতরাং point_labelস্তর / দর্শনটির আর প্রয়োজন হয় না।
মাইক টি

মাইকের চমৎকার কাজ! একটি সরানোর পরে label_geomআমি স্তর সম্পাদনাটি সংরক্ষণ করতে এবং লেবেলের আসল অবস্থানটি দেখতে ক্যানভাসকে রিফ্রেশ করব। এটি অত্যন্ত দুঃখের বিষয় যে QGIS "মুভ লেবেল" সরঞ্জামটির সাহায্যে কোয়াড্রেন্ট স্পেসিফায়ার ব্যবহারের কোনও উপায় নেই।
চন্দ্র সমুদ্র

1

ঠিক আছে .. যেহেতু এটি মানচিত্রের ইউনিটে রয়েছে এটি সীমাবদ্ধতার মধ্যে মোটামুটি সোজা-এগিয়ে হওয়া উচিত। আপনি ইতিমধ্যে লেবেলের উচ্চতা জানেন। এটি যদি পয়েন্টগুলিতে থাকে তবে এটি স্কেল-নির্ভর।

এটি একটি স্থির লেবেলের আকার অনুমান করে, সুতরাং আপনার লেবেলগুলি কতটা সমান, এবং আপনি একটি সমানুপাতিক বা স্থির-প্রস্থের ফন্ট ব্যবহার করবেন কিনা তা নির্ভর করে (এটি নির্দিষ্ট প্রস্থটি সহজ - লেবেলের দৈর্ঘ্যের সাথে লেবেলের দৈর্ঘ্যকে গুণান) লেবেলের প্রস্থ পান)।

দুঃখের বিষয় কীভাবে লেবেলের সীমানা রেন্ডার করা যায় তা কীভাবে পাওয়া যায় সে সম্পর্কে এটি আপনার প্রশ্নের উত্তর দেয় না ।

আপনার 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 পয়েন্ট যুক্ত করুন (সমস্ত অভিন্ন) তবে 4 টি প্রধান ব্যবহারের ক্ষেত্রে প্রতিনিধিত্ব করতে 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')

আমি সিআরএস 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);

Affine রূপান্তর

আর একটি সম্ভাবনা হ'ল 80% বলতে গেলে সমস্ত নেতৃস্থানীয় লাইন সংক্ষিপ্ত করা।

  • আপনি জিম_ও পেতে লাইনটি উত্সের দিকে সরানোর জন্য ST_Translate (geom, -ST_X (geom), - ST_Y (geom)) ব্যবহার করতে পারেন
  • জিওম_ও_সেস্কেল করতে এসT_স্কেল (জিওম_ও, 0.8,0.8) ব্যবহার করুন
  • তারপরে ST_Translate (geom_o_scaled, ST_X (geom), ST_Y (geom)) ব্যবহার করে মূল অবস্থানে ফিরে যান।

এটি আরও ভাল কাজ করতে পারে, যদিও আমি এটি চেষ্টা করেছিলাম না।


আপনার প্রশ্রয় দেওয়ার জন্য আপনাকে ধন্যবাদ, দুর্ভাগ্যক্রমে লিডার লাইনগুলি খুব ভাল লেবেলের সাথে মেলে না।
চন্দ্র সমুদ্র
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.