Setting door position relative to nearby walls

A reader sent the image on the right and asked: “can we make door with specific distance to face of waDoorPositionll like 20 cm without every time need to adjust distance in temporary dimension ?”

This seemed like a good excuse to stop writing code dealing with Family Parameters (I was getting tired of writing it, were you getting tired of reading about it?).

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

    // establish an offset of 20cm that will be applied to the door and wall
    // Revit's internal units for distance is feet
    double doorToWallDistance = 20 / (12 * 2.54); // convert 20 cm to 1 ft

    try // try/catch block with PickObject is used to give the user a way to get out of the infinite loop of while (true)
        // PickObject throws an exception when user aborts from selection
    {
        while (true)
        {
            FamilyInstance door = doc.GetElement(uidoc.Selection.PickObject(ObjectType.Element, "Select a door. ESC when finished.").ElementId) as FamilyInstance;
            double doorWidth = door.Symbol.get_Parameter(BuiltInParameter.DOOR_WIDTH).AsDouble();

            Wall sideWall = doc.GetElement(uidoc.Selection.PickObject(ObjectType.Element, "Select a wall. ESC when finished.").ElementId) as Wall;
            double sideWallWidth = sideWall.Width;

            // get the curve that defines the centerline of the side wall
            LocationCurve sideWallLocationCurve = sideWall.Location as LocationCurve;
            Curve sideWallCurve = sideWallLocationCurve.Curve;

            // get the curve that defines the centerline of the wall that hosts the door
            Wall hostWall = door.Host as Wall;
            LocationCurve hostWallLocationCurve = hostWall.Location as LocationCurve;
            Curve hostWallCurve = hostWallLocationCurve.Curve;

            // find the point of intersection of these two wall curves (intersectionXYZ)
            // and the position of this point on the wall that hosts the door (intersectionParam)
            IntersectionResultArray ira = new IntersectionResultArray();
            SetComparisonResult scr = sideWallCurve.Intersect(hostWallCurve, out ira);
            var iter = ira.GetEnumerator();
            iter.MoveNext();
            IntersectionResult ir = iter.Current as IntersectionResult;
            XYZ intersectionXYZ = ir.XYZPoint;
            double intersectionParam = hostWallCurve.Project(intersectionXYZ).Parameter;

            // find the position of the door in its host wall
            LocationPoint doorPoint = door.Location as LocationPoint;
            XYZ doorXYZ = doorPoint.Point;
            double doorParam = hostWallCurve.Project(doorXYZ).Parameter;

            // compute the translation vector between the edge of the door closest to the wall and the side face of the wall
            XYZ translation = null;
            XYZ doorEdgeXYZ = null;
            XYZ intersectionOffsetXYZ = null;
            if (intersectionParam > doorParam)
            {
                intersectionOffsetXYZ = hostWallCurve.Evaluate(intersectionParam - doorToWallDistance - sideWallWidth/2, false);
                doorEdgeXYZ = hostWallCurve.Evaluate(doorParam + doorWidth/2, false);
                translation = intersectionOffsetXYZ.Subtract(doorEdgeXYZ);
            }
            else
            {
                intersectionOffsetXYZ = hostWallCurve.Evaluate(intersectionParam + doorToWallDistance + sideWallWidth/2, false);
                doorEdgeXYZ = hostWallCurve.Evaluate(doorParam - doorWidth/2, false);
                translation = doorEdgeXYZ.Subtract(intersectionOffsetXYZ).Negate();
            }

            // Move the door
            using (Transaction t = new Transaction(doc,"move door"))
            {
                t.Start();
                ElementTransformUtils.MoveElement(doc,door.Id,translation);
                t.Commit();
            }
        }
    }
    catch{}
}
About these ads

8 thoughts on “Setting door position relative to nearby walls

  1. People worry about this too early. In preliminary design the walls are not usually the correct (or final) thickness. We should just “agree we need a door here” in that stage of design. If we fuss with it “now”, we just end up adjusting the placement of doors again later, if we ever actually do revisit this. The “value” “we” use is also usually a minimum requirement or ideal value, big enough to allow for framing and trimming the door, particularly. I think a cooler tool would be one that adjust door positions relative to adjacent walls later, after the walls are the correct thickness, either by picking or just broadly all doors closer than “x” distance from the adjacent wall.

    • Hi Steve,

      I’m not sure I understand the difference between this tool and a cooler one that could be used later after the walls are the correct thickness. In the video all the walls are the Generic 8″ type, but this tool works just as well with any wall types of any thickness.

      Also, the concept of “adjacent wall” is trivial to us humans, but is fairly complicated to figure out with the API. That is why I went with this approach of having the user select each door and wall.

      Regards,
      Harry

  2. Harry On the view range API you wrote If you change the 3d section box of say the 1st floor it works great Then right click on the view cube and say orient to 1st floor the 3d section box has a zero height Dies the API change this? Any way to make it make view range as the developers intended? Thx Marcello

    Sent from my iPhone

    • I don’t think I am seeing the problem. Maybe I am doing something different? The macro sets the Plan View’s view range as follows. – All four planes (top, cut, bottom, depth) are set to the plan view’s level – The view depth offset is set to the height of the bottom of the section box. – The offsets for the other 3 planes are all set to the top of the section box The result should be no different than what you would get from setting these manually with the UI.

      // Set all planes of the view range to use the plan view’s level viewRange.SetLevelId(PlanViewPlane.TopClipPlane, level.Id); viewRange.SetLevelId(PlanViewPlane.CutPlane, level.Id); viewRange.SetLevelId(PlanViewPlane.BottomClipPlane, level.Id); viewRange.SetLevelId(PlanViewPlane.ViewDepthPlane, level.Id);

      // Set the view depth offset to the difference between the bottom of the section box and // the elevation of the level viewRange.SetOffset(PlanViewPlane.ViewDepthPlane, minZ – level.Elevation );

      // Set all other offsets to to the difference between the top of the section box and // the elevation of the level viewRange.SetOffset(PlanViewPlane.TopClipPlane, maxZ – level.Elevation); viewRange.SetOffset(PlanViewPlane.CutPlane, maxZ – level.Elevation); viewRange.SetOffset(PlanViewPlane.BottomClipPlane, maxZ – level. Elevation);

      Regards, Harry http://boostyourbim.wordpress.com https://twitter.com/BoostYourBIM https://www.facebook.com/BoostYourBim

  3. Harry Some people have asked me when you plan to put up the analytical adjustment app on the App Store ? Thx Marcello

    Sent from my iPhone

Leave a Reply

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

WordPress.com Logo

You are commenting using your WordPress.com 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