チュートリアル 10: Python スクリプティング

チュートリアル データ

チュートリアル データは、[Help] メニュー → [Download Tutorials and Examples…] を選択し、[CityEngine Tutorial] からダウンロードできます。

概要

Python スクリプト インターフェイスを利用すると、CityEngine の可能性をより広げることができます。このチュートリアルでは、Python Console および Editor の基本的な使用方法を解説し、CityEngine タスクの自動化の例を 2 つ紹介します。詳細については CityEngine Python reference をご参照ください。

なお、Python スクリプト インターフェイス は、すべてのバージョンの CityEngine で利用できるわけではありません。

演習
Part 1: Python Console および Editor
Part 2: 道路幅の変更
Part 3: FBX ファイルからのカメラ設定
Part 4: 建物の変化アニメーション
Part 5: アセット ライブラリ ルール ファイルの作成
Part 6: startup.py を用いた CityEngine タスクの自動化

Part 1: Python Console および Editor

チュートリアルのセットアップ

  1. Tutorial_10_Python_Scripting を自分の CityEngine ワークスペースにインポートします。
  2. [Scene] フォルダーから、Tutorial_10_Python_Scripting/scenes/01_PythonScripting.cej を開きます。

Python Console

新規 Python Console ウィンドウを起動します。

  1. [Window] メニュー → [Console] から [Console] ウィンドウを開きます。
  2. ツールバーの右端にある小さな三角形から [Python Console] ウィンドウを開きます。

最初の CityEngine Python コマンドとして、シーン要素を固有の名前ですばやく選択する方法を紹介します。

  1. はじめに、以下のコマンドをタイプします。
ce.setSelection

タイプ中に Ctrl+Space キーを押すとコマンド補完のポップアップが表示されます。

  1. 以下のコマンドをタイプします。
ce.setSelection(ce.getObjectsFrom(ce.scene, ce.withName("*Broadway*")))
  1. Enter を押してコマンドを実行します。
    これにより、名前に Broadway を含むすべてのシーン要素が選択されます。

Python Editor

より長く、より高度な Python コマンド、あるいはコマンド群を使おうと思ったら、すぐに CityEngine の Python Editor を使うのが便利です。

  1. [File] メニュー → [New…][Python Module] から新規 Python スクリプトを作成します。Python モジュール ダイアログで、プロジェクト内の scripts フォルダーを選択します。

  2. 新しい Python モジュールに対する名前として [Name] に「myHelpers」と入力します。

  3. [Finish] をクリックします。

  4. [Template] ポップアップで [Module:Main] を選択します。

  5. [OK] をクリックします。
    Python モジュール myHelpers が CityEngine に組み込まれた [Python Editor] ウィンドウに開いたはずです。

ce = CE () の行の後に、新しい関数 selectByAttribute (attr, value) を追加します。

def selectByAttribute(attr, value):
    objects = ce.getObjectsFrom(ce.scene)
    selection = []
    for o in objects:
        attrvalue = ce.getAttribute(o, attr)
        if attrvalue  ==  value:
            selection.append(o)
        
    ce.setSelection(selection)

そしてこれをスクリプトの main 文の中で特定のパラメーターとともに使用します。

if __name__ == '__main__':
    selectByAttribute("connectionStart","JUNCTION")

[Python] メニュー → [Run Script] をクリックするか、[Python Editor] ウィンドウ内で F9キーを押し、スクリプトを実行します。

Console からのスクリプト実行

別の方法として、Helper スクリプトを Python Console から呼び出すことができます。

  1. [Python Console] ウィンドウで、システムパスに自分のモジュールへのパスを追加します。
  2. モジュールをインポートします。
>>> sys.path.append(ce.toFSPath("scripts"))
>>> import myHelpers
  1. これで以下の方法により、Console に MyHelpers 関数を任意のパラメーターで呼び出せるようになりました。
>>> myHelpers.selectByAttribute("connectionEnd", "JUNCTION")

scripting.py スクリプトの拡張

scripting.py スクリプトを拡張するには、以下の作業を行います。

  1. 新規ファイル startup.py を自分の CityEngine ワークスペース内に作成します。
  2. これらの行を追加し、スタートアップ時に Helper スクリプトが自動的にマップされるようにします。
import sys

sys.path.append({PATH_TO_YOUR_SCRIPTS_DIRECTORY})
# e.g. sys.path.append("C:\user\CityEngine\MyProject\scripts")
import myHelpers

次回 CityEngine を起動した時には、myHelpers モジュールは自動的に読み込まれます。以下の方法で、Console で selection 関数を呼び出すことができます。

>>> myHelpers.selectByAttribute("connectionEnd", "JUNCTION")

任意のコードをファイル startup.py に追加することができます。Python Console が CityEngine の中で起動したときにこれが実行されます。
作成した startup.py ファイルの内容が正しく、正常に実行できることを確認してください。そうでない場合は CityEngine 内の Python コードは実行できません。startup.py を作成、変更した後に CityEngine の Python Console を開くと、スタートアップ ファイルの実行に伴う問題はそこに表示されます。
startup.py は CityEngine の起動時には読み取り専用です。変更する際は CityEngine を再起動してください。
CityEngine の起動時にスクリプトが正常に更新されない場合、Python キャッシュ ディレクトリ $USER_DIR/.cityengine/$CEVERSION_DIR/pythonCache/ を削除してください。

Part 2: 道路幅の変更

多くのセグメントについて道路幅の属性値を加減したいという場合は少なからずあります。GUI でこれを行うのは容易ではありませんが、簡単な Python によって実現可能です。

チュートリアルの設定

[Scene] フォルダーから [Tutorial_10_Python_Scripting/scenes/02_PythonScripting.cej] を開きます。

新規 Python スクリプトの作成

  1. [File] メニュー → [New…] → [Python] → [Python Module] から新しいルール ファイルを作成します。
  2. プロジェクトの [script] フォルダーを選択して 「setStreetWidths」 という名前を付け、テンプレートとして [Module: Main] を選択します。

incrementStreetWidth() 関数

この関数は、選択されているすべての道路セグメントの streetWidth 属性値をユーザーが設定した値の分だけ増加します。

最初は関数定義です。

def incrementStreetWidth(increment):

選択されているすべてのセグメントを取得し、それらについてループします。

    selectedSegments = ce.getObjectsFrom(ce.selection, ce.isGraphSegment)
        for segment in selectedSegments:

新しい道路幅を計算するために、まずコマンド ce.getAttribute() を使用して現在の値を取得する必要があります。属性名の文法上の名前には先頭に “/ce/street/” が付くことに注意してください。これによりオブジェクトのユーザー属性にアクセスすることができます。

        oldWidth = ce.getAttribute(segment, "/ce/street/streetWidth")

最後に、ユーザーが与えたパラメーター increment だけ加えた新しい道路幅を計算し、新しい値をセグメントに割り当てます。

    newWidth = oldWidth+increment
        ce.setAttribute(segment, "/ce/street/streetWidth", newWidth)

関数の全体

''' increment the street width parameter of all selected street segments'''
def incrementStreetWidths(increment):
    selectedSegments = ce.getObjectsFrom(ce.selection, ce.isGraphSegment)
    for segment in selectedSegments:
        oldWidth = ce.getAttribute(segment, "streetWidth")
        newWidth = oldWidth+increment
        ce.setAttribute(segment, "/ce/street/streetWidth", newWidth)

スクリプトのメイン ブロックに関数呼び出しを追加し、増加量を指定します。

if __name__ == '__main__':
   incrementStreetWidths(10)

複数の道路セグメントを同時選択します。

[Python] メニュー → [Run Script] をクリックするか、[Python Editor] ウィンドウ内で F9キーを押し、スクリプトを実行します。

処理のスピードアップ: @noUIupdate

上のスクリプトを実行するとやや時間がかかってしまいます。これはCityEngineにおいてスクリプトは別々のスレッドで実行され、GUI と [3D Viewport] ウィンドウの各コマンドが実行される度に更新されるためです。この場合は、各 setAttribute() が呼び出されるたびに道路ネットワークが更新され 3D Viewport ウィンドウ内が再描画されます。
上の例のような処理が役に立つケースでは実行は速いに越したことはありません。これは関数定義の上に @noUIupdate マーカーを追加することで実現可能です。

@noUIupdate
def incrementStreetWidth(increment):

このようにマークされた関数は実行中の GUI の更新をブロックしますが処理内容によっては数倍早く実行されます。

スクリプトコマンドによっては @noUIupdate マーカーと組み合わせることでユーザー インターフェイスがフリーズしてしまうこともありますので注意してください。 @noUIupdate を使用した時にユーザー インターフェイスがフリーズ、または予期せぬ挙動が発生した場合は、スクリプトを修正して @noUIupdate がスクリプト全体ではなく、特定の関数のみに適用されるようにします。

multiplySegmentWidths() 関数

2 つ目の関数は同時に複数の属性 streetWidth と sidewalkWidthLeft と sidewalkWidthRight を同時に設定するものです。ユーザーは道路幅の値に掛ける数値を指定することができます。

@noUIupdate
def multiplySegmentWidths(factor):
    selectedSegments = ce.getObjectsFrom(ce.selection, ce.isGraphSegment)
    for segment in selectedSegments:

以下のヘルパー関数 multiplyAttribute により異なる属性に掛け算を実行することができます。

        multiplyAttribute(segment, "/ce/street/streetWidth", factor)
        multiplyAttribute(segment, "/ce/street/sidewalkWidthLeft", factor)
        multiplyAttribute(segment, "/ce/street/sidewalkWidthRight", factor)

def multiplyAttribute(object, attrname, factor):
    oldval = ce.getAttribute(object, attrname)
    newval = oldval*factor
    ce.setAttribute(object, attrname, newval)

2 つの関数

''' multiply street and sidewalk widths of all selected street segments by factor '''
@noUIupdate
def multiplySegmentWidths(factor):
    selectedSegments = ce.getObjectsFrom(ce.selection, ce.isGraphSegment)
    for segment in selectedSegments:
        multiplyAttribute(segment, "/ce/street/streetWidth", factor)
        multiplyAttribute(segment, "/ce/street/sidewalkWidthLeft", factor)
        multiplyAttribute(segment, "/ce/street/sidewalkWidthRight", factor)

''' multiply attribute of object by factor '''
def multiplyAttribute(object, attrname, factor):
    oldval = ce.getAttribute(object, attrname)
    newval = oldval*factor
    ce.setAttribute(object, attrname, newval)

スクリプトのメインブロックに関数呼び出しを追加し、掛ける数値を指定します。

if __name__ == '__main__':
   multiplySegmentWidths(1.5)

複数の道路セグメントを同時選択します。
[Python] メニュー → [Run Script] をクリックするか、[Python Editor] ウィンドウ内で F9キーを押し、スクリプトを実行します。

Console からの実行

[Python Editor] ウィンドウ で関数の引数を設定する代わりに、[Python Console] ウィンドウでもスクリプト モジュールをインポート後に上の関数を容易に呼び出すことができます。

>> scriptpath = ce.toFSPath("scripts")
>> sys.path.append(scriptpath)
>> import setStreetWidths
>> setStreetWidths.multiplySegmentWidths(0.5)

Part 3: FBX ファイルからのカメラ設定

このパートでは静的なカメラ データを Maya からの FBX へのエクスポートを経由して CityEngine に取り込む方法を紹介します。

チュートリアルの設定

Tutorial_10_Python_Scripting/scenes/02_PythonScripting.cej を開きます。

カメラを FBX へエクスポート(Maya)

Maya をお持ちでない場合は、以下のステップは飛ばして予め用意してある “data/camera.fbx” ファイルを使用してください。

  1. Maya でエクスポートしたいカメラを選択します。
  2. [File] メニュー → [Export Selection] を選択します。 エクスポート ダイアログで下図に示すような設定になっていることを確認してください。


カメラ インポート スクリプト

  1. [File] メニュー → [New …] → [Python] → [Python Module] から新規 Pythonファイルを作成します。
  2. プロジェクトの scripts フォルダーを選択し、importFBXCamera_dist という名前を付け、テンプレートとして Module: Main を選択します。

FBX ファイルの読み取り

  1. 行を読み込んで id を見つけます。
  2. カメラ データを格納する配列を用意します。
  3. カメラ データを保存している FBX ファイルから行を読み取ります。
def parseLine(lines, id):
    data = False
    for line in lines:
        if line.find(id) >=0 :
            data = line.partition(id)[2]
            break
    if data:
        data = data[:len(data)-1] # strip \n
        data = data.split(",")        
    return data

def parseFbxCam(filename):
    f=open(filename)
    lines = f.readlines()
    cnt = 0
    loc =  parseLine(lines, 'Property: "Lcl Translation", "Lcl Translation", "A+",')
    rot =  parseLine(lines, 'Property: "Lcl Rotation", "Lcl Rotation", "A+",')
    return [loc,rot]

CityEngine カメラの設定

CityEngine Viewport を取得して位置と回転を設定する関数を呼び出します。

def setCamData(data):
    viewport = ce.getObjectsFrom(ce.get3DViews(), ce.isViewport)[0]
    setCamPosV(viewport, data[0])
    setCamRotV(viewport, data[1])
def setCamPosV(v, vec):
    v.setCameraPosition(vec[0], vec[1], vec[2])
    
def setCamRotV(v, vec):
    v.setCameraRotation(vec[0], vec[1], vec[2])

マスター関数

def importFbxCamera(fbxfile):
   
    data = parseFbxCam(fbxfile)
    if(data[0] and data[1]) :
        setCamData(data)
        print "Camera set to "+str(data)
    else:
        print "No camera data found in file "+file

メイン ブロックからの呼び出し

if __name__ == '__main__':
    camfile = ce.toFSPath("data/camera.fbx")
    importFbxCamera(camfile)

[Python] メニュー → [Run Script] をクリックするか、[Python Editor] ウィンドウ内で F9キーを押し、スクリプトを実行します。下図のような形でカメラが配置されるはずです。

アニメーション カーブは読み込まれません。フレーム エクスポート時におけるカメラ変化 (Transformation) のみが読み込まれます。
カメラは単一のオブジェクトとしてエクスポートされる必要があります。

Part 4: 建物の変化アニメーション

Python スクリプトは生成やエクスポートの処理の自動化に使用することができます。 この例では、建物の属性を設定してその結果のモデルをエクスポートすることでシンプルな建物のアニメーションの処理を 1 ステップで作成する方法を紹介します。

チュートリアルの設定

[Tutorial_10_Python_Scripting/scenes/03_PythonScripting.cej] を開きます。

  1. シーンの中で区画を 1 つ選択します。
  2. ルール ファイル growingBuilding.cga をその区画に適用します。
  3. 建物が生成されない場合は、ツールバーの中にある [Generate] をクリックします。

ルール ファイルには建物のサイズを変更するための属性が用意されています。これらの値をマニュアルで設定する代わりに、値を変更して様々なモデルをバッチで生成するスクリプトを作成します。

アニメーション スクリプト

新しい Python Main モジュール my_grow_building.py を作成します。

def growBuilding
この関数は、2 つのレンジをループする非常にシンプルなタイムラインを作成し、setAttribute 関数を呼び出します。

def growBuilding():
    for i in range(1,14):
        height = 20+i
        doStep(i,height,1)

    for i in range(15,35):
        height = 34
        width = i-14
        doStep(i,height,width)

def doStep
区画のオブジェクトに対し、2 つの属性の height と width が変更されます。

def doStep(i,height,width):    
    object = ce.getObjectsFrom(ce.scene, ce.withName("'Lot1'"))
    ce.setAttributeSource(object, "height", "OBJECT")
    ce.setAttributeSource(object, "width", "OBJECT")
    ce.setAttribute(object, "height", height)
    ce.setAttribute(object, "width", width)
    
    Generate(object)

def Generate
単純に建物を生成します。

def Generate(object):
    ce.generateModels(object)

main
スクリプトのメイン節の中で growBuilding が呼び出されます。

if __name__ == '__main__':
   growBuilding()

建物のバッチ生成

  1. シーンの中で区画を選択します。
  2. [Python Editor] ウィンドウ の中で F9 キーを押し、スクリプトを実行します。

バッチ エクスポート

生成されたモデルが満足のいくものであれば、さらに Export 関数を追加します。

def Export(i, object):
    dir = ce.toFSPath("models")
    file = "building_merge_" + str(i)
    #prepare export settings
    settings = OBJExportModelSettings()
    settings.setBaseName(file)
    settings.setOutputPath(dir)
    #do export
    ce.export(object, settings)

doStep() の中の Generate コールを置き換えます。

    #Generate(object)
        Export(i, object)

エクスポート結果は models フォルダーに格納されています。

Part 5: アセット ライブラリ ルール ファイルの作成

大量のアセットがある場合には、それらすべてを一度に見られると便利です。このパートでは、プロジェクトに含まれるアセットを表示する CGA ルール ファイルを自動的に作成する方法を紹介します。

チュートリアルの設定

Tutorial_10_Python_Scripting/scenes/03_PythonScripting.cej を開きます。

Python スクリプトにより生成するルール ファイルは以下のような構造を持つことになります。

Lot -->  Geometries Textures

Geometries --> 
	 Geometry(assetpath)
	 Geometry(assetpath)
	 ...

Geometry(asset) --> i(asset)

これらはジオメトリ アセットおよびそれと同様のテクスチャ画像のための構造です。

  • 新規 Python メイン モジュール my_asset_lib.py を作成します。
  • 新規関数 writeCGALib を作成します。
def writeCGAlib():

ヘッダー情報、スタート ルール Lot および Geometries ルールを書き出します。:

    cga = "/*Asset Library Loader : Generated by asset_lib.py*/\n version \"2011.1\"\n\n"

    #write start rule
    cga += "Lot -->  Geometries Textures"
    
    #write rule showing geometries
    cga += "\n\nGeometries --> "

asset フォルダーに含まれるすべての obj ファイルについて繰り返し、各アセットに対してルール コール Geometry(assetpath) を用意します。

    #get all .obj files from asset directory, and call their loader
    for obj in ce.getObjectsFrom("/", ce.isFile, ce.withName("/Tutorial_10*/assets/*.obj")):     
        #and write 
        cga += "\n\t t(2,0,0)  Geometry(\""+obj+"\")"

テクスチャ アセットについても同様のルールを書き出します。

    #write rule showing jpg textures
    cga+="\n\nTextures-->\n\ts(1,0,0) set(scope.ty,-2) set(scope.tz,0) i(\"facades/xy-plane.obj\")"
    
    #get all .jpg files from asset directory, and call their loader
    for jpg in ce.getObjectsFrom("/", ce.isFile, ce.withName("/Tutorial_10*/assets/*.jpg")):   
        cga += "\n\tt(2,0,0)  Texture(\""+jpg+"\")"

実際のアセット ローダーのルールを書き出します。

    //write geometry loader rule
    cga += "\n\n Geometry(asset) --> s(1,0,0) i(asset) set(scope.ty,0) set(scope.tz,0)"
    
    //write texture loader rule
    cga += "\n\n Texture(asset) --> set(material.colormap, asset)"

将来の .cga ファイル用のファイル ハンドルを開き、cga の内容を書き出します。

    cgafile = ce.toFSPath("rules/asset_lib.cga")
    CGA = open(cgafile, "w")
    CGA.write(cga)
    CGA.close()
    print "written file "+cgafile

新しい関数 assignAndGenerateLib() を追加します。これは生成された CGA ファイルをシーンの区画に適用し、モデルを生成します。

def assignAndGenerateLib():
    object = ce.getObjectsFrom(ce.scene, ce.withName("'Lot2'"))
    ce.refreshWorkspace()
    ce.setRuleFile(object, "asset_lib.cga")
    ce.setStartRule(object, "Lot")
    ce.generateModels(object)

最後に、メイン節の中から 2 つの関数を呼び出します。

if __name__ == '__main__':
    writeCGAlib() 
    assignAndGenerateLib()

ライブラリ モデルの生成

[Python Editor] ウィンドウ にファイル asset_lib.py を開き、F9 キーを押します。

Part 6: startup.py を用いた CityEngine タスクの自動化

Python を使用して、大きなタスクや反復的なタスクを自動化することができます。例えば 1 区画の情報を元に全体のモデル作成を自動化することができます。

  1. プロジェクトを作成するか、既存のプロジェクトを利用します。 ここでは、チュートリアル プロジェクトの Tutorial_10_Python_Scripting__2019_0 を使います。
  2. プロジェクトの scripts フォルダーに Python Main モジュールを作成します。チュートリアルに最小限のジョブ automationJob.py が含まれているので、こちらを利用します。
  3. 自動化ジョブのタスクを含む関数を挿入します。テストのために、この関数への呼び出しをメイン節に追加します。今回、例として提供されている fgdbToKml では、fileGDB から図形をインポートしてモデルを生成し、KML に書き出します。

automationJob.py

from scripting import *
#get a CityEngine instance
ce = CE()
 
def fgdbToKml(pathFGDB,layerName,ruleName,startRule = "Generate"):
    #open scene in the automation project
    ce.newFile('/scenes/emptyScene.cej')
     
    #load a database
    importSettings = FGDBImportSettings()
    importSettings.setDatasetFilter(['/'+layerName])
    ce.importFile(ce.toFSPath(pathFGDB), importSettings)
     
    #assign rule file based on the layer name
    layer = ce.getObjectsFrom(ce.scene, ce.isShapeLayer, ce.withName(layerName))[0]
    shapes = ce.getObjectsFrom(layer, ce.isShape)
    ce.setRuleFile(shapes, ruleName)
    ce.setStartRule(shapes, startRule)
     
    #export models to KML
    exportSettings = KMLExportModelSettings()
    exportSettings.setOutputPath(ce.toFSPath("models"))
    exportSettings.setBaseName(layerName)
    exportSettings.setCompression(True)
    ce.export(shapes, exportSettings)
     
    #close CityEngine
    ce.waitForUIIdle()
    ce.closeFile()

if __name__ == '__main__':
    fgdbToKml("data/CityData.gdb", "NewShapes", "/ESRI.lib/rules/Buildings/Building_From_Footprint.cga", "Generate")
    pass
  1. ジョブのパラメーターを定義するために構成ファイルを作成します。チュートリアルの \data\jobConfig.cfg にサンプルが含まれています。

jobConfig.cfg

[config]
pathFGDB=data/CityData.gdb
layerName=NewShapes
ruleName=/ESRI.lib/rules/Buildings/Building_From_Footprint.cga
startRule=Generate
  1. 構成ファイルに保管されているパラメーターを使用して自動化ジョブを実行するために、2 つの関数、run(cfg) と getCfgValue(cfg,name) を automationJob.py へ追加します。

automationJob.py

def getCfgValue(cfg,name):
    for c in cfg:
        if  c[0] == name: return c[1]
    return None
 
def run(cfg):
    pathFGDB = getCfgValue(cfg,'pathfgdb')
    layerName = getCfgValue(cfg,'layername')
    ruleName = getCfgValue(cfg,'rulename')
    startRule = getCfgValue(cfg,'startrule')
     
    fgdbToKml(pathFGDB, layerName, ruleName, startRule)
  1. 自動化のために別々の CityEngine ワーク スペースを使用することをお勧めします。 システムに新しい C:\Automation Workspace フォルダーを作成します。
  2. /scripts/startup.py ファイルをチュートリアル プロジェクトから、新しい C:\Automation Workspace ルート ディレクトリにコピーします。

この Python スクリプトの ‘startup’ セクションのコマンドは、CityEngine の起動時に自動的に実行されます。最初の起動引数は、自動化ジョブを含む CityEngine プロジェクトを定義します。これは Automation Workspace にリンクされます。2 番目の引数には設定ファイルが含まれています。これは解析され、 (name,value) ペアのリストとして自動化ジョブに引き渡されます。ジョブが完了したら、CityEngine は安全にシャットダウンされます。

startup.py

from scripting import *
from java import lang
import ConfigParser, sys
 
if __name__ == '__startup__':
   // get a CityEngine instance
    ce = CE()
     
    // get startup arguments
    projectFolder = lang.System.getProperty("projectFolder")
    configFilePath = lang.System.getProperty("configFilePath")
     
    // link the automation project into automation workspace
    if "automationProject" in ce.listProjects(): ce.removeProject("automationProject")
    ce.importProject(projectFolder, False, "automationProject")
     
    // read configuration file
    cp = ConfigParser.ConfigParser()
    cp.read(configFilePath)
    cfg = cp.items('config') # list of (name,value) pairs
     
    // run automation job
    sys.path.append(ce.toFSPath("/automationProject/scripts"))
    import automationJob
    automationJob.run(cfg)
     
    // safely shut down CityEngine
    ce.exit()
  1. コマンド ラインを開いて Automation Workspace で CityEngine を起動し、ジョブ定義とパラメーターを渡します。

Command

<Path_to_CityEngine.exe> -data <Workspace_Folder> -vmargs -DprojectFolder=<Project_Folder> -DconfigFilePath=<Configuration_FilePath>
 
#Example:
> "C:\Program Files\Esri\CityEngine2018.0\CityEngine.exe" -data "C:\Automation Workspace" -vmargs -DprojectFolder="C:\CE_Workspace\Tutorial_10_Python_Scripting__2018_0" -DconfigFilePath="C:\CE_Workspace\Tutorial_10_Python_Scripting__2018_0\data\jobConfig.cfg"
  1. ジョブが完了したら、models フォルダー に ArcGIS Earth で表示できる Footprints.kmz 出力ファイルが格納されます。

automationJob.py ファイルには最小限のジョブしか含まれていません。CityEngine Python ヘルプを参照して、必要に応じて調整をしてください。