天天看點

C# Revit二次開發關于元素Element

知識點

     yunyou.ke.qq.com有相關免費課程

    元素Element的基礎概念、如何編輯元素

  • 具體内容
  1. 元素Element基礎

元素在Revit裡面尤其重要,使用者能看見的大多數對象都是元素,比如牆、族、族類型、族執行個體、标高、軸網、視圖等。Revit中的大多數類都是繼承自元素。元素是可序列化的,即是可以儲存到RVT項目檔案中。

(1)相關類圖

  1. 族、族執行個體相關
  1. 模型元素相關
  1. 設定相關
  1. 二維元素
  1. 其他元素
  1. 如何擷取元素

1)通過ID擷取元素: 必須要知道ID才可以擷取到元素。

//============代碼片段3-1通過Id擷取元素============

ElementId levelId = new ElementId(766598);

Element element = RevitDoc.GetElement(levelId);

Level level = element as Level;

if(level != null)

{

   //使用level

}

2)通過過濾器來擷取元素(推薦使用)

//============代碼片段3-2 過濾所有外牆============

FilteredElementCollector filteredElements = new FilteredElementCollector(RevitDoc);

ElementClassFilter classFilter = new ElementClassFilter(typeof(Wall));

filteredElements = filteredElements.WherePasses(classFilter);

foreach (Wall wall in filteredElements)

{

   // 擷取牆類型“功能”參數,它用來訓示牆是否為外牆。

   var functionParameter = wall.WallType.get_Parameter(BuiltInParameter.FUNCTION_PARAM);

   if (functionParameter != null && functionParameter.StorageType == StorageType.Integer)

   {

      if (functionParameter.AsInteger() == (int)WallFunction.Exterior)

      {

         // 使用wall

      }

   }

}

  1. 通過選擇

//============代碼片段3-3 擷取被選元素============

[Autodesk.Revit.Attributes.Transaction(Autodesk.Revit.Attributes.TransactionMode.Manual)]

public class MyExternalCommand : Autodesk.Revit.UI.IExternalCommand

{

   public Autodesk.Revit.UI.Result Execute(Autodesk.Revit.UI.ExternalCommandData commandData,

      ref string message, ElementSet elements)

   {

      if (commandData.Application.ActiveUIDocument != null)

      {

         foreach (Element selected in

            commandData.Application.ActiveUIDocument.Selection.Elements)

         {

            Wall wall = selected as Wall;

            if(wall != null)

            {

               //使用wall

            }

         }

      }

      return Autodesk.Revit.UI.Result.Succeeded;

   }

}

  1. 擷取和修改元素參數

每個元素都有參數,Element.Parameters擷取到所有的參數,然後周遊找到需要的參數。也可以通過Element. get_Paramete(參數)來取得到單個參數,括号裡面的“參數”,有四種選擇:string參數名字、BuiltInParameter參數枚舉、Definition參數定義和Guid參數的guid。

//============代碼片段3-4 擷取“長度”參數============

ParameterSet parameters = element.Parameters;

foreach (Parameter parameter in parameters)

{

   if(parameter.Definition.Name == "長度" && parameter.StorageType == StorageType.Double)

   {

      double length = parameter.AsDouble();

      // 使用length

      break;

   }

}

//============代碼片段3-5 使用BuiltInParameter擷取長度============

Wall wall = null;

//中間有一段代碼就是将wall指派。

Parameter parameterLength = wall.get_Parameter(BuiltInParameter.CURVE_ELEM_LENGTH);

if (parameterLength != null && parameterLength.StorageType == StorageType.Double)

{

   double length = parameterLength.AsDouble();

   // 使用length

}

//============代碼片段3-6 修改參數============直接調用對象的Set方法。

Parameter parameterBaseOffset = wall.get_Parameter(BuiltInParameter.WALL_BASE_OFFSET);

if (parameterBaseOffset != null && parameterBaseOffset.StorageType == StorageType.Double)

{

   if (!parameterBaseOffset.IsReadOnly)

   {

      bool success = parameterBaseOffset.Set(10.0);

      if (!success)

      {

         // 更新錯誤報告

      }

   }

   else

   {

      // 參數是隻讀的

   }

}

//Revit除了内建的參數BuiltInParameter、還允許使用者定義自定義參數:共享參數和項目參數。

//對應的界面上的額菜單分别是“管理—共享參數”、“管理—項目參數”。

//============代碼片段3-7 擷取共享參數============

// 打開共享參數檔案

DefinitionFile definitionFile = RevitApp.OpenSharedParameterFile();

// 擷取參數組的集合

DefinitionGroups groups = definitionFile.Groups;

foreach (DefinitionGroup group in groups)

{

   // 擷取參數組内的參數定義

   foreach (Definition definition in group.Definitions)

   {

      string name = definition.Name;

      ParameterType type = definition.ParameterType;

      // 對參數定義的其他操作

   }

}

//============代碼片段3-8 建立共享參數============

string sharedParametersFilename = @"C:\shared-parameters.txt";

string groupName = "MyGroup";

string definitionName = "MyDefinition";

ParameterType parameterType = ParameterType.Text;

CategorySet categorySet = new CategorySet();

Category wallCategory = RevitDoc.Settings.Categories.get_Item(BuiltInCategory.OST_Walls);

categorySet.Insert(wallCategory);

bool instanceParameter = true;

BuiltInParameterGroup parameterGroup = BuiltInParameterGroup.PG_DATA;

if (!System.IO.File.Exists(sharedParametersFilename))

{

   try

   {

      System.IO.StreamWriter sw = System.IO.File.CreateText(sharedParametersFilename);

      sw.Close();

   }

   catch (Exception)

   {

      throw new Exception("Can't create shared parameter file: " + sharedParametersFilename);

   }

}

// 設定共享參數檔案

RevitApp.SharedParametersFilename = sharedParametersFilename;

// 打開共享參數檔案

DefinitionFile definitionFile = RevitApp.OpenSharedParameterFile();

if (definitionFile == null)

{

   throw new Exception("Can not open shared parameter file!");

}

// 擷取參數組的集合

DefinitionGroups groups = definitionFile.Groups;

// 擷取參數組

DefinitionGroup group = groups.get_Item(groupName);

if (null == group)

{

   // 如果參數組不存在,則建立一個

   group = groups.Create(groupName);

}

if (null == group)

   throw new Exception("Failed to get or create group: " + groupName);

// 擷取參數定義

Definition definition = group.Definitions.get_Item(definitionName);

if (definition == null)

{

   // 如果參數定義不存在,則建立一個

   definition = group.Definitions.Create(definitionName, parameterType);

}

// 調用不同的函數建立類型參數或者執行個體參數

ElementBinding binding = null;

if (instanceParameter)

{

   binding = RevitApp.Create.NewInstanceBinding(categorySet);

}

else

{

   binding = RevitApp.Create.NewTypeBinding(categorySet);

}

// 把參數定義和類别綁定起來(下面的小節會提到“綁定”),元素的新的參數就建立成功了。

bool insertSuccess = RevitDoc.ParameterBindings.Insert(definition, binding, parameterGroup);

if (!insertSuccess)

{

   throw new Exception("Failed to bind definition to category");

}

//============代碼片段3-9 擷取類别和參數的綁定============

BindingMap map = RevitDoc.ParameterBindings;

DefinitionBindingMapIterator dep = map.ForwardIterator();

while (dep.MoveNext())

{

   Definition definition = dep.Key;

   // 擷取參數定義的基本資訊

   string definitionName = definition.Name;

   ParameterType parameterType = definition.ParameterType;

   // 幾乎都可以轉型為InstanceBinding,筆者沒有碰到過其他情況,如有例外,請聯系我們。

   InstanceBinding instanceBinding = dep.Current as InstanceBinding;

   if (instanceBinding != null)

   {

      // 擷取綁定的類别清單

      CategorySet categorySet = instanceBinding.Categories;

   }

}

//============代碼片段3-10 判斷共享參數和項目參數============

Parameter parameter;

InternalDefinition definition = parameter.Definition as InternalDefinition;

bool isSharedParameter = parameter.IsShared; //共享參數

bool isProjectParameter = definition.BuiltInParameter == BuiltInParameter.INVALID && !parameter.IsShared; //項目參數

//============代碼片段3-11 擷取分析模型的幾何資訊============

Element element = RevitDoc.GetElement(new ElementId(183554));

if (element == null) return;

AnalyticalModel analyticalModel = element.GetAnalyticalModel();

if(analyticalModel.IsSingleCurve())

{

   Curve curve = analyticalModel.GetCurve();

   // work with curve

}

else if(analyticalModel.IsSinglePoint())

{

   XYZ p = analyticalModel.GetPoint();

   // work with point

}

else

{

   IList<Curve> curves = analyticalModel.GetCurves(AnalyticalCurveType.ActiveCurves);

   // work with curves

}

//============代碼片段3-12 放置類型為"0762 x 2032 mm"的門============

string doorTypeName = "0762 x 2032 mm";

FamilySymbol doorType = null;

// 在文檔中找到名字為"0762 x 2032 mm"的門類型

ElementFilter doorCategoryFilter = new ElementCategoryFilter(BuiltInCategory.OST_Doors);

ElementFilter familySymbolFilter = new ElementClassFilter(typeof(FamilySymbol));

LogicalAndFilter andFilter = new LogicalAndFilter(doorCategoryFilter, familySymbolFilter);

FilteredElementCollector doorSymbols = new FilteredElementCollector(RevitDoc);

doorSymbols = doorSymbols.WherePasses(andFilter);

bool symbolFound = false;

foreach (FamilySymbol element in doorSymbols)

{

   if (element.Name == doorTypeName)

   {

      symbolFound = true;

      doorType = element;

      break;

   }

}

// 如果沒有找到,就加載一個族檔案

if (!symbolFound)

{

   string file = @"C:\ProgramData\Autodesk\RVT 2014\Libraries\Chinese_INTL\門\M_單-嵌闆 4.rfa";

   Family family;

   bool loadSuccess = RevitDoc.LoadFamily(file, out family);

   if (loadSuccess)

   {

      foreach (ElementId doorTypeId in family.GetValidTypes())

      {

         doorType = RevitDoc.GetElement(doorTypeId) as FamilySymbol;

         if (doorType != null)

         {

            if (doorType.Name == doorTypeName)

            {

               break;

            }

         }

      }

   }

   else

   {

      Autodesk.Revit.UI.TaskDialog.Show("Load family failed", "Could not load family file '" + file + "'");

   }

}

// 使用族類型建立門

if (doorType != null)

{

   // 首先找到線形的牆

   ElementFilter wallFilter = new ElementClassFilter(typeof(Wall));

   FilteredElementCollector filteredElements = new FilteredElementCollector(RevitDoc);

   filteredElements = filteredElements.WherePasses(wallFilter);

   Wall wall = null;

   Line line = null;

   foreach (Wall element in filteredElements)

   {

      LocationCurve locationCurve = element.Location as LocationCurve;

      if (locationCurve != null)

      {

         line = locationCurve.Curve as Line;

         if (line != null)

         {

            wall = element;

            break;

         }

      }

   }

   // 在牆的中心位置建立一個門

   if (wall != null)

   {

      XYZ midPoint = (line.get_EndPoint(0) + line.get_EndPoint(1)) / 2;

      Level wallLevel = RevitDoc.GetElement(wall.LevelId) as Level;

      //建立門:傳入标高參數,作為門的預設标高

      FamilyInstance door = RevitDoc.Create.NewFamilyInstance(midPoint, doorType, wall, wallLevel, Autodesk.Revit.DB.Structure.StructuralType.NonStructural);

      Autodesk.Revit.UI.TaskDialog.Show("Succeed", door.Id.ToString());

      Trace.WriteLine("Door created: " + door.Id.ToString());

   }

   else

   {

      Autodesk.Revit.UI.TaskDialog.Show("元素不存在", "沒有找到符合條件的牆");

   }

}

else

{

   Autodesk.Revit.UI.TaskDialog.Show("族類型不存在", "沒有找到族類型'" + doorTypeName + "'");

}

//============代碼片段3-13 建立拉伸實體族============

//建立族文檔

Document familyDoc = RevitApp.NewFamilyDocument(@"C:\ProgramData\Autodesk\RVT 2014\Family Templates\Chinese\公制正常模型.rft");

using (Transaction transaction = new Transaction(familyDoc))

{

   transaction.Start("Create family");

   CurveArray curveArray = new CurveArray();

   curveArray.Append(Line.CreateBound(new XYZ(0, 0, 0), new XYZ(5, 0, 0)));

   curveArray.Append(Line.CreateBound(new XYZ(5, 0, 0), new XYZ(5, 5, 0)));

   curveArray.Append(Line.CreateBound(new XYZ(5, 5, 0), new XYZ(0, 5, 0)));

   curveArray.Append(Line.CreateBound(new XYZ(0, 5, 0), new XYZ(0, 0, 0)));

   CurveArrArray curveArrArray = new CurveArrArray();

   curveArrArray.Append(curveArray);

   //建立一個拉伸實體

   familyDoc.FamilyCreate.NewExtrusion(true, curveArrArray, SketchPlane.Create(familyDoc, RevitApp.Create.NewPlane(new XYZ(0, 0, 1), XYZ.Zero)), 10);

   //建立一個族類型

   familyDoc.FamilyManager.NewType("MyNewType");

   transaction.Commit();

   familyDoc.SaveAs("MyNewFamily.rfa");

   familyDoc.Close();

}

//============代碼片段3-14 複制牆類型============

Wall wall = RevitDoc.GetElement(new ElementId(185521)) as Wall;

WallType wallType = wall.WallType;

ElementType duplicatedWallType = wallType.Duplicate(wallType.Name + " (duplicated)");

四、總結

1、Revit API提供的元素相關的類。

2、如何擷取元素。

3、擷取和修改元素的參數。