We demonstrated how to create custom Performance Advisor Rule (IPerformanceAdviserRule) before such as the WallCanNotBeTooShort both from scratch and with the assistance of the Performance Advisor Rule Creator of RevitAddinWizard.
In this post, let us create another custom Performance Advisor Rule (IPerformanceAdviserRule), TooManyDoorsInWall.
Here is the main class to implement the IPerformanceAdviserRule interface.
#region Namespaces
using System;
using System.Text;
using System.Linq;
using System.Xml;
using System.Reflection;
using System.ComponentModel;
using System.Collections;
using System.Collections.Generic;
using System.Windows;
using System.Windows.Media.Imaging;
using System.Windows.Forms;
using System.IO;
using Autodesk.Revit.ApplicationServices;
using Autodesk.Revit.Attributes;
using Autodesk.Revit.DB;
using Autodesk.Revit.DB.Events;
using Autodesk.Revit.DB.Architecture;
using Autodesk.Revit.DB.Structure;
using Autodesk.Revit.DB.Mechanical;
using Autodesk.Revit.DB.Electrical;
using Autodesk.Revit.DB.Plumbing;
using Autodesk.Revit.UI;
using Autodesk.Revit.UI.Selection;
using Autodesk.Revit.UI.Events;
using Autodesk.Revit.Collections;
using Autodesk.Revit.Exceptions;
using Autodesk.Revit.Utility;
using RvtApplication = Autodesk.Revit.ApplicationServices.Application;
using RvtDocument = Autodesk.Revit.DB.Document;
#endregion
namespace RevitAddinCS1
{
public class TooManyDoorsInWall : IPerformanceAdviserRule
{
private List<ElementId> mElementIds;
public static PerformanceAdviserRuleId RuleId = new PerformanceAdviserRuleId(new Guid("d0247ab5-6725-45a4-8a54-748bcba76dab"));
public static FailureDefinitionId FailureDefId = new FailureDefinitionId(new Guid("37f01ddd-6117-4b09-94b8-276617350828"));
public TooManyDoorsInWall()
{
//Construct the element list and the failure definition object.
mElementIds = new List<ElementId>();
FailureDefinition.CreateFailureDefinition(FailureDefId, FailureSeverity.Warning, "Cannot Create More Than 2 Doors in a Single Wall");
}
public void InitCheck(RvtDocument document)
{
//Clear the cached element list for this run.
mElementIds.Clear();
}
public void ExecuteElementCheck(RvtDocument document, Element element)
{
if (element is FamilyInstance)
{
//TODO: add the element checking code below and collect the element of interest into the list. e.g.
//NOTE: The following code was manually added.
if (mElementIds.Count > 0) return; //Already found some bad doors.
Wall host = (element as FamilyInstance).Host as Wall;
if (element.Category.Id.IntegerValue == (int)BuiltInCategory.OST_Doors && host != null)
{
IList<ElementId> inserts = host.FindInserts(false, false, false, false);
using (SubTransaction subT = new SubTransaction(document))
{
IEnumerable<ElementId> doors = from ElementId id in inserts
where (document.get_Element(id)).Category.Id.IntegerValue == (int)BuiltInCategory.OST_Doors
select id;
if (doors.Count() > 2)
{
mElementIds.AddRange(doors); //Add all to the list so that users can choose which to keep or delete.
}
}
}
}
}
public void FinalizeCheck(RvtDocument document)
{
//Set the failing elements as collected above and post the failure message as created at top.
if (mElementIds != null && mElementIds.Count > 0)
{
FailureMessage fm = new FailureMessage(FailureDefId);
fm.SetFailingElements(mElementIds);
PerformanceAdviser.GetPerformanceAdviser().PostWarning(fm);
}
}
public bool WillCheckElements()
{
//NOTE: by default the performance advisor rule will check elements. change it to false if necessary.
return true;
}
public ElementFilter GetElementFilter(RvtDocument document)
{
//NOTE: change the class filter if necessary.
return new ElementClassFilter(typeof(FamilyInstance));
}
public string GetDescription()
{
return "Too Many Doors In Wall";
}
public string GetName()
{
return "TooManyDoorsInWall";
}
}
}
Here is the registration and unregistration code:
public Result OnStartup(UIControlledApplication uiApp)
{
try
{
Autodesk.Revit.DB.PerformanceAdviser.GetPerformanceAdviser().AddRule(TooManyDoorsInWall.RuleId, new TooManyDoorsInWall());
return Result.Succeeded;
}
catch (Exception ex)
{
MessageBox.Show( ex.ToString() );
return Result.Failed;
}
}
public Result OnShutdown(UIControlledApplication uiApp)
{
try
{
Autodesk.Revit.DB.PerformanceAdviser.GetPerformanceAdviser().DeleteRule(TooManyDoorsInWall.RuleId);
return Result.Succeeded;
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString());
return Result.Failed;
}
}
Here is the code to execute the custom performance advisor rule.
PerformanceAdviser adviser = PerformanceAdviser.GetPerformanceAdviser();
PerformanceAdviserRuleId ruleId = TooManyDoorsInWall.RuleId;
if (ruleId != null)
{
IList<FailureMessage> msgList = adviser.ExecuteRules(CachedDoc, new List<PerformanceAdviserRuleId> { ruleId });
Transaction tr = new Transaction(CachedDoc, "FailureMessage Posting");
tr.Start();
foreach (FailureMessage m in msgList)
{
CachedDoc.PostFailure(m);
}
tr.Commit();
}
Here is the checking result for some such doors in a single wall.
If the last two doors are selected and the Delete Checked… button is pressed, they will be removed from the wall to meet the custom performance advisor rule.
Readers may have already noticed that most of the above code was automatically generated by the Performance Advisor Rule Creator of RevitAddinWizard. The RevitAddinWizard will not only save time but also guarantee that a valid Performance Advisor Rule (IPerformanceAdviserRule) will be there with wanted options. It can be found and downloaded from bottom link on the blog index page.
Recent Comments