Community
I need to pick 2 points in an elevation and know which curtain panels I've picked on; it's seeming to be going too wide with the bounding box? I pick 2 points over module 29 and it keeps giving me module 30 next to it?
#region Namespaces
using Autodesk.Revit.Attributes;
using Autodesk.Revit.DB;
using Autodesk.Revit.UI;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
#endregion
namespace Trinam_23
{
[Transaction(TransactionMode.Manual)]
public class Detailing_14 : IExternalCommand
{
// Precision threshold for bounding box to prevent selecting nearby modules
private const double BoundingBoxPrecisionThreshold = 0.02; // Example value, adjust based on requirements
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;
XYZ viewDirection = view.ViewDirection.Normalize();
try
{
// Ensure a SketchPlane is set for picking points
SetSketchPlaneForElevationView(doc);
// Retrieve and list all curtain panels in the view
string initialPanelList = ListCurtainPanelsInView(doc, view);
// Prompt user to select two points in the elevation view
XYZ point1 = uidoc.Selection.PickPoint("Select the first point on the elevation view");
XYZ point2 = uidoc.Selection.PickPoint("Select the second point on the elevation view");
// Adjust the bounding box to account for narrow vertical selections
BoundingBoxXYZ boundingBox = CreateAdjustedBoundingBox(doc, point1, point2);
// Filter and retrieve curtain panels based on the adjusted bounding box
List<Element> curtainPanels = FindCurtainPanels(doc, boundingBox);
if (!curtainPanels.Any())
{
TaskDialog.Show("Result", "No curtain panels found within the selected area.");
return Result.Succeeded;
}
// Show the list of found curtain panels
string panelList = GeneratePanelList(curtainPanels);
// string logMessage = $"Bounding Box Details:\nMin: {boundingBox.Min}\nMax: {boundingBox.Max}\nView Direction: {viewDirection}";
// TaskDialog.Show("Result", panelList + "\n\n" + logMessage);
// Show the list of found curtain panels along with initial list
string finalPanelList = GeneratePanelList(curtainPanels);
string logMessage = $"Initial Curtain Panels:\n{initialPanelList}\n\nSelected Curtain Panels:\n{finalPanelList}\n\nBounding Box Details:\nMin: {boundingBox.Min}\nMax: {boundingBox.Max}\nView Direction: {viewDirection}";
TaskDialog.Show("Result", logMessage);
return Result.Succeeded;
}
catch (OperationCanceledException)
{
message = "Selection canceled by the user.";
return Result.Cancelled;
}
catch (Exception ex)
{
message = "An error occurred: " + ex.Message;
TaskDialog.Show("Error", message);
return Result.Failed;
}
}
private void SetSketchPlaneForElevationView(Document doc)
{
View view = doc.ActiveView;
// Only set a sketch plane if one is not already set
if (view.SketchPlane == null)
{
using (Transaction trans = new Transaction(doc, "Set SketchPlane"))
{
trans.Start();
Plane plane = Plane.CreateByNormalAndOrigin(view.ViewDirection, view.Origin);
SketchPlane sketchPlane = SketchPlane.Create(doc, plane);
view.SketchPlane = sketchPlane;
trans.Commit();
}
}
}
private BoundingBoxXYZ CreateAdjustedBoundingBox(Document doc, XYZ point1, XYZ point2, double panelWidth = 0.1)
{
// Convert feet to Revit internal units (decimal feet to feet, assuming your project is in feet)
panelWidth = panelWidth / 0.3048; // 1 foot = 0.3048 meters
// Calculate the horizontal midpoint between point1 and point2
double midX = (point1.X + point2.X) / 2.0;
// Adjust minX and maxX based on the midpoint and half the panel width
double minX = midX - (panelWidth / 2.0);
double maxX = midX + (panelWidth / 2.0);
// Calculate the minY, maxY, minZ, and maxZ as before
double minY = Math.Min(point1.Y, point2.Y);
double maxY = Math.Max(point1.Y, point2.Y);
double minZ = Math.Min(point1.Z, point2.Z);
double maxZ = Math.Max(point1.Z, point2.Z);
// Create the bounding box
BoundingBoxXYZ boundingBox = new BoundingBoxXYZ();
boundingBox.Min = new XYZ(minX, minY, minZ);
boundingBox.Max = new XYZ(maxX, maxY, maxZ);
return boundingBox;
}
private List<Element> FindCurtainPanels(Document doc, BoundingBoxXYZ boundingBox)
{
Outline outline = new Outline(boundingBox.Min, boundingBox.Max);
BoundingBoxIntersectsFilter filter = new BoundingBoxIntersectsFilter(outline);
FilteredElementCollector collector = new FilteredElementCollector(doc)
.OfClass(typeof(FamilyInstance))
.OfCategory(BuiltInCategory.OST_CurtainWallPanels)
.WherePasses(filter);
return collector.ToList();
}
private string GeneratePanelList(IEnumerable<Element> curtainPanels)
{
StringBuilder sb = new StringBuilder("Found curtain panels with 'Module Number':\n");
foreach (Element panel in curtainPanels)
{
Parameter param = panel.LookupParameter("Module Number");
string moduleNumber = param?.AsValueString() ?? "N/A";
sb.AppendLine($"Panel ID: {panel.Id.IntegerValue}, Module Number: {moduleNumber}");
}
return sb.ToString();
}
private string ListCurtainPanelsInView(Document doc, View view)
{
// Retrieve all curtain panels in the view
IList<Element> curtainPanelsInView = new FilteredElementCollector(doc, view.Id)
.OfCategory(BuiltInCategory.OST_CurtainWallPanels)
.WhereElementIsNotElementType()
.ToElements();
StringBuilder sb = new StringBuilder();
// Determine the bounding box for each curtain panel
foreach (Element panel in curtainPanelsInView)
{
BoundingBoxXYZ boundingBox = panel.get_BoundingBox(view);
sb.AppendLine($"Panel ID: {panel.Id}, Module Number: {GetModuleNumber(panel)}");
sb.AppendLine($"Min: {boundingBox.Min}");
sb.AppendLine($"Max: {boundingBox.Max}");
sb.AppendLine();
}
return sb.ToString().Trim();
}
private string GetModuleNumber(Element element)
{
Parameter param = element.LookupParameter("Module Number");
return param?.AsValueString() ?? "N/A";
}
}
}
I need to pick 2 points in an elevation and know which curtain panels I've picked on; it's seeming to be going too wide with the bounding box? I pick 2 points over module 29 and it keeps giving me module 30 next to it?
#region Namespaces
using Autodesk.Revit.Attributes;
using Autodesk.Revit.DB;
using Autodesk.Revit.UI;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
#endregion
namespace Trinam_23
{
[Transaction(TransactionMode.Manual)]
public class Detailing_14 : IExternalCommand
{
// Precision threshold for bounding box to prevent selecting nearby modules
private const double BoundingBoxPrecisionThreshold = 0.02; // Example value, adjust based on requirements
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;
XYZ viewDirection = view.ViewDirection.Normalize();
try
{
// Ensure a SketchPlane is set for picking points
SetSketchPlaneForElevationView(doc);
// Retrieve and list all curtain panels in the view
string initialPanelList = ListCurtainPanelsInView(doc, view);
// Prompt user to select two points in the elevation view
XYZ point1 = uidoc.Selection.PickPoint("Select the first point on the elevation view");
XYZ point2 = uidoc.Selection.PickPoint("Select the second point on the elevation view");
// Adjust the bounding box to account for narrow vertical selections
BoundingBoxXYZ boundingBox = CreateAdjustedBoundingBox(doc, point1, point2);
// Filter and retrieve curtain panels based on the adjusted bounding box
List<Element> curtainPanels = FindCurtainPanels(doc, boundingBox);
if (!curtainPanels.Any())
{
TaskDialog.Show("Result", "No curtain panels found within the selected area.");
return Result.Succeeded;
}
// Show the list of found curtain panels
string panelList = GeneratePanelList(curtainPanels);
// string logMessage = $"Bounding Box Details:\nMin: {boundingBox.Min}\nMax: {boundingBox.Max}\nView Direction: {viewDirection}";
// TaskDialog.Show("Result", panelList + "\n\n" + logMessage);
// Show the list of found curtain panels along with initial list
string finalPanelList = GeneratePanelList(curtainPanels);
string logMessage = $"Initial Curtain Panels:\n{initialPanelList}\n\nSelected Curtain Panels:\n{finalPanelList}\n\nBounding Box Details:\nMin: {boundingBox.Min}\nMax: {boundingBox.Max}\nView Direction: {viewDirection}";
TaskDialog.Show("Result", logMessage);
return Result.Succeeded;
}
catch (OperationCanceledException)
{
message = "Selection canceled by the user.";
return Result.Cancelled;
}
catch (Exception ex)
{
message = "An error occurred: " + ex.Message;
TaskDialog.Show("Error", message);
return Result.Failed;
}
}
private void SetSketchPlaneForElevationView(Document doc)
{
View view = doc.ActiveView;
// Only set a sketch plane if one is not already set
if (view.SketchPlane == null)
{
using (Transaction trans = new Transaction(doc, "Set SketchPlane"))
{
trans.Start();
Plane plane = Plane.CreateByNormalAndOrigin(view.ViewDirection, view.Origin);
SketchPlane sketchPlane = SketchPlane.Create(doc, plane);
view.SketchPlane = sketchPlane;
trans.Commit();
}
}
}
private BoundingBoxXYZ CreateAdjustedBoundingBox(Document doc, XYZ point1, XYZ point2, double panelWidth = 0.1)
{
// Convert feet to Revit internal units (decimal feet to feet, assuming your project is in feet)
panelWidth = panelWidth / 0.3048; // 1 foot = 0.3048 meters
// Calculate the horizontal midpoint between point1 and point2
double midX = (point1.X + point2.X) / 2.0;
// Adjust minX and maxX based on the midpoint and half the panel width
double minX = midX - (panelWidth / 2.0);
double maxX = midX + (panelWidth / 2.0);
// Calculate the minY, maxY, minZ, and maxZ as before
double minY = Math.Min(point1.Y, point2.Y);
double maxY = Math.Max(point1.Y, point2.Y);
double minZ = Math.Min(point1.Z, point2.Z);
double maxZ = Math.Max(point1.Z, point2.Z);
// Create the bounding box
BoundingBoxXYZ boundingBox = new BoundingBoxXYZ();
boundingBox.Min = new XYZ(minX, minY, minZ);
boundingBox.Max = new XYZ(maxX, maxY, maxZ);
return boundingBox;
}
private List<Element> FindCurtainPanels(Document doc, BoundingBoxXYZ boundingBox)
{
Outline outline = new Outline(boundingBox.Min, boundingBox.Max);
BoundingBoxIntersectsFilter filter = new BoundingBoxIntersectsFilter(outline);
FilteredElementCollector collector = new FilteredElementCollector(doc)
.OfClass(typeof(FamilyInstance))
.OfCategory(BuiltInCategory.OST_CurtainWallPanels)
.WherePasses(filter);
return collector.ToList();
}
private string GeneratePanelList(IEnumerable<Element> curtainPanels)
{
StringBuilder sb = new StringBuilder("Found curtain panels with 'Module Number':\n");
foreach (Element panel in curtainPanels)
{
Parameter param = panel.LookupParameter("Module Number");
string moduleNumber = param?.AsValueString() ?? "N/A";
sb.AppendLine($"Panel ID: {panel.Id.IntegerValue}, Module Number: {moduleNumber}");
}
return sb.ToString();
}
private string ListCurtainPanelsInView(Document doc, View view)
{
// Retrieve all curtain panels in the view
IList<Element> curtainPanelsInView = new FilteredElementCollector(doc, view.Id)
.OfCategory(BuiltInCategory.OST_CurtainWallPanels)
.WhereElementIsNotElementType()
.ToElements();
StringBuilder sb = new StringBuilder();
// Determine the bounding box for each curtain panel
foreach (Element panel in curtainPanelsInView)
{
BoundingBoxXYZ boundingBox = panel.get_BoundingBox(view);
sb.AppendLine($"Panel ID: {panel.Id}, Module Number: {GetModuleNumber(panel)}");
sb.AppendLine($"Min: {boundingBox.Min}");
sb.AppendLine($"Max: {boundingBox.Max}");
sb.AppendLine();
}
return sb.ToString().Trim();
}
private string GetModuleNumber(Element element)
{
Parameter param = element.LookupParameter("Module Number");
return param?.AsValueString() ?? "N/A";
}
}
}
Can't find what you're looking for? Ask the community or share your knowledge.