0

generate_tiles.pyを使用してタイルを作成しようとしていますが、スクリプトを実行するたびに、次のエラーが発生します。

スレッドThread-2の例外:トレースバック(最後の最後の呼び出し):ファイル "/usr/lib/python2.7/threading.py"、行552、__ bootstrap_inner self.run()ファイル "/ usr / lib/python2。 7 / threading.py "、行505、実行中self .__ target(* self .__ args、** self .__ kwargs)ファイル" render_tiles.py "、行114、ループ内self.render_tile(tile_uri、x、y、z )ファイル "render_tiles.py"、96行目、render_tile mapnik.render(self.m、im)MemoryError

これが私のスクリプトです。

#!/ usr / bin / python
数学からインポートpi、cos、sin、log、exp、atan
サブプロセスインポート呼び出しから
sys、osをインポートします
キューからインポートキュー
mapnikをインポートする
スレッドのインポート
ランダムにインポート
argparseをインポートします

custom_fonts_dir ='/ usr / share / fonts /'
mapnik.register_fonts(custom_fonts_dir)

DEG_TO_RAD = pi / 180
RAD_TO_DEG = 180 / pi

#生成するレンダリングスレッドのデフォルト数。使用可能なCPUコアの数とほぼ同じである必要があります。
NUM_THREADS = 4

def minmax(a、b、c):
    a = max(a、b)
    a = min(a、c)
    を返す

クラスGoogleProjection:
    def __init __(self、levels = 18):
        self.Bc = []
        self.Cc = []
        self.zc = []
        self.Ac = []
        c = 256
        range(0、levels)のdの場合:
            e = c / 2;
            self.Bc.append(c / 360.0)
            self.Cc.append(c /(2 * pi))
            self.zc.append((e、e))
            self.Ac.append(c)
            c * = 2

    def fromLLtoPixel(self、ll、zoom):
         d = self.zc [int(zoom)]
         e = round(d [0] + float(ll [0])* self.Bc [zoom])
         f = minmax(sin(DEG_TO_RAD * float(ll [1]))、-0.9999,0.9999)
         g = round(d [1] + 0.5 * log((1 + f)/(1-f))*-self.Cc [zoom])
         戻る(例)

    def fromPixelToLL(self、px、zoom):
         e = self.zc [zoom]
         f =(px [0]-e [0])/ self.Bc [zoom]
         g =(px [1] --e [1])/-self.Cc [zoom]
         h = RAD_TO_DEG *(2 * atan(exp(g))-0.5 * pi)
         return(f、h)



クラスRenderThread:
    def __init __(self、tile_dir、mapfile、q、printLock、maxZoom):
        self.tile_dir = tile_dir
        self.q = q
        self.m = mapnik.Map(256、256)
        self.printLock = printLock
        #スタイルXMLをロード
        mapnik.load_map(self.m、mapfile)
        #投影を取得する
        self.prj = mapnik.Projection(self.m.srs)
        #タイルピクセル座標とLatLongの間のプロジェクト(EPSG:4326)
        self.tileproj = GoogleProjection(maxZoom + 1)


    def render_tile(self、tile_uri、x、y、z):
        #左下と右上のピクセル位置を計算します
        p0 =(x * 256、(y + 1)* 256)
        p1 =((x + 1)* 256、y * 256)

        #LatLongに変換(EPSG:4326)
        l0 = self.tileproj.fromPixelToLL(p0、z);
        l1 = self.tileproj.fromPixelToLL(p1、z);

        #地図投影法に変換する(例:メルカトルコーディネイトEPSG:900913)
        c0 = self.prj.forward(mapnik.Coord(l0 [0]、l0 [1]))
        c1 = self.prj.forward(mapnik.Coord(l1 [0]、l1 [1]))

        #タイルのバウンディングボックス
        hasattr(mapnik、'mapnik_version')およびmapnik.mapnik_version()> = 800の場合:
            bbox = mapnik.Box2d(c0.x、c0.y、c1.x、c1.y)
        そうしないと:
            bbox = mapnik.Envelope(c0.x、c0.y、c1.x、c1.y)
        render_size = 256
        self.m.resize(render_size、render_size)
        self.m.zoom_to_box(bbox)
        self.m.buffer_size = 128

        #デフォルトのAggレンダラーで画像をレンダリングする
        im = mapnik.Image(render_size、render_size)
        mapnik.render(self.m、im)
        im.save(tile_uri、'png256')


    def loop(self):
        Trueの場合:
            #キューからタイルを取得してレンダリングします
            r = self.q.get()
            if(r == None):
                self.q.task_done()
                壊す
            そうしないと:
                (名前、tile_uri、x、y、z)= r

            存在する=""
            os.path.isfile(tile_uri)の場合:
                存在する="存在する"
            そうしないと:
                self.render_tile(tile_uri、x、y、z)
            bytes = os.stat(tile_uri)[6]
            empty =''
            バイト==103の場合:
                empty="空のタイル"
            self.printLock.acquire()
            印刷名、 ":"、z、x、y、存在、空
            self.printLock.release()
            self.q.task_done()



def render_tiles(bbox、mapfile、tile_dir、minZoom = 1、maxZoom = 18、name = "unknown"、num_threads = NUM​​_THREADS):
    print "render_tiles("、bbox、mapfile、tile_dir、minZoom、maxZoom、name、 ")"

    #レンダリングスレッドを起動する
    queue = Queue(32)
    printLock = threading.Lock()
    レンダラー={}
    範囲内のiの場合(num_threads):
        レンダラー=RenderThread(tile_dir、mapfile、queue、printLock、maxZoom)
        render_thread = threading.Thread(target = renderer.loop)
        render_thread.start()
        #print "開始されたレンダリングスレッド%s"%render_thread.getName()
        renderers [i] = render_thread

    os.path.isdir(tile_dir)でない場合:
         os.mkdir(tile_dir)

    gprj = GoogleProjection(maxZoom + 1)

    ll0 =(bbox [0]、bbox [3])
    ll1 =(bbox [2]、bbox [1])

    範囲内のzの場合(minZoom、maxZoom + 1):
        px0 = gprj.fromLLtoPixel(ll0、z)
        px1 = gprj.fromLLtoPixel(ll1、z)
        「fromlattolon」を印刷

        #ディレクトリが配置されているかどうかを確認します
        ズーム="%s"%z
        os.path.isdir(tile_dir +ズーム)でない場合:
            os.mkdir(tile_dir +ズーム)
        範囲内のxの場合(int(px0 [0] /256.0),int(px1[0]/256.0)+1):
            #x座標を検証する
            if(x = 2 ** z):
                継続する
            #ディレクトリが配置されているかどうかを確認します
            str_x = "%s"%x
            そうでない場合os.path.isdir(tile_dir + Zoom +'/' + str_x):
                os.mkdir(tile_dir+ズーム+'/' + str_x)
            範囲内のyの場合(int(px0 [1] /256.0),int(px1[1]/256.0)+1):
                #x座標を検証する
                if(y = 2 ** z):
                    継続する
                str_y = "%s"%y
                tile_uri = tile_dir + Zoom +'/' + str_x +'/' + str_y +'.png'
                #キューにレンダリングするタイルを送信する
                t =(name、tile_uri、x、y、z)
                queue.put(t)

    #空のリクエストをキューに送信して、レンダリングスレッドに終了するように通知します
    範囲内のiの場合(num_threads):
        queue.put(なし)
    #保留中のレンダリングジョブが完了するのを待つ
    queue.join()
    範囲内のiの場合(num_threads):
        レンダラー[i].join()



__name__ == "__main__"の場合:
    MIN_LON = '29.5732';
    MAX_LON = '35.0360';
    MIN_LAT ='-1.4840';
    MAX_LAT = '4.2144';
    bbox =(MIN_LON、MIN_LAT、MAX_LON、MAX_LAT)
    style_file = "/ home / mossplix / projects / Dev / mapit / map / static / tilemill / uganda_districts.xml"
    tile_dir = "/ home / mossplix / projects / UnicefDev / mapit / map / static / tiles /"
    min_zoom = 7
    max_zoom = 14
    render_tiles(bbox、style_file、tile_dir、min_zoom、max_zoom)

これがmapnik設定ファイル mapnikconfig で、これが シェープファイルです。私はソースからmapnikをコンパイルしたので、それは良いはずです。何が問題なのか?

4

2 に答える 2

3

generate_tiles.pyもともと少し変更されていることがわかります。

MemoryErrorは、異常に大きな画像のレンダリングを要求しているか、Mapnikのバグを発見したことを示します。

前者の方が可能性が高いので、の変更中に間違えたと思いますgenerate_tiles.py。だから私はあなたのスクリプトを取り、svnの最新バージョンを上書きし、違いの差分を取り出しました:https ://gist.github.com/1197587 。

行#106および#115では、使用したく==ない可能性があります。そうしない=と、非常に大きなx値とy値が無効になり、非常に大きな画像要求の原因となる可能性があります(特定のタイルでは間違っています)。

于 2011-09-06T14:03:06.997 に答える
0

生成するレンダリングスレッドのデフォルト数は、使用可能なCPUコアの数とほぼ同じである必要がありますNUM_THREADS = 4

NUM_THREADS=4でもまったく同じエラーが発生しました。NUM_THREADSのデフォルト値を1に変更します。i5(4コア/ 1スレッド/コア)があり、NUM_THREADS=4は非常に不安定です。NUM_THREADS = 1の場合、正常に機能します。NUM_THREADS = 1で動作する場合は、何もクラッシュしない場合はNUM_THREADS=2およびNUM_THREADS=3で試してください。

于 2013-05-23T13:28:18.253 に答える