11. العلاقات المكانية

استخدمنا حتى الآن فقط الدوال المكانية التي تقيس الأشكال الهندسية (ST_Area، ST_Length)، أو تسلسلها (ST_GeomFromText)، أو تلغي تسلسلها (ST_AsGML). وما يجمع هذه الدوال هو أنها تعمل على شكل هندسي واحد فقط في كل مرة.

تكمن قوة قواعد البيانات المكانية في أنها لا تخزّن الأشكال الهندسية فحسب، بل تملك أيضًا القدرة على مقارنة العلاقات بين الأشكال الهندسية.

أسئلة مثل "ما أقرب حوامل الدراجات إلى حديقة ما؟" أو "أين تتقاطع خطوط المترو مع الشوارع؟" لا يمكن الإجابة عنها إلا بمقارنة الأشكال الهندسية التي تمثل حوامل الدراجات والشوارع وخطوط المترو.

يعرّف معيار OGC مجموعة الدوال التالية لمقارنة الأشكال الهندسية.

11.1. ST_Equals

تختبر ST_Equals(geometry A, geometry B) التساوي المكاني لشكلين هندسيين.

_images/st_equals.png

تعيد ST_Equals القيمة TRUE إذا كان لشكلين هندسيين من النوع نفسه قيم إحداثيات x,y متطابقة، أي إذا كان الشكل الثاني مساويًا (مطابقًا) للشكل الأول.

أولًا، لنسترجع تمثيلًا لنقطة من جدولنا nyc_subway_stations. سنأخذ فقط المُدخل الخاص بـ 'Broad St'.

SELECT name, geom
FROM nyc_subway_stations
WHERE name = 'Broad St';
   name   |                      geom
----------+---------------------------------------------------
 Broad St | 0101000020266900000EEBD4CF27CF2141BC17D69516315141

ثم أدخِل تمثيل الشكل الهندسي مرة أخرى في اختبار ST_Equals:

SELECT name
FROM nyc_subway_stations
WHERE ST_Equals(
  geom,
  '0101000020266900000EEBD4CF27CF2141BC17D69516315141');
Broad St

ملاحظة

لم يكن تمثيل النقطة مقروءًا بسهولة للبشر (0101000020266900000EEBD4CF27CF2141BC17D69516315141)، لكنه كان تمثيلًا دقيقًا لقيم الإحداثيات. وفي اختبار مثل التساوي، يلزم استخدام الإحداثيات الدقيقة.

11.2. ST_Intersects و ST_Disjoint و ST_Crosses و ST_Overlaps

تختبر ST_Intersects و ST_Crosses و ST_Overlaps ما إذا كانت المناطق الداخلية للأشكال الهندسية متقاطعة.

_images/st_intersects.png

تعيد ST_Intersects(geometry A, geometry B) القيمة t (TRUE) إذا كان للشكلين أي حيّز مشترك، أي إذا تقاطعت حدودهما أو مناطقهما الداخلية.

_images/st_disjoint.png

عكس ST_Intersects هو ST_Disjoint(geometry A , geometry B). فإذا كان شكلان هندسيان منفصلين فإنهما لا يتقاطعان، والعكس صحيح. وفي الواقع، غالبًا ما يكون اختبار "عدم التقاطع" أكفأ من اختبار "الانفصال"، لأن اختبارات التقاطع يمكن أن تستفيد من الفهرس المكاني، بينما لا يمكن ذلك لاختبار الانفصال.

_images/st_crosses.png

في مقارنات multipoint/polygon و multipoint/linestring و linestring/linestring و linestring/polygon و linestring/multipolygon، تعيد ST_Crosses(geometry A, geometry B) القيمة t (TRUE) إذا نتج عن التقاطع شكل هندسي بُعده أقل بواحد من البُعد الأكبر للشكلين المصدرين، وكانت مجموعة التقاطع داخلية في كلا الشكلين المصدرين.

_images/st_overlaps.png

تقارن ST_Overlaps(geometry A, geometry B) بين شكلين هندسيين من البُعد نفسه، وتعيد TRUE إذا نتج عن مجموعة تقاطعهما شكل هندسي مختلف عن كليهما لكنه من البُعد نفسه.

لنأخذ محطة مترو Broad Street ونحدد الحي الذي تقع فيه باستخدام الدالة ST_Intersects:

SELECT name, ST_AsText(geom)
FROM nyc_subway_stations
WHERE name = 'Broad St';
POINT(583571 4506714)
SELECT name, boroname
FROM nyc_neighborhoods
WHERE ST_Intersects(geom, ST_GeomFromText('POINT(583571 4506714)',26918));
        name        | boroname
--------------------+-----------
 Financial District | Manhattan

11.3. ST_Touches

تختبر ST_Touches ما إذا كان شكلان هندسيان يتلامسان عند حدودهما دون أن تتقاطع مناطقهما الداخلية

_images/st_touches.png

تعيد ST_Touches(geometry A, geometry B) القيمة TRUE إذا تقاطعت حدود الشكلين، أو إذا تقاطعت المنطقة الداخلية لأحدهما فقط مع حدود الآخر.

11.4. ST_Within و ST_Contains

تختبر ST_Within و ST_Contains ما إذا كان أحد الشكلين الهندسيين يقع بالكامل داخل الآخر.

_images/st_within.png

تعيد ST_Within(geometry A , geometry B) القيمة TRUE إذا كان الشكل الهندسي الأول يقع بالكامل داخل الشكل الهندسي الثاني. وتختبر ST_Within النتيجة المعاكسة تمامًا لـ ST_Contains.

تعيد ST_Contains(geometry A, geometry B) القيمة TRUE إذا كان الشكل الهندسي الثاني محتوى بالكامل داخل الشكل الهندسي الأول.

11.5. ST_Distance و ST_DWithin

من أكثر أسئلة نظم المعلومات الجغرافية (GIS) شيوعًا: "أوجد كل الأشياء الواقعة ضمن مسافة X من تلك الأشياء الأخرى".

تحسب ST_Distance(geometry A, geometry B) المسافة الأقصر بين شكلين هندسيين وتعيدها كعدد عشري (float). وهذا مفيد لإعادة المسافة الفعلية بين الكائنات.

SELECT ST_Distance(
  ST_GeometryFromText('POINT(0 5)'),
  ST_GeometryFromText('LINESTRING(-2 2, 2 2)'));
3

لاختبار ما إذا كان كائنان ضمن مسافة معينة من بعضهما، توفر الدالة ST_DWithin اختبار صحيح/خطأ مُسرَّعًا بالفهرس. وهذا مفيد لأسئلة مثل "كم عدد الأشجار الواقعة ضمن نطاق عازل بعرض 500 متر من الطريق؟". لست بحاجة إلى حساب نطاق عازل فعلي، بل يكفي اختبار علاقة المسافة.

_images/st_dwithin.png

باستخدام محطة مترو Broad Street مرة أخرى، يمكننا إيجاد الشوارع القريبة من المحطة (ضمن 10 أمتار منها):

SELECT name
FROM nyc_streets
WHERE ST_DWithin(
        geom,
        ST_GeomFromText('POINT(583571 4506714)',26918),
        10
      );
     name
--------------
   Wall St
   Broad St
   Nassau St

ويمكننا التحقق من الإجابة على الخريطة. فمحطة Broad St تقع فعليًا عند تقاطع شوارع Wall و Broad و Nassau.

_images/broad_st.jpg

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

ST_Contains(geometry A, geometry B): تعيد true إذا وفقط إذا لم تقع أي نقطة من B خارج A، ووقعت نقطة واحدة على الأقل من داخل B في داخل A.

ST_Crosses(geometry A, geometry B): تعيد TRUE إذا كان للأشكال الهندسية المُعطاة بعض النقاط الداخلية المشتركة، لا كلها.

ST_Disjoint(geometry A , geometry B): تعيد TRUE إذا كانت الأشكال الهندسية "لا تتقاطع مكانيًا"، أي إذا لم تشترك في أي حيّز.

ST_Distance(geometry A, geometry B): تعيد أدنى مسافة ديكارتية ثنائية الأبعاد (بناءً على النظام المرجعي المكاني) بين شكلين هندسيين بوحدات الإسقاط.

ST_DWithin(geometry A, geometry B, radius): تعيد true إذا كانت الأشكال الهندسية ضمن المسافة المحددة (نصف القطر) من بعضها.

ST_Equals(geometry A, geometry B): تعيد true إذا كانت الأشكال الهندسية المُعطاة تمثل الشكل الهندسي نفسه. ويُتجاهل الاتجاه.

ST_Intersects(geometry A, geometry B): تعيد TRUE إذا كانت الأشكال الهندسية/الجغرافية "تتقاطع مكانيًا" (تشترك في أي جزء من الحيّز)، و FALSE إذا لم تكن كذلك (أي منفصلة).

ST_Overlaps(geometry A, geometry B): تعيد TRUE إذا كانت الأشكال الهندسية تشترك في حيّز، ومن البُعد نفسه، لكن لا يحتوي أحدها الآخر بالكامل.

ST_Touches(geometry A, geometry B): تعيد TRUE إذا كان للأشكال الهندسية نقطة مشتركة واحدة على الأقل، لكن مناطقها الداخلية لا تتقاطع.

ST_Within(geometry A , geometry B): تعيد true إذا كان الشكل الهندسي A يقع بالكامل داخل الشكل الهندسي B