การฉาย Ortho ผลิตสิ่งประดิษฐ์


14

ฉันกำลังพยายามสร้างมุมมองคล้ายทรงกลมโดยใช้ qgis และ "โลกจากอวกาศ" -project http://spatialreference.org/ref/sr-org/6980/ (จำเป็นต้องฉาย Ortho) ArcGIS ล้อมรูปร่างได้อย่างถูกต้อง แต่ QGIS (2.01) สร้างสิ่งประดิษฐ์ที่น่ารังเกียจ

ป้อนคำอธิบายรูปภาพที่นี่

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


1
รายงานข้อผิดพลาดเกี่ยวกับ QGIS ที่เกี่ยวข้อง: hub.qgis.org/issues/2703
naught101

เป็นปัญหาทางเทคนิคที่ใหญ่เกินไปหรือไม่ที่จะมีการฉายภาพ orthographic ล่วงหน้าล่วงหน้าซึ่งสามารถกลับไปที่มุมมองใด ๆ

นี่ไม่ได้ตอบคำถาม โปรดทัวร์เพื่อเรียนรู้วิธีถามคำถามที่เพ่งความสนใจไป
John Powell

คำตอบ:


23

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

นี่คือสคริปต์ (ตอนนี้ยังมีให้ใช้ในรูปแบบปลั๊กอิน Clip to Hemisphere QGIS ) ที่ใช้วิธีการที่แตกต่างกันเล็กน้อย: เลเยอร์เลเยอร์ถูกสร้างขึ้นในระบบอ้างอิงพิกัดพิกัดของไฟล์ต้นฉบับดั้งเดิมโดยฉายวงกลมจาก orthographic ไปยังแหล่ง CRS ตรวจสอบให้แน่ใจว่าครอบคลุมทั้งซีกโลกที่มองเห็นได้รวมถึงเสาที่มองเห็นได้

นี่คือลักษณะของเลเยอร์การเล็มภาพสำหรับการฉายภาพออโทกราฟเชิงกึ่งกลางที่ 30 ° N, 110 ° E:

จากนั้นสคริปต์คลิปเลเยอร์ที่เลือกในปัจจุบันด้วยเลเยอร์เล็มและเพิ่มเลเยอร์ที่เป็นผลลัพธ์ให้กับโครงการ เลเยอร์นั้นจะสามารถฉายภาพไปยังออโธกราฟฟิคได้ไม่ว่าจะเป็นการบินหรือโดยการบันทึกในออร์โธกราฟซีอาร์ซีเอส:

นี่คือสคริปต์ ตรวจสอบให้แน่ใจว่าได้บันทึกไว้ในพา ธ Python ของคุณเช่น 'cliportho.py' จากนั้นคุณสามารถนำเข้าในคอนโซล QGIS import cliporthoหลามใช้ cliportho.doClip(iface, lat=30, lon=110, filename='A.shp')คลิปชั้นโทร


import numpy as np
from qgis.core import *
import qgis.utils

import sys, os, imp


def doClip(iface, lat=30, lon=110, filename='result.shp'):
    sourceLayer = iface.activeLayer()

    sourceCrs = sourceLayer.dataProvider().crs()

    targetProjString = "+proj=ortho +lat_0=" + str(lat) + " +lon_0=" + str(lon) + "+x_0=0 +y_0=0 +a=6370997 +b=6370997 +units=m +no_defs"
    targetCrs = QgsCoordinateReferenceSystem()
    targetCrs.createFromProj4(targetProjString)

    transformTargetToSrc = QgsCoordinateTransform(targetCrs, sourceCrs).transform

    def circlePolygon(nPoints=20, radius=6370000, center=[0,0]):
        clipdisc = QgsVectorLayer("Polygon?crs=epsg:4326", "Clip disc", "memory")
        angles = np.linspace(0, 2*np.pi, nPoints, endpoint=False)
        circlePoints = np.array([ transformTargetToSrc(QgsPoint(center[0]+np.cos(angle)*radius, center[1]+np.sin(angle)*radius)) for angle in angles ])
        sortIdx = np.argsort(circlePoints[:,0])
        circlePoints = circlePoints[sortIdx,:]
        circlePoints = [ QgsPoint(point[0], point[1]) for point in circlePoints ]
        circlePoints.extend([QgsPoint(180,circlePoints[-1][1]), QgsPoint(180,np.sign(lat)*90), QgsPoint(-180,np.sign(lat)*90), QgsPoint(-180,circlePoints[0][1])])
        circle = QgsFeature()
        circle.setGeometry(QgsGeometry.fromPolygon( [circlePoints] ) )
        clipdisc.dataProvider().addFeatures([circle])
        QgsMapLayerRegistry.instance().addMapLayer(clipdisc)
        return clipdisc

    auxDisc = circlePolygon(nPoints = 3600)

    ###### The clipping stuff
    ## Code taken from the fTools plugin

    vproviderA = sourceLayer.dataProvider()
    vproviderB = auxDisc.dataProvider()

    inFeatA = QgsFeature()
    inFeatB = QgsFeature()
    outFeat = QgsFeature()

    fitA = vproviderA.getFeatures()

    nElement = 0  
    writer = QgsVectorFileWriter( filename, 'UTF8', vproviderA.fields(),
                                  vproviderA.geometryType(), vproviderA.crs() )

    index = QgsSpatialIndex()
    feat = QgsFeature()
    index = QgsSpatialIndex()
    fit = vproviderB.getFeatures()
    while fit.nextFeature( feat ):
        index.insertFeature( feat )

    while fitA.nextFeature( inFeatA ):
      nElement += 1
      geom = QgsGeometry( inFeatA.geometry() )
      atMap = inFeatA.attributes()
      intersects = index.intersects( geom.boundingBox() )
      first = True
      found = False
      if len( intersects ) > 0:
        for id in intersects:
          vproviderB.getFeatures( QgsFeatureRequest().setFilterFid( int( id ) ) ).nextFeature( inFeatB )
          tmpGeom = QgsGeometry( inFeatB.geometry() )
          if tmpGeom.intersects( geom ):
            found = True
            if first:
              outFeat.setGeometry( QgsGeometry( tmpGeom ) )
              first = False
            else:
              try:
                cur_geom = QgsGeometry( outFeat.geometry() )
                new_geom = QgsGeometry( cur_geom.combine( tmpGeom ) )
                outFeat.setGeometry( QgsGeometry( new_geom ) )
              except:
                GEOS_EXCEPT = False
                break
        if found:
          try:
            cur_geom = QgsGeometry( outFeat.geometry() )
            new_geom = QgsGeometry( geom.intersection( cur_geom ) )
            if new_geom.wkbType() == 0:
              int_com = QgsGeometry( geom.combine( cur_geom ) )
              int_sym = QgsGeometry( geom.symDifference( cur_geom ) )
              new_geom = QgsGeometry( int_com.difference( int_sym ) )
            try:
              outFeat.setGeometry( new_geom )
              outFeat.setAttributes( atMap )
              writer.addFeature( outFeat )
            except:
              FEAT_EXCEPT = False
              continue
          except:
            GEOS_EXCEPT = False
            continue
    del writer

    resultLayer = QgsVectorLayer(filename, sourceLayer.name() + " - Ortho: Lat " + str(lat) + ", Lon " + str(lon), "ogr")
    QgsMapLayerRegistry.instance().addMapLayer(resultLayer)

ดูมีแนวโน้มมาก - ฉันจะลองทำอย่างนี้และยินดีให้คำติชม I`ma เล็กน้อยในการเขียนโปรแกรม arcpy แต่ยังไม่ได้เริ่มต้นด้วยการเขียนโปรแกรม qgis - แต่ฉันจะพยายามเข้าใจสิ่งที่คุณกำลังทำ ;-) ปลั๊กอิน (อาจทำงานเป็นชุดหลายชั้น) จะเป็นประโยชน์มาก!
user1523709

1
FYI, สคริปต์นี้ไม่ทำงานใน QGIS 2.16 อีกต่อไปเนื่องจากการลบแพคเกจ "fTools"
Spike Williams

2
@SpikeWilliams: ฉันได้อัปเดตสคริปต์เพื่อลบการพึ่งพา fTools
Jake

5

คุณต้องครอบตัดข้อมูลรูปหลายเหลี่ยมของคุณไปครึ่งโลกที่มองเห็นเพราะ QGIS ไม่ได้ทำด้วยตัวเอง

ฉันเขียนบทช่วยสอนที่นี่:

รูปหลายเหลี่ยมหายไปไหนหลังจากฉายแผนที่ใน QGIS?


แก้ไข

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

QGIS แสดงไฟล์ข้อมูลรูปร่างของประเทศโลกกลางทะเลมหาสมุทรแปซิฟิกโดยใช้ Robinson, Miller Cylindrical หรือการฉายภาพอื่น ๆ


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

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