Hello Jeremy,
This is me example with comments:
// I found that solid's graphics style name is equal to category name of instance family components.
// So I can exclude unnessossory solids from consideration.
public void Example()
{
// List of excluded category name
List<string> excludedSolids = new List<string> { "Light Source" };
// Take the Duct for our test
FilteredElementCollector collector = new FilteredElementCollector(Document);
collector.WhereElementIsNotElementType().OfCategory(BuiltInCategory.OST_DuctCurves);
Element element = collector.FirstElement();
collector.Dispose();
List<Element> elements = new List<Element>();
// Retrieve all solids from the duct, build ElementIntersectsSolidFilter for each excluding defained before in excluded list,
// and get list of intersected elements
IEnumerable<GeometryObject> solids = getSolids(element);
foreach (Solid solid in solids)
{
if (solid.GraphicsStyleId != null && !solid.GraphicsStyleId.Equals(ElementId.InvalidElementId) &&
excludedSolids.Contains(Document.GetElement(solid.GraphicsStyleId).Name))
continue;
ElementFilter intersectsFilter = new ElementIntersectsSolidFilter(solid);
collector = new FilteredElementCollector(Document);
IList<Element> intersected = collector.WhereElementIsNotElementType()
.Excluding(new List<ElementId> { element.Id })
.WherePasses(intersectsFilter).ToElements();
collector.Dispose();
foreach (Element intersect in intersected)
if (!elements.Exists(el => el.Id.Equals(intersect.Id)))
elements.Add(intersect);
}
// But found intersected elements in its turn can have excluded solids, so we have to do second check:
// for each found element retrive solids, exclude defained before in excluded list, build ElementIntersectsSolidFilter for each
// and check intersection with the source element (Duct in our test)
List<ElementId> removingElements = new List<ElementId>();
foreach (Element intersectedElement in elements)
{
solids = getSolids(intersectedElement);
bool solidSecondChecked = false;
foreach (Solid solid in solids)
{
if (solid.GraphicsStyleId != null && !solid.GraphicsStyleId.Equals(ElementId.InvalidElementId) &&
excludedSolids.Contains(Document.GetElement(solid.GraphicsStyleId).Name))
continue;
ElementFilter intersectsFilter = new ElementIntersectsSolidFilter(solid);
collector = new FilteredElementCollector(Document, new List<ElementId> { element.Id });
solidSecondChecked = collector.Excluding(new List<ElementId> { intersectedElement.Id })
.WherePasses(intersectsFilter).Any();
collector.Dispose();
if (solidSecondChecked)
break;
}
if (!solidSecondChecked)
removingElements.Add(intersectedElement.Id);
}
elements.RemoveAll(el => removingElements.Contains(el.Id));
Selection.SetElementIds(elements.Select(el => el.Id).ToArray());
TaskDialog.Show("Result", "Duct intersects " + elements.Count + " element.");
}
// Finaly, we have correct list of intersected elements with the duct.
private IEnumerable<GeometryObject> getSolids(Element checkingElement)
{
IEnumerable<GeometryObject> solids;
GeometryElement geometryElement = checkingElement.get_Geometry(new Options { DetailLevel = ViewDetailLevel.Fine });
solids = geometryElement.Where(geometry => geometry.GetType().Equals(typeof(Solid)));
if (!solids.Any())
{
GeometryInstance geometryInstance = (GeometryInstance)geometryElement.FirstOrDefault(geometry => geometry.GetType().Equals(typeof(GeometryInstance)));
if (geometryInstance != null && geometryInstance.Transform.IsConformal)
{
geometryElement = geometryInstance.GetInstanceGeometry();
solids = geometryElement.Where(geometry => geometry.GetType().Equals(typeof(Solid)));
}
}
return solids;
}
Thanks,
Anatoly.