نظرة عامة
MVTEncodeGeom— دالة قياسية تُسقِط شكلاً هندسياً إلى فضاء البكسلات المحلي للبلاطة ضمن slippy-map وتقصّه إلى حدود البلاطة.MVTEncode— دالة تجميعية تجمع الأشكال الهندسية المُسقطة لمجموعة ما في بايتات ثنائية لبلاطة أحادية الطبقة.
MVTBoundingBox وMVTBoundingBoxMercator المربع المحيط للبلاطة، بحيث يمكن
تقييد الصفوف به في عبارة WHERE باستخدام فهرس.
تدعم هذه الدوال الأشكال الهندسية النقطية والخطية ومتعددة الأضلاع، بما في ذلك النوع Geometry والأنواع الجغرافية المحددة (Point,
LineString, MultiLineString, Ring, Polygon, MultiPolygon).
تمثل البايتات الناتجة بلاطة كاملة يمكن إرجاعه مباشرةً عبر واجهة HTTP باستخدام FORMAT RawBLOB.
تحاكي هذه الدوال سير العمل في PostGIS، وهي متاحة أيضاً تحت أسماء PostGIS الخاصة بها كأسماء مستعارة: ST_AsMVTGeom
لـ MVTEncodeGeom وST_AsMVT لـ MVTEncode.
MVTEncodeGeom
slippy-map المحددة بواسطة zoom وtile_x وtile_y، ثم يقصّه إلى حدود البلاطة، ويطابقه مع شبكة
البكسلات الصحيحة، ويُرجع الشكل الهندسي في tile-space.
يكون الإسقاط وفق Web Mercator على كامل نطاق الإحداثيات UInt32. وتكون الإحداثيات المُعادة ذات أصل عند
الزاوية العلوية اليسرى للبلاطة مع اتجاه المحور y إلى الأسفل، وهو اصطلاح الإحداثيات المستخدم في تنسيق Mapbox Vector
Tile، لذلك يمكن تمرير النتيجة مباشرةً إلى MVTEncode. وتُقرَّب الإحداثيات إلى بكسلات كاملة، لذا فإن التجميع حسب
MVTEncodeGeom يدمج الأشكال الهندسية الواقعة على الشبكة نفسها في عنقود واحد.
عندما يكون clip مفعّلاً (وهو الإعداد الافتراضي)، يُقصّ الشكل الهندسي إلى البلاطة الموسَّعة بمقدار buffer من البكسلات (النطاق
[-buffer, extent + buffer] على كل محور)؛ أما الشكل الهندسي الذي يقع بالكامل خارجها فيصبح NULL. وهذا هو النظير لـ
PostGIS ST_AsMVTGeom.
يعتمد نوع الشكل الهندسي الناتج على المُدخل: إذ يُرجع Point قيمة Point؛ ويُرجع LineString أو MultiLineString
قيمة MultiLineString؛ وتُرجع Ring أو Polygon أو MultiPolygon قيمة MultiPolygon (إذ قد يؤدي القص إلى تقسيم الشكل الهندسي إلى
عدة أجزاء).
الصيغة
geometry— كائن هندسي بإحداثيات درجات الطول/العرض. يُقيَّد خط الطول إلى[-180, 180]وخط العرض إلى نطاق Web Mercator[-85.05112878, 85.05112878].Point/LineString/MultiLineString/Ring/Polygon/MultiPolygon/Geometry.zoom— مستوى التكبير في slippy-map، ضمن النطاق[0, 32].UInt8.tile_x— فهرس عمود البلاطة، ضمن النطاق[0, 2^zoom - 1].UInt32.tile_y— فهرس صف البلاطة، ضمن النطاق[0, 2^zoom - 1].UInt32.extent— الامتداد الاختياري للبلاطة، بالبكسل لكل ضلع، ضمن النطاق[1, 2147483647]. القيمة الافتراضية هي4096، وهي القيمة الافتراضية في Mapbox Vector Tile.UInt32.buffer— هامش اقتصاص اختياري بالبكسل، ضمن النطاق[0, 2147483647]. القيمة الافتراضية هي1.UInt32.clip— علامة اختيارية؛ عند كونها غير صفرية (وهو الإعداد الافتراضي)، يُقتص الكائن الهندسي إلى حدود البلاطة مع الهامش.UInt8.
NULL إذا جرى اقتصاصه بالكامل. Geometry.
مثال
MVTEncode
MVTEncodeGeom. يتحول كل صف إدخال إلى معلم واحد؛ كما أن هندسة النقطة والخط والمضلع مدعومة.
تكون الوسيطة geometry من النوع Geometry بإحداثيات فضاء البلاطة، وعادةً ما تُنتَج بواسطة MVTEncodeGeom. وتُتخطى
الصفوف التي تكون فيها الهندسة NULL (على سبيل المثال، التي اقتطعها MVTEncodeGeom). أما الوسيطة الاختيارية properties فهي
Tuple مسمّى، بحيث تصبح أسماء عناصره مفاتيح سمات المعلم، وتحدد أنواع عناصره أنواع القيم في البلاطة المتجهية.
النتيجة هي البايتات الخام لبلاطة أحادية الطبقة. وتنتج المجموعة الفارغة بلاطة فارغة. وهذا هو النظير لـ
PostGIS ST_AsMVT.
الصيغة
layer_name— اسم طبقة البلاطة المتجهة.String.extent— امتداد البلاطة بالبكسل لكل ضلع، ضمن النطاق[1, 2147483647]. القيمة الافتراضية هي4096.UInt32.feature_id_name— اسم اختياري لعنصر عددٍ صحيح غير موقّع ضمن الـ tuplepropertiesلإخراجه باعتبارهidلمعلم MVT (من النوعUInt64) بدلًا من إخراجه كوسم. تُرفَض الأعداد الصحيحة الموقّعة. وإذا كانت قيمةidهيNULL، يُحذَف هذا المعرّف لذلك المعلم. المعلمات موضعية، لذا يجب تمريرextentلاستخدامه.String.stringify_unsupported— علامة اختيارية (0/1، والقيمة الافتراضية0)؛ عند ضبطها على1، تُشفَّر أنواع الخصائص غير المدعومة مباشرةً (مثل الأعداد الصحيحة الكبيرة وUUIDوDecimal) على هيئةstring_valueنصية بدلًا من إطلاق خطأ.UInt8.
geometry— هندسة ضمن فضاء البلاطة، على سبيل المثال منMVTEncodeGeom.Geometry.properties—named tupleاختياري لسمات المعلم. وتصبح أسماء العناصر مفاتيح للسمات.Tuple.
String.
أنواع الخصائص
Value من Mapbox Vector Tile المطابق لنوعه في ClickHouse:
| نوع ClickHouse | نوع قيمة Vector Tile |
|---|---|
String / FixedString | string_value |
Float32 / BFloat16 | float_value |
Float64 | double_value |
Bool | bool_value |
Int8 / Int16 / Int32 / Int64 / Date32 | sint_value |
UInt8 / UInt16 / UInt32 / UInt64 / Date / DateTime | uint_value |
Nullable و/أو LowCardinality. تؤدي القيمة NULL إلى حذف تلك السمة من المعلم، لأن
تنسيق Vector Tile لا يحتوي على قيمة null. وأي نوع خاصية آخر يثير استثناءً، ما لم يتم تعيين stringify_unsupported،
وعندئذٍ يُرمَّز على أنه string_value النصي المقابل له.
تُخزَّن قيم الخصائص المتطابقة في مخزن القيم المشترك الخاص بالطبقة، لذا فإن القيمة التي تظهر في العديد من المعالم
لا تُخزَّن إلا مرة واحدة.
تسمية Tuple properties
tuple(...) على أسماء عناصر
الـTuple، لذا سمِّ العناصر باستخدام CAST:
التجميع العنقودي
MVTEncodeGeom يقرّب القيم إلى بكسلات كاملة، فإن التجميع حسب
هندسة البكسل يدمج الأشكال الهندسية المتطابقة؛ نفِّذ التجميع في استعلام فرعي، ثم مرِّر صفًا واحدًا لكل عنقود إلى
MVTEncode:
Geometry ضبط allow_suspicious_types_in_group_by = 1، لأن التجميع حسب النوع Geometry
القائم على Variant مقيَّد افتراضيًا. احذف GROUP BY الداخلي (وcount()) لإخراج معلم واحد لكل صف إدخال
بدلًا من المعالم المجمَّعة.
MVTBoundingBox
zoom وtile_x وtile_y على شكل tuple
(min_lon, min_lat, max_lon, max_lat) بالدرجات.
استخدمها لحصر الصفوف ضمن بلاطة معيّنة عند التصفية مباشرةً على العمودين longitude/latitude — بحيث يمكن استخدام مفتاح أساسي أو
فهرس على هذين العمودين — بدلًا من إعادة حساب إسقاط Web Mercator لكل صف. يوسّع الخيار الاختياري margin
المربع من كل جانب بهذا الكسر من حجم البلاطة؛ اضبطه على buffer / extent لتغطية clip buffer الخاص بـ
MVTEncodeGeom.
الصيغة
zoom— مستوى التكبير في slippy-map، ضمن النطاق[0, 32].UInt8.tile_x— فهرس عمود البلاطة، ضمن النطاق[0, 2^zoom - 1].UInt32.tile_y— فهرس صف البلاطة، ضمن النطاق[0, 2^zoom - 1].UInt32.margin— نسبة اختيارية من حجم البلاطة لتوسيع المربع المحيط من جميع الجوانب. القيمة الافتراضية هي0.Float64.
(min_lon, min_lat, max_lon, max_lat) بالدرجات. Tuple(Float64, Float64, Float64, Float64).
مثال
MVTBoundingBoxMercator
MVTBoundingBox. تُرجِع
المربع المحيط للبلاطة في فضاء إحداثيات Web Mercator الكامل من نوع UInt32 والمستخدَم داخليًا بواسطة MVTEncodeGeom، على هيئة tuple
(min_x, min_y, max_x, max_y). يزداد المحور y باتجاه الأسفل (الشمال في الأعلى). وهي مخصّصة للجداول التي تُخزِّن
أعمدة إحداثيات Mercator فعليًا وتُفهرِسها بدلًا من longitude/latitude.
الصيغة
MVTBoundingBox.
القيمة المُعادة
تعيد المربع المحيط للبلاطة على شكل tuple (min_x, min_y, max_x, max_y) بإحداثيات Web Mercator. Tuple(Float64, Float64, Float64, Float64).
مثال
تقييد الصفوف ضمن بلاطة
WHERE (للأداء)، ثم القص في MVTEncodeGeom (للصحة).
يستبعد القص الأشكال الهندسية الواقعة خارج البلاطة، لذا حتى شرط مربع الإحاطة المتساهل لا يمكنه أن يسرّب
أشكالًا هندسية من خارج البلاطة إلى النتيجة.
MVTEncodeGeom. مرّر clip => false (المعامل السابع) إلى MVTEncodeGeom لتعطيل القص والاعتماد على
شرط WHERE وحده.
تقديم البلاطات عبر HTTP
/. ويضيف المشغّل عنوان URL نظيفًا
/tile/{z}/{x}/{y} باستخدام معالج استعلام مُعرّف مسبقًا في
إعدادات الخادم. ويستخدم url الخاص بالمعالج صيغة regex: لالتقاط مقاطع المسار، وربطها بمعلمات
الاستعلام، ثم إرجاع البايتات باستخدام FORMAT RawBLOB.
في أبسط الحالات، يحتوي الجدول على عمود Geometry، ويعرض المعالج معلمًا واحدًا لكل صف — إذ يقوم MVTEncodeGeom
بإسقاط كل شكل هندسي على البلاطة المطلوبة وقصّه، بحيث تُستبعَد الصفوف الواقعة خارج البلاطة تلقائيًا:
shapes هو جدول يحتوي على عمود geom Geometry (أي مزيج من النقاط والخطوط والمضلعات). ويعيد GET /tile/10/550/335
البلاطة المُرمَّزة.
بالنسبة إلى بيانات النقاط، يعمل هذا بالقدر نفسه من الفعالية مع أعمدة longitude/latitude العادية أيضًا، وذلك ببناء النقطة مباشرةً باستخدام
MVTEncodeGeom((lon, lat)::Point, …). ولتجميع المعالم المتطابقة مكانيًا، أو لإضافة تصفية مسبقة باستخدام مربع الإحاطة تعتمد على الفهرس
للجداول الكبيرة، وسّع الاستعلام الداخلي كما هو موضح في تجميع عنقودي و
تقييد الصفوف إلى بلاطة.
القيود
-
يقيّد إسقاط Web Mercator خط العرض إلى
±85.05112878°، ولا يتعامل مع المدخلات التي تعبر خط الطول المقابل. -
لا يضمن قصّ المضلع إخراجًا صالحًا لـ MVT. يُصحّح القص اتجاه الحلقة وانغلاقها، لكنه لا يُصلح التقاطعات الذاتية. لذلك لا تُصلَح الحلقة ذاتية التقاطع (“ربطة الفراشة”): فبحسب كيفية تقاطعها مع الـ
tile، إمّا تُخرَج كما هي (وتظل غير صالحة)، أو تُسقَط إلىNULL. على سبيل المثال، تُسقَط ربطة فراشة تقع بالكامل داخل الـtile، بينما تُحفَظ الزوايا الأربع نفسها إذا لُفَّت على هيئة حلقة بسيطة:
- تُقصّ الهندسة قبل تقريبها إلى شبكة البكسلات ذات الإحداثيات الصحيحة. يقوم PostGIS أولًا بمواءمة الهندسة مع شبكة البكسلات ذات الإحداثيات الصحيحة ثم يقصّها ثانيًا؛ أما
MVTEncodeGeomفيقصّ أولًا (على الإحداثيات المُسقطة ذات الفاصلة العائمة) ثم يقرّب ثانيًا. وبالقرب من حافة البلاطة، قد يؤدي ذلك إلى إسقاط إحداثي كان سيُقرَّب بخلاف ذلك إلى بكسل الحافة. على سبيل المثال، عندbuffer = 0، تُقصّ نقطة تقع مباشرةً شرق حافة البلاطة، رغم أنها تُقرَّب إلى بكسل الحافة4096الذي كان نهج التقريب أولًا سيُبقي عليه: