- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report
Hi,
I'm very much a beginner in C#, I have written this code and would be grateful for any and all comments (please be gentle!).
I have a ribbon button method which assesses dimensions in a view according to whether they are brick-dimensions... Overriding by colour and adding a suffix. I also have a second method (called from a WPF button) which returns a dialogue to aid users if they have a non-brick dimension (there are fewer cross overs than you might think!).
I would particularly appreciate advice as to structuring my code, handling exceptions and speed enhancements... I am currently filtering through every dimension in the project to see which are visible in the active view. The project might have 10k, but I am only interested in 10... It seems inefficient and slow! I will probably change to a user drag selection if there is no better alternative.
I am not really looking for suggestions as to how to find whether a dimension is a brick-dimension, I have explored various methods and I am happy with this.
I have obviously copied and adjusted many people's code to generate this, thank you everyone for your help.
Cheers,
Mark
using System;
using System.Text;
using System.Linq;
using System.Collections.Generic;
using Autodesk.Revit.UI;
using Autodesk.Revit.DB;
using Autodesk.Revit.UI.Selection;
namespace BrickDims
{
[Autodesk.Revit.Attributes.Transaction(Autodesk.Revit.Attributes.TransactionMode.Manual)]
public class BrickDimsColourOverride : IExternalCommand
{
public Result Execute(ExternalCommandData commandData, ref string message, ElementSet elements)
{
BrickDimsColour(commandData.Application.ActiveUIDocument);
return Result.Succeeded;
}
private void Module_Startup(object sender, EventArgs e)
{
}
private void Module_Shutdown(object sender, EventArgs e)
{
}
public void BrickDimsColour(UIDocument uidoc)
{
//filtered element collector dimensions in active view
//create graphic settings to override dims in view
//CO
OverrideGraphicSettings ogsCO = new OverrideGraphicSettings();
ogsCO.SetProjectionLineColor(new Color(100, 200, 100)); //green
//CO minus
OverrideGraphicSettings ogsCOminus = new OverrideGraphicSettings();
ogsCOminus.SetProjectionLineColor(new Color(100, 100, 200)); //blue
//CO plus
OverrideGraphicSettings ogsCOplus = new OverrideGraphicSettings();
ogsCOplus.SetProjectionLineColor(new Color(200, 200, 50)); //yellow
//Cut
OverrideGraphicSettings ogsCut = new OverrideGraphicSettings();
ogsCut.SetProjectionLineColor(new Color(200, 0, 0)); //red
//Joint
OverrideGraphicSettings ogsJoint = new OverrideGraphicSettings();
ogsJoint.SetProjectionLineColor(new Color(128, 0, 128)); //purple
//Multi
OverrideGraphicSettings ogsMulti = new OverrideGraphicSettings();
ogsMulti.SetProjectionLineColor(new Color(255, 192, 203)); //pink
Transaction transaction = new Transaction(uidoc.Document);
transaction.Start("Colour Dims By Brick Dim");
List<Element> linearDimensions = new FilteredElementCollector(uidoc.Document).OfCategory(BuiltInCategory.OST_Dimensions).ToList();
//error catching list
List<Element> errorCatch = new List<Element>();
//create lists of dimensions
foreach (Dimension dim in linearDimensions)
{
bool test = Container.IsElementVisibleInView(uidoc.ActiveView, dim);
if (test == true)
{
//if empty add to cut brick list list
//we could also check for multi dims and flag to user, poss with split method...
if (dim.Value == null)
{
uidoc.ActiveView.SetElementOverrides(dim.Id, ogsJoint);
//we could probably override suffixes here if we wanted...dim.Suffix = "Joint";
errorCatch.Add(dim);
}
else
{
//get dimension value in mm
double dimValue = Convert.ToDouble(dim.Value);
double dimValueMm = UnitUtils.ConvertFromInternalUnits(dimValue, UnitTypeId.Millimeters);
double dimValueMmRnd = BrickFuncts.round(dimValueMm); //round to 1 dp
if (dimValueMmRnd == 10)
{
//if value == 10, add item to cut brick list
uidoc.ActiveView.SetElementOverrides(dim.Id, ogsJoint);
dim.Suffix = "Joint";
errorCatch.Add(dim);
}
else
{
//divide by CO
double dimCO = dimValueMmRnd / BrickFuncts.CO(1);
//get math floor and set of CO values
double dimCOflr = Math.Floor(dimCO);
double dimCOflrCO = BrickFuncts.round(BrickFuncts.CO(dimCOflr));
double dimCOflrCOminus = BrickFuncts.round(BrickFuncts.COMinus(dimCOflr));
double dimCOflrCOPlus = BrickFuncts.round(BrickFuncts.COPlus(dimCOflr));
//get math ceiling and set of CO values
double dimCOclng = Math.Ceiling(dimCO);
double dimCOclngCO = BrickFuncts.round(BrickFuncts.CO(dimCOclng));
double dimCOclngCOminus = BrickFuncts.round(BrickFuncts.COMinus(dimCOclng));
double dimCOclngCOPlus = BrickFuncts.round(BrickFuncts.COPlus(dimCOclng));
if ((dimValueMmRnd == dimCOflrCO) || (dimValueMmRnd == dimCOclngCO))
{
dim.Suffix = "CO";
uidoc.ActiveView.SetElementOverrides(dim.Id, ogsCO);
errorCatch.Add(dim);
}
else if ((dimValueMmRnd == dimCOflrCOminus) || (dimValueMmRnd == dimCOclngCOminus))
{
dim.Suffix = "CO-";
uidoc.ActiveView.SetElementOverrides(dim.Id, ogsCOminus);
errorCatch.Add(dim);
}
else if ((dimValueMmRnd == dimCOflrCOPlus) || (dimValueMmRnd == dimCOclngCOPlus))
{
dim.Suffix = "CO+";
uidoc.ActiveView.SetElementOverrides(dim.Id, ogsCOplus);
errorCatch.Add(dim);
}
else
{
dim.Suffix = "cut";
uidoc.ActiveView.SetElementOverrides(dim.Id, ogsCut);
errorCatch.Add(dim);
}
}
//sb.AppendLine(dimValueMmRnd.ToString());
}
}
}
//mainDialog.MainInstruction = sb.ToString();
//TaskDialogResult tResult = mainDialog.Show();
if (errorCatch.Count == 0)
{
TaskDialog.Show("fail", "oops that didn't work, perhaps try another view? or adding some dimensions?");
}
transaction.Commit();
}
}
internal class Methods
{
public static void BrickDimCheck(Ui ui, UIDocument uidoc, Document doc)
{
ISelectionFilter dimsFilt = new SelectionFilterDims();
ElementId dimId = uidoc.Selection.PickObject(ObjectType.Element, dimsFilt).ElementId;
Dimension dim = doc.GetElement(dimId) as Dimension;
StringBuilder sb = new StringBuilder();
//if empty add to cut brick list list
//we could also check for multi dims and flag to user, poss with split method...
if (dim.Value == null)
{
sb.Append("Something went wrong, perhaps this is a multi-dim?");
ui.TbDebug.Content = sb.ToString();
//we could probably override suffixes here if we wanted...dim.Suffix = "Joint";
//this is probably a multi one, we could give a list?!
}
else
{
//get dimension value in mm
double dimValue = Convert.ToDouble(dim.Value);
double dimValueMm = UnitUtils.ConvertFromInternalUnits(dimValue, UnitTypeId.Millimeters);
double dimValueMmRnd = BrickFuncts.round(dimValueMm); //round to 1 dp
//divide by CO
double dimCO = dimValueMmRnd / BrickFuncts.CO(1);
//get math floor and set of CO values
double dimCOflr = Math.Floor(dimCO);
double dimCOflrCO = BrickFuncts.round(BrickFuncts.CO(dimCOflr));
double dimCOflrCOminus = BrickFuncts.round(BrickFuncts.COMinus(dimCOflr));
double dimCOflrCOPlus = BrickFuncts.round(BrickFuncts.COPlus(dimCOflr));
//get math ceiling and set of CO values
double dimCOclng = Math.Ceiling(dimCO);
double dimCOclngCO = BrickFuncts.round(BrickFuncts.CO(dimCOclng));
double dimCOclngCOminus = BrickFuncts.round(BrickFuncts.COMinus(dimCOclng));
double dimCOclngCOPlus = BrickFuncts.round(BrickFuncts.COPlus(dimCOclng));
sb.Append("CO-\t\tCO\t\tCO+\n");
sb.Append(dimCOflrCOminus.ToString() + "\t\t" + dimCOflrCO.ToString() + "\t\t" + dimCOflrCOPlus.ToString()+"\n");
sb.Append(dimCOclngCOminus.ToString() + "\t\t" + dimCOclngCO.ToString() + "\t\t" + dimCOclngCOPlus.ToString());
ui.TbDebug.Content = sb.ToString();
ui.DimSelClick.Text = dimValueMmRnd.ToString();
}
}
}
public static class BrickFuncts
{
//base input CO-
public static double brick = 102.5;
//CO for x bricks
public static double CO(double a)
{
return (brick + 10) * a;
}
//co for y bricks
public static double COPlus(double a)
{
return CO(a) + 10;
}
//co- for z bricks
public static double COMinus(double a)
{
return CO(a) - 10;
}
public static double round(double a)
{
return (Math.Round(a * 10)) / 10;
}
}
public static class Container
{
public static bool IsElementVisibleInView(View view, Element el)
{
if (view == null)
{
TaskDialog nullEx = new TaskDialog("That didn't work, perhaps this isn't a view with dimensions?");
TaskDialogResult nullRes = nullEx.Show();
throw new ArgumentNullException(nameof(view));
}
if (el == null)
{
TaskDialog nullEx = new TaskDialog("That didn't work, perhaps you didn't select a dimension?");
TaskDialogResult nullRes = nullEx.Show();
throw new ArgumentNullException(nameof(el));
}
// Obtain the element's document.
Document doc = el.Document;
ElementId elId = el.Id;
// Create a FilterRule that searches
// for an element matching the given Id.
FilterRule idRule = ParameterFilterRuleFactory
.CreateEqualsRule(
new ElementId(BuiltInParameter.ID_PARAM),
elId);
var idFilter = new ElementParameterFilter(idRule);
// Use an ElementCategoryFilter to speed up the
// search, as ElementParameterFilter is a slow filter.
Category cat = el.Category;
var catFilter = new ElementCategoryFilter(cat.Id);
// Use the constructor of FilteredElementCollector
// that accepts a view id as a parameter to only
// search that view.
// Also use the WhereElementIsNotElementType filter
// to eliminate element types.
FilteredElementCollector collector =
new FilteredElementCollector(doc, view.Id)
.WhereElementIsNotElementType()
.WherePasses(catFilter)
.WherePasses(idFilter);
// If the collector contains any items, then
// we know that the element is visible in the
// given view.
return collector.Any();
}
}
public class SelectionFilterDims : ISelectionFilter
{
public bool AllowElement(Element elem)
{
if (elem is Dimension) return true;
return false;
}
public bool AllowReference(Reference refer, XYZ pos)
{
return false;
}
}
}
Solved! Go to Solution.