เปรียบเทียบรูปทรงเรขาคณิตสองแบบใน ArcPy หรือไม่


18

ฉันพยายามเปรียบเทียบสองฟีเจอร์แยกต่างหากเพื่อระบุความแตกต่างระหว่างคลาสเหล่านั้น (เรียงลำดับของฟังก์ชั่น diff) เวิร์กโฟลว์พื้นฐานของฉัน:

  1. ฉันแยกรูปทรงเรขาคณิตโดยใช้SearchCursor
  2. บันทึกรูปทรงเรขาคณิตของสองฟีเจอร์คลาสเป็น GeoJSON โดยใช้การแก้ไข__geo_interface__(ได้มาจากvalveLondon return {'type': 'Polygon', 'coordinates': [[((pt.X, pt.Y) if pt else None) for pt in part] for part in self]} ) นี่คือเพื่อหลีกเลี่ยงวัตถุเรขาคณิตที่ใช้ร่วมกันที่ ESRI ใช้กับเคอร์เซอร์และไม่สามารถทำสำเนาลึก ๆ (การสนทนาบางอย่างที่นี่ใน gis.stackexchange พูดถึงมัน)
  3. ตรวจสอบรูปทรงเรขาคณิตของคลาสฟีเจอร์สองคลาสตามตัวระบุเฉพาะ ตัวอย่างเช่นเปรียบเทียบเรขาคณิต FC1 OID1 กับเรขาคณิต FC2 OID1 เพื่อให้ได้รูปทรงเรขาคณิตเป็น ESRI ตัวอย่างวัตถุโทรarcpy.AsShape()(แก้ไขการอ่านรูปหลายเหลี่ยมที่มีรู (ดูจุดที่ 2 ข้างต้น) กับreturn cls(Array([map(lambda p: Point(*p) if p is not None else Point(), part) for part in coordinates])). การเปรียบเทียบเป็นเพียงการgeom1.equals(geom2)ตามที่ระบุไว้ในชั้นเรขาคณิต

ฉันคาดหวังว่าจะพบการเปลี่ยนแปลงรูปทรงเรขาคณิตประมาณ 140 ~ 140 รายการ แต่สคริปต์ของฉันยืนยันว่ามี 430 ฉันพยายามตรวจสอบการเป็นตัวแทน GeoJSON เหล่านั้นและพวกเขาเหมือนกัน แต่ Geometry Class เท่ากับ () ปฏิเสธที่จะพูดอย่างนั้น

ตัวอย่างด้านล่าง:

>>> geom1geoJSON 
{'type': 'Polygon', 'coordinates': [[(-122.8423481559999, 47.060497293000083), (-122.84239755599992, 47.059262423000064), (-122.84416913599989, 47.059309693000046), (-122.84416913599989, 47.060497293000083), (-122.8423481559999, 47.060497293000083)]]}
>>> geom2geoJSON 
{'type': 'Polygon', 'coordinates': [[(-122.8423481559999, 47.060497293000083), (-122.84239755599992, 47.059262423000064), (-122.84416913599989, 47.059309693000046), (-122.84416913599989, 47.060497293000083), (-122.8423481559999, 47.060497293000083)]]}
>>> geom1 = arcpy.AsShape(geom1geoJSON)
>>> geom2 = arcpy.AsShape(geom2geoJSON)
>>> geom1.equals(geom2)
False
>>> geom2.equals(geom1)
False

พฤติกรรมที่คาดหวังที่นี่ควรเป็นจริง (ไม่ใช่เท็จ)

ใครบ้างมีคำแนะนำก่อนที่ฉันจะย้ายทุกอย่างไปยังรูปทรงเรขาคณิตของ ogr? (ฉันลังเลในฐานะ ogr.CreateGeometryFromGeoJSON () คาดว่าจะมีสตริงและ arcpy __geo_interface__ส่งคืนพจนานุกรมและฉันรู้สึกว่าฉันกำลังเพิ่มความซับซ้อนเป็นพิเศษ)

พบแหล่งข้อมูลต่อไปนี้ที่เป็นประโยชน์แม้ว่าพวกเขาจะไม่ตอบคำถาม:

  1. คำถาม arcpy.Geometryที่นี่ใน gis.stackexchange.com ซึ่งเชื่อมโยงข้างต้นในข้อความของฉัน
  2. ข้อผิดพลาดในระดับรูปหลายเหลี่ยมของ arcpyจากฟอรัม arcgis.com (เห็นได้ชัดว่ามีข้อผิดพลาดความแม่นยำจำนวนมากใน ArcGIS 10.0 ซึ่งในทางทฤษฎีได้รับการแก้ไขใน 10.1 แต่ฉันไม่สามารถตรวจสอบได้ใน 10.0 SP5 คุณยังได้รับข้อผิดพลาด)

คำตอบ:


12

ปัญหาที่มีแนวโน้มมากที่สุดคนหนึ่งของความแม่นยำจุดลอย ในกรณีของคุณคุณได้แยกรูปทรงเรขาคณิตโดยใช้อาร์คีและคุณได้จับคู่กับ RUID ของคุณ

อย่างมีความสุขเนื่องจากคุณได้ติดตั้งอาร์คpyแล้วคุณก็มีจำนวนมากซึ่งทำให้การเปรียบเทียบชุดของตัวเลขเป็นเรื่องง่าย ในกรณีนี้ฉันขอแนะนำให้ใช้ฟังก์ชันnumpy.allcloseซึ่งมีให้ใช้ใน numpy 1.3.0 (ติดตั้งด้วย ArcGIS 10)

จากตัวอย่างที่คุณให้ไว้ข้างต้น

geom1geoJSON = {'type': 'Polygon', 'coordinates': [[(-122.8423481559999, 47.060497293000083), (-122.84239755599992, 47.059262423000064), (-122.84416913599989, 47.059309693000046), (-122.84416913599989, 47.060497293000083), (-122.8423481559999, 47.060497293000083)]]}
geom2geoJSON = {'type': 'Polygon', 'coordinates': [[(-122.8423481559999, 47.060497293000083), (-122.84239755599992, 47.059262423000064), (-122.84416913599989, 47.059309693000046), (-122.84416913599989, 47.060497293000083), (-122.8423481559999, 47.060497293000083)]]}

import numpy as np

close = np.allclose(np.array(geom1geoJSON["coordinates"]), np.array(geom2geoJSON["coordinates"]), atol=1e-7)
#Returns True

atolคำหลักที่ระบุค่าความอดทน

โปรดทราบว่าคุณไม่ควรใช้arcpy.AsShapeเลย เคย ดังที่ฉันได้กล่าวไว้ในคำถามนี้ (/ shameless plug) มีข้อผิดพลาดที่รู้จักกันใน ArcGIS ที่ตัดทอนรูปทรงเรขาคณิตเมื่อสร้างขึ้นโดยไม่มีระบบพิกัด (แม้หลังจากการตั้งค่าenv.XYToleranceตัวแปรสภาพแวดล้อม) ในarcpy.AsShapeไม่มีวิธีที่จะหลีกเลี่ยงสิ่งนี้ โชคดีที่geometry.__geo_interface__ดึงรูปทรงเรขาคณิตที่ถูกต้องออกจากรูปทรงเรขาคณิตที่มีอยู่ (แม้ว่ามันจะไม่จัดการรูปหลายเหลี่ยมที่ซับซ้อนโดยไม่ต้องแก้ไขจาก @JasonScheirer)


ขอขอบคุณ. ฉันไม่คิดว่าจะใช้สิ่งที่มีค่าในการทำสิ่งนี้ โซลูชันอื่นดูเหมือนว่าจะใช้โมดูลทศนิยมและทำงานผ่านสิ่งนั้น แต่ต้องใช้งานมากกว่านี้มาก
Michalis Avraam

ฉันคิดว่ามันเป็นสิ่งสำคัญที่จะตั้งค่าnumpy.allclose() rtolพารามิเตอร์เป็น 0 โดยค่าเริ่มต้นคือ 1e-05 และสามารถนำไปสู่ความอดทนมากถ้าค่าอาร์เรย์มีขนาดใหญ่ดู: stackoverflow.com/a/57063678/1914034
ใต้ Radar

11

ความแม่นยำในการประสานงานจะเป็นสิ่งสำคัญในการพิจารณา ไม่สามารถเก็บหมายเลขทศนิยมได้อย่างแน่นอน

หากคุณใช้เครื่องมือเปรียบเทียบคุณสมบัติจะเกิดขึ้นกับผลลัพธ์ที่คาดหวังโดยใช้ค่าเผื่อ XY เริ่มต้นหรือไม่


ฉันไม่ได้ตรวจสอบเครื่องมือการเปรียบเทียบคุณสมบัติเป็นเครื่องมือที่ฉันสร้างขึ้นจริง ๆ แล้วเปรียบเทียบคุณสมบัติแต่ละอย่างที่ย้ายระหว่างคลาสฟีเจอร์ที่แตกต่างกัน กล่าวคือฟีเจอร์สามารถย้ายจาก CityRoads ไปเป็น CountyRoads ดังนั้นฉันต้องคิดออกว่ามีอะไรเปลี่ยนแปลงในรูปทรงเรขาคณิตและคุณลักษณะอื่น ๆ นอกเหนือจากคลาสคุณลักษณะที่เก็บไว้ มีคลาสคุณลักษณะทั้งหมด 24 คลาสและคุณลักษณะสามารถย้ายระหว่างคลาส การเปรียบเทียบคุณสมบัติจะเปรียบเทียบคลาสฟีเจอร์เพียง 2 คลาสดังนั้นจึงสามารถบอกได้ว่ามันไม่มีอยู่ใน FC อีกต่อไป จากนั้นฉันยังจำเป็นต้องเปรียบเทียบคุณลักษณะเพื่อให้แน่ใจว่ามันจะไม่เปลี่ยนแปลง
มิคาลิสอาวารัม

ฉันตรวจสอบเครื่องมือเปรียบเทียบคุณสมบัติด้วยค่าเผื่อเริ่มต้น (8.983e-009 ซึ่งค่อนข้างเล็ก แต่เป็นไฟล์ GDB) และรายงานการเปลี่ยนแปลงบางอย่าง แต่ไม่ใช่ค่าที่เหมาะสม โดยเฉพาะมันบอกว่ามีการเปลี่ยนแปลงทางเรขาคณิต 69 แบบ (ฉันเดาได้ดีกว่า แต่ก่อน) แต่ดูเหมือนว่าสมมติว่า OID เป็นวิธีการระบุคุณลักษณะเฉพาะ (ค้นหา OID1 เก่าและ OID1 ใหม่) ซึ่งไม่จำเป็นต้องเป็นจริง (ฉันได้ตั้งค่าให้ใช้ RUID ของฉันเป็นแบบเรียงลำดับ แต่ไม่ชอบ) ดังนั้นกลับไปที่กระดานวาดภาพ
Michalis Avraam

4

ข้าง @ blah328 คำตอบให้คุณเลือก hava เพื่อเปรียบเทียบสองตารางสำหรับการรายงานความแตกต่างและความคล้ายคลึงกันกับค่านิยมแบบตารางและคำจำกัดความของเขตข้อมูลที่มีตารางเปรียบเทียบ

ตัวอย่าง:

import arcpy
from arcpy import env
arcpy.TableCompare_management(r'c:\Workspace\wells.dbf', r'c:\Workspace
\wells_new.dbf', 'WELL_ID', 'ALL', 'IGNORE_EXTENSION_PROPERTIES', 'WELL_DEPTH 0.001',
'#','CONTINUE_COMPARE', r'C:\Workspace\well_compare.txt' 

ขอบคุณฉันจะตรวจสอบมันเมื่อฉันพยายามเปรียบเทียบข้อมูลคุณลักษณะ ตอนนี้ดูเหมือนว่าฉันไม่สามารถเปรียบเทียบรูปทรงเรขาคณิตซึ่งมีความสำคัญมากกว่า
Michalis Avraam

3
def truncateCoordinates(myGeometry)
    trucated_coords = []
    partnum = 0

    for part in (myGeometry):
        for pnt in myGeometry.getPart(partnum):
            if pnt:
                trucated_coords.append("{:10.4f}".format(pnt.X))
                trucated_coords.append("{:10.4f}".format(pnt.Y))
             else:
                continue
        partnum += 1     
    return truncated_coords

หาก.equals()ฟังก์ชันไม่ทำงานตามที่คาดไว้และ / หรือพิกัดมีการเปลี่ยนแปลงเล็กน้อยใน ArcGIS คุณสามารถนวดพิกัด XY แล้วเปรียบเทียบค่าสตริงเทียบเท่าของเรขาคณิต สังเกตเห็นtruncateCoordinates()ตัดค่าทั้งหมดที่เกินทศนิยม 4

geom1 = truncateCoordinates(feature1.Shape)
geom2 = truncateCoordinates(feature2.Shape)

geom1 == geom2

@ klewis- นั่นเป็นวิธีหนึ่งในการเปรียบเทียบรูปทรงเรขาคณิต แต่มันให้ความรู้สึกเหมือน geometry.equals (รูปทรงเรขาคณิต) ควรจะกลับมาจริงเมื่อคุณเปรียบเทียบรูปทรงเรขาคณิตที่เหมือนกัน การตัดทอนพิกัดเป็นการแฮ็คอย่างหนึ่ง บางที ESRI ต้องเริ่มใช้ทศนิยม () แทนการลอยถ้าพวกเขาไม่สามารถจัดการค่าทศนิยมได้อย่างถูกต้องภายใน แต่สามารถแสดงว่ามันเป็นสตริงที่เท่ากัน
Michalis Avraam

1

คุณสามารถใช้เครื่องมือเลือกเลเยอร์ตามตำแหน่ง (การจัดการข้อมูล)กับพารามิเตอร์ "ARE_IDENTICAL_TO" overlap_type สลับการเลือกตรวจสอบการนับจำนวนแถวจากนั้นวนรอบแถวเพื่อรวบรวมวัตถุหรือข้อมูลอื่น ๆ ที่เกี่ยวข้อง

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