CityEngine+Python自动化建模实现【系列文章之四】

4 篇文章 4 订阅
4 篇文章 1 订阅

上篇文章介绍了CityEngine + Python自动化建模的原理,本篇文章给出自动化建模的实际代码(代码已经过实际验证,可放心使用),将对应内容修改为自己项目中的实际内容即可。

如果你喜欢本文,欢迎收藏、分享和转载,转载请注明出处:https://blog.csdn.net/shaxiaozilove/article/details/116903530

如果你有任何问题,欢迎与我联系和沟通,谢谢。

下面是自动化建模全面和详细的代码,欢迎参考:

'''
Created on 2020-10-27

@author: QinC
'''
from scripting import *
import os
import math

# get a CityEngine instance
ce = CE()

def isFileExist(f_path):
    return os.path.exists(f_path)

# create a new scene and set it's spatial reference system
def createScene(scene_name, wkid):
    if not scene_name.endswith('.cej'):
        scene_name = scene_name + '.cej'
        
    ce.newFile('scenes/' + scene_name)
    ce.setSceneCoordSystem(wkid)
    print 'create secne and set srs successfully'
    
# import spefify layer from gdb
def importShapeFromGDB(gdb_path, dataset):
    absolute_path = ce.toFSPath(gdb_path)
    if not isFileExist(absolute_path):
        print 'path of gdb not exist: %s' % absolute_path
        return
    
    if not isinstance(dataset, list):
        print 'parameter type of dataset should be list: %s' % str(dataset)
        return
    
    if not len(dataset):
        print 'at least one feature class should be imported: %s' % str(dataset)
        return
            
    gdbSettings = FGDBImportSettings()
    gdbSettings.setDatasetFilter(dataset)
    ce.importFile(ce.toFSPath(gdb_path), gdbSettings, False)
    
    ce.setSelection(None)
    
    print 'import shape successfully'

'''
    first, set cga rule file and start rule for scene whole shapes
    next, set cag's parameter Floor from Object(connect Floor to layer's attribute Floor)
    then, set new name for object if specify a valid field_name
    
    cga_path: relative path of cga
    start_rule: start rule, string type
'''
def setRule(cga_path, start_rule):
    # judge if the cga_path exist by absolute path
    if not isFileExist(ce.toFSPath(cga_path)):
        print 'the specified cga file not exist: %s' % cga_path
        return
    
    shapes = ce.getObjectsFrom(ce.scene, ce.isShape)
    ce.setRuleFile(shapes, cga_path, True)
    ce.setStartRule(shapes, start_rule)
    print 'set rule file and start rule successfully'
    
    '''
        if attr in cga file has the same name with one of layer's attribute table fields, 
        then it's attr source is Object default and value is same
        so, if you want to get value from layer attribute table, it is import to set attr name in cga
        the next line is not necessary
    '''
    ce.setAttributeSource(shapes, '/ce/rule/Floor', 'Object')
    print 'set Floor attr source successfully'
        
    ce.saveFile()
    

'''
    set shape name use layer's field value
    shapes: shaped to set new name
    field_name: the field to set shape's name
'''
def setObjectName(shapes, field_name):
    for shape in shapes:
        ce.setName(shape, ce.getAttribute(shape, field_name))
'''
    export models
    format: format to export, eg. gdb, gltf, glb ...
    path: where the model to export, use relative path
    base_name: base name of the exported file
    field_name: source layer's field name, used to reset object name
    admin_codes: admin codes of a city, generate model of this area each time, default value is empty list,
                if not assigned or pass empty list, generate and export a certain number of model each time
    certain_number: the number of models generate and export each time
'''
def exportModels(format, path, base_name, field_name = None, admin_codes = [], certain_number = 10000):
    shapes = ce.getObjectsFrom(ce.scene, ce.isShape)
    if field_name and len(admin_codes) > 0:
        # set a new name for object(here is shapes)
        setObjectName(shapes, field_name)
        print 'set object name with category code successfully'
        
        # generate and export model by category code        
        for code in admin_codes:
            # filter scene shapes with name
            classified_shapes = ce.getObjectsFrom(ce.scene, ce.isShape, ce.withName('"' + code + '"'))
            doGenerateAndExport(classified_shapes, format, path, base_name, code)
            
        print 'generate and export models successfully with field name [%s], codes %s.' % (field_name, str(admin_codes))
    else:
        # export certain number model each time
        length = len(shapes)
        count = int(math.floor(length / certain_number))
        for i in range(count):
            certain_shapes = shapes[i * certain_number: (i + 1) * certain_number]
            doGenerateAndExport(certain_shapes, format, path, base_name, i + 1)
            
        # left models to process(number should be int, not floor)
        left_shapes = shapes[count * certain_number: length]
        doGenerateAndExport(left_shapes, format, path, base_name, count + 1)
        
        print 'generate and export models with certain number each time successfully, and total %d parts.' % (count + 1)
        
    ce.saveFile()

'''
    genarate and export model, you can specify format, path and base name
    shapes: objects to generate model
    format: format to export, eg. gdb, gltf, glb ...
    path: where the model to export, use relative path
    base_name: base name of the exported file
    suffix: used as suffix of base name to distingush different part, default value is 1
'''
def doGenerateAndExport(shapes, format, path, base_name, suffix = 1):
    models = ce.generateModels(shapes, True, False)
    if len(models):
        exportSetting = getExportSetting(format, path, base_name, suffix)
        ce.export(models, exportSetting, False)
        print 'models of part %d has generate and export successfully' % suffix
    else:
        print 'models of part %d has no model to generate and export' % suffix


# get export setting info
def getExportSetting(format, path, f_name, suffix):
    if not f_name.endswith('.' + format):
        f_name = f_name + '_' + str(suffix) +  '.' + format
    else:
        f_name = os.path.splitext(f_name)[0] + '_' + str(suffix) + '.' + format

    exportSettings = FGDBExportModelSettings()
    if format == 'gdb':
        exportSettings.setOutputPath(ce.toFSPath(path) + '/')           
        exportSettings.setGeodatabaseName(f_name)
    elif format == 'gltf' or format == 'glb':
        exportSettings = GLTFExportModelSettings()
        exportSettings.setOutputPath(ce.toFSPath(path))
        exportSettings.setBaseName(f_name)

    return exportSettings
    
    
if __name__ == '__main__':   
    scene_name = 'wuhan_auto_cga.cej'
    # coordinate system code, eg 3857 4547
    wkid = 'EPSG:4547'
    
    gdb_path = 'data/building.gdb'
    dataset = ['/wuhan_for_local_test']
    
    cga_path = 'rules/wuhan_blank.cga'
    start_rule = 'Lot'
    
    field_name = 'Adcode'
    # admin code of wuhan
    adcodes = ['420102', '420103', '420104', '420105', '420106', '420107', '420111', '420112', '420113', '420114', '420115', '420116', '420117']
    
    certain_number = 10000
    
    export_path = 'models'
    base_name = 'wuhan'
    
    createScene(scene_name, wkid)
    importShapeFromGDB(gdb_path, dataset)
    setRule(cga_path, start_rule)
    exportModels('gdb', export_path, base_name, certain_number = 5000)
    
    ce.refreshWorkspace()

 

  • 4
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是一个简单的Java实现示例,可以自动运行CityEngine中的python代码: ```java import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.util.ArrayList; import java.util.List; public class PythonRunner { public static void main(String[] args) throws IOException { List<String> command = new ArrayList<String>(); command.add("C:/path/to/python.exe"); // 设置Python解释器路径 command.add("C:/path/to/python_script.py"); // 设置要执行的Python脚本路径 ProcessBuilder pb = new ProcessBuilder(command); pb.redirectErrorStream(true); Process process = pb.start(); // 将要执行的Python代码写入输入流中 String pythonCode = "print('Hello, World!')\n"; process.getOutputStream().write(pythonCode.getBytes()); process.getOutputStream().flush(); process.getOutputStream().close(); // 读取进程输出结果并进行处理 InputStream inputStream = process.getInputStream(); BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream)); String line; while ((line = reader.readLine()) != null) { System.out.println(line); } } } ``` 在上述示例中,我们使用了ProcessBuilder类启动了一个新的进程,并将要执行的Python代码写入了进程的输入流中。然后通过读取进程的输出流来获取到执行结果,并进行处理。需要注意的是,这里只是一个简单的示例,具体实现还需要根据实际情况进行优化和改进。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值