กำหนดและย้ายเซนทรอยด์ไปยังรูปหลายเหลี่ยม


9

ฉันใช้ QGIS 1.8 Lisboa หลังจากคำนวณเซนทรอยด์จากรูปหลายเหลี่ยมรูปร่างแล้วหากบางส่วนอยู่นอกเส้นขอบรูปหลายเหลี่ยมฉันต้องการย้ายรูปเหล่านั้นบนรูปหลายเหลี่ยมที่มาจาก เกณฑ์ที่ควรจะเป็น univocal เป็นฉันต้องใช้พวกเขาเพื่อแยกพิกัดที่จะใช้เป็นรหัสประจำตัวของรูปหลายเหลี่ยมตัวเอง ดังนั้นขั้นตอนควรส่งออกตำแหน่งจุดเดียวกันทุกครั้งที่มันทำงานสำหรับรูปหลายเหลี่ยมเดียวกัน (ไม่ใช่ตำแหน่งแบบสุ่มเช่นเดียวกับที่กำหนดโดยฟังก์ชั่น "จุดสุ่ม" ซึ่งให้ผลลัพธ์ใหม่ทุกครั้งที่วิ่ง)


1
ฟังดูเหมือนคำถามสองข้อ หากฉันเข้าใจถูกต้องคุณต้องการ (a) เพิ่มจุดสุ่มภายในรูปหลายเหลี่ยมและ (b) ให้ ID ที่ไม่ซ้ำกับพวกเขาหรือรูปหลายเหลี่ยมโดยยึดตามสิ่งนี้ สิ่งที่ง่ายที่สุดที่ควรคำนึงถึงคือ (a) คือการใช้ความสามารถของจุดสุ่มที่มีอยู่แล้วใน QGIS จากนั้นก็ตัดจุดคลาวด์นั้นด้วยรูปหลายเหลี่ยมของคุณ
lynxlynxlynx

การใช้ฟังก์ชั่น "สุ่มคะแนน" เวลาที่ต่างกันด้วยรูปหลายเหลี่ยมเดียวกันนำไปสู่ผลลัพธ์ที่แตกต่างกัน (กล่าวคือตำแหน่งของคะแนนที่ได้จากรูปหลายเหลี่ยมแต่ละครั้งนั้นแตกต่างกันในการใช้ฟังก์ชันใหม่แต่ละครั้ง) และฉันต้องการสร้างวิธีที่ จุดเดียวกันต่อรูปหลายเหลี่ยมเสมอจากที่ฉันสามารถแยกพิกัดที่ฉันต้องการใช้เป็นรหัสประจำตัวสำหรับรูปหลายเหลี่ยมตัวเอง
umbe1987

ใช้เครื่องมือ 'จริง centroid' ของ fTools ภายใต้เครื่องมือรูปทรงเรขาคณิต - docs.qgis.org/html/en/docs/user_manual/plugins/
Mapperz

มันให้เซนทรอยด์แก่ฉัน แต่สิ่งนี้อาจอยู่นอกโพลิกอนซึ่งฉันต้องหลีกเลี่ยง ฉันต้องการย้ายพวกเขาไปบนรูปหลายเหลี่ยมที่พวกเขาได้รับมาจากการใช้ฟังก์ชั่นเช่นระยะทางขั้นต่ำ (แต่ฉันไม่สนใจระยะทางฉันต้องการที่จะย้าย) ในบล็อกอื่นมีคนบอกให้ฉันใช้ ST_PointOnSurface ของ PostGIS (แต่ฉันใช้ QGIS)
umbe1987

2
นี่เป็นข้อมูลซ้ำซ้อนของgis.stackexchange.com/questions/50029/หรือไม่
underdark

คำตอบ:


7

คุณสามารถใช้ไลบรารี Shapely python ซึ่งมีฟังก์ชันrepresentative_point()ที่รับประกันว่าจะอยู่ในรูปหลายเหลี่ยม

นี่คือสคริปต์ Python ที่สามารถเรียกใช้ในคอนโซล QGIS Python ควรเลือกเลเยอร์รูปหลายเหลี่ยมที่คุณต้องการสร้างแอททริบิว ฟังก์ชันใช้ชื่อของแอตทริบิวต์ที่คุณต้องการอัปเดต แอตทริบิวต์ต้องมีอยู่ในเลเยอร์ของคุณแล้วต้องเป็นประเภทสตริงและควรยาวพอ (30 อักขระ)

นี่คือตัวอย่างของคะแนนที่อัลกอริทึมพบ:

import shapely.wkb

def setIDPoint(attributename):
 layer = qgis.utils.iface.activeLayer()
 provider = layer.dataProvider()
 fields = provider.fields()
 provider.select(provider.attributeIndexes() )
 attributeID = provider.fieldNameIndex(attributename)
 feature = QgsFeature()
 layer.startEditing()
 while provider.nextFeature(feature):
  wkb = feature.geometry().asWkb()
  polygon = shapely.wkb.loads(wkb)
  reprPoint = ','.join([str(polygon.representative_point().x), str(polygon.representative_point().y)] )
  feature.changeAttribute(attributeID, reprPoint)
  layer.updateFeature(feature)
 layer.commitChanges()

ฉันพยายามที่จะทดสอบดูเหมือนว่าสิ่งที่ฉันกำลังมองหา ฉันจะแจ้งให้คุณทราบทันทีที่ฉันเรียกใช้!
umbe1987

สิ่งหนึ่งที่ฉันไม่เข้าใจเกี่ยวกับมันคือสิ่งที่คุณหมายถึงด้วย "มันจะต้องเป็นประเภทสตริงและมันควรจะยาวพอ (30 ตัวอักษร)" ไลบรารีนี้ทำงานโดยตรงกับรูปหลายเหลี่ยม shpfiles หรือไม่ ถ้าเป็นเช่นนั้นฉันควรจะสร้างฟิลด์ประเภทสตริงใหม่ในแท็บ Att โดยมีอักขระอย่างน้อย 30 ตัวและนี่จะเป็นฟิลด์ที่จะอัปเดตหรือไม่
umbe1987

@ user9518: ใช่วิธีการเขียนฟังก์ชั่นในขณะที่คุณต้องสร้างคุณลักษณะในตารางด้วยตัวคุณเองแล้วเพียงส่งชื่อของเขตข้อมูลไปยังฟังก์ชัน สคริปต์ยังสามารถปรับเปลี่ยนได้อย่างง่ายดายเพื่อสร้างเขตข้อมูลที่จำเป็นเองหากเป็นสิ่งที่จำเป็น
Jake

ฉันเพิ่งพลาดสิ่งหนึ่ง ดูเหมือนว่าตอนนี้ฉันกำลังกำหนดฟังก์ชั่น (หรือคลาส) โดยการพิมพ์ "def" แต่เมื่อฉันจบการเขียนสคริปต์มันจะไม่เกิดอะไรขึ้น ในที่สุดฉันจะได้ผลลัพธ์ในตารางของฉันได้อย่างไร
umbe1987

1
มันทำงานได้อย่างสมบูรณ์แบบ !!! ฉันจินตนาการว่าพิกัดถูกเขียนตามระบบพิกัดของเลเยอร์และถ้าฉันต้องการให้มีจุดที่ฉันต้องการในการสร้าง shp ด้วยพิกัดเหล่านั้นใช่ไหม ถ้าคุณอยู่ที่นี่ฉันจะเสนอ 3 เบียร์ให้คุณอย่างน้อย! ขอบคุณมากสำหรับความพยายามของคุณ !!!
umbe1987

5

เครื่องมือ centools ftools สามารถวาง centroid นอกรูปหลายเหลี่ยมถ้ามันเว้า

ST_PointOnSurfaceจะทำสิ่งที่คุณต้องการอย่างแน่นอน คุณสามารถใช้คำสั่งจากภายใน QGIS หากคุณติดตั้งโดยใช้ SPIT เพื่อให้ shapefile ของคุณเป็น PostGIS จากนั้นใช้ปลั๊กอิน PgQuery เพื่อเรียกใช้แบบสอบถาม

อีกทางเลือกหนึ่งถ้าติดตั้ง PostGIS เพียงเล็กน้อยสำหรับการใช้ครั้งเดียวคุณสามารถใช้Spatialiteจากภายใน QGIS จากนั้นคุณสามารถใช้ปลั๊กอิน QSpatiaLite เพื่อนำเข้าข้อมูลของคุณไปยัง SpatiaLite และเรียกใช้แบบสอบถาม (SpatialLite honors ST_PointOnSurface)


2

เมื่อฉันเข้าใจคุณถูกต้องให้ใช้: Vector-> เครื่องมือวิจัย _> คะแนนสุ่ม ตอนนี้เลือกภายใต้ "การออกแบบการเก็บตัวอย่างแบบแบ่งชั้น (รูปหลายเหลี่ยมแต่ละส่วน)" ใช้ค่าจากช่องป้อนข้อมูลและใช้ฟิลด์ที่มีความเหมาะสมซึ่งให้ค่าตัวเลขของคะแนน


คุณหมายถึงอะไรกับ "ฟิลด์ที่เหมาะสม" ฉันกำลังคิดที่จะใช้เซนทรอยด์แล้วเชื่อมโยงไปยังส่วนที่ใกล้ที่สุดของรูปหลายเหลี่ยมที่มันอ้างถึงหากมันอยู่นอกโครงร่างโดย (เช่น) คำนวณระยะทางขั้นต่ำของจุดนั้นไปยังรูปหลายเหลี่ยมที่ใกล้ที่สุด จุดประสงค์คือการแยกพิกัดจุดนั้นเพื่อใช้เป็นรหัสประจำตัวเฉพาะของรูปหลายเหลี่ยม
umbe1987

โดยพื้นฐานแล้วสิ่งที่ฉันพยายามทำคือการกำหนดเซนทรอยด์แต่ละอันให้กับรูปหลายเหลี่ยมแบบสัมพัทธ์ของมันและย้ายไปอยู่ภายในรูปหลายเหลี่ยมของมัน (หรืออย่างน้อยก็แตะเส้นเขตแดน)
umbe1987

@ user9518: ขอโทษฉันเข้าใจผิดคำถามของคุณ ฉันคิดว่าคุณต้องการจำนวนเฉพาะคะแนนสุ่มในแต่ละโพลีเช่น 2 คะแนน fpr โพลี 1, 10 คะแนนภายในโพลี 2 เป็นต้นดังนั้นคำว่า "ฟิลด์ที่เหมาะสม" แน่นอนคุณสามารถเลือก 1 สำหรับ "ใช้จำนวนคะแนนนี้" เพื่อสร้างเพียงหนึ่งจุดสำหรับทุกโพลี จุดนี้อยู่ข้างในโพลีหรืออย่างน้อยก็แตะกับเส้นเขตแดน แต่จุดนี้ยังคงพบต่อการสุ่มดังนั้นเมื่อคุณทำซ้ำขั้นตอนที่คุณได้รับคะแนนอื่น ๆ :-(
Kurt

1

ปลั๊กอิน realcentroids สามารถติดตั้งผ่านปลั๊กอิน> จัดการและติดตั้งปลั๊กอินทำงานให้ฉันใน QGIS 2.2 เพื่อสร้างจุดที่คล้ายกับเซนทรอยด์บังคับภายในรูปหลายเหลี่ยมถ้าเว้า (จุดจะอยู่ใกล้กับขอบมาก) ฉันลองใช้เครื่องมือสุ่มคะแนนตามที่ Kurt แนะนำ แต่ถึงแม้ว่าฉันจะระบุ 1 จุดต่อรูปหลายเหลี่ยม แต่ก็สร้างสองจุดแทน ข้อเสียที่เพิ่มเติมคือในกรณีส่วนใหญ่จุดไม่ได้แสดงถึงเซนทรอยด์เนื่องจากเป็นแบบสุ่ม

http://www.agt.bme.hu/gis/qgis/realcentroid/

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.