28. الأبعاد الثلاثية (3-D)

28.1. الأشكال الهندسية ثلاثية الأبعاد

عملنا حتى الآن مع أشكال هندسية ثنائية الأبعاد، بإحداثيات X و Y فقط. لكن PostGIS يدعم أبعادًا إضافية في جميع أنواع الأشكال الهندسية: البعد "Z" لإضافة معلومات الارتفاع، والبعد "M" لمعلومات بُعدية إضافية (غالبًا الزمن، أو المسافة بالأميال على الطريق، أو المسافة باتجاه المنبع) لكل إحداثي.

في الأشكال الهندسية ثلاثية ورباعية الأبعاد، تُضاف الأبعاد الإضافية كإحداثيات إضافية لكل رأس في الشكل الهندسي، ويُوسَّع نوع الشكل الهندسي ليبيّن كيفية تفسير هذه الأبعاد الإضافية. وينتج عن إضافة الأبعاد الإضافية ثلاثة أنواع هندسية إضافية ممكنة لكل شكل هندسي أوّلي:

  • ينضم إلى النوع Point (نوع ثنائي الأبعاد) الأنواع PointZ و PointM و PointZM.

  • ينضم إلى النوع Linestring (نوع ثنائي الأبعاد) الأنواع LinestringZ و LinestringM و LinestringZM.

  • ينضم إلى النوع Polygon (نوع ثنائي الأبعاد) الأنواع PolygonZ و PolygonM و PolygonZM.

  • وهكذا.

في تمثيل النص المعروف ( WKT )، تحدّد مواصفة ISO SQL/MM صيغة الأشكال الهندسية ذات الأبعاد الأعلى. تُضاف معلومات الأبعاد الإضافية ببساطة إلى السلسلة النصية بعد اسم النوع، وتُضاف الإحداثيات الإضافية بعد معلومات X/Y. على سبيل المثال:

  • POINT ZM (1 2 3 4)

  • LINESTRING M (1 1 0, 1 2 0, 1 3 1, 2 2 0)

  • POLYGON Z ((0 0 0, 0 1 0, 1 1 0, 1 0 0, 0 0 0))

تُعيد الدالة ST_AsText() التمثيلات السابقة عند التعامل مع الأشكال الهندسية ثلاثية ورباعية الأبعاد.

في تمثيل الثنائي المعروف ( WKB )، تحدّد مواصفة ISO SQL/MM صيغة الأشكال الهندسية ذات الأبعاد الأعلى. وتتوفر صيغة BNF لهذا التنسيق على الرابط https://git.osgeo.org/gitea/postgis/postgis/src/branch/master/doc/bnf-wkb.txt.

إضافة إلى الصيغ عالية الأبعاد للأنواع القياسية، يتضمن PostGIS بعض الأنواع الجديدة التي يكون لها معنى في الفضاء ثلاثي الأبعاد:

  • يتيح لك النوع TIN نمذجة الشبكات المثلثية كصفوف في قاعدة بياناتك.

  • يتيح لك النوع POLYHEDRALSURFACE نمذجة الأجسام الحجمية في قاعدة بياناتك.

بما أن كلا النوعين مخصص لنمذجة الأجسام ثلاثية الأبعاد، فلا معنى حقيقيًا إلا لاستخدام صيغتيهما من النوع Z. ومن أمثلة POLYHEDRALSURFACE Z المكعب ذو الوحدة الواحدة:

POLYHEDRALSURFACE Z (
  ((0 0 0, 0 1 0, 1 1 0, 1 0 0, 0 0 0)),
  ((0 0 0, 0 1 0, 0 1 1, 0 0 1, 0 0 0)),
  ((0 0 0, 1 0 0, 1 0 1, 0 0 1, 0 0 0)),
  ((1 1 1, 1 0 1, 0 0 1, 0 1 1, 1 1 1)),
  ((1 1 1, 1 0 1, 1 0 0, 1 1 0, 1 1 1)),
  ((1 1 1, 1 1 0, 0 1 0, 0 1 1, 1 1 1))
)

28.2. الدوال ثلاثية الأبعاد

هناك عدد من الدوال المصممة لحساب العلاقات بين الأجسام ثلاثية الأبعاد:

  • ST_3DClosestPoint — تُعيد النقطة ثلاثية الأبعاد على g1 الأقرب إلى g2. وهي النقطة الأولى من أقصر خط ثلاثي الأبعاد.

  • ST_3DDistance — للنوع geometry، تُعيد أقل مسافة ديكارتية ثلاثية الأبعاد (بناءً على النظام المرجعي المكاني) بين شكلين هندسيين بوحدات الإسقاط.

  • ST_3DDWithin — للنوع geometry ثلاثي الأبعاد (z)، تُعيد true إذا كانت المسافة ثلاثية الأبعاد بين شكلين هندسيين ضمن عدد الوحدات المحدد.

  • ST_3DDFullyWithin — تُعيد true إذا كانت جميع الأشكال الهندسية ثلاثية الأبعاد ضمن المسافة المحددة بعضها من بعض.

  • ST_3DIntersects — تُعيد TRUE إذا كانت الأشكال الهندسية "تتقاطع مكانيًا" في الأبعاد الثلاثية - للنقاط والخطوط فقط

  • ST_3DLongestLine — تُعيد أطول خط ثلاثي الأبعاد بين شكلين هندسيين

  • ST_3DMaxDistance — للنوع geometry، تُعيد أكبر مسافة ديكارتية ثلاثية الأبعاد (بناءً على النظام المرجعي المكاني) بين شكلين هندسيين بوحدات الإسقاط.

  • ST_3DShortestLine — تُعيد أقصر خط ثلاثي الأبعاد بين شكلين هندسيين

على سبيل المثال، يمكننا حساب المسافة بين المكعب ذي الوحدة الواحدة ونقطة باستخدام الدالة ST_3DDistance:

-- This is really the distance between the top corner
-- and the point.
SELECT ST_3DDistance(
  'POLYHEDRALSURFACE Z (
    ((0 0 0, 0 1 0, 1 1 0, 1 0 0, 0 0 0)),
    ((0 0 0, 0 1 0, 0 1 1, 0 0 1, 0 0 0)),
    ((0 0 0, 1 0 0, 1 0 1, 0 0 1, 0 0 0)),
    ((1 1 1, 1 0 1, 0 0 1, 0 1 1, 1 1 1)),
    ((1 1 1, 1 0 1, 1 0 0, 1 1 0, 1 1 1)),
    ((1 1 1, 1 1 0, 0 1 0, 0 1 1, 1 1 1))
  )'::geometry,
  'POINT Z (2 2 2)'::geometry
);

-- So here's a shorter form.
SELECT ST_3DDistance(
  'POINT Z (1 1 1)'::geometry,
  'POINT Z (2 2 2)'::geometry
);

-- Both return 1.73205080756888 == sqrt(3) as expected

28.3. الفهارس متعددة الأبعاد (N-D)

عندما تكون لديك بيانات بأبعاد أعلى، قد يكون من المنطقي فهرستها. لكن عليك التفكير بعناية في توزيع بياناتك في جميع الأبعاد قبل تطبيق فهرس متعدد الأبعاد.

لا تكون الفهارس مفيدة إلا عندما تتيح لقاعدة البيانات تقليص عدد الصفوف المُعادة تقليصًا كبيرًا نتيجة شرط WHERE. ولكي يكون الفهرس عالي الأبعاد مفيدًا، يجب أن تغطي البيانات نطاقًا واسعًا من ذلك البعد، مقارنةً بأنواع الاستعلامات التي تنشئها.

  • من المرجح أن تكون مجموعة من نقاط نموذج الارتفاع الرقمي (DEM) مرشحًا ضعيفًا لفهرس ثلاثي الأبعاد، لأن الاستعلامات عادةً ما تستخرج مربعًا ثنائي الأبعاد من النقاط، ونادرًا ما تحاول تحديد شريحة Z من النقاط.

  • قد تكون مجموعة من مسارات GPS في الفضاء X/Y/T مرشحًا جيدًا لفهرس ثلاثي الأبعاد، إذا كانت مسارات GPS تتداخل كثيرًا في جميع الأبعاد (مثل قيادة السيارة على المسار نفسه مرارًا في أوقات مختلفة)، إذ سيكون هناك تباين كبير في جميع أبعاد مجموعة البيانات.

يمكنك إنشاء فهرس متعدد الأبعاد على بيانات من أي عدد من الأبعاد (حتى البيانات مختلطة الأبعاد). على سبيل المثال، لإنشاء فهرس متعدد الأبعاد على الجدول nyc_streets،

CREATE INDEX nyc_streets_gix_nd ON nyc_streets
USING GIST (geom gist_geometry_ops_nd);

تُخبر المعاملة gist_geometry_ops_nd نظام PostGIS باستخدام الفهرس متعدد الأبعاد (N-D) بدلًا من الفهرس القياسي ثنائي الأبعاد.

بعد بناء الفهرس، يمكنك استخدامه في الاستعلامات عبر عامل الفهرس &&&. للعامل &&& الدلالة نفسها التي للعامل &&، أي "تفاعل المستطيلات المحيطة"، لكنه يطبقها باستخدام جميع أبعاد الأشكال الهندسية المُدخلة. ولا تتفاعل الأشكال الهندسية غير المتطابقة في عدد الأبعاد.

-- Returns true (both 3-D on the zero plane)
SELECT 'POINT Z (1 1 0)'::geometry &&&
       'POLYGON ((0 0 0, 0 2 0, 2 2 0, 2 0 0, 0 0 0))'::geometry;

-- Returns false (one 2-D one 3-D)
SELECT 'POINT Z (3 3 3)'::geometry &&&
       'POLYGON ((0 0, 0 2, 2 2, 2 0, 0 0))'::geometry;

-- Returns true (the volume around the linestring interacts with the point)
SELECT 'LINESTRING Z(0 0 0, 1 1 1)'::geometry &&&
       'POINT(0 1 1)'::geometry;

للبحث في الجدول nyc_streets باستخدام الفهرس متعدد الأبعاد، استبدل فقط عامل الفهرس ثنائي الأبعاد المعتاد && بالعامل &&&.

-- N-D index operator
SELECT gid, name
FROM nyc_streets
WHERE geom &&&
      ST_SetSRID('LINESTRING(586785 4492901,587561 4493037)'::geometry,26918);

-- 2-D index operator
SELECT gid, name
FROM nyc_streets
WHERE geom &&
      ST_SetSRID('LINESTRING(586785 4492901,587561 4493037)'::geometry,26918);

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