So i actually go the got it to work using a Reference intersector. However it only works with openings created with window or door families. It return a reference for openings created "By face", but the reference return doesn't seem to be stable enough to dimension to. My code is nearly a thousand lines long so here's the important bits.
private List<Reference> GetWallOpenings(Wall wall, View3D view )
{
Document doc = wall.Document;
Level level = doc.GetElement( wall.LevelId ) as Level;
double elevation = level.Elevation;
Curve c = ( wall.Location as LocationCurve ).Curve;
XYZ wallOrigin = c.GetEndPoint( 0 );
XYZ wallEndPoint = c.GetEndPoint( 1 );
XYZ wallDirection = wallEndPoint - wallOrigin;
double wallLength = wallDirection.GetLength();
wallDirection = wallDirection.Normalize();
UV offsetOut = _offset * new UV( wallDirection.X, wallDirection.Y );
XYZ rayStart = new XYZ( wallOrigin.X - offsetOut.U, wallOrigin.Y - offsetOut.V, elevation + _offset );
ReferenceIntersector intersector = new ReferenceIntersector( wall.Id, FindReferenceTarget.Face, view );
IList<ReferenceWithContext> refs = intersector.Find( rayStart, wallDirection );
List<Reference> faceReferenceList = new List<Reference>( refs
.Where<ReferenceWithContext>( r => IsSurface(
r.GetReference() ) )
.Where<ReferenceWithContext>( r => r.Proximity
< wallLength + _offset + _offset )
.Select<ReferenceWithContext, Reference>( r
=> r.GetReference()));
return faceReferenceList;
}
public void test()
{
UIDocument uidoc = this.ActiveUIDocument;
Document doc = uidoc.Document;
ReferenceArray refs = new ReferenceArray();
Reference myRef = uidoc.Selection.PickObject(ObjectType.Element, new MySelectionFilter("Walls"), "Select a wall");
Wall wall = doc.GetElement(myRef) as Wall;
//Creates an element e from the selected object reference -- this will be the wall element
Element e = doc.GetElement(myRef);
//Creates a selection filter to dump objects in for later selection
ICollection<ElementId> selSet = new List<ElementId>();
//Gets the bounding box of the selected wall element picked above
BoundingBoxXYZ bb = e.get_BoundingBox(doc.ActiveView);
//adds a buffer to the bounding box to ensure all elements are contained within the box
XYZ buffer = new XYZ(0.1, 0.1, 0.1);
//creates an ouline based on the boundingbox corners of the panel and adds the buffer
Outline outline = new Outline(bb.Min - buffer, bb.Max + buffer);
//filters the selection by the bounding box of the selected object
//the "true" statement inverts the selection and selects all other objects
BoundingBoxIsInsideFilter bbfilter = new BoundingBoxIsInsideFilter(outline, false);
ICollection<BuiltInCategory> bcat = new List<BuiltInCategory>();
//creates a new filtered element collector that filters by the active view settings
FilteredElementCollector collector = new FilteredElementCollector(doc, doc.ActiveView.Id);
//collects all objects that pass through the requirements of the bbfilter
collector.WherePasses(bbfilter);
//add all levels and grids to filter -- these are filtered out by the viewtemplate, but are nice to have
bcat.Add(BuiltInCategory.OST_StructConnections);
//create new multi category filter
ElementMulticategoryFilter multiCatFilter = new ElementMulticategoryFilter(bcat);
//create new filtered element collector, add the passing levels and grids, then remove them from the selection
foreach (Element el in collector.WherePasses(multiCatFilter))
{
if (el.Name.Equals("EMBEDS"))
{
selSet.Add(el.Id);
}
}
XYZ[] pts = new XYZ[99];
//View3D view = doc.ActiveView as View3D;
View3D view = Get3dView(doc);
//THIS IS WHERE IT RETURNS THE WALL OPENING REFERENCES. HOWEVER THEY ONLY ARE ABLE TO BE USED FOR DIMENSIONS IF THE OPENING IS CREATED USING A FAMILY SUCH AS A WINDOW OR DOOR. OPENING BY FACE/WALL DOES NOT WORK, EVEN THOUGH IT RETURNS PROPER REFERENCES
List<Reference> openings = GetWallOpenings(e as Wall, view );
foreach (Reference reference in openings) {
refs.Append(reference);
}
TaskDialog.Show("REFERE",refs.Size.ToString());
Curve wallLocation = (wall.Location as LocationCurve).Curve;
int i = 0;
foreach (ElementId ele in selSet) {
FamilyInstance fi = doc.GetElement(ele) as FamilyInstance;
Reference reference = ScottWilsonVoodooMagic.GetSpecialFamilyReference(fi,ScottWilsonVoodooMagic.SpecialReferenceType.CenterLR,doc);
refs.Append(reference);
pts[i] = ( fi.Location as LocationPoint ).Point;
i++;
}
XYZ offset = new XYZ(0,0,4);
Line line = Line.CreateBound( pts[0]+offset, pts[1]+offset );
using( Transaction t = new Transaction( doc ) )
{
t.Start( "dimension embeds" );
Dimension dim = doc.Create.NewDimension(doc.ActiveView, line, refs );
t.Commit();
}
}
sorry for the messy code. i'm in the process of cleaning it up. it also uses Jeremy's Utils classes.