Ortho Projection eser üretiyor


14

Ben qgis ve "uzaydan dünya" kullanarak bir küre benzeri görünüm oluşturmaya çalışıyorum -projection http://spatialreference.org/ref/sr-org/6980/ (aslında bir orto-projeksiyon). ArcGIS şekilleri doğru bir şekilde sarar ancak QGIS (2.01) kötü eserler üretir.

resim açıklamasını buraya girin

Yerküreleri farklı açılardan düzenli olarak üretmeliyim, bu yüzden dışarıdaki herkes bu sorunu nasıl çözeceğine dair bir fikre sahip mi?


1
ilgili QGIS hata raporu: hub.qgis.org/issues/2703
naught101

Önceden yüklenmiş ortografik bir projeksiyona sahip olmak, herhangi bir görünüme yeniden merkezlenebilecek teknik bir sorun mu?

Bu soruya cevap vermiyor. Odaklanmış bir soruyu nasıl soracağınızı öğrenmek için lütfen tura katılın.
John Powell

Yanıtlar:


23

Andre'nin dediği gibi, bunun çalışması için, katmanınızı yansıtmadan önce kırpmanız gerekir. Andre , birçok durumda iyi çalışan manuel bir yöntemi açıklar : Şekil dosyanızı, ortografik projeksiyon ile aynı parametrelerle azimuthal eşitlikli bir projeksiyona yansıtın, ortografik projeksiyonda görünecek yarım küreyi kaplayan bir kırpma dairesi oluşturun ve bununla şekil dosyasını kırpın. Bununla birlikte, bu yöntem oldukça az manuel çaba gerektirir ve tüm projeksiyon parametreleri için işe yaramaz, çünkü azimuthal eşitlikli bir projeksiyona yansıtmak, bir ortografik projeksiyona yansıtmak gibi benzer sorunlara yol açabilir.

İşte biraz farklı bir yaklaşım gerektiren bir komut dosyası (artık Clip to Hemisphere QGIS eklentisi olarak da kullanılabilir ): Ortografikten kaynak CRS'ye bir daire yansıtarak orijinal şekil dosyasının koordinat referans sisteminde bir kırpma katmanı oluşturulur. görünür kutup dahil olmak üzere tüm görünür yarımküreyi kapladığınızdan emin olun.

30 ° N, 110 ° E merkezli bir ortografik projeksiyon için kırpma katmanı şöyle görünür:

Komut dosyası daha sonra seçili katmanı kırpma katmanıyla klipsler ve ortaya çıkan katmanı projeye ekler. Bu katman daha sonra ortografik projeksiyona anında veya ortografik CRS'ye kaydedilerek yansıtılabilir:

İşte senaryo. Python yolunuza kaydettiğinizden emin olun, örneğin 'cliportho.py'. Ardından kullanarak QGIS Python konsoluna aktarabilirsiniz import cliportho. Bir katmanı kırpmak için arayın 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)

Çok ümit verici görünüyor - kesinlikle bunu deneyeceğim ve geribildirim vermekten mutluluk duyacağım. Ben Arcpy programlama içine biraz ama qgis programlama ile başlamamış - ama ne yaptığını anlamaya çalışacağım ;-) Bir eklenti (belki birkaç katman için toplu çalışma) çok yararlı olacaktır!
user1523709

1
Bilginize, Bu komut dosyası artık "fTools" paketinin kaldırılması nedeniyle QGIS 2.16'da çalışmaz.
Spike Williams

2
@SpikeWilliams: Komut dosyasını fTools'a olan bağımlılığı kaldırmak için güncelledim.
Jake

5

Çokgen verilerinizi dünyanın görünür yarısına kırpmanız gerekir, çünkü QGIS bunu tek başına yapmaz.

Burada bir eğitim yazdım:

QGIS'de bir harita tasarladıktan sonra çokgenler nereye gitti?


DÜZENLE

Gösterdiğiniz resim aslında tüm dünyayı gösterdiği gibi bir orto projeksiyonu değil, sadece uzaydan görüldüğü gibi görünür yarısı değil. Dünya haritaları için, burada açıklandığı gibi kesim biraz daha kolaydır:

QGIS, Robinson, Miller Cylindrical veya diğer projeksiyonları kullanarak pasifik okyanusu merkezli dünya ülke şekil dosyalarını görüntüler


Teşekkürler Andre, bu sorunu anlamak için oldukça yardımcı oldu - ama bu tür küreleri neredeyse günlük olarak oluşturmam gerektiğinden ve değişen perspektiflerle çok fazla manuel çalışma gerektiriyor. Herhangi bir eklenti vb biliyor musunuz. otomatikleştirmek için?
user1523709

Bir kırpma çemberi oluşturduktan sonra, geri kalanı bir toplu komut dosyası kullanılarak komut satırı düzeyinde GDAL kullanılarak yapılabilir.
AndreJ
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.