美文网首页
平面图到Houdini

平面图到Houdini

作者: Dragon_boy | 来源:发表于2022-03-28 22:30 被阅读0次

    平面图

    平面图以draw.io为例:


    每个图形拥有多种属性。尺寸,旋转角度,颜色分类,文本。
    文件以xml形式存在。以一个方块为例:
            <mxCell id="MKHcSDxkE1IUyaGT8GKl-13" value="25" style="rounded=0;whiteSpace=wrap;html=1;fontSize=240;fillColor=#FF0000;" parent="MKHcSDxkE1IUyaGT8GKl-9" vertex="1">
              <mxGeometry x="23475" y="8425" width="5700" height="1200" as="geometry" />
            </mxCell>
    

    value为方块上的文本,这里的25指方块儿的高度。
    style为方块儿的样式,主要的属性为fillColor。可能会有rotation属性,代表方块的旋转角度。
    mxGeometry标签为实际的几何属性,x y为方块中心点,width为宽度,height为高度(2D视图下)

    每组mxCell标签上方会有一个mxCell标签:

            <mxCell id="MKHcSDxkE1IUyaGT8GKl-5" value="地面" style="" parent="0" />
    

    其中的value属性为当前方块儿的分组。

    Houdini 读取 xml


    grid中心设为

    python节点用于读取xml
    读取xml使用python内置的xml模块:
    import xml.etree.ElementTree as ET
    

    首先设置方块儿所需的属性:

    node = hou.pwd()
    geo = node.geometry()
    
    geo.addAttrib(hou.attribType.Point, "trans", hou.Vector3(0.0,0.0,0.0))
    geo.addAttrib(hou.attribType.Point, "scale", hou.Vector3(1.0,1.0,1.0))
    geo.addAttrib(hou.attribType.Point, "orient", hou.Quaternion(0.0, (0,1,0)))
    geo.addAttrib(hou.attribType.Point, "Cd", hou.Vector3(1.0,1.0,1.0))
    geo.addAttrib(hou.attribType.Point, "pivot", hou.Vector3(0.0,0.0,0.0))
    geo.addAttrib(hou.attribType.Point, "height", 0.0)
    

    新建一个文件属性,利用ET模块读取文件:

    xml_file = node.evalParm("xml_file")
    
    tree = ET.iterparse(xml_file)
    

    遍历xml节点:

    pack_points = []
    
    group = None
    for event, elem in tree:
        if event == 'end':
            if elem.tag == 'mxCell':
                attrib = elem.attrib
                rotation = hou.Quaternion(0.0,(0,1,0))
                color = hou.Vector3(1.0,1.0,1.0)
                id = ""
                parent = ""
                h = 0.0
    

    获取mxCell标签的元素,attrib为该元素的内容。

                if "value" in attrib.keys():
                    value = attrib["value"]
                    if value.isdigit():
                        h = float(value)
                    if is_all_chinese(value) and value != '':
                        if geo.findPointGroup(Name_map[value]) == None:
                            group = geo.createPointGroup(Name_map[value])
                        else:
                            group = geo.findPointGroup(Name_map[value])
    

    获取value属性,其中包含方块的文本内容,如果为数字则代表高度,如果为汉字的代表是组名。Name_map为手动创建的字典(houdini不支持汉字):

    Name_map = {"地面":"A",
                "建筑":"B",
                "道路":"C",
                "植被":"D",
                "大门":"E"}
    
                if "style" in attrib.keys():
                    data = attrib["style"]
                    if len(data) > 11 and data[0:11] == "shape=image":
                        continue
                    style = data.split(";")
                    for i in range(0, len(style)):
                        split_style = style[i].split("=")
                        if split_style[0] == "rotation":
                            rotation = hou.Quaternion(-float(split_style[1]),(0,1,0))
                        if split_style[0] == "fillColor":
                            if split_style[1] == "none":
                                continue
                            color = hou.Vector3(hex_to_rgb(split_style[1]))  
    

    读取style属性,如果是图片就跳过。根据;分割字符串,得到其中的rotationfillColor属性。hex_to_rgb16进制颜色转rgb:

    def hex_to_rgb(hex):
        h = hex.lstrip("#")
        rgb = tuple(int(h[i:i+2], 16) for i in (0,2,4))
        rgb = (rgb[0]/255.0, rgb[1]/255.0, rgb[2]/255.0)
        return rgb
    
                if len(elem) > 0: 
                    child = elem[0]
                    if child.tag == 'mxGeometry':
    

    如果元素长度大于0,则代表有mxGeometry标签元素,可以据此得到几何信息。

                        attrib = child.attrib
                        pos = hou.Vector3(0.0,0.0,0.0)
                        scale = hou.Vector3(1.0,1.0,1.0)
                        pivot = hou.Vector3(0.0,0.0,0.0)
                        if "x" in attrib.keys():
                            x = attrib["x"]
                            pos[0] = float(x) * 0.01
                        if "y" in attrib.keys():
                            y = attrib["y"]
                            pos[2] = float(y) * 0.01
                        if "width" in attrib.keys():
                            width = attrib["width"]
                            scale[0] = float(width) * 0.01
                        if "height" in attrib.keys():
                            height = attrib["height"]
                            scale[2] = float(height) * 0.01
    

    读取x y width height属性,并存起来(单位cm->m(houdini))。
    创建一个PackPoint类,存储每个pack点的属性:

    class PackPoint():
        def __init__(self, trans=hou.Vector3(), scale=hou.Vector3(), 
                        orient=hou.Quaternion(), Cd=hou.Vector3(), pivot=hou.Vector3(), 
                        height=0.0, group=None):
            self.trans = trans
            self.scale = scale
            self.orient = orient
            self.Cd = Cd
            self.pivot = pivot
            self.height = height
            self.group = group
            
        def create_point(self):
            point = geo.createPoint()
            point.setAttribValue("trans", self.trans)
            point.setAttribValue("scale", self.scale)
            point.setAttribValue("pivot", self.pivot)
            point.setAttribValue("orient", self.orient)
            point.setAttribValue("Cd", self.Cd)
            point.setAttribValue("height", self.height)
            self.group.add(point)
            return point
    

    其中的create_point可用来创建实际的点。

                        pack_point = PackPoint()
                        pivot[0] = 0.5
                        pivot[1] = 0
                        pivot[2] = 0.5
                        trans = hou.Vector3(pos) + hou.Vector3(scale[0]/2, 0, scale[2]/2)
                        pack_point.trans = trans
                        pack_point.scale = scale
                        pack_point.pivot = pivot
                        pack_point.orient = rotation
                        pack_point.Cd = color
                        pack_point.height = h
                        pack_point.group = group
                        pack_points.append(pack_point)
    

    创建多个PackPoint实例。pivottrans用于将点的置于实例网格的中心点。
    最后一个循环调用create_point方法创建点:

    for pack_point in pack_points:
        pack_point.create_point()
    

    最后使用copy_to_point节点:


    结果示例

    利用pack点上的height属性可以挤出方块儿:




    白模示例:


    相关文章

      网友评论

          本文标题:平面图到Houdini

          本文链接:https://www.haomeiwen.com/subject/hzcejrtx.html