Revit API中的元素的高级过滤

时间:2019-03-04 11:49:17

标签: revit-api revitpythonshell pyrevit

我正在观看此youtube视频(https://www.youtube.com/watch?v=WU_D2qNnuGg&index=7&list=PLc_1PNcpnV5742XyF8z7xyL9OF8XJNYnv)中显示的示例,该示例说明Revit API中的过滤方法优于常规迭代。但是我的代码比迭代方法要慢得多:
筛选器方法-0.16秒
迭代方法-0.06秒

我使用过滤器方法的代码是:

#include <stdio.h>
#include <string.h>

struct game {
  const char *teamA;
  int scoreA;
  const char *teamB;
  int scoreB;
};

struct team {
  const char *teamA;
  int score;
  int wins;
  int losses;
  int ties;
  int scored;
  int suff;

};

struct team team_new(const char *teamA, int score, int wins, int losses, int ties, int scored, int suff)
{
  struct team t;
  t.teamA = strdup(teamA);
  t.score = score;
  t.wins = wins;
  t.losses = losses;
  t.ties = ties;
  t.scored = scored;
  t.suff = suff;

  return t;
};

struct game game_new(const char *teamA, int scoreA, const char *teamB, int scoreB)
{
  struct game g;
  g.teamA = strdup(teamA);
  g.scoreA = scoreA;
  g.teamB = strdup(teamB);
  g.scoreB = scoreB;
  return g;
};

int main(void)
{

  int i, j, teams, nrgames, biggestScore, whichTeam;

  scanf("Teams and number of games %d %d", &teams, &nrgames);

  //add team names to theTeamss struct
  struct team theTeams[teams];
  size_t num_teams = 0;
  for (i = 0; i < teams; ++i)
  {
    char teamA[20];
    if (scanf("%s", teamA) != 1)
      exit(0);
    theTeams[++num_teams] = team_new(teamA, 0, 0, 0, 0, 0, 0);
  }


  struct game games[nrgames]; //add games
  size_t num_games = 0;
  for (i = 0; i < sizeof games / sizeof *games; ++i)
  {
    char teamA[20], teamB[20];
    int scoreA, scoreB;
    if (scanf(" %s %d - %s %d", teamA, &scoreA, teamB, &scoreB) != 4)
      exit(0);
    games[++num_games] = game_new(teamA, scoreA, teamB, scoreB);
  }


     //run through games[] to change values of theTeams[] scores

  //games - A against B
  for (i = 0; i < sizeof games / sizeof *games; ++i)
  {
    for (j = 0; j < sizeof theTeams / sizeof *theTeams; ++j)
    {
      if ((games[i].teamA == theTeams[j].teamA)) //team(A)
      {
        //if A wins
        if(games[i].scoreA > games[i].scoreB)
        {
          theTeams[j].score += 3;
          theTeams[j].wins += 1;
          theTeams[j].scored = games[i].scoreA;
        }
        //if A loses
        else if (games[i].scoreA < games[i].scoreB)
        {
          theTeams[j].score += 0;
          theTeams[j].losses += 1;
          theTeams[j].suff = games[i].scoreB;
        }
        else //tied
        {
          theTeams[j].score += 1;
          theTeams[j].ties += 1;
          theTeams[j].suff = games[i].scoreA;
        }
      }

      if ((games[i].teamB ==  theTeams[j].teamA))//team(B)
      {
        //if B wins
        if(games[i].scoreB > games[i].scoreA)
        {
          theTeams[j].score += 3;
          theTeams[j].wins += 1;
          theTeams[j].scored = games[i].scoreB;
        }
        //if B loses
        else if (games[i].scoreB < games[i].scoreA)
        {
          theTeams[j].score += 0;
          theTeams[j].losses += 1;
          theTeams[j].suff = games[i].scoreA;
        }
        else //tied
        {
          theTeams[j].score += 1;
          theTeams[j].ties += 1;
          theTeams[j].suff = games[i].scoreB;
        }
      }
    }
  }


  //accessing to the winner team
  biggestScore = theTeams[0].score;
  whichTeam = 0;
  for (i = 0; i < sizeof theTeams / sizeof *theTeams; ++i){
    if (theTeams[i].score > biggestScore){
      biggestScore = theTeams[i].score;
      whichTeam = i;

    }
  }

  //output
  printf("\n This winner is %s, with %d point(s), Won %d game(s), tied %d game(s) and lost %d game(s), Scored %d goal(s) e suffered %d goal(s)\n", theTeams[whichTeam].teamA, theTeams[whichTeam].score, theTeams[whichTeam].wins, theTeams[whichTeam].losses, theTeams[whichTeam].ties, theTeams[whichTeam].scored, theTeams[whichTeam].suff);

  return 0;
}

对于迭代,使用以下代码。

import Autodesk.Revit.DB as DB
doc=__revit__.ActiveUIDocument.Document
uidoc=__revit__.ActiveUIDocument

height_param_id=DB.ElementId(DB.BuiltInParameter.WALL_USER_HEIGHT_PARAM)
height_param_prov=DB.ParameterValueProvider(height_param_id)
param_equality=DB.FilterNumericEquals() # equality class
height_value_rule=DB.FilterDoubleRule(height_param_prov,param_equality,10,1e-02)
param_filter=DB.ElementParameterFilter(height_value_rule)

# This program significantly slows down for the next line
walls=DB.FilteredElementCollector(doc)\
                        .WherePasses(param_filter)\
                        .ToElementIds()

uidoc.Selection.SetElementIds(walls) 

2 个答案:

答案 0 :(得分:0)

什么迭代方法?

如今,过滤后的元素收集器通常是检索和遍历Revit数据库元素的唯一方法。

过滤后的元素收集器本身可能很快。

如果墙壁的数量巨大并且内存有限,则对ToElementIds的调用可能会消耗大量资源。

SetElementIds也可能会花费时间。

有关filtered element collector by pipe system types的更多Revit API论坛讨论,以获取更多信息。

我建议您为每个这些方法调用提供一个装有基准代码的complete minimal reproducible sample case,以证明性能下降。

答案 1 :(得分:0)

如果您考虑这两种方法必须考虑的元素数量,这是有道理的。第一种方法:

walls=DB.FilteredElementCollector(doc)\
                        .WherePasses(param_filter)\
                        .ToElementIds()

在这种方法中,您要让过滤器考虑模型中的所有元素。可能有很多元素要通过过滤器。反对:

walls=DB.FilteredElementCollector(doc)\
                        .OfCategory(DB.BuiltInCategory.OST_Walls)\
                        .WhereElementIsNotElementType()\
                        .ToElements()

在这种方法中,您使用QUICK过滤器OfCategory()和另一个WhereElementIsNotElementType()将选择范围缩小到仅Wall个实例。即使您通过一个简单的for循环(此处是缓慢的组件)来进行跟踪,它仍然比通过第一个过滤器传递模型中的所有元素更快。

您可以通过创建过滤器来对其进行优化,如下所示:

walls=DB.FilteredElementCollector(doc)\
                        .OfCategory(DB.BuiltInCategory.OST_Walls)\
                        .WhereElementIsNotElementType()\
                        .WherePasses(param_filter)
                        .ToElements()

这实际上会将快速类别过滤器,元素类型过滤器和慢速参数过滤器组合在一起,从而可能成为整体上更快速,更易于阅读的解决方案。

试试吧,让我知道这是否有意义。

干杯!