Creating a mass from Toposurface geometry

Following up this suggestion from Julien, here’s a look at how to create a massing family with geometry built from the mesh of a toposurface.

public void topoToMass()
    Document doc = this.ActiveUIDocument.Document;
    UIDocument uidoc = this.ActiveUIDocument;
    Application app = this.Application;

    TopographySurface topo = doc.GetElement(uidoc.Selection.PickObject(ObjectType.Element)) as TopographySurface;

    Mesh mesh = topo.get_Geometry(new Options()).First(q => q is Mesh) as Mesh;

    Document famDoc = app.NewFamilyDocument(@"C:\ProgramData\Autodesk\RAC 2014\Family Templates\English_I\Conceptual Mass\Mass.rft");

    using (Transaction t = new Transaction(famDoc,"Create massing surfaces"))

        for (int i = 0; i < mesh.NumTriangles; i++)
            MeshTriangle mt = mesh.get_Triangle(i);
            makeForm(famDoc, mt.get_Vertex(0), mt.get_Vertex(1), mt.get_Vertex(2));

            if (i > 0 && i % 100 == 0)
                TaskDialog td = new TaskDialog("Form Counter");
                td.CommonButtons = TaskDialogCommonButtons.Yes|TaskDialogCommonButtons.No;
                td.MainInstruction = i + " out of " + mesh.NumTriangles + " triangles processed. Do you want to continue?";
                if (td.Show() == TaskDialogResult.No)

private Form makeForm(Document doc, XYZ pt1, XYZ pt2, XYZ pt3)
    Form form = null;

    XYZ u = pt2.Subtract(pt1);
    XYZ v = pt3.Subtract(pt1);
    double area = u.CrossProduct(v).GetLength()/2;
    if (area < 10)
        return null;

    ReferenceArray ra = new ReferenceArray();
    ra.Append(MakeCuveByPoints(doc, pt1, pt2).GeometryCurve.Reference);
    ra.Append(MakeCuveByPoints(doc, pt2, pt3).GeometryCurve.Reference);
    ra.Append(MakeCuveByPoints(doc, pt3, pt1).GeometryCurve.Reference);

    form = doc.FamilyCreate.NewFormByCap(true, ra);

    return form;

private CurveByPoints MakeCuveByPoints(Document doc, XYZ ptA, XYZ ptB)
    ReferencePointArray rpa = new ReferencePointArray();
    return doc.FamilyCreate.NewCurveByPoints(rpa);

11 thoughts on “Creating a mass from Toposurface geometry

  1. Hi, this looks extremely useful thanks for sharing the code. I am unable to run the code though, it always throws an exception when I go to load the family ‘famDoc.LoadFamily(doc);’? Do you know whats going wrong and how I can fix it? The exception is ‘Revit encountered a System.Runtime.InteropServices.SEHException: External component has thrown an exception.’

    The code is exactly like your sample except that the path to ‘Mass.rft’ is different on my computer (using Revit 2014 in Australia); theres no ‘C:\ProgramData\Autodesk\RAC 2014\Family Templates\English_I\Conceptual Mass\Mass.rft’ but I do have ‘C:\ProgramData\Autodesk\RVT 2014\Family Templates\English\Conceptual Mass\Metric Mass.rft’ which is what I am using. Maybe this is the cause of the error?

  2. Harry,

    I was running in to the same issue as above. It turns out the problem was the LoadFamily was returning this error if you didn’t have SP2 installed. Installed that and the program runs without a hitch.

  3. Hi Harry,

    I have a question. Is there any way where we can code the api so that it is placed exactly on the topo-surface. I might need to create the mass and discard the topo-surface. Please advise.



    • The easiest way would be to use the Element.Location property, but that property has no data for a toposurface. Perhaps it would work to match the BoundingBox.Min or Max points for the topo and family instance.

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s