Revit 2012 API 新引入了 GeometryCreationUtilities 類來幫助創建實體。然而它沒有提供直接的球體創建方法,而是提供了以下五個根據輸入曲線創建幾何實體的輔助方法:
CreateBlendGeometry 融合
CreateExtrusionGeometry 拉伸
CreateRevolvedGeometry 旋轉
CreateSweptGeometry 放樣
CreateSweptBlendGeometry 放樣融合
創建之後的幾何結果並不會作為元素添加到文檔中。不過你可以使用創建的實體、實體的面和邊做如下操作:
- 作為Analysis Visualization Framework(AVF)方法的面輸入參數
例如:SpatialFieldManager.AddSpatialFieldPrimitive
- 作為確定三維元素空間相交情況的實體輸入參數
- 作為布爾操作的輸入參數
- 作為幾何計算的輸入參數
例如:面投影(Face.Project)、面相交(Face.Intersect)、和其它有關面、實體、邊的幾何方法
既然這種方式創建的實體只存在於內存中,無法添加到 Revit 文件數據庫與文件一起保存,那它們有什麼作用呢?
正如我們上面提到的,你可以使用這些實體通過AVF來可視化地顯示一些結果;或者在搜索相交元素時(ElementIntersectsFilter)將范圍限定在一個空間區域。
創建球體
我們可以使用 CreateRevolvedGeometry() 方法:首先創建一個表示半圓的閉合曲線,包括180度的圓弧和連接圓弧兩個端點的直線(即經過圓心的直徑線)。然後將半圓面以直徑線為軸旋轉360度就可以了。
這裡我們首先需要創建一個 Revit 稱之為 Frame 的對象。為了使我的代碼能允許在任意位置創建球體,我還需要將球心和球半徑作為輸入參數。我可以使用球心來定義 Frame 的位置。起初我以為既然半圓面的閉合曲線是針對全局坐標系的,那麼 Frame 應該會自動將半圓面的其它幾何數據轉換為全局坐標系。但是當我使用以球心為原點的局部坐標系定義圓弧和直徑線時,CreateRevolvedGeometry() 方法會拋出異常:閉合曲線必須位於Z軸的右側(X坐標 >= 0)。
所以我們必須在創建圓弧和直徑線時,就使用已經轉換到全局坐標系的坐標值。
[csharp
<span style="font-size:12px;"> /// <summary>
/// 使用指定的球心和半徑創建球體
/// </summary>
static public Solid CreateSphereAt(
CreationApp creapp,
XYZ centre,
double radius )
{
// 使用標准的全局坐標系創建 Frame
Frame frame = new Frame( centre,
XYZ.BasisX, XYZ.BasisY, XYZ.BasisZ );
// 創建一個Z軸方向的半圓閉合曲線(注意所有的坐標都是相對全局坐標系的)
Arc arc = creapp.NewArc(
centre - radius * XYZ.BasisZ,
centre + radius * XYZ.BasisZ,
centre + radius * XYZ.BasisX );
Line line = creapp.NewLineBound(
arc.get_EndPoint( 1 ),
arc.get_EndPoint( 0 ) );
CurveLoop halfCircle = new CurveLoop();
halfCircle.Append( arc );
halfCircle.Append( line );
List<CurveLoop> loops = new List<CurveLoop>( 1 );
loops.Add( halfCircle );
return GeometryCreationUtilities
.CreateRevolvedGeometry(
frame, loops, 0, 2 * Math.PI );
}</span>
使用AVF顯示實體
使用幾何創建工具類創建的臨時實體的一個重要用途就是用於根據幾何特征過濾元素,我會在最近另外討論這個問題。現在先讓我們使用AVF顯示這些幾何實體。
[csharp]
void PaintSolids(
Document doc,
Solid solid,
int level )
{
Application app = doc.Application;
View view = doc.ActiveView;
if( view.AnalysisDisplayStyleId == ElementId.InvalidElementId )
{
CreateAvfDisplayStyle( doc, view );
}
SpatialFieldManager sfm = SpatialFieldManager.GetSpatialFieldManager( view );
if( null == sfm )
{
sfm = SpatialFieldManager.CreateSpatialFieldManager( view, 1 );
}
if( _schemaId != -1 )
{
IList<int> results = sfm.GetRegisteredResults();
if( !results.Contains( _schemaId ) )
{
_schemaId = -1;
}
}
if( _schemaId == -1 )
{
AnalysisResultSchema resultSchema = new AnalysisResultSchema( "PaintedSolids", "Description" );
_schemaId = sfm.RegisterResult( resultSchema );
}
FaceArray faces = solid.Faces;
Transform trf = Transform.Identity;
foreach( Face face in faces )
{
int idx = sfm.AddSpatialFieldPrimitive( face, trf );
IList<UV> uvPts = new List<UV>( 1 );
uvPts.Add( face.GetBoundingBox().Min );
FieldDomainPointsByUV pnts = new FieldDomainPointsByUV( uvPts );
List<double> doubleList = new List<double>( 1 );
doubleList.Add( level );
IList<ValueAtPoint> valList = new List<ValueAtPoint>( 1 );
valList.Add( new ValueAtPoint( doubleList ) );
FieldValues vals = new FieldValues( valList );
sfm.UpdateSpatialFieldPrimitive( idx, pnts, vals, _schemaId );
}
}