public Result Execute( ExternalCommandData commandData, ref string message, ElementSet elements) { UIApplication app = commandData.Application; UIDocument uidoc = app.ActiveUIDocument; Document doc = uidoc.Document; string s = "a wall, to retrieve its bottom face"; Wall wall = Util.SelectSingleElementOfType( uidoc, typeof(Wall), s, false) as Wall; if (null == wall) { message = "Please select a wall."; } else { Options opt = app.Application.Create.NewGeometryOptions(); GeometryElement e = wall.get_Geometry(opt); //foreach( GeometryObject obj in e.Objects ) // 2012 foreach (GeometryObject obj in e) // 2013 { Solid solid = obj as Solid; if (null != solid) { foreach (Face face in solid.Faces) { PlanarFace pf = face as PlanarFace; if (null != pf) { if (Util.IsVertical(pf.Normal, _tolerance) && pf.Normal.Z < 0) { Util.InfoMsg(string.Format( "The bottom face area is {0}," + " and its origin is at {1}.", Util.RealString(pf.Area), Util.PointString(pf.Origin))); break; } } } } } } return(Result.Failed); }
/// <summary> /// Return the largest horizontal face of the given /// element e, either top or bottom, optionally /// computing references. /// </summary> /// <param name="e"></param> /// <param name="computReferences">Compute references?</param> /// <param name="bottomFace">Top or bottom?</param> PlanarFace GetLargestHorizontalFace( Element e, bool computReferences = true, bool bottomFace = true) { //Options opt = app.Application.Create.NewGeometryOptions(); Options opt = new Options(); opt.ComputeReferences = computReferences; GeometryElement geo = e.get_Geometry(opt); PlanarFace largest_face = null; foreach (GeometryObject obj in geo) { Solid solid = obj as Solid; if (null != solid) { foreach (Face face in solid.Faces) { PlanarFace pf = face as PlanarFace; if (null != pf) { XYZ normal = pf.FaceNormal.Normalize(); if (Util.IsVertical(normal) && (bottomFace ? 0.0 > normal.Z : 0.0 < normal.Z) && (null == largest_face || largest_face.Area < pf.Area)) { largest_face = pf; break; } } } } } return(largest_face); }
/// <summary> /// Determine the vertical boundary faces /// of a given "horizontal" solid object /// such as a floor slab. Currently only /// supports planar and cylindrical faces. /// </summary> /// <param name="verticalFaces">Return solid vertical boundary faces, i.e. 'sides'</param> /// <param name="solid">Input solid</param> void GetSideFaces( List <Face> verticalFaces, Solid solid) { FaceArray faces = solid.Faces; foreach (Face f in faces) { if (f is PlanarFace) { if (Util.IsVertical(f as PlanarFace)) { verticalFaces.Add(f); } } if (f is CylindricalFace) { if (Util.IsVertical(f as CylindricalFace)) { verticalFaces.Add(f); } } } }
public Result Execute( ExternalCommandData commandData, ref string message, ElementSet elements) { UIApplication app = commandData.Application; UIDocument uidoc = app.ActiveUIDocument; Document doc = uidoc.Document; Result rc = Result.Failed; using (Transaction t = new Transaction(doc)) { t.Start("Place a New Sprinkler Instance"); // retrieve the sprinkler family symbol: #if _2010 Filter filter = app.Create.Filter.NewFamilyFilter( _name); List <Element> families = new List <Element>(); doc.get_Elements(filter, families); Family family = null; foreach (Element e in families) { family = e as Family; if (null != family) { break; } } #endif // _2010 Family family = Util.GetFirstElementOfTypeNamed( doc, typeof(Family), _name) as Family; if (null == family) { if (!doc.LoadFamily(_filename, out family)) { message = "Unable to load '" + _filename + "'."; return(rc); } } FamilySymbol sprinklerSymbol = null; //foreach( FamilySymbol fs in family.Symbols ) // 2014 foreach (ElementId id in family.GetFamilySymbolIds()) // 2015 { sprinklerSymbol = doc.GetElement(id) as FamilySymbol; break; } Debug.Assert(null != sprinklerSymbol, "expected at least one sprinkler symbol" + " to be defined in family"); // pick the host ceiling: Element ceiling = Util.SelectSingleElement( uidoc, "ceiling to host sprinkler"); if (null == ceiling || !ceiling.Category.Id.IntegerValue.Equals( (int)BuiltInCategory.OST_Ceilings)) { message = "No ceiling selected."; return(rc); } //Level level = ceiling.Level; //XYZ p = new XYZ( 40.1432351841559, 30.09700395984548, 8.0000 ); // these two methods cannot create the sprinkler on the ceiling: //FamilyInstance fi = doc.Create.NewFamilyInstance( p, sprinklerSymbol, ceiling, level, StructuralType.NonStructural ); //FamilyInstance fi = doc.Create.NewFamilyInstance( p, sprinklerSymbol, ceiling, StructuralType.NonStructural ); // use this overload so get the bottom face of the ceiling instead: // FamilyInstance NewFamilyInstance( Face face, XYZ location, XYZ referenceDirection, FamilySymbol symbol ) // retrieve the bottom face of the ceiling: Options opt = app.Application.Create.NewGeometryOptions(); opt.ComputeReferences = true; GeometryElement geo = ceiling.get_Geometry(opt); PlanarFace ceilingBottom = null; foreach (GeometryObject obj in geo) { Solid solid = obj as Solid; if (null != solid) { foreach (Face face in solid.Faces) { PlanarFace pf = face as PlanarFace; if (null != pf) { XYZ normal = pf.FaceNormal.Normalize(); if (Util.IsVertical(normal) && 0.0 > normal.Z) { ceilingBottom = pf; break; } } } } } if (null != ceilingBottom) { XYZ p = PointOnFace(ceilingBottom); // Create the sprinkler family instance: FamilyInstance fi = doc.Create.NewFamilyInstance( ceilingBottom, p, XYZ.BasisX, sprinklerSymbol); rc = Result.Succeeded; } t.Commit(); } return(rc); }
static void CreateFaceWalls( Document doc) { Application app = doc.Application; Document massDoc = app.NewFamilyDocument( _conceptual_mass_template_path); CreateMassExtrusion(massDoc); //if( File.Exists( _family_path ) ) // File.Delete( _family_path ); SaveAsOptions opt = new SaveAsOptions(); opt.OverwriteExistingFile = true; massDoc.SaveAs(_family_path, opt); using (Transaction tx = new Transaction(doc)) { tx.Start("Create FaceWall"); if (!doc.LoadFamily(_family_path)) { throw new Exception("DID NOT LOAD FAMILY"); } Family family = new FilteredElementCollector(doc) .OfClass(typeof(Family)) .Where <Element>(x => x.Name.Equals(_family_name)) .Cast <Family>() .FirstOrDefault(); FamilySymbol fs = doc.GetElement( family.GetFamilySymbolIds().First <ElementId>()) as FamilySymbol; // Create a family instance Level level = doc.ActiveView.GenLevel; FamilyInstance fi = doc.Create.NewFamilyInstance( XYZ.Zero, fs, level, StructuralType.NonStructural); doc.Regenerate(); // required to generate the geometry! // Determine wall type. WallType wallType = new FilteredElementCollector(doc) .OfClass(typeof(WallType)) .Cast <WallType>() .Where <WallType>(x => FaceWall.IsWallTypeValidForFaceWall(doc, x.Id)) .FirstOrDefault(); // Retrieve mass element geometry. Options options = app.Create.NewGeometryOptions(); options.ComputeReferences = true; //options.View = doc.ActiveView; // conceptual mass is not visible in default view GeometryElement geo = fi.get_Geometry(options); // Create a sloped wall from the geometry. foreach (GeometryObject obj in geo) { Solid solid = obj as Solid; if (null != solid) { foreach (Face f in solid.Faces) { Debug.Assert(null != f.Reference, "we asked for references, didn't we?"); PlanarFace pf = f as PlanarFace; if (null != pf) { XYZ v = pf.FaceNormal; // Errors: // // Could not create a face wall. // // Caused by using ActiveView.Level // instead of ActiveView.GenLevel. // // This reference cannot be applied to a face wall. // // Caused by using this on a horizontal face. if (!Util.IsVertical(v)) { FaceWall.Create( doc, wallType.Id, WallLocationLine.CoreCenterline, f.Reference); } } } } } tx.Commit(); } }
/// <summary> /// Determine the elevation boundary profile /// polygons of the exterior vertical planar /// face of the given wall solid. /// </summary> /// <param name="polygons">Return polygonal boundary /// loops of exterior vertical planar face, i.e. /// profile of wall elevation incl. holes</param> /// <param name="solid">Input solid</param> /// <param name="w">Vector pointing along /// wall centre line</param> /// <param name="w">Vector pointing towards /// exterior wall face</param> /// <returns>False if no exterior vertical /// planar face was found, else true</returns> static bool GetProfile( List <List <XYZ> > polygons, Solid solid, XYZ v, XYZ w) { double d, dmax = 0; PlanarFace outermost = null; FaceArray faces = solid.Faces; foreach (Face f in faces) { PlanarFace pf = f as PlanarFace; if (null != pf && Util.IsVertical(pf) && Util.IsZero(v.DotProduct(pf.FaceNormal))) { d = pf.Origin.DotProduct(w); if ((null == outermost) || (dmax < d)) { outermost = pf; dmax = d; } } } if (null != outermost) { XYZ voffset = _offset * w; XYZ p, q = XYZ.Zero; bool first; int i, n; EdgeArrayArray loops = outermost.EdgeLoops; foreach (EdgeArray loop in loops) { List <XYZ> vertices = new List <XYZ>(); first = true; foreach (Edge e in loop) { IList <XYZ> points = e.Tessellate(); p = points[0]; if (!first) { Debug.Assert(p.IsAlmostEqualTo(q), "expected subsequent start point" + " to equal previous end point"); } n = points.Count; q = points[n - 1]; for (i = 0; i < n - 1; ++i) { XYZ a = points[i]; a += voffset; vertices.Add(a); } } q += voffset; Debug.Assert(q.IsAlmostEqualTo(vertices[0]), "expected last end point to equal" + " first start point"); polygons.Add(vertices); } } return(null != outermost); }