LoginSignup
2
1

More than 3 years have passed since last update.

Maya + pyshp でシェープファイル (.shp)を取り込む

Last updated at Posted at 2019-05-25

CGソフトにShapefileを取り込みたい

建築系CGプロダクションで働く3DCGモデラーです。

建築CGを制作していると、時々、シェープファイル(.shp)をCGソフトに取り込みたい時があります。
地図なんかを取り込みたいときです。
GIS系のソフトは持ってないけど、何かお手軽に取り込むことは出来ないか?
というときに使える方法を紹介します。

Python + pyshp

CG系のソフトはスクリプティング環境としてPythonを使えることが多いです。
Pythonには pyshp というシェープファイルを扱うライブラリがあるので、それを使って.shpファイルを取り込めます。
pyshp

Maya

この記事ではMayaに.shpファイルを取り込み、Curveとして描画する方法について書きます。

pyshpをMayaへインストール

まず、Maya上のPythonである、"mayapy"にpyshpをインストールします。

install.bat
cd "C:\Program Files\Autodesk\Maya2018\bin"
"mayapy.exe" -m pip install "C:\Users\Takeharu\Documents\maya\3rdParty\pyshp-2.1.0.tar.gz"

スクリプティング

そしてMaya用のPythonスクリプト。

import_shapefile.py

# -*- coding: utf-8 -*-
import pymel.core as pm
import shapefile
import os.path

#  ファイルオープンダイアログ
def get_file():
    startdir = ''
    if pm.optionVar( exists='defaultStarDirectoryOfImportShapefile' ):
        startdir = pm.optionVar( q='defaultStarDirectoryOfImportShapefile' )
    else:
        startdir = 'C:/Users/Takeharu/Documents'
    fn = pm.fileDialog2(fileMode=1, caption="Open Shape File...", fileFilter="*.shp", startingDirectory=startdir, okCaption='Open')
    pm.optionVar( sv=('defaultStarDirectoryOfImportShapefile', os.path.dirname(fn[0])) )
    return fn[0]



file_path = get_file()  # ファイルパス取得
with open(file_path, "rb") as myshp:  #  ファイルを開く
    r = shapefile.Reader(shp = myshp)  # リーダー
    if len(r.shapes()):
        pm.refresh(suspend=True)
        grp = pm.group(empty=1,name='shp_group0')
        crvs = []
        for s in r.shapes():
            t = s.shapeType
            if t == 3 or t == 5:  # 今回は地図をCurveで描画したいだけなので、シェイプのタイプを 3:Polyline5:Polygonに限定します。
                mapped = map(lambda x: x+(0.0,), s.points)  # 元が2D座標データなので、Z軸座標を追加して3次元座標に変換します。
                crv = None
                if len(s.parts) == 1:
                    crv = pm.curve(p=mapped,d=1)
                    crvs.append(crv)
                else:  # ひとつのシェイプに複数のPolygonが含まれることがあります。それ切り分けます。
                       # parts`が[0,256,150] みたいなリストなら、複数のオブジェクトを内包しています。
                       # 数字は座標リストの区切りです。
                    for i in range(0,len(s.parts)-1):  
                        pnts = []
                        pnts = mapped[s.parts[i]:s.parts[i+1]]
                        crv = pm.curve(p=pnts,d=1)
                        crvs.append(crv)
                    crv = pm.curve(p=mapped[s.parts[-1]:],d=1)
                    crvs.append(crv)

        pm.parent(crvs,grp)
        g = grp.getParent()
        pm.select(grp,r=1)
        pm.rotate(g, [-90.0,0,0]) # MayaY-Upに合わせて全体を回転します。
        pm.viewFit( pm.selected())
        pm.refresh(suspend=False)

    for c in pm.ls(cameras=1): # 地図の場合、巨大な図形となるので、カメラのクリッピングプレーンを調整します。
        c.setFarClipPlane(1000000)
        c.setNearClipPlane(1)


# ※コピペするときは、使う前にコメントを全部削除してください。
シェルフボタン

import sys
if 'terrain.import_shapefile' in sys.modules:
    reload(terrain.import_shapefile)
else:
    import terrain.import_shapefile

道路のデータを取り込んでみた状態
sct20190524091323.png
元データが大きいと、結構時間がかかります。時に数時間かかることもあります。
一見、フリーズしたように見えても放っておけばそのうち終わります。
それがMaya。

Mayaの単位の話

Mayaの単位について知っておくといいと思います。
MayaはCADソフトなどに比べて内部精度が低いです。
そのため、原点から遠く離れた位置に図形を描画するのが苦手です。

GIS系のデータであるシェープファイルは、この "原点から遠く離れた位置" に座標を持つことが珍しくありません。
これをMayaのデフォルト単位であるcmに変換して取り込もうとすると、描画エラーになることがあります。

詳しいことはわかりませんが、"桁落ち"とかそういう類のエラーだと思われます。
DXF/DWGを取り込もうとして、なぜか図が出てこないようなときはこれかもしれません。

面倒を避けたいなら、1ユニット = 1cm ではなく、1ユニット = 1m に読み換えて作業するといいです。
取り込み後に、原点の近くにオブジェクトを移動させてしまえば、その後はスケールを修正しても大丈夫です。

2
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
1