25. الإسناد الخطي

الإسناد الخطي (ويُسمّى أحيانًا "التقطيع الديناميكي" أو dynamic segmentation) وسيلة لتمثيل المعالم التي يمكن وصفها بالإشارة إلى مجموعة أساسية من المعالم الخطية. ومن الأمثلة الشائعة على المعالم التي تُنمذج باستخدام الإسناد الخطي:

  • أصول الطرق السريعة، التي يُشار إلى مواقعها بالأميال على امتداد شبكة الطرق السريعة

  • عمليات صيانة الطرق، التي يُشار إليها على أنها تجري على امتداد شبكة الطرق بين قياسين بالأميال.

  • حصر الأحياء المائية، حيث يُسجَّل وجود الأسماك بين قياسين بالأميال باتجاه أعلى المجرى.

  • التوصيفات الهيدرولوجية لمقاطع الجداول المائية ("reaches")، المسجّلة بمسافة بداية ومسافة نهاية بالأميال.

تكمن فائدة نماذج الإسناد الخطي في أن الملاحظات المكانية التابعة لا تحتاج إلى تسجيلها بمعزل عن الملاحظات الأساسية، ويمكن تحديث طبقة الملاحظات الأساسية مع العلم بأن الملاحظات التابعة ستتبع الشكل الهندسي الجديد تلقائيًا.

ملاحظة

يقوم العرف الاصطلاحي لدى Esri في الإسناد الخطي على وجود جدول أساسي من المعالم المكانية الخطية، وجدول غير مكاني من "الأحداث" يتضمن مفتاحًا أجنبيًا يشير إلى المعلم المكاني وقياسًا على امتداد ذلك المعلم. وسنستخدم مصطلح "جدول الأحداث" للإشارة إلى الجداول غير المكانية التي ننشئها.

25.1. إنشاء الإسنادات الخطية

إذا كان لديك جدول نقاط موجود وتريد إسناده إلى شبكة خطية، فاستخدم الدالة ST_LineLocatePoint، التي تأخذ خطًا ونقطة، وتعيد النسبة على امتداد الخط التي توجد عندها النقطة.

-- Simple example of locating a point half-way along a line
SELECT ST_LineLocatePoint('LINESTRING(0 0, 2 2)', 'POINT(1 1)');
-- Answer 0.5

-- What if the point is not on the line? It projects to closest point
SELECT ST_LineLocatePoint('LINESTRING(0 0, 2 2)', 'POINT(0 2)');
-- Answer 0.5

يمكننا تحويل nyc_subway_stations إلى "جدول أحداث" نسبةً إلى الشوارع باستخدام ST_LineLocatePoint.

-- All the SQL below is in aid of creating the new event table
CREATE TABLE nyc_subway_station_events AS
-- We first need to get a candidate set of maybe-closest
-- streets, ordered by id and distance...
WITH ordered_nearest AS (
SELECT
  ST_GeometryN(streets.geom,1) AS streets_geom,
  streets.gid AS streets_gid,
  subways.geom AS subways_geom,
  subways.gid AS subways_gid,
  ST_Distance(streets.geom, subways.geom) AS distance
FROM nyc_streets streets
  JOIN nyc_subway_stations subways
  ON ST_DWithin(streets.geom, subways.geom, 200)
ORDER BY subways_gid, distance ASC
)
-- We use the 'distinct on' PostgreSQL feature to get the first
-- street (the nearest) for each unique street gid. We can then
-- pass that one street into ST_LineLocatePoint along with
-- its candidate subway station to calculate the measure.
SELECT
  DISTINCT ON (subways_gid)
  subways_gid,
  streets_gid,
  ST_LineLocatePoint(streets_geom, subways_geom) AS measure,
  distance
FROM ordered_nearest;

-- Primary keys are useful for visualization softwares
ALTER TABLE nyc_subway_station_events ADD PRIMARY KEY (subways_gid);

بعد أن يصبح لدينا جدول أحداث، من الممتع تحويله مجددًا إلى عرض (view) مكاني، كي نتمكن من تصوّر الأحداث نسبةً إلى النقاط الأصلية التي اشتُقّت منها.

للانتقال من قياس إلى نقطة، نستخدم الدالة ST_LineInterpolatePoint. إليك أمثلتنا البسيطة السابقة معكوسة:

-- Simple example of locating a point half-way along a line
SELECT ST_AsText(ST_LineInterpolatePoint('LINESTRING(0 0, 2 2)', 0.5));

-- Answer POINT(1 1)

ويمكننا ربط الجدول nyc_subway_station_events مجددًا بالجدول nyc_streets واستخدام السمة measure لتوليد نقاط الأحداث المكانية، دون الرجوع إلى الجدول الأصلي nyc_subway_stations.

-- New view that turns events back into spatial objects
CREATE OR REPLACE VIEW nyc_subway_stations_lrs AS
SELECT
  events.subways_gid,
  ST_LineInterpolatePoint(ST_GeometryN(streets.geom, 1), events.measure)AS geom,
  events.streets_gid
FROM nyc_subway_station_events events
JOIN nyc_streets streets
ON (streets.gid = events.streets_gid);

عند عرض النقاط الأصلية (النجمة الحمراء) ونقاط الأحداث (الدائرة الزرقاء) مع الشوارع، يمكنك أن ترى كيف تُلتقط الأحداث مباشرة إلى أقرب خطوط الشوارع.

_images/lrs1.jpg

ملاحظة

من الاستخدامات المفاجئة لدوال الإسناد الخطي استخدامٌ لا علاقة له بنماذج الإسناد الخطي. فكما هو موضّح أعلاه، يمكن استخدام هذه الدوال لالتقاط النقاط إلى المعالم الخطية. وفي حالات الاستخدام مثل مسارات GPS أو المدخلات الأخرى التي يُتوقّع أن تُسند إلى شبكة خطية، يُعدّ الالتقاط ميزة مفيدة.

25.2. قائمة الدوال

  • ST_LineInterpolatePoint(geometry A, double measure): تعيد نقطة مستكمَلة (interpolated) على امتداد خط.

  • ST_LineLocatePoint(geometry A, geometry B): تعيد عددًا عشريًا بين 0 و 1 يمثّل موقع أقرب نقطة على LineString إلى النقطة المعطاة.

  • ST_LineSubstring(geometry A, double from, double to): تعيد خطًا (linestring) يمثّل جزءًا من الخط المُدخل يبدأ وينتهي عند الكسور المعطاة من الطول الكلي ثنائي الأبعاد.

  • ST_LocateAlong(geometry A, double measure): تعيد قيمة مجموعة أشكال هندسية مشتقة تتضمن العناصر المطابقة للقياس المحدد.

  • ST_LocateBetween(geometry A, double from, double to): تعيد قيمة مجموعة أشكال هندسية مشتقة تتضمن العناصر المطابقة لنطاق القياسات المحدد شاملًا حدّيه.

  • ST_AddMeasure(geometry A, double from, double to): تحوّل linestring أو multilinestring إلى مسار ذي قياسات (قيم M). تخيّله طريقًا تريد أن تخصّص فيه أرقام المنازل تدريجيًا من البداية إلى النهاية. تخصّص هذه الدالة قيم "القياس" (مثل أرقام المنازل أو الكيلومترات أو أزمنة السفر) التي تزداد خطيًا على امتداد الخط. إذا كان الشكل الهندسي لا يحتوي على إحداثيات M، فإنها تُضاف. وإذا كان يحتوي على قيم M مسبقًا، فإنها تُستبدل. لا يُدعم إلا LINESTRING و MULTILINESTRING.

    مثال (أرقام المنازل): البداية (المنزل 10) --- نقاط وسيطة --- النهاية (المنزل 100) → تحصل كل نقطة على قيمة متناسبة.