平面图到Houdini

平面图

平面图以draw.io为例:


每个图形拥有多种属性。尺寸,旋转角度,颜色分类,文本。
文件以xml形式存在。以一个方块为例:

        
          
        

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

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

        

其中的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)