how to connect line with multiple family

how to connect line with multiple family

thsa2501
Enthusiast Enthusiast
348 Views
4 Replies
Message 1 of 5

how to connect line with multiple family

thsa2501
Enthusiast
Enthusiast

hi everyone ,

i want to make an automatic line for family like l shape. i made this code . The line connecting the family did not meet what I expected. kindly tell me what is wrong in this code.

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

namespace PlaceDim
{
    [Transaction(TransactionMode.Manual)]
    public class Command : IExternalCommand
    {
        public Result Execute(ExternalCommandData commandData, ref string message, ElementSet elements)
        {
            UIDocument uidoc = commandData.Application.ActiveUIDocument;
            Document doc = uidoc.Document;

            try
            {
                // Prompt the user to select multiple elements
                var selectedElements = uidoc.Selection.PickObjects(ObjectType.Element, "Select multiple families (or elements)");

                if (selectedElements.Count < 2)
                {
                    message = "Please select at least two elements.";
                    return Result.Failed;
                }

                // Get the points of the selected elements
                List<XYZ> points = new List<XYZ>();
                foreach (var selected in selectedElements)
                {
                    Element element = doc.GetElement(selected);
                    LocationPoint location = element.Location as LocationPoint;

                    if (location == null)
                    {
                        message = "Selected elements must have valid location points.";
                        return Result.Failed;
                    }

                    points.Add(location.Point);
                }

                if (points.Count < 2)
                {
                    message = "Failed to retrieve sufficient points from selected elements.";
                    return Result.Failed;
                }

                // Remove duplicate points using a HashSet
                HashSet<XYZ> uniquePoints = new HashSet<XYZ>(points);

                // Convert the HashSet back to a List (to allow sorting)
                points = uniquePoints.ToList();

                // Sort the points in ascending order first by X, then by Y
                points = points.OrderBy(p => p.X).ThenBy(p => p.Y).ToList();

                // Get the active view's plane
                View activeView = doc.ActiveView;
                Plane viewPlane = Plane.CreateByNormalAndOrigin(activeView.ViewDirection, activeView.Origin);

                // Start transaction to draw lines
                using (Transaction tx = new Transaction(doc, "Create 90 Degree L-shaped Lines"))
                {
                    tx.Start();

                    // Create the SketchPlane inside the transaction
                    SketchPlane sketchPlane = SketchPlane.Create(doc, viewPlane);
                    if (sketchPlane == null)
                    {
                        message = "Failed to create sketch plane.";
                        return Result.Failed;
                    }

                    // Iterate through sorted points and create L-shaped lines
                    for (int i = 0; i < points.Count - 1; i++)
                    {
                        XYZ startPoint = ProjectOntoPlane(points[i], viewPlane);
                        XYZ endPoint = ProjectOntoPlane(points[i + 1], viewPlane);

                        // If the points are in the same horizontal (X) or vertical (Y) direction, create a single line
                        if (startPoint.X == endPoint.X) // Vertical line
                        {
                            Line verticalLine = Line.CreateBound(startPoint, endPoint);
                            doc.Create.NewDetailCurve(activeView, verticalLine);
                        }
                        else if (startPoint.Y == endPoint.Y) // Horizontal line
                        {
                            Line horizontalLine = Line.CreateBound(startPoint, endPoint);
                            doc.Create.NewDetailCurve(activeView, horizontalLine);
                        }
                        else
                        {
                            // Create an L-shaped line (90-degree turn)
                            // First, create a horizontal line from the start to the same X as the endPoint
                            XYZ horizontalEnd = new XYZ(endPoint.X, startPoint.Y, startPoint.Z);
                            Line horizontalLine = Line.CreateBound(startPoint, horizontalEnd);
                            doc.Create.NewDetailCurve(activeView, horizontalLine);

                            // Second, create a vertical line from horizontalEnd to the endPoint
                            Line verticalLine = Line.CreateBound(horizontalEnd, endPoint);
                            doc.Create.NewDetailCurve(activeView, verticalLine);
                        }
                    }

                    tx.Commit();
                }

                return Result.Succeeded;
            }
            catch (Autodesk.Revit.Exceptions.OperationCanceledException)
            {
                return Result.Cancelled;
            }
            catch (Exception ex)
            {
                message = $"Error: {ex.Message} \nStackTrace: {ex.StackTrace}";
                return Result.Failed;
            }
        }

        private XYZ ProjectOntoPlane(XYZ point, Plane plane)
        {
            // Project a point onto a given plane
            XYZ normal = plane.Normal;
            double distance = normal.DotProduct(point - plane.Origin);
            return point - distance * normal;
        }
    }
}

 the first image actual result from code 

thsa2501_0-1735891506819.png

I want like this 

thsa2501_1-1735891569389.png

 

 

0 Likes
349 Views
4 Replies
Replies (4)
Message 2 of 5

jeremy_tammik
Alumni
Alumni

Please describe more precisely what you are trying to achieve. Are those three things three family instances? Would you like the connecting lines to be axis aligned? Are you working in 2D only? Do you want the connections to be as short as possible? Is the round thing marked DB always in the middle between the other two? Are there other constraints that I have not listed yet?

   

Jeremy Tammik Developer Advocacy and Support + The Building Coder + Autodesk Developer Network + ADN Open
0 Likes
Message 3 of 5

thsa2501
Enthusiast
Enthusiast

hi @jeremy_tammik 

Sorry for the late reply,i need to connect multiple families with the line. The code is not coming as per the image attached.

 

 

thsa2501_1-1736149834319.png

as per the image the code wants to work. please help me.

 

what are you trying to say(Are you working in 2D only?).

 

0 Likes
Message 4 of 5

scgq425
Advocate
Advocate

in you result image , the result is likely get the diff result , in you code line 63 , create a viewplane base on active view and use the view normal direction , this is the diff result reason , you can create a plane just use the (+-1,0,0) or (0,0,+-1) and run code again .

LanHui Xu 徐兰辉
Did you find this post helpful? Feel free to Like this post.
Did your question get successfully answered? Then click on the ACCEPT SOLUTION button.

Blog
LinkedIn
Revit/CAD Development | Steel Product Manager

EESignature

0 Likes
Message 5 of 5

thsa2501
Enthusiast
Enthusiast

hi,

thanks for the reply.it did not work.

thsa2501_0-1736241845912.png

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

namespace PlaceDim
{
    [Transaction(TransactionMode.Manual)]
    public class Command : IExternalCommand
    {
        public Result Execute(ExternalCommandData commandData, ref string message, ElementSet elements)
        {
            UIDocument uidoc = commandData.Application.ActiveUIDocument;
            Document doc = uidoc.Document;

            try
            {
                // Prompt the user to select multiple elements
                var selectedElements = uidoc.Selection.PickObjects(ObjectType.Element, "Select multiple families (or elements)");

                if (selectedElements.Count < 2)
                {
                    message = "Please select at least two elements.";
                    return Result.Failed;
                }

                // Get the points of the selected elements
                List<XYZ> points = new List<XYZ>();
                foreach (var selected in selectedElements)
                {
                    Element element = doc.GetElement(selected);
                    LocationPoint location = element.Location as LocationPoint;

                    if (location == null)
                    {
                        message = "Selected elements must have valid location points.";
                        return Result.Failed;
                    }

                    points.Add(location.Point);
                }

                if (points.Count < 2)
                {
                    message = "Failed to retrieve sufficient points from selected elements.";
                    return Result.Failed;
                }

                // Remove duplicate points using a HashSet
                HashSet<XYZ> uniquePoints = new HashSet<XYZ>(points);

                // Convert the HashSet back to a List (to allow sorting)
                points = uniquePoints.ToList();

                // Sort the points in ascending order first by X, then by Y
                points = points.OrderBy(p => p.X).ThenBy(p => p.Y).ToList();

                // Create a custom view plane
                Plane viewPlane = Plane.CreateByNormalAndOrigin(new XYZ(0, 0, +-1), XYZ.Zero); // Use Z-axis normal for a horizontal plane

                // Start transaction to draw lines
                using (Transaction tx = new Transaction(doc, "Create 90 Degree L-shaped Lines"))
                {
                    tx.Start();

                    // Create the SketchPlane inside the transaction
                    SketchPlane sketchPlane = SketchPlane.Create(doc, viewPlane);
                    if (sketchPlane == null)
                    {
                        message = "Failed to create sketch plane.";
                        return Result.Failed;
                    }

                    // Iterate through sorted points and create L-shaped lines
                    for (int i = 0; i < points.Count - 1; i++)
                    {
                        XYZ startPoint = ProjectOntoPlane(points[i], viewPlane);
                        XYZ endPoint = ProjectOntoPlane(points[i + 1], viewPlane);

                        // If the points are in the same horizontal (X) or vertical (Y) direction, create a single line
                        if (Math.Abs(startPoint.X - endPoint.X) < 1e-6) // Vertical line
                        {
                            Line verticalLine = Line.CreateBound(startPoint, endPoint);
                            doc.Create.NewDetailCurve(doc.ActiveView, verticalLine);
                        }
                        else if (Math.Abs(startPoint.Y - endPoint.Y) < 1e-6) // Horizontal line
                        {
                            Line horizontalLine = Line.CreateBound(startPoint, endPoint);
                            doc.Create.NewDetailCurve(doc.ActiveView, horizontalLine);
                        }
                        else
                        {
                            // Create an L-shaped line (90-degree turn)
                            // First, create a horizontal line from the start to the same X as the endPoint
                            XYZ horizontalEnd = new XYZ(endPoint.X, startPoint.Y, startPoint.Z);
                            Line horizontalLine = Line.CreateBound(startPoint, horizontalEnd);
                            doc.Create.NewDetailCurve(doc.ActiveView, horizontalLine);

                            // Second, create a vertical line from horizontalEnd to the endPoint
                            Line verticalLine = Line.CreateBound(horizontalEnd, endPoint);
                            doc.Create.NewDetailCurve(doc.ActiveView, verticalLine);
                        }
                    }

                    tx.Commit();
                }

                return Result.Succeeded;
            }
            catch (Autodesk.Revit.Exceptions.OperationCanceledException)
            {
                return Result.Cancelled;
            }
            catch (Exception ex)
            {
                message = $"Error: {ex.Message} \nStackTrace: {ex.StackTrace}";
                return Result.Failed;
            }
        }

        private XYZ ProjectOntoPlane(XYZ point, Plane plane)
        {
            // Project a point onto a given plane
            XYZ normal = plane.Normal;
            double distance = normal.DotProduct(point - plane.Origin);
            return point - distance * normal;
        }
    }
}
0 Likes