#BILTNA2018 Wish granted: Align a straight wall with a curved grid

The problem:

The solution:

public void alignWallToCurvedGrid()
{
    UIDocument uidoc = this.ActiveUIDocument;
    Document doc = this.ActiveUIDocument.Document;
    Wall wall = doc.GetElement(uidoc.Selection.PickObject(ObjectType.Element, "Select wall")) as Wall;
    Grid grid = doc.GetElement(uidoc.Selection.PickObject(ObjectType.Element, "Select grid")) as Grid;
    Curve gridCurve = grid.Curve;
    Line wallLine = (((LocationCurve)wall.Location).Curve as Line);
    XYZ wallDirection = wallLine.Direction;
    XYZ wallPerpendicular = XYZ.BasisZ.CrossProduct(wallDirection);
    
    XYZ intersection0 = intersect(wallLine.GetEndPoint(0), wallPerpendicular, gridCurve);
    XYZ intersection1 = intersect(wallLine.GetEndPoint(1), wallPerpendicular, gridCurve);
    XYZ intersectionMid = intersect(wallLine.Evaluate(0.5, true), wallPerpendicular, gridCurve);
    
    Arc arc = Arc.Create(intersection0, intersection1, intersectionMid);
    
    List wallChildren = new FilteredElementCollector(doc)
             .OfClass(typeof(FamilyInstance))
             .Cast()
        .Where(q => q.Host.Id == wall.Id).ToList();
    
    using (Transaction t = new Transaction(doc, "Wall to Curve"))
    {
        t.Start();
        Wall newWall = Wall.Create(doc, arc, wall.LevelId, false);
        newWall.WallType = doc.GetElement(wall.GetTypeId()) as WallType;
        foreach (FamilyInstance fi in wallChildren)
        {
            XYZ fiPoint = (fi.Location as LocationPoint).Point;
            XYZ fiIntersection = intersect(fiPoint, wallPerpendicular, gridCurve);
            if (fiIntersection != null)
            {
                FamilyInstance fiNew = doc.Create.NewFamilyInstance(fiIntersection, 
                fi.Symbol,
                newWall,
                doc.GetElement(fi.LevelId) as Level,
                StructuralType.NonStructural);
                
                if (fi.FacingFlipped)
                    fiNew.flipFacing();
                if (fi.HandFlipped)
                    fiNew.flipHand();
            }
        }
        doc.Delete(wall.Id);
        t.Commit();
    }
}

private XYZ intersect(XYZ point, XYZ direction, Curve curve)
{
    Line unbound = Line.CreateUnbound(new XYZ(point.X, point.Y, curve.GetEndPoint(0).Z), direction);
    IntersectionResultArray ira = null;
    unbound.Intersect(curve, out ira);
    if (ira == null)
    {
        TaskDialog td = new TaskDialog("Error");
        td.MainInstruction = "no intersection";
        td.MainContent = point.ToString() + Environment.NewLine + direction.ToString();
        td.Show();
            
        return null;
    }
    IntersectionResult ir = ira.Cast().First();
    return ir.XYZPoint;
}

4 thoughts on “#BILTNA2018 Wish granted: Align a straight wall with a curved grid

  1. Hi,

    did you try
    (wall.Location as LocationCurve).Curve = arc;

    I didnt test this, but if it worked, no new elements would need to be created.
    In fact, if a new element is created as a successor/heir of another one, the old parameter values need to be transferred to the new element – information is lost otherwise.

    Revitalizer

    • That is a good idea, and setting the LocationCurve.Curve works if you want to use a different line for a straight wall. It also works if you want to change an arc wall to use a different arc. But it does not do anything when you try to change a straight wall to an arc wall.

    • Can the wall children be re-hosted instead of re-created?

      There are 2 issues that arise due to re-creating the wall children:
      1. When re-creating the hosted elements (wall children) in the curved wall, setting the family type is not enough. The instance parameters must also be updated, otherwise they will be set using default values.

      2. For some of us, changing the element ID after re-creating new elements is problematic. So re-hosting the same elements may save the day by maintaining the same ID, instance parameters, tags etc…

      • Unfortunately Revit does not let us re-host the existing wall. You are right that the instance parameters should also be transferred and that changing the element ID is not great. But it is the best we can do with the API in its current form

Leave a comment