أكثر

إنشاء مضلعات متساوية الحجم على طول الخط مع PyQGIS


أرغب في إنشاء مضلعات على طول الخط لاستخدامها في AtlasCreator في الخطوة التالية.

يحتوي ArcMap على أداة تسمى ميزات فهرس خريطة الشريط.

باستخدام هذه الأداة ، يمكنني اختيار ارتفاع وعرض المضلعات الخاصة بي (لنقل 8 كم × 4 كم) وإنتاجها / تدويرها على طول الخط تلقائيًا.

إحدى السمات التي تم إنشاؤها لكل مضلع هي زاوية الدوران التي أحتاجها لتدوير أسهمي الشمالية في Atlas Generator بعد ذلك.

هل لدى أي شخص فكرة عن كيفية حل هذه المهمة في QGIS / باستخدام PyQGIS؟

خوارزميات GRASS أو SAGA أو نموذج صندوق أدوات prossessing الذي يمكن استخدامه داخل مكون إضافي مخصص سيكون جيدًا أيضًا.

لا أحتاج إلى نطاقات الطباعة فحسب ، بل أحتاج أيضًا إلى المضلعات نفسها لأنني أريد طباعة خريطة بجميع المضلعات / النطاقات كنوع من خريطة النظرة العامة. أنا أبحث عن حل PyQGIS يمكن استخدامه في البرنامج المساعد QGIS دون الحاجة إلى تثبيت برنامج بخلاف QGIS (لا توجد RDBMS مثل PostGIS / Oracle).


سؤال مهم! إنه شيء أردت أن أجربه بنفسي ، لذا جربته.

يمكنك القيام بذلك في PostGRES / POSTGIS بوظيفة تنشئ مجموعة من المضلعات.

في حالتي ، لدي جدول بميزة واحدة (MULTILINESTRING) تمثل خط سكة حديد. يحتاج إلى استخدام CRS بالأمتار ، أنا أستخدم osgb (27700). لقد أنجزت "صفحات" 4 كم × 2 كم.

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

ها هي الوظيفة ...

إنشاء أو استبدال وظيفة getAllPages (تعويم wid ، عائم hite ، عدد صحيح srid ، تعويم متداخل) إرجاع هندسة SETOF كـ $ BODY $ DECLARE هندسة الصفحة ؛ - يحمل كل صفحة كما تم إنشاؤها myline geometry ؛ - يحمل هندسة نقطة بداية الخط ؛ هندسة نقطة النهاية السمت تطفو - زاوية دوران المؤشر: = 0.0 ؛ - إلى أي مدى يتم تعويم الخطوة على طول خط الحافة اليسرى ؛ تعويم خطوة هندسة الكشمش - تستخدم لعمل هندسة متغيرة للصفحات ؛ كرنجل تعويم numpages تطفو. BEGIN - قم بإسقاط مكالمة ST_LineMerge إذا كنت تستخدم LineString - استبدل هذا بالجدول الخاص بك. حدد ST_LineMerge (geom) INTO myline من traced_osgb ؛ numpages: = ST_Length (myline) / wid ؛ الخطوة: = 1.0 / numpages ؛ stepnudge: = (1.0 - تداخل) * خطوة ؛ لـ r في 1 ... cast (numpages كعدد صحيح) LOOP - عمل على نقطة بداية مقطع السطر الحالي: = ST_SetSRID (ST_Line_Interpolate_Point (myline ، curs) ، srid) ؛ نقطة النهاية: = ST_SetSRID (ST_Line_Interpolate_Point (myline ، curs + step) ، srid) ؛ curline: = ST_SetSRID (ST_MakeLine (نقطة البداية ، نقطة النهاية) ، srid) ؛ - عمل مضلع بالحجم المناسب عند أصل عملة CRS: = ST_SetSRID (ST_Extent (ST_MakeLine (ST_MakePoint (0.0،0.0) ، ST_MakePoint (wid ، hite))) ، srid) ؛ - ثم دفع لأسفل بحيث يتطابق خط الوسط مع تيار قطعة الخط الحالي: = ST_Translate (curpoly، 0.0، -hite / 2.0) ؛ - تدوير لمطابقة الزاوية - ليس لدي أي فكرة على الإطلاق عن كيفية عمل هذا الجزء. currangle: = -ST_Azimuth (نقطة البداية ، نقطة النهاية) - (PI () / 2.0) + PI () ؛ الكشمش: = ST_Rotate (كريب ، كورانجل) ؛ - ثم الانتقال إلى بداية تيار القطعة الحالية: = ST_Translate (curpoly ، ST_X (نقطة البداية) ، ST_Y (نقطة البداية)) ؛ الصفحة: عودة الصفحة التالية باسم geom ؛ - ينتج عن مؤشرات النتيجة التالية: = curs + stepnudge ؛ نهاية الحلقة ؛ إرجاع؛ END $ BODY $ LANGUAGE 'plpgsql'؛

باستخدام هذه الوظيفة

هنا مثال. 4 كم × 2 كم صفحة ، epsg: 27700 و 10٪ تداخل

حدد st_asEwkt (getallpages) من getAllPages (4000.0 ، 2000.0 ، 27700 ، 0.1) ؛

بعد تشغيل هذا ، يمكنك بعد ذلك التصدير من PgAdminIII إلى ملف csv. يمكنك استيراد هذا إلى QGIS ، ولكن قد تحتاج إلى ضبط CRS يدويًا للطبقة - لا يستخدم QGIS SRID في EWKT لتعيين طبقة CRS لك: /

مضيفا السمة تحمل

ربما يكون هذا أسهل في postgis ، ويمكن إجراؤه في تعبيرات QGIS ولكن ستحتاج إلى كتابة بعض التعليمات البرمجية. شيء من هذا القبيل…

إنشاء صفحات جدول كـ (حدد getallpages من getAllPages (4000.0 ، 2000.0 ، 27700 ، 0.1)) ؛ تعديل صفحات الجدول إضافة عمود تحمل الطفو ؛ تعيين صفحات التحديث المحمل = ST_Azimuth (ST_PointN (getallpages ، 1) ، ST_PointN (getallpages ، 2)) ؛

تحفظات

لقد تم اختراقها قليلاً ، ولم يكن لديها سوى فرصة للاختبار على مجموعة بيانات واحدة.

لست متأكدًا بنسبة 100٪ من القمتين اللتين ستحتاج إلى اختيارهما في تحديث السمة المحملاستفسار... قد تحتاج إلى التجربة.

يجب أن أعترف أنه ليس لدي أي فكرة عن سبب حاجتي لعمل مثل هذه الصيغة المعقدة لتدوير المضلع لمطابقة مقطع الخط الحالي. اعتقدت أنه يمكنني استخدام الإخراج من ST_Azimuth () في ST_Rotate () ، ولكن على ما يبدو لا.


إجابة @ Steven Kays في PyQGIS.

ما عليك سوى تحديد الخطوط في طبقتك قبل تشغيل البرنامج النصي. لا يدعم البرنامج النصي الدمج الخطي ، لذا لا يمكن أن يعمل على طبقة ذات سلسلة متعددة الأسطر

#! python # coding: utf-8 # / questions / 173127 / إنشاء مضلعات متساوية الحجم على طول الخط مع pyqgis من استيراد qgis.core (QgsMapLayerRegistry و QgsGeometry و QgsField و QgsFeature و QgsPoint) من PyQt4.QtCore استيراد QVariant def getAllPages (طبقة ، عرض ، ارتفاع ، srid ، تداخل): للميزة في layer.selectedFeatures (): geom = feature.geometry () if geom.type () <> QGis.Line: print "يجب أن يكون نوع الهندسة a LineString "إرجاع صفحتين = QgsVectorLayer (" Polygon؟ crs = epsg: "+ str (srid) ، layer.name () + '_ id _' + str (feature.id ()) + '_ pages' ،" الذاكرة ") fid = QgsField ("fid"، QVariant.Int، "int") angle = QgsField ("angle"، QVariant.Double، "double") سمات = [fid، angle] pages.startEditing () pagesProvider = pages.dataProvider ( ) pagesProvider.addAttributes (السمات) curs = 0 numpages = geom.length () / (width) step = 1.0 / numpages stepnudge = (1.0-interap) * step pageFeatures = [] r = 1 currangle = 0 while curs <= 1 : # print 'r =' + str (r) # print 'curs =' + str (curs) startpoint = geom.interpolate (curs * geo m.length ()) endpoint = geom.interpolate ((curs + step) * geom.length ()) x_start = startpoint.asPoint (). x () y_start = startpoint.asPoint (). y () x_end = نقطة النهاية. asPoint (). x () y_end = endpoint.asPoint (). y () # print 'x_start:' + str (x_start) # print 'y_start:' + str (y_start) Currline = QgsGeometry (). fromWkt ('LINESTRING ({} {}، {} {}) '. تنسيق (x_start، y_start، x_end، y_end)) curpoly = QgsGeometry (). fromWkt (' POLYGON ((0 0، 0 {height}، {width} {height} ، {width} 0، 0 0)) '. format (height = height، width = width)) curpoly.translate (0، -height / 2) azimuth = startpoint.asPoint (). azimuth (endpoint.asPoint ()) currangle = (startpoint.asPoint (). السمت (endpoint.asPoint ()) + 270)٪ 360 # print 'السمت:' + str (السمت) # print 'currangle:' + str (currangle) currpoly.rotate (currangle ، QgsPoint (0،0)) curpoly.translate (x_start، y_start) صفحة curpoly.asPolygon () = curspoly curs = curs + stepnudge feat = QgsFeature () feat.setAttributes ([r، currangle]) feat.setGeometry (page) pageFeatures . append (feat) r = r + 1 صفحة vider.addFeatures (pageFeatures) pages.commitChanges () QgsMapLayerRegistry.instance (). addMapLayer (صفحات) تُرجع 0 layer = iface.activeLayer () getAllPages (layer، 500، 200، 2154، 0.4)

هناك حلول مختلفة. ويمكن أن يعمل هذا مع كيانات متعددة الخطوط بسيطة والعديد من الكيانات المحددة

مخطط كتلة:

  1. المعلمات

    1. حدد الاتجاه للإنشاء وقراءة الفهرس (من اليسار إلى اليمين ، ومن الشمال إلى الجنوب ...)
    2. تعيين حجم الكائن
    الشكل = (4000،8000) # (,)
    1. تحديد coef التراكب (10٪ افتراضيًا؟)
  2. فيه
    1. ترتيب متعدد الخطوط (قارن نقطة البداية والنهاية) يعتمد على اختيار الاتجاه الخاص بك> إنشاء نقاط ترتيب ترتيب الميزات فئة OrderNodes
  3. حلقة على OrderNodes

    1. خلق لك النقطة الأولى كمرساة

    2. لكل رأس قم بإضافته إلى dict x و y و id وحساب المتجه

    3. إنشاء مضلع (على الطول والاتجاه المتجه) مع تقليل التراكب (10٪ / 2)> 5٪ مضلع يسار 5٪ مضلع أيمن مع نفس نقطة الربط
    4. توقف عندما تكون نقطة قمة سابقة خارج المضلع أو إذا كان المتجه len> لتشكيل الطول
    5. أنشئ مضلعًا باستخدام حل جيد سابق وحدد نقطة ربط مع آخر موضع جيد
    6. قم بتنفيذ حلقة جديدة وأعد تعيين dt x ، y ، id لإنشاء كائن مضلع تالٍ.

يمكنك تغيير هذا الاقتراح إذا لم يكن حقًا واضحًا أو تعليقًا.


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

أولا ألق نظرة على منصبي هنا. يمنحك هذا كيفية إنشاء أغلفة خرائط لـ Atlas. الطريقة التي تريدها هي تكييف "Workflow 2" في الكيفية. قسّم الميزة الخطية الخاصة بك عن طريق الرؤوس أو الطول وقم بتخزين الميزات بأي مقدار. سيحدد المبلغ الذي تخزنه مؤقتًا التداخل جزئيًا (لكن انظر أدناه) ولكن الأهم من ذلك ، أنه ينشئ ميزة بمنطقة. يمكنك استخدام أي عدد من المكونات الإضافية لتقسيم الأسطر ولكن GRASS v.split.length و v.split.vert هما خياران جيدان (متاحان في Processing Toolbox).

بعد تمكين Atlas Generation في Map Composer وتحديد الطبقة المخزنة مؤقتًا ، قم بالرجوع إلى علامة تبويب العناصر وحدد كائن الخريطة. حدد "تحت سيطرة أطلس" ، وفي حالة الاستخدام الخاصة بك ، سأختار الهامش حول الميزة. سيتحكم هذا في التداخل بين الخرائط (بدلاً من ذلك ، قد تفضل مقياسًا ثابتًا).

يمكنك معاينة أطلس باستخدام زر معاينة الأطلس في شريط أدوات الملحن العلوي ومعرفة عدد الصفحات التي سينتجها. ملاحظة يمكنك اختيار تصدير كل الصفحات في ملف PDF واحد أو كملفات منفصلة.

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


أعلم أن هذا سؤال قديم ولكن تم إنشاء مكون إضافي جديد لمعالجة هذه المشكلة. https://plugins.qgis.org/plugins/polystrip/

أنا لست منشئ البرنامج ولا أحصل على الفضل في المكون الإضافي.


شاهد الفيديو: QGIS Python PyQGIS - Calculate Field Values Field Calculator (شهر اكتوبر 2021).