我正在使用c#通过REVIT创建宏。我想要做的是按特定顺序对对象进行编号,它们按放置级别排序。我希望代码循环遍历第一级,计算对象并对它们进行编号,然后转到计算的第二级并开始使用之前的级别引用进行编号,例如,如果第一组对象的编号从1到1 10然后下一组对象将从11开始编号,直到这组新对象的计数为止,如果它们为5,则编号将为15,依此类推
这是我试过的代码。问题是编号现在每次都从1开始。
public void UniqueTag()
{
Document document = Application.ActiveUIDocument.Document;
FilteredElementCollector collector = new FilteredElementCollector(document);
IList<Element> AllWindows = collector.OfCategory(BuiltInCategory.OST_Windows).OfClass(typeof(FamilyInstance)).ToList(); // gets only placed instances
Transaction tran = new Transaction(document, "Tags Modification");
tran.Start();
int start = 1;
foreach (Element window in AllWindows)
{
string WindowLevel = window.LookupParameter("Level").AsValueString();
FilteredElementCollector LevelCollector = new FilteredElementCollector(document);
ICollection<Element> levels = LevelCollector.OfClass(typeof(Level)).ToElements();
foreach (Level le in levels)
{
var LevelName = le.Name;
if (WindowLevel == LevelName)
{
var query = from element in LevelCollector where element.Name == LevelName select element;
List<Element> level = query.ToList<Element>();
ElementId levelId = level[0].Id;
ElementLevelFilter levelFilter = new ElementLevelFilter(levelId);
LevelCollector = new FilteredElementCollector(document);
ICollection<Element> allWindowssOnLevel = LevelCollector.OfCategory(BuiltInCategory.OST_Windows).OfClass(typeof(FamilyInstance)).WherePasses(levelFilter).ToElements();
int count = allWindowssOnLevel.Count;
for (int i = start; i <= count ; i++) // work correct for the first loop, need to be changed for the second loop
{
foreach (Element e in allWindowssOnLevel)
{
var tag = e.GetParameters("Tag#")[0].Set(i++);
start=count+1;
}//End of foreach allWindowssOnLevel
}//End of for
}//End of if
}//End of foreach levels
}//End of foreachAllWindows
tran.Commit();
} // End of UniqueTag
更新此版本的代码,所有循环之外的计数开始在第一级正确编号窗口,然后从最后一个标记+ 1开始正确跳过第二级和第三级编号窗口。如果在第三个之后有更多级别,则其中没有窗口被编号。
我认为你的错误在于你正在将循环中的标签#本地化。你应该在所有循环之外声明int
,因为你想在循环的层中修改它。实际上,你将它设置为在每个级别从1开始,这是你所有困境的根源。
我也看到了我认为对你的整个循环有轻微的结构错误:你的第一个循环是查看整个文档中的每个窗口。然后,你看看关卡,然后你回头看看关卡的窗户。这意味着你至少要看两次Element
。不仅如此,你将会执行一个潜在的疯狂长循环。如果你有15个级别,每个级别有50个窗口,这意味着你将按如下方式执行:
foreach (Element window in AllWindows) //750 iterations
{
foreach (Level le in levels) //15 iterations
{
for (int i = start; i <= count ; i++) //50 iterations
{
foreach ((Element e in allWindowssOnLevel) //50 iterations
{ //It should also be noted that this is going through the same set of elements as the for loop.
当你通过最后的foreach
循环时,你经历了50次迭代;在for
循环结束时 - 2500次迭代;在foreach (Level le in levels)
循环结束时 - 37,500次迭代;并在foreach (Element window in AllWindows)
循环结束时 - 28,125,000次迭代。所有750个窗口。我认为你应该将它改进为:
int iCtr = 1;
foreach (Level le in levels)
{
var query = from element in LevelCollector where element.Name == LevelName select element;
List<Element> level = query.ToList<Element>();
ElementId levelId = level[0].Id;
ElementLevelFilter levelFilter = new ElementLevelFilter(levelId);
var LevelCollector = new FilteredElementCollector(document);
ICollection<Element> allWindowssOnLevel = LevelCollector.OfCategory(BuiltInCategory.OST_Windows).OfClass(typeof(FamilyInstance)).WherePasses(levelFilter).ToElements();
foreach (Element pElt in allWindowsOnLevel)
{
var tag = e.GetParameters("Tag#")[0].Set(iCtr);
iCtr+=1; //only increments when we set a tag #
} //End of foreach - only runs #OfWindowsOnLevel times/level
}//end of foreach (Level ... ) - only runs #OfLevels
//if we had 15 floor of 50 windows, we only looped 750 times - not 28mil...
我希望这有帮助。我不得不在Revit中处理节点标签,并不总是那么简单。