平面图
平面图以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
属性,如果是图片就跳过。根据;
分割字符串,得到其中的rotation
和fillColor
属性。hex_to_rgb
16进制颜色转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
实例。pivot
和trans
用于将点的置于实例网格的中心点。
最后一个循环调用create_point
方法创建点:
for pack_point in pack_points:
pack_point.create_point()
最后使用copy_to_point
节点:
结果示例
利用pack点上的height属性可以挤出方块儿:
白模示例: