Problem Creating a FaceWall on a DirectShape Face

Problem Creating a FaceWall on a DirectShape Face

nikita_mitenkovs
Explorer Explorer
241 Views
3 Replies
Message 1 of 4

Problem Creating a FaceWall on a DirectShape Face

nikita_mitenkovs
Explorer
Explorer

Hi everyone,

I'm trying to create a `FaceWall` on the face of a `DirectShape` object of the Mass category. According to the Revit API documentation and The Building Coder article, this should be possible by using the face reference of the `DirectShape` as input for:

 

public static FaceWall Create(
    Document document,
    ElementId wallType,
    WallLocationLine locationLine,
    Reference faceReference
)

 



The relevant documentation states:

"DirectShape elements, by default, support element references, including dimensions, alignments, and face hosting, as well as snapping. This default behavior can be changed using the DirectShapeOptions.ReferencingOption property."

 

Sources:
https://thebuildingcoder.typepad.com/blog/2018/01/directshape-topics-and-happy-new-year.html#4 

https://help.autodesk.com/view/RVT/2024/ENU/?guid=Revit_API_Revit_API_Developers_Guide_Revit_Geometr... 

 

Despite this, I encounter the following error:

Failed to create FaceWall: This reference cannot be applied to a face wall.
Parameter name: faceReference

 

Additionally, I cannot manually select `DirectShape` faces to create a `WallByFace`.

Here's a simplified version of my code:

 

 

# -*- coding: utf-8 -*-
# Imports
from Autodesk.Revit.DB import *
from pyrevit import revit

doc = revit.doc

# Create a rectangle for extrusion
p1 = XYZ(0, 0, 0)
p2 = XYZ(10, 0, 20)
p3 = XYZ(10, 10, 20)
p4 = XYZ(0, 10, 0)

line1 = Line.CreateBound(p1, p2)
line2 = Line.CreateBound(p2, p3)
line3 = Line.CreateBound(p3, p4)
line4 = Line.CreateBound(p4, p1)

curve_loop = CurveLoop()
for line in [line1, line2, line3, line4]:
    curve_loop.Append(line)

# Create DirectShape
with Transaction(doc, 'Create Direct Shape') as t1:
    t1.Start()
    extrusion = GeometryCreationUtilities.CreateExtrusionGeometry([curve_loop], XYZ.BasisX, 100)
    ds = DirectShape.CreateElement(doc, ElementId(BuiltInCategory.OST_Mass))
    ds.SetShape([extrusion])
    ds.Name = "TechMass"
    ds_options = ds.GetOptions()
    ds_options.ReferencingOption = DirectShapeReferencingOption.Referenceable
    ds.SetOptions(ds_options)
    t1.Commit()

# Create FaceWall
with Transaction(doc, 'Create Face Wall') as t2:
    t2.Start()
    opt = Options()
    opt.ComputeReferences = True
    opt.IncludeNonVisibleObjects = True
    opt.View = doc.ActiveView

    # Find largest planar face
    max_face_ref = None
    max_area = 0
    ds_geos = ds.get_Geometry(opt)
    for geo in ds_geos:
        if isinstance(geo, Solid):
            for face in geo.Faces:
                area = face.Area
                if area > max_area and face.GetSurface().Normal:
                    max_area = area
                    max_face_ref = face.Reference

    if max_face_ref:
        try:
            wall = FaceWall.Create(doc, ElementId(771976), WallLocationLine.CoreCenterline, max_face_ref)
        except Exception as e:
            print("Failed to create FaceWall:", e)
    t2.Commit()

 

 

Here is the debug output I receive:
Max face reference found: <Autodesk.Revit.DB.Reference object at 0x0000000000001079 [Autodesk.Revit.DB.Reference]>
Failed to create FaceWall: This reference cannot be applied to a face wall.
Parameter name: faceReference


Additional Notes:

  • I am using two transactions and explicitly setting the `DirectShapeOptions.ReferencingOption` to `Referenceable`.
  • This script is executed using pyRevit

I will also provide screenshots of the DirectShape and its face reference details from RevitLookup:

 

DirectShapeMass.pngDirectShapeMassRevitLookup.pngDirectShapeMassRevitLookup2.png

 

Does anyone know why this reference cannot be applied to create a `FaceWall`? Is there a limitation with `DirectShape` references for this method, or am I missing something in the implementation?

 

Thanks in advance for any help or suggestions!

0 Likes
242 Views
3 Replies
Replies (3)
Message 2 of 4

ricaun
Advisor
Advisor

I never use this FaceWall class.

 

But there is two useful methods to check if the reference is valid and to check if the walltype if valid.

 

var isValidReference = FaceWall.IsValidFaceReferenceForFaceWall(document, reference);
var isValidWallType = FaceWall.IsWallTypeValidForFaceWall(document, wallType);

 

You probably should try to select any face and make sure the IsValidFaceReferenceForFaceWall is true.

 

After some quick testing looks like the FaceWall does not work with DirectShape, only manage to make work in a model In-Place with the category Mass.

 

Here is the command I'm using to create FaceWall in faces.

using Autodesk.Revit.Attributes;
using Autodesk.Revit.DB;
using Autodesk.Revit.UI;
using Autodesk.Revit.UI.Selection;
using System.Linq;

[Transaction(TransactionMode.Manual)]
public class CommandWallFace : IExternalCommand
{
    public Result Execute(ExternalCommandData commandData, ref string message, ElementSet elementSet)
    {
        UIApplication uiapp = commandData.Application;

        UIDocument uidoc = uiapp.ActiveUIDocument;
        Document document = uidoc.Document;
        View view = uidoc.ActiveView;
        Selection selection = uidoc.Selection;

        Reference reference = selection.PickObject(ObjectType.Face, "Select a face");

        while (FaceWall.IsValidFaceReferenceForFaceWall(document, reference) == false)
        {
            reference = selection.PickObject(ObjectType.Face, "Select a face");
        }

        Element wallType = new FilteredElementCollector(document)
            .OfClass(typeof(WallType))
            .Where(e => FaceWall.IsWallTypeValidForFaceWall(document, e.Id))
            .FirstOrDefault();

        var wallTypeId = wallType.Id;

        using (Transaction transaction = new Transaction(document))
        {
            transaction.Start("FaceWall.Create");

            FaceWall.Create(document, wallTypeId, WallLocationLine.WallCenterline, reference);

            transaction.Commit();
        }

        return Result.Succeeded;
    }
}

 

Luiz Henrique Cassettari

ricaun.com - Revit API Developer

AppLoader EasyConduit WireInConduit ConduitMaterial CircuitName ElectricalUtils

0 Likes
Message 3 of 4

nikita_mitenkovs
Explorer
Explorer

Hi Ricaun,

 

Thank you for your reply!

 

I’ve tested this on my end and got the same results as you.


Specifically:

 

var isValidWallType = FaceWall.IsWallTypeValidForFaceWall(document, wallType);

 

This returns true. However,

 

var isValidFaceReference = FaceWall.IsValidFaceReference(document, faceReference);

 

 Always returns false when I pick a face of the DirectShape object and returns true if I pick a face of a manually created InPlaceMass.

 

It feels like there might be some kind of limitation with DirectShape references.

Let me know if you have any further insights or workarounds!

0 Likes
Message 4 of 4

ricaun
Advisor
Advisor

Looks like the FaceWall only works in FamilyInstance with Mass category.

 

Unfortunately is not possible to create a InPlaceMass using the API.

 

But looks like the InPlaceMass and a normal Mass Family is basically the same thing.

 

If you create a Mass Family and put a Solid and create a FaceWall works fine.

 

The FreeFormElement.Create(familyDocument, solid) could be used to create a solid inside the family mass.

 

The annoying part is to load the family template of the mass.

 

Here is a sample that creates the family, loads in the document and create the instance.

[Transaction(TransactionMode.Manual)]
public class CommandCreateMass : IExternalCommand
{
    public Result Execute(ExternalCommandData commandData, ref string message, ElementSet elementSet)
    {
        UIApplication uiapp = commandData.Application;
        Document document = uiapp.ActiveUIDocument.Document;

        var massFamilyTemplate = @"C:\ProgramData\Autodesk\RVT 2025\Family Templates\English-Imperial\Conceptual Mass\Mass.rft";

        var familyDocument = uiapp.Application.NewFamilyDocument(massFamilyTemplate);

        using (Transaction transaction = new Transaction(familyDocument))
        {
            transaction.Start("Create.Mass");
            Solid solid = ricaun.Revit.DB.Shape.ShapeCreator.CreateBox(new XYZ(0, 0, 0), 10);
            FreeFormElement.Create(familyDocument, solid);
            transaction.Commit();
        }

        Family family = familyDocument.LoadFamily(document);

        using (Transaction transaction = new Transaction(document))
        {
            transaction.Start("Create.Instance");

            var symbol = document.GetElement(family.GetFamilySymbolIds().First()) as FamilySymbol;
            symbol.Activate();

            document.Create.NewFamilyInstance(new XYZ(0, 0, 0), symbol, Autodesk.Revit.DB.Structure.StructuralType.NonStructural);

            transaction.Commit();
        }

        familyDocument.Close(false);

        return Result.Succeeded;
    }
}

 

Luiz Henrique Cassettari

ricaun.com - Revit API Developer

AppLoader EasyConduit WireInConduit ConduitMaterial CircuitName ElectricalUtils

0 Likes