🎁
PythonとC#で始めるRevit API
作成したコードのGithubはこちらです
ISelectionFilterについて
FamilyInstance
でフィルタリング
例1 DB classのC#の場合
public class ClassISelectionFilter : ISelectionFilter
{
public bool AllowElement(Element elem)
{
if (elem is FamilyInstance) return true;
return false;
}
public bool AllowReference(Reference refer, XYZ pos)
{
return false;
}
}
Pythonの場合
class ClassISelectionFilter(UI.Selection.ISelectionFilter):
def AllowElement(self, e):
if isinstance(e, DB.FamilyInstance):
return True
else:
return False
例2 Categoryの名前でフィルタリング
C#の場合
public class CategoryISelectionFilterByName : ISelectionFilter
{
string catName = String.Empty;
public CategoryISelectionFilterByName(String selectedCatName)
{
catName = selectedCatName;
}
public bool AllowElement(Element elem)
{
if (elem.Category.Name == catName ) return true;
return false;
}
public bool AllowReference(Reference refer, XYZ pos)
{
return false;
}
}
Pythonの場合
class CategoryISelectionFilterByName(UI.Selection.ISelectionFilter):
def __init__(self, bi_cat):
self.bi_cat = bi_cat
def AllowElement(self, e):
if e.Category.Name == self.bi_cat:
return True
else:
return False
例3 BuiltInCategoryでフィルタリング
public class CategoryISelectionFilterByName : ISelectionFilter
{
string catName = String.Empty;
public CategoryISelectionFilterByName(String selectedCatName)
{
catName = selectedCatName;
}
public bool AllowElement(Element elem)
{
if (elem.Category.Name == catName ) return true;
return false;
}
public bool AllowReference(Reference refer, XYZ pos)
{
return false;
}
}
Pythonの場合
class CategoryISelectionFilterByBuiltInCategory(UI.Selection.ISelectionFilter):
def __init__(self, bi_cat):
self.bi_cat = bi_cat
def AllowElement(self, e):
if e.Category.Id.IntegerValue == int(self.bi_cat):
return True
else:
return False
FilteredElementCollectorについて
FamilyType
をコレクトする
特定のC#の場合
リスト内はFamilyInstance classであるため違うタイプとして利用するためにはキャストする必要があります。
List<FamilyInstance> selectedElements = new FilteredElementCollector(doc)
.OfClass(typeof(FamilyInstance))
.WhereElementIsNotElementType()
.Where(e => e.GetTypeId() == sourceFI.GetTypeId())
.Cast<FamilyInstance>()
.ToList();
Pythonの場合
Revit Python Wrapper(rpw)を使用しています。rpwはpyRevitの標準機能としてついていますので、追加設定をする必要なく使用可能です。get_elements()
によりDB
クラスのElementではなく、rpw
クラスのElementになります。どのようなことができるかはこちらをご参照ください。
from rpw import db
selected_elements = db.Collector(
of_class="FamilyInstance",
is_not_type = True,
where=lambda x: x.GetTypeId() == source_fi.GetTypeId()).get_elements()
Room Propertyについて
FamilyInstanceクラスの例 選択したRoomに所属するものだけ条件分岐する
C#の場合
foreach (FamilyInstance fi in selectedElements)
{
if (fi.Room.Id == sourceRoom.Id)
{
do something
}
else
{
do other stuff
}
}
Pythonの場合
Pythonで使う場合にはPhaseを指定する必要があります。様々なPhaseの取得方法はあるかと思いますが、ここでは一例を紹介してます。
def get_phase(phase_name):
phases = doc.Phases
for p in phases:
if p.Name == phase_name:
return p
phase = get_phase(phase_name)
for e in selected_elements:
if e.Room[phase].Id == source_room.Id:
do something
else:
do other stuff
Transactionについて
選択したElementのパラメータに値をセットする
C#の場合
Transaction tx = new Transaction(doc, "Selected Element by CSharp");
tx.Start();
((Element)fi).LookupParameter("Selected Comment").Set("Selected");
tx.Commit();
Pythonの場合
with db.Transaction("Selected Element by Python"):
e.parameters['Selected Comment'].value = "Selected"
TaskDialogについて
取得結果の表示
C#の場合
TaskDialog dialog = new TaskDialog("Selected Elements/Room");
dialog.TitleAutoPrefix = false;
dialog.MainInstruction = $"Room Name: {sourceRoom.Name} Room Number: {((SpatialElement)sourceRoom).Number}";
dialog.MainContent = $"Family Name: {sourceFI.Name}\nType Name: {((FamilyInstance)sourceFI).Symbol.FamilyName}\nFamily Count: {selectedElementByRoom.Count}";
dialog.Show();
Pythonの場合
from rpw import ui
ui.forms.Alert(
"Family Name: {}\nType Name: {}\nFamily Count: {}".format(source_fi.Symbol.FamilyName, db.Element(source_fi).name, len(selected_element_by_room)), title="Selected Elements/Room", header="Room Name: {} Room Number: {}".format(db.Room(source_room).name, source_room.Number))
Selection.SetElementIdsについて
List[]の使い方
C#の場合
List<ElementId> selectedElementByRoom = new List<ElementId>();
foreach (FamilyInstance fi in selectedElements)
{
selectedElementByRoom.Add(fi.Id);
}
uidoc.Selection.SetElementIds(selectedElementByRoom);
Pythonの場合
from System.Collections.Generic import List
selected_element_by_room = []
for e in selected_elements:
selected_element_by_room.append(e)
uidoc.Selection.SetElementIds(List[DB.ElementId](e.Id for e in selected_element_by_room))
参考
作成したコード
C#の場合
#region Namespaces
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using Autodesk.Revit.ApplicationServices;
using Autodesk.Revit.Attributes;
using Autodesk.Revit.DB;
using Autodesk.Revit.DB.Architecture;
using Autodesk.Revit.UI;
using Autodesk.Revit.UI.Selection;
#endregion
namespace Selector.pushbutton
{
[Transaction(TransactionMode.Manual)]
public class Command : IExternalCommand
{
public Result Execute(
ExternalCommandData commandData,
ref string message,
ElementSet elements)
{
UIApplication uiapp = commandData.Application;
UIDocument uidoc = uiapp.ActiveUIDocument;
Application app = uiapp.Application;
Document doc = uidoc.Document;
List<ElementId> selectedElementByRoom = new List<ElementId>();
ISelectionFilter classFilter = new ClassISelectionFilter();
Reference familyInstanceReference = uidoc.Selection.PickObject(ObjectType.Element, classFilter, "Select FamilyInstance");
ISelectionFilter catFilterByName = new CategoryISelectionFilterByName("Rooms");
Reference roomReference = uidoc.Selection.PickObject(ObjectType.Element, catFilterByName, "Select Room");
ISelectionFilter catFilterByBuiltInCategory = new CategoryISelectionFilterByBuiltInCategory(BuiltInCategory.OST_Rooms);
// Reference roomReference = uidoc.Selection.PickObject(ObjectType.Element, catFilterByBuiltInCategory, "Select Room");
Element sourceFI = doc.GetElement(familyInstanceReference.ElementId);
Element sourceRoom = doc.GetElement(roomReference.ElementId);
List<FamilyInstance> selectedElements = new FilteredElementCollector(doc)
.OfClass(typeof(FamilyInstance))
.WhereElementIsNotElementType()
.Where(e => e.GetTypeId() == sourceFI.GetTypeId())
.Cast<FamilyInstance>()
.ToList();
View view = uidoc.ActiveView;
Transaction tx = new Transaction(doc, "Selected Element by CSharp");
tx.Start();
foreach (FamilyInstance fi in selectedElements)
{
if (fi.Room.Id == sourceRoom.Id)
{
selectedElementByRoom.Add(fi.Id);
((Element)fi).LookupParameter("Selected Comment").Set("Selected");
}
else
{
((Element)fi).LookupParameter("Selected Comment").Set("");
}
}
tx.Commit();
TaskDialog dialog = new TaskDialog("Selected Elements/Room");
dialog.TitleAutoPrefix = false;
dialog.MainInstruction = $"Room Name: {sourceRoom.Name} Room Number: {((SpatialElement)sourceRoom).Number}";
dialog.MainContent = $"Family Name: {sourceFI.Name}\nType Name: {((FamilyInstance)sourceFI).Symbol.FamilyName}\nFamily Count: {selectedElementByRoom.Count}";
dialog.Show();
uidoc.Selection.SetElementIds(selectedElementByRoom);
return Result.Succeeded;
}
}
public class ClassISelectionFilter : ISelectionFilter
{
public bool AllowElement(Element elem)
{
if (elem is FamilyInstance) return true;
return false;
}
public bool AllowReference(Reference refer, XYZ pos)
{
return false;
}
}
public class CategoryISelectionFilterByName : ISelectionFilter
{
string catName = String.Empty;
public CategoryISelectionFilterByName(String selectedCatName)
{
catName = selectedCatName;
}
public bool AllowElement(Element elem)
{
if (elem.Category.Name == catName ) return true;
return false;
}
public bool AllowReference(Reference refer, XYZ pos)
{
return false;
}
}
public class CategoryISelectionFilterByBuiltInCategory : ISelectionFilter
{
BuiltInCategory BIC = BuiltInCategory.INVALID;
public CategoryISelectionFilterByBuiltInCategory(BuiltInCategory bic)
{
BIC = bic;
}
public bool AllowElement(Element elem)
{
if (((BuiltInCategory)elem.Category.Id.IntegerValue) == BIC) return true;
return false;
}
public bool AllowReference(Reference refer, XYZ pos)
{
return false;
}
}
}
Pythonの場合
# -*- coding: utf-8 -*-
from Autodesk.Revit import DB, UI
from rpw import db, ui
from System.Collections.Generic import List
uiapp = __revit__ # noqa F821
uidoc = uiapp.ActiveUIDocument
app = uiapp.Application
doc = uidoc.Document
class ClassISelectionFilter(UI.Selection.ISelectionFilter):
def AllowElement(self, e):
if isinstance(e, DB.FamilyInstance):
return True
else:
return False
class CategoryISelectionFilterByName(UI.Selection.ISelectionFilter):
def __init__(self, bi_cat):
self.bi_cat = bi_cat
def AllowElement(self, e):
if e.Category.Name == self.bi_cat:
return True
else:
return False
class CategoryISelectionFilterByBuiltInCategory(UI.Selection.ISelectionFilter):
def __init__(self, bi_cat):
self.bi_cat = bi_cat
def AllowElement(self, e):
if e.Category.Id.IntegerValue == int(self.bi_cat):
return True
else:
return False
def main():
selected_element_by_room = []
family_instance_reference = uidoc.Selection.PickObject(
UI.Selection.ObjectType.Element,
ClassISelectionFilter(),
"Select FamilyInstance")
room_reference = uidoc.Selection.PickObject(
UI.Selection.ObjectType.Element,
CategoryISelectionFilterByName("Rooms"),
"Select Room")
"""
room_reference = uidoc.Selection.PickObject(
UI.Selection.ObjectType.Element,
CategoryISelectionFilterByBuiltInCategory(
DB.BuiltInCategory.OST_Rooms),
"Select Room")
"""
source_fi = doc.GetElement(family_instance_reference.ElementId)
source_room = doc.GetElement(room_reference.ElementId)
# print(source_fi)
selected_elements = db.Collector(
of_class="FamilyInstance",
is_not_type = True,
where=lambda x: x.GetTypeId() == source_fi.GetTypeId()).get_elements()
view = uidoc.ActiveView
phase_name = view.get_Parameter(DB.BuiltInParameter.VIEW_PHASE).AsValueString()
phase = get_phase(phase_name)
with db.Transaction("Selected Element by Python"):
for e in selected_elements:
if e.Room[phase].Id == source_room.Id:
selected_element_by_room.append(e)
e.parameters['Selected Comment'].value = "Selected"
else:
e.parameters['Selected Comment'].value = ""
ui.forms.Alert(
"Family Name: {}\nType Name: {}\nFamily Count: {}".format(source_fi.Symbol.FamilyName, db.Element(source_fi).name, len(selected_element_by_room)), title="Selected Elements/Room", header="Room Name: {} Room Number: {}".format(db.Room(source_room).name, source_room.Number))
uidoc.Selection.SetElementIds(List[DB.ElementId](e.Id for e in selected_element_by_room))
def get_phase(phase_name):
phases = doc.Phases
for p in phases:
if p.Name == phase_name:
return p
if __name__ == "__main__":
main()
Discussion