【提问】如何解决对象属性中阻止 FileGDB 导出的类型不匹配问题-CGA规则论坛-编程语言-ArcGIS CityEngine中文网社区
幻灯片-ArcGIS CityEngine中文网社区

提问如何解决对象属性中阻止 FileGDB 导出的类型不匹配问题

在 CityEngine 中,对象属性值的类型不必在多个形状中相同,但这是 Esri 的 FileGDB 格式的要求。如果场景中存在此类类型不匹配,则导出到 FileGDB 将失败,并显示以下消息:

d0b49f1ac520240614164751

批处理导出已完成,但至少发生一个错误。有关详细的错误信息,请参阅导出日志文件。

如果在日志(窗口 -> 日志 ->选择条目 ->上下文菜单 ->事件详细信息)中检查条目的详细信息,则可以在异常堆栈跟踪的顶部找到类似于以下行的行:

java.lang.IllegalArgumentException:esriFieldTypeDouble

这样做的原因是 CityEngine 会检查值的类型,并在向形状添加对象属性时相应地设置该值。一个典型的例子是门牌号:值为 12 的数字类型为 float,而值为 12a 的数字类型为 string。这对于从“获取地图数据/OSM”导入的形状非常常见。

解决方案:不导出对象属性

简单的解决方法是首先不导出对象属性,方法是取消选中 FileGDB 导出中“常规设置”下的“导出对象属性”选项。

JonasObertuefer_1-1716390534023.png

解决方案:使用 python 对齐对象属性类型

如果需要进一步处理对象属性,则在导出前需要确保所有同名属性的值都属于同一类型。这可以使用 python 脚本来实现:

'''
@version: 1.0
@author: Esri R&D Center Zurich
'''

from scripting import *


# get a CityEngine instance
ce = CE()

def findTypeMismatches(objects):
    allAttributes = {}
    mismatchAttributes = []
    
    print("object attributes type mismatch:")
    for object in objects:
        attributes = ce.getAttributeList(object)
        for attr in attributes:
            if not attr.startswith('/'):  # only check object attributes
                attrType = type(ce.getAttribute(object, attr))  
                if attr not in allAttributes:
                    allAttributes[attr] = [attrType,ce.getOID(object)]
                else:
                    if allAttributes[attr][0] != 0:
                        if allAttributes[attr][0] != attrType:
                            mismatchAttributes.append(attr)
                            print("Attribute " + attr +
                                  " is of " + str(attrType) + 
                                  " in OID: " + ce.getOID(object) + 
                                  " ref is of " + str(allAttributes[attr][0]) + 
                                  " in OID: " + allAttributes[attr][1])
                            allAttributes[attr][0] = 0
    
    return mismatchAttributes

@noUIupdate
def resolveTypeMismatch(mismatches, objects):
    # object attributes needed by ESRI.lib rules as type float
    exceptionAttributes = ["building__levels", "roof__height", 
                           "roof__direction", "building__levels__underground", 
                           "building__min_level", "min_heigh", "width", "lanes"]
    
    for object in objects:
        attributes = ce.getAttributeList(object)
        for attr in attributes:
            if attr in mismatches:
                attrValue = ce.getAttribute(object, attr)
                if attr in exceptionAttributes:
                    if not isinstance(attrValue, float):
                        ce.deleteAttribute(object, attr) 
                        print("Deleting " + attr + 
                              " of type " + str(type(attrValue)) +
                              " in OID: " + ce.getOID(object))
                else:
                    if not isinstance(attrValue, str):
                        newValue = str(attrValue)
                        ce.setAttribute(object, attr, newValue)
                        print("Updating " + attr + 
                              " from " + str(type(attrValue)) + 
                              " to <type 'str'> in OID: " + ce.getOID(object))
                         
    print("Done!")
    
def main():
    #objects = ce.getObjectsFrom(ce.scene)
    objects = ce.getObjectsFrom(ce.selection)
    
    mismatches = findTypeMismatches(objects)
    resolveTypeMismatch(mismatches,objects)
    
if __name__ == '__main__':
    main()

该脚本分为两部分:

  1. 查找类型不匹配的属性。
  2. 解决不匹配问题:
    • 如果 ESRI.lib OSM 建筑物/街道规则类型为 float 所需的属性类型为字符串,则会将其从形状中删除,因为字符串到浮点数转换的预期结果可能不明确。
    • 所有其他不匹配的属性都将转换为字符串类型。
请登录后发表评论

    没有回复内容