Collection the axes between two points in Revit.

Collection the axes between two points in Revit.

andrianitra_ra
Explorer Explorer
643 Views
7 Replies
Message 1 of 8

Collection the axes between two points in Revit.

andrianitra_ra
Explorer
Explorer

Could you please explain why my code is not collecting the grids (axis) between the two points placed in Revit?

 

 

private ICollection<Element> GetSelection(Document doc, XYZ point1, XYZ point2)
{
    View view = doc.ActiveView;
    double deltaX = Math.Abs(point2.X - point1.X);
    double deltaY = Math.Abs(point2.Y - point1.Y);
    double deltaZ = Math.Abs(point2.Z - point1.Z);

    // Créer une boîte englobante (bounding box) à partir des deux points
    XYZ min = new XYZ(Math.Min(point1.X, point2.X), Math.Min(point1.Y, point2.Y), Math.Min(point1.Z, point2.Z));
    XYZ max = new XYZ(Math.Max(point1.X, point2.X), Math.Max(point1.Y, point2.Y), Math.Max(point1.Z, point2.Z));

    if (view is ViewSection)
    {
        if (deltaX < deltaY)
        {
            min = new XYZ(double.MinValue, min.Y, min.Z);
            max = new XYZ(double.MaxValue, max.Y, max.Z);
        }
        else
        {
            min = new XYZ(min.X, double.MinValue, min.Z);
            max = new XYZ(max.X, double.MaxValue, max.Z);
        }
    }

    Outline outline = new Outline(min, max);
    BoundingBoxIntersectsFilter intersectsFilter = new BoundingBoxIntersectsFilter(outline);

    FilteredElementCollector collector = new FilteredElementCollector(doc, doc.ActiveView.Id);
    ICollection<Element> elementsInBoundingBox = collector
        .WhereElementIsNotElementType()
        .WherePasses(intersectsFilter)
        .ToElements();

    return elementsInBoundingBox;
}

 

 

 

 

0 Likes
Accepted solutions (1)
644 Views
7 Replies
Replies (7)
Message 2 of 8

ctm_mka
Collaborator
Collaborator

first question, is your "elementsInBoundingBox" returning anything? perhaps try refining your collector by adding in a class/category filter, something like this:

ICollection<Element> elementsInBoundingBox = collector
.OfClass(typeof(Grid)) //class filter 
.OfCategory(BuiltInCategory.OST_Grids) //cat filter 
        .WhereElementIsNotElementType()
        .WherePasses(intersectsFilter)
        .ToElements();
0 Likes
Message 3 of 8

andrianitra_ra
Explorer
Explorer
Thank you for your response. I'm currently working on a script that places two points on the screen and selects all the elements between those two points. The script works fine for most elements, but I'm having trouble with the axes and annotations.

It seems that these elements (axes and annotations) do not have a boundingBoxXYZ, which prevents them from being correctly selected in my script. I've already tried your solution, but it doesn't work. Do you have any idea how to work around this issue or another solution for handling these types of elements?

Your help would be greatly appreciated.

Thanks in advance!

Have a great day,
0 Likes
Message 4 of 8

ctm_mka
Collaborator
Collaborator

so turns out Grids do have a bounding box. However, as you can see, they are flat in the Z direction, so almost impossible to intersect them in plan.

ctm_mka_0-1724169631925.png

 

0 Likes
Message 5 of 8

ctm_mka
Collaborator
Collaborator

This is proving to be and interesting challenge. I just tried  doing a solid intersect filter by creating an extrusion by making two extra point from the outline min and max, then making a curve loop to feed to the extrusion. Did not work. So next thought for grids in a plan view, untested:

  • Create a bound line from your two initial points.
  • Gather all the grids in the view via filtered element collector. 
  • Loop through, and gather their geometry definition (which is a line).
  • perform line.intersects() test on each grid line.
0 Likes
Message 6 of 8

andrianitra_ra
Explorer
Explorer

Hi

 

I tried what you suggested, but it still doesn't work.

 

public Result Execute(ExternalCommandData commandData, ref string message, ElementSet elements)
{
    UIApplication uiApp = commandData.Application;
    UIDocument uidoc = uiApp.ActiveUIDocument;
    Document doc = uidoc.Document;
    View view = doc.ActiveView;

    using (Transaction t = new Transaction(doc, "Set Work Plane"))
    {
        t.Start();
        if (doc.ActiveView.SketchPlane == null)
        {
            Plane plane = Plane.CreateByNormalAndOrigin(view.ViewDirection, view.Origin);
            SketchPlane sketchPlane = SketchPlane.Create(doc, plane);
            doc.ActiveView.SketchPlane = sketchPlane;
        }
        t.Commit();
    }

    try
    {
        // Select the two points
        Selection sel = uidoc.Selection;
        XYZ point1 = sel.PickPoint("Select the first point");
        XYZ point2 = sel.PickPoint("Select the second point");

        // Create a line from the two points
        Line line = Line.CreateBound(point1, point2);

        // Retrieve all the grids in the view using the filtered element collector
        FilteredElementCollector collector = new FilteredElementCollector(doc, doc.ActiveView.Id);
        ICollection<Element> gridElements = collector
            .OfClass(typeof(Grid))
            .OfCategory(BuiltInCategory.OST_Grids)
            .WhereElementIsNotElementType()
            .ToElements();

        // Iterate over each grid and retrieve its geometric definition
        foreach (Element element in gridElements)
        {
            Grid grid = element as Grid;
            if (grid != null)
            {
                Line gridLine = grid.Curve as Line; // Assuming the grid curve is a line

                if (gridLine != null)
                {
                    // Perform the intersection test between the selected line and the grid line
                    IntersectionResultArray results;
                    SetComparisonResult comparisonResult = line.Intersect(gridLine, out results);

                    if (comparisonResult == SetComparisonResult.Overlap)
                    {
                        TaskDialog.Show("Intersection", "The line intersects with the grid: " + grid.Name);
                    }
                }
            }
        }
    }
    catch (OperationCanceledException)
    {
        // If the user cancels the selection
        return Result.Cancelled;
    }
    catch (Exception ex)
    {
        message = ex.Message;
        return Result.Failed;
    }

    return Result.Succeeded;
}
0 Likes
Message 7 of 8

ctm_mka
Collaborator
Collaborator

well shoot. you might be able to make it work by transforming gridline to the z elevation of your pick points. Other than that im out of ideas.

0 Likes
Message 8 of 8

andrianitra_ra
Explorer
Explorer
Accepted solution

Hello, 

 

I tried to complete this task, but the selection between the two points is unstable. Sometimes, the script selects all the axes, sometimes it works correctly, and other times it doesn't work at all. Could you please help identify the error?

public Result Execute(ExternalCommandData commandData, ref string message, ElementSet elements)
{
    UIApplication uiapp = commandData.Application;
    UIDocument uidoc = uiapp.ActiveUIDocument;
    Document doc = uidoc.Document;

    try
    {
        // Ask the user to select two points
        XYZ point1 = uidoc.Selection.PickPoint("Select the first point");
        XYZ point2 = uidoc.Selection.PickPoint("Select the second point");

        // Filter all elements of type Grid in the document
        FilteredElementCollector collector = new FilteredElementCollector(doc);
        ICollection<Element> grids = collector.OfClass(typeof(Grid)).ToElements();

        // List to store curves between the two points
        List<Curve> curvesBetweenPoints = new List<Curve>();

        // Iterate through the grids and check if their curve passes between the two points
        foreach (Element element in grids)
        {
            Grid grid = element as Grid;
            if (grid != null)
            {
                Curve curve = grid.Curve;

                // Check if the curve is between the two points
                if (IsCurveBetweenPoints(curve, point1, point2))
                {
                    curvesBetweenPoints.Add(curve);
                }
            }
        }

        // Display the number of curves found
        TaskDialog.Show("Result", $"Number of curves found between the two points: {curvesBetweenPoints.Count}");
        Selection sel = uidoc.Selection;
        sel.SetElementIds(curvesBetweenPoints.Select(c => c.Reference.ElementId).ToList());
    }
    catch (Autodesk.Revit.Exceptions.OperationCanceledException)
    {
        // Handle user cancellation
        message = "Operation canceled by the user.";
        return Result.Cancelled;
    }
    catch (System.Exception ex)
    {
        message = ex.Message;
        return Result.Failed;
    }

    return Result.Succeeded;
}

private bool IsCurveBetweenPoints(Curve curve, XYZ point1, XYZ point2)
{
    // Check if the projections of the curve's endpoints on the line are between the two points
    XYZ startProjection = ProjectPointOnLine(curve.GetEndPoint(0), point1, point2);
    XYZ endProjection = ProjectPointOnLine(curve.GetEndPoint(1), point1, point2);

    bool isStartBetween = IsPointOnSegment(startProjection, point1, point2);
    bool isEndBetween = IsPointOnSegment(endProjection, point1, point2);

    return isStartBetween || isEndBetween;
}

private XYZ ProjectPointOnLine(XYZ point, XYZ linePoint1, XYZ linePoint2)
{
    // Calculate the direction vector of the line
    XYZ lineDirection = (linePoint2 - linePoint1).Normalize();

    // Calculate the projection of the point on the line
    XYZ vector = point - linePoint1;
    double projectionLength = vector.DotProduct(lineDirection);
    return linePoint1 + projectionLength * lineDirection;
}

private bool IsPointOnSegment(XYZ point, XYZ start, XYZ end, double tolerance = 1e-6)
{
    // Check if a projected point is on a segment defined by start and end with a tolerance
    double segmentLength = start.DistanceTo(end);
    double distToStart = point.DistanceTo(start);
    double distToEnd = point.DistanceTo(end);

    // The point is on the segment if the sum of the distances to the start and end is approximately equal to the length of the segment
    return Math.Abs((distToStart + distToEnd) - segmentLength) < tolerance;
}

 

0 Likes