#RTCEUR Wish 3: Scheduling adaptive point location values

Brian asked how to schedule the location value for placement points in adaptive components.

In a post at https://boostyourbim.wordpress.com/2013/02/14/set-adaptive-component-parameter-values-with-placement-point-coordinates/ I showed how user-defined parameters can be automatically updated with XYZ values of adaptive component points.

If instead what you’d like to do is schedule point parameters such as Measurement Type, Chord Length, and Measure From, the workflow could be something like this:

Capture

 

  1. Create user parameters for each point for each of these parameters
    1. Measurement Type 1
    2. Point Location 1
    3. Measurement Type 2
    4. Point Location 2
    5. etc
  2. Use the API to set these values for every family instance
  3. Use dynamic model update to:
    1. automatically update these user parameters any time the reference point parameters change
    2. automatically update the reference point parameters any time the user parameters change

Capture

This code does step 2 listed above. The approach for Step 3 is covered in the post linked above.
You will note that the Measurement Type is stored internally as an integer and we need to convert from that integer to the corresponding string (Chord Length, Segment Length…) so that we can get the length value from the parameter of the same name.

public void adapt()
{
    Document doc = this.ActiveUIDocument.Document;
    using (Transaction t = new Transaction(doc,"Set Adapt Comp Data"))
    {
        t.Start();
        foreach (FamilyInstance fi in new FilteredElementCollector(doc).OfClass(typeof(FamilyInstance)).Cast<FamilyInstance>())
        {
            int ctr = 1;
            foreach (ElementId pointId in AdaptiveComponentInstanceUtils.GetInstancePlacementPointElementRefIds(fi))
            {
                ReferencePoint referencePoint = doc.GetElement(pointId) as ReferencePoint;
                Parameter measurementTypeParam = referencePoint.get_Parameter("Measurement Type");
                if (measurementTypeParam == null)
                    continue;
                
                int i = measurementTypeParam.AsInteger();
                string s = "";
                double paramValue = 0;
                if (i == 1)
                    s = "Non-Normalized Curve Parameter";
                else if (i == 2)
                    s = "Normalized Curve Parameter";
                else if (i == 3)
                    s = "Segment Length";
                else if (i == 4)
                    s = "Normalized Segment Length";
                else if (i == 5)
                    s = "Chord Length";
                
                paramValue = referencePoint.get_Parameter(s).AsDouble();
                
                fi.get_Parameter("Measurement Type " + ctr).Set(s);
                fi.get_Parameter("Point " + ctr).Set(paramValue);
                
                ctr++;
            }
        }
        t.Commit();
    }
}
Advertisements

#RTCEUR Wish 2: Override element display by View Filters

To conclude this set of 3 posts showing how to override display of elements, this shows how to create a view filter for elements with a Comments instance parameter equal to “override”. The list of element ids is used to set this instance parameter. A view filter is created and set to use this rule, the view filter is applied to the view, and the graphics of this filter is overridden.


public void viewFilter()
{
    Document doc = this.ActiveUIDocument.Document;

    OverrideGraphicSettings ogs = new OverrideGraphicSettings();
    ogs.SetCutLineColor(new Color(255,255,0));
    ogs.SetCutLineWeight(6);
    ogs.SetProjectionLineColor(new Color(0,255,255));    
    ogs.SetProjectionLineWeight(6);
    
    IList<ElementId> catIds = new List<ElementId>();
    catIds.Add(doc.Settings.Categories.get_Item("Furniture").Id);
    catIds.Add(doc.Settings.Categories.get_Item("Casework").Id);
    
    IList<FilterRule> rules = new List<FilterRule>();
    ElementId commentParamId = new ElementId(BuiltInParameter.ALL_MODEL_INSTANCE_COMMENTS);
    rules.Add(ParameterFilterRuleFactory.CreateEqualsRule(commentParamId, "override", true));
    using (Transaction t = new Transaction(doc,"View Filter"))
    {
        t.Start();
                        
        foreach (ElementId id in getIds(doc))
        {
            doc.GetElement(id).get_Parameter(BuiltInParameter.ALL_MODEL_INSTANCE_COMMENTS).Set("override");
        }
        
        ParameterFilterElement filter = ParameterFilterElement.Create(doc, "New Filter", catIds, rules);
        doc.ActiveView.AddFilter(filter.Id);
        doc.ActiveView.SetFilterOverrides(filter.Id, ogs);
        t.Commit();
    }
}

#RTCEUR Wish 2: Override graphics by Element

Increasing the complexity a bit from the previous post, this sample shows how to Override Graphics by Element. In this case, the cut & project line weight and color are overridden in the active view for the specified elements.

public void overrideElements()
{
    Document doc = this.ActiveUIDocument.Document;
    OverrideGraphicSettings ogs = new OverrideGraphicSettings();
    ogs.SetCutLineColor(new Color(0,255,0));
    ogs.SetCutLineWeight(6);
    ogs.SetProjectionLineColor(new Color(0,0,255));
    ogs.SetProjectionLineWeight(6);
    using (Transaction t = new Transaction(doc,"Overrides"))
    {
        t.Start();
        foreach (ElementId id in getIds(doc))
        {
            doc.ActiveView.SetElementOverrides(id, ogs);
        }
        t.Commit();
    }
}

#RTCEUR API Wish 2: Override display by element ids (isolate)

@DigDesRev asked “so clash detection gives a report w/ element IDs, can we review the report and on 1 view, override the display settings?”

The simplest way to visualize these elements is with Revit’s ‘Temporary Hide/Isolate’ tool

public void isolateElements()
{
    Document doc = this.ActiveUIDocument.Document;    
    using (Transaction t = new Transaction(doc,"Isolate"))
    {
        t.Start();
        doc.ActiveView.IsolateElementsTemporary(getIds(doc));
        t.Commit();
    }
}

getIds() can be whatever function you want to read a clash detection report from disk, find elements in the Revit model, etc.

#RTCEUR Wish #1: #Revit Change Tracking

Dieter asked “What about a tool that can help you tracking changes in your #Revit model. E.g. select elements that were affected by an indicated change. Eg after updating model from RSA. Maybe a dialog showing the history”

If you want to log every change made to your Revit model and what elements are affected by that change, the DocumentChanged event is what you need.

The code below outputs the time, user name, transaction name, and all added, modified, and deleted elements for each transaction.

For simple annotation operations, the output is relatively straightforward:

10/30/2014 3:58:43 PM,harry_000,Edit Text,ADDED,1074184(Text Notes: 2.5mm Arial),,DELETED,,MODIFIED,
10/30/2014 3:58:54 PM,harry_000,Add Left Arc Leader,ADDED,,DELETED,,MODIFIED,1074184(Text Notes: 2.5mm Arial),
10/30/2014 3:59:02 PM,harry_000,Detail Lines,ADDED,1074193(Lines: Detail Lines),,DELETED,,MODIFIED,
10/30/2014 3:59:11 PM,harry_000,Place Dimensions,ADDED,1074208(Dimensions: Feet & Inches),,DELETED,,MODIFIED,

For other transactions (such as creating a column or moving a grid), the output shows that Revit is making a whole lot of changes.

10/30/2014 4:01:05 PM,harry_000,Structural Column,ADDED,1074223(Structural Columns: L127X127X9.5),1074224(Analytical Columns),1074245(Analytical Nodes),1074246(Analytical Nodes),1074247(Analytical Nodes),1074248(Analytical Nodes),,DELETED,,MODIFIED,102467(AutoJoin Tracker Element),102521(Element to track Analytical Sets during regeneration),103632(GCS Tracker),132466(Hubs Tracker),

10/30/2014 4:01:54 PM,harry_000,Nudge Right,ADDED,,DELETED,,MODIFIED,9745(System Data),86962(System Data),102467(AutoJoin Tracker Element),103632(GCS Tracker),132466(Hubs Tracker),195239(Grids: 2),414482(Structural Columns: M_1000),414483(Analytical Columns),414562(Analytical Nodes),414564(Analytical Nodes),428588(Walls: SIP 202mm Wall – conc clad),428745(Walls: SIP 202mm Wall – conc clad),457479(Windows: Standard),485432(Windows: Standard),554066(Constraints: Alignment),554069(Constraints: Alignment),670283(Dimensions: Feet & Inches),760918(M_1000),857235(<Area Boundary>: Model Lines),857236(<Area Boundary>: Model Lines),857239(),940871(Window Tags: M_Window Tag),940919(Window Tags: M_Window Tag),941385(Dimensions: Feet & Inches),

For a real application you might want to write this data to a database instead of a text file, and build a viewer to get more info about the added and modified elements based on their element ids.

void ControlledApplication_DocumentChanged(object sender, Autodesk.Revit.DB.Events.DocumentChangedEventArgs e)
{
    string file = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments), "CommandLogging.csv");
    using (StreamWriter sw = new StreamWriter(file, true))
    {
        foreach (string transactionName in e.GetTransactionNames())
        {
            sw.Write(DateTime.Now + "," + Utils.username + "," + transactionName);
            sw.Write(",ADDED," + idCollectionToString(e.GetDocument(), e.GetAddedElementIds()));
            sw.Write(",DELETED," + idCollectionToString(e.GetDocument(), e.GetDeletedElementIds()));
            sw.Write(",MODIFIED," + idCollectionToString(e.GetDocument(), e.GetModifiedElementIds()));
            sw.Write(Environment.NewLine);
        }
    }
}

private string idCollectionToString(Document doc, ICollection<ElementId> coll)
{
    string ret = "";
    foreach (ElementId id in coll)
    {
        Element e = doc.GetElement(id);
        string name = "";
        if (e != null)
        {
            string catName = "";
            if (e.Category != null)
                catName = e.Category.Name;
            if (e.Name != "" && catName != "")
                catName += ": ";
            name = "(" + catName + e.Name + ")";
        }
        ret += id.IntegerValue.ToString() + name + ",";
    }
    return ret;
}

It’s Almost #RTCEUR Wishlist Time!

RTC Europe starts tomorrow, and I’m looking forward to my class “Maintaining Order & Preventing Chaos with the Revit API” on Friday morning.

But more importantly, another RTC means another chance for you to send your RTC Wish List ideas and get some free API code written while I’m in Dublin!

So tweet your best ideas for little Revit API apps to https://twitter.com/BoostYourBIM and I look forward to seeing what you dream up. Suggestions from folks who are actually at RTC of course get first priority.