#AU2013 Wish granted – Delete topo points in elevation range

Kelly asked “Is it possible to delete points within a range of elevation values?”

Yes!


public void deleteTopoPointsByElevation()
{
    Document doc = this.ActiveUIDocument.Document;
    UIDocument uidoc = new UIDocument(doc);

    double min = 20;
    double max = 30;

    TopographySurface topo = doc.GetElement(uidoc.Selection.PickObject(ObjectType.Element)) as TopographySurface;
    IList<XYZ> pointsToDelete = new List<XYZ>();

    foreach (XYZ pt in topo.GetPoints())
    {
        if (pt.Z > min && pt.Z < max)
            pointsToDelete.Add(pt);
    }

    using (TopographyEditScope tes = new TopographyEditScope(doc, "Topo Edit Scope"))
    {
        tes.Start(topo.Id);

            using (Transaction t = new Transaction(doc, "Update Topo"))
            {
                t.Start();
                topo.DeletePoints(pointsToDelete);
                t.Commit();
            }

        tes.Commit(new myFailuresPreprocessor());
    }
}

public class myFailuresPreprocessor : IFailuresPreprocessor
{
    public FailureProcessingResult PreprocessFailures(FailuresAccessor failuresAccessor)
    {
        return FailureProcessingResult.Continue;
    }
}

#AU2013 Wish granted! Convert multiple dimensions into one

Brok asked “Can you via #Revit API combine individual dims into a single string and remove the old dims?”

Yes!

The tricky part was figuring out how to avoid creating zero-length dimension segments between the references used by adjacent dimensions.

public void dimensionConsolidation()
{
    Document doc = this.ActiveUIDocument.Document;
    Application app = this.Application;
    UIDocument uidoc = new UIDocument(doc);

    IList<ElementId> idsToDelete = new List<ElementId>();
    ReferenceArray dimensionRefsForNewDimension = new ReferenceArray();

    // list of element ids and geometry objects used to weed out duplicate references
    IList<Tuple<ElementId,GeometryObject>> geomObjList = new List<Tuple<ElementId,GeometryObject>>();

    Line line = null;
    DimensionType dimType = null;
    IList<Element> elementList = uidoc.Selection.PickElementsByRectangle();    
    if (elementList.Count == 0)
        return;

    foreach (Element selectedElement in elementList)
    {
        Dimension d = selectedElement as Dimension;
        idsToDelete.Add(d.Id);

        // take the dimension line & dimension type from the first dimension
        if (line == null)
        {
            line = d.Curve as Line;
            dimType = d.DimensionType;
        }

        foreach (Reference dr in d.References)
        {
            Element thisElement = doc.GetElement(dr);
            GeometryObject thisGeomObj = thisElement.GetGeometryObjectFromReference(dr);

            // do not add references to the array if the array already contains a reference
            // to the same geometry element in the same element
            bool duplicate = false;
            foreach (Tuple<ElementId,GeometryObject> myTuple in geomObjList)
            {
                ElementId idInList = myTuple.Item1;
                GeometryObject geomObjInList = myTuple.Item2;
                if (thisElement.Id == idInList && thisGeomObj == geomObjInList)
                {
                    duplicate = true;
                    break;
                }
            }

            if (!duplicate)
            {
                dimensionRefsForNewDimension.Append(dr);
                geomObjList.Add(new Tuple<ElementId, GeometryObject>(thisElement.Id, thisGeomObj));
            }
        }
    }    

    using (Transaction t = new Transaction(doc, "Dimension Consolidation"))
    {
        t.Start();
        Dimension newDim = doc.Create.NewDimension(doc.ActiveView, line, dimensionRefsForNewDimension, dimType);
        doc.Delete(idsToDelete);
        t.Commit();
    }

}

#AU2013 Wish 4 – API-Based Performance Benchmarking

https://twitter.com/PragmaticPrxs says it would be great to have an API-based performance benchmarking tool.

This macro opens every view in the RVT, does some zoom in/zoom out, and iterates through all display styles.  With the Revit 2014 rac_basic_sample_project.rvt, how long does it take to run on your machine?

public void viewPerf()
{
    Document doc = this.ActiveUIDocument.Document;
    Application app = this.Application;
    UIDocument uidoc = new UIDocument(doc);

    Stopwatch sw = new Stopwatch();
    sw.Start();
    int ctr = 0;
    foreach (View v in new FilteredElementCollector(doc)
             .OfClass(typeof(View)).Cast<View>()
             .Where(q => !q.IsTemplate && q.ViewType != ViewType.Internal && q.ViewType != ViewType.ProjectBrowser && q.ViewType != ViewType.Undefined && q.ViewType != ViewType.SystemBrowser && q.ViewType != ViewType.Schedule && q.ViewType != ViewType.ColumnSchedule && q.ViewType != ViewType.PanelSchedule))
    {    
        uidoc.ActiveView = v;                
        uidoc.RefreshActiveView();
        UIView uiview = uidoc.GetOpenUIViews().Cast<UIView>().First(q => q.ViewId == v.Id);
        uidoc.RefreshActiveView();
        uiview.ZoomToFit();
        uidoc.RefreshActiveView();
        uiview.Zoom(2);
        uidoc.RefreshActiveView();
        uiview.Zoom(0.5);
        uidoc.RefreshActiveView();    
        switchDisplayStyles(v, uidoc);

        if (uidoc.GetOpenUIViews().Count > 1)
            uiview.Close();

        ctr++;    
    }
    sw.Stop();
    TaskDialog.Show("Time", sw.Elapsed.ToString());
}

private void switchDisplayStyles(View v, UIDocument uidoc)
{
    if (v.ViewType == ViewType.DraftingView || v.ViewType == ViewType.DrawingSheet || v.ViewType == ViewType.Detail || v.ViewType == ViewType.Legend || v.ViewType == ViewType.Rendering)
        return;

    try
    {
    using (Transaction t = new Transaction(uidoc.Document,"display style"))
    {
        t.Start();
        foreach (DisplayStyle ds in Enum.GetValues(typeof(DisplayStyle)))
        {
            if (ds == DisplayStyle.Undefined || ds == DisplayStyle.Rendering || ds == DisplayStyle.Raytrace)
                continue;

            v.DisplayStyle = ds;
            uidoc.RefreshActiveView();
        }
        t.RollBack();
    }
    }
    catch
    {
        TaskDialog.Show("d",v.ViewType.ToString() + " - " + v.ViewName);
    }
}

#AU2013 Wish #3 – Dockable web browser

Sean asked “Question for you: Is it possible to replace the #Revit Recent Files page with custom HTML, either local file or online?”

There is no straightforward way to replace the Recent Files page (it is built at run-time by Revit). But here are two ways to show a web browser as part of the Revit session.

  1. A modeless, independent dialog with a web browser is showed when Revit starts
  2. A dockable web browser is created after the first Revit file is opened

#AU2013 Wish 2 Granted!

Nancy asked for “auto duplicating and placing views through Design Option set creation”

Here is a macro that creates new views and sheets, with a new view for each design option. Each duplicated view is set to display a different design option and is placed on a sheet in the same location as on the sheet hosting the main model viewport.

public void ViewDuplicateOptions()
{
    Document doc = this.ActiveUIDocument.Document;
    UIDocument uidoc = this.ActiveUIDocument;
    IEnumerable<DesignOption> designOptions = new FilteredElementCollector(doc).OfClass(typeof(DesignOption)).Cast<DesignOption>().Where(q => !q.IsPrimary);
    if (designOptions.Count() == 1)
    {
        TaskDialog.Show("Error","Only one design option exists. No views duplicated.");
        return;
    }

    IList<ViewSheet> newSheets = new List<ViewSheet>();

    IList<ViewSheet> viewSheets = new FilteredElementCollector(doc).OfClass(typeof(ViewSheet)).Cast<ViewSheet>().ToList();

    using (Transaction t = new Transaction(doc,"Duplicate Views by Option"))
    {
        t.Start();
        foreach (ViewSheet vs in viewSheets)
        {
            IEnumerable<Viewport> viewportsOnSheet = new FilteredElementCollector(doc).OfClass(typeof(Viewport)).Cast<Viewport>().Where(q => q.SheetId == vs.Id);
            if (viewportsOnSheet.Count() == 0)
                continue;

            FamilyInstance titleblock = new FilteredElementCollector(doc).OfClass(typeof(FamilyInstance)).OfCategory(BuiltInCategory.OST_TitleBlocks).Cast<FamilyInstance>().First(q => q.OwnerViewId == vs.Id);

            foreach (DesignOption dOpt in designOptions)
            {
                ViewSheet newSheet = ViewSheet.Create(doc, titleblock.GetTypeId());
                newSheet.Name = vs.Name + " - " + dOpt.Name;
                newSheets.Add(newSheet);
                foreach (Viewport vp in viewportsOnSheet)
                {
                    View view = doc.GetElement(vp.ViewId) as View;
                    XYZ vpCenter = vp.GetBoxCenter();
                    View newView = doc.GetElement(view.Duplicate(ViewDuplicateOption.WithDetailing)) as View;
                    newView.Name = view.Name.Replace("{","").Replace("}","") + " - " + dOpt.Name;
                    newView.get_Parameter("Visible In Option").Set(dOpt.Id);
                    Viewport newVp = Viewport.Create(doc, newSheet.Id, newView.Id, vpCenter);
                }
            }
        }
        t.Commit();
    }

    foreach(ViewSheet v in newSheets)
    {
        uidoc.ActiveView = v;
    }
}

#AU2013 Wish 1 Granted!

Matt asked to “duplicate scope box across models”. Open the source file (in this case named “scope boxes.rvt”), then activate the target document and run the macro.

public void CopyScopeBoxBtwDoc()
{
    Document doc = this.ActiveUIDocument.Document;
    Application app = this.Application;

    string filename = "scope boxes.rvt";

    Document sourceDoc = app.Documents.Cast<Document>().FirstOrDefault(q => q.PathName.EndsWith(filename));

    if (sourceDoc == null)
    {
        TaskDialog.Show("Error", "No open document named " + filename);
        return;
    }

    ICollection<ElementId> elementsToCopy = new FilteredElementCollector(sourceDoc).OfCategory(BuiltInCategory.OST_VolumeOfInterest).ToElementIds();

    using (Transaction t = new Transaction(doc,"Copy Scope Box from " + filename))
    {
        t.Start();
        ElementTransformUtils.CopyElements(sourceDoc, elementsToCopy, doc, Transform.Identity, new CopyPasteOptions());
        t.Commit();
    }

}