Dynamo應用秘籍:7:Revit地形到Dynamo的Surface

地形(Topography)是Revit中特殊一種實體類型,當需要在Dynamo中對地形進行分析、處理時,首先需要將Revit的地形實體轉換成常用的Dynamo支持的圖形類型:Surface或者Solid。但是Dynamo解析地形不會生成需要的Surface,而是Mesh。在Dynamo裡面,既有單獨的Topography.Mesh節點,也可以使用Element.Geometry節點來生成地形對應的Mesh。

Mesh在Dynamo裡面需要特殊的處理,而且Mesh本身均是一系列的小三角形面,光滑度上遠遠不夠,在Geometry的節點庫中,對Mesh的處理節點也非常有限,因此基於Mesh的很多後繼處理工作會比較困難。這種時候,或者需要另外搜素下載MeshToolKit的軟體包,從中找出更多對Mesh進行處理的節點,或者使用該軟體包及內置節點組合將Mesh轉換成PolySurface。這樣很多後繼的處理可以在PolySurface上進行而Dynamo提供了大量的PolySurface操控節點。

使用Dynamo內置節點將Mesh轉換成PolySurface,需要提取整個Mesh的點集合,然後根據點位索引重建一個個小三角面的Surface(提取3個點,連線成閉合三角形,再Patch三角形成Surface),最後組合成一個與Mesh對應的PolySurface。這個思路很簡單,但是這種在Mesh的面非常多(超過10K)時,Dynamo的運行效率會大打折扣,因此需要從演算法進行優化。優化的方法是把所有的Mesh分成幾個組,每個組的Mesh總數量控制在一定範圍(如10)內;或者創建多個線程(如4個)來分批處理Mesh分組,這樣可以極大的提高運行速度。

下面的代碼是摘自SpringNodes軟體包中Mesh.ToPolySurface節點:

#Copyright(c) 2016, Dimitar Venkov# @5devene, dimitar.ven@gmail.comimport clrfrom System.Threading import Thread, ThreadStartclr.AddReference("ProtoGeometry")from Autodesk.DesignScript.Geometry import *def tolist(obj1): if hasattr(obj1,"__iter__"): return obj1 else: return [obj1]def output1(l1): if len(l1) == 1: return l1[0] else: return l1def chop1(l1, n): return [l1[x:x+n] for x in xrange(0, len(l1), n)]def mesh2ps(topo, f_chop = chop1, f_ps1 = PolySurface.ByJoinedSurfaces): vp = topo.VertexPositions fi = topo.FaceIndices xr1 = xrange(len(fi) ) ind = [(fi[i].A, fi[i].B, fi[i].C) for i in xr1] ptslist = [ map(vp.__getitem__, ind[i]) for i in xr1] len1 = int(round(len(ptslist) ) ) / 4 + 1 ptslist = f_chop(ptslist, len1) surf = [None, None, None, None] def ps_generator(i, f_chop = chop1, f_ps1 = PolySurface.ByJoinedSurfaces, f_sf1 = Surface.ByPerimeterPoints): sflist = [f_sf1(pts) for pts in ptslist[i] ] while len(sflist) > 10 : sflist = f_chop(sflist,10) sflist = [f_ps1(sf1) for sf1 in sflist] surf[i] = sflist return def threaded_ps0(): return ps_generator(0) def threaded_ps1(): return ps_generator(1) def threaded_ps2(): return ps_generator(2) def threaded_ps3(): return ps_generator(3) threads = (Thread(ThreadStart(threaded_ps0) ), Thread(ThreadStart(threaded_ps1) ), Thread(ThreadStart(threaded_ps2) ), Thread(ThreadStart(threaded_ps3) ) ) for t in threads: t.Start() for t in threads: t.Join() return f_ps1(surf[0] + surf[1] + surf[2] + surf[3]) for t in threads: t.Finalize()meshes = tolist(IN[0])OUT = output1(map(mesh2ps,meshes) )

在上面的代碼里,Dimitar同時使用了分組和多線程這兩種演算法,運行速度提升很多。這是一種通用的方法。如果我們的地形恰巧是由點坐標文件形成的,而且我們的點位置再平面投影上是嚴格的矩形矩陣形式,如下圖所示:

那麼我們可以使用比較簡單的Dynamo內置節點來組合出一個比較光滑的NurbsSurface。

具體方法如下:

  • 首先提取所有的地形定位點。

  • 將定位點按照指定的規則進行排序,如首先將地形臨時旋轉到點位為水平垂直排布,然後按照行列的XY進行矩陣式組合,形成一個X*Y的二維列表的點集合。

  • 根據點集合的每一項(一系列的點的列表)構建一個PolyCurve或者NurbsCruve,這樣會形成一個Curve的列表。

  • 對Curve的列表使用ByLoft將他們組合成一個Surface或者NurbsSurface。

這樣的流程節點如下:

裡面使用了一個自定義節點,此節點可在QQ群「Dynamo程序設計教程」中下載。

地形在Dynamo中轉換成PolySuface後,還可以進一步生成Solid,具體的操作方法,請關注Dynamo應用秘籍:8。

-------我是分隔線--------

另外需要介紹一下,因為地形的複雜程度不一,尤其是有些時候,還在地形上繪製了SubRegion、道路後,使用Dynamo的節點轉換出來的Mesh可能會有局部位置飛起的亂象,如下圖所示:

因此比較穩妥的方式,還是需要使用Python Script的節點來實現,如下圖:

連載鏈接:上一篇 << ooo >> 下一篇


推薦閱讀:

Dynamo應用秘籍:8:Revit地形到Dynamo的Solid
Dynamo應用秘籍:10:使用周期性運行製作動畫演示
什麼軟體可以給實體模型分層用作激光切割?

TAG:Dynamo | AutoDeskRevit | 参数化设计 |