using Autodesk.Revit.DB; using Autodesk.Revit.UI; using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; using GeoInstance = Autodesk.Revit.DB.GeometryInstance; using GeoElement = Autodesk.Revit.DB.GeometryElement; using RevitElement = Autodesk.Revit.DB.Element; namespace KMBIM.Revit.Tools.Utils { /// /// This is main data class for creating family Instance by face /// public class FamilyInstanceCreator { #region Fields // Revit document private UIDocument m_revitDoc; private Autodesk.Revit.Creation.Application m_appCreator; // all face names private List m_faceNameList = new List(); // all face instances private List m_faceList = new List(); // all family symbols private Dictionary dictFamilySymbol = new Dictionary(); // all family symbol names private List m_familySymbolNameList = new List(); // the index default family symbol in family list private FamilySymbol m_symbol; #endregion #region Properties /// /// Store the all face names, they will be displayed in a combo box /// public List FaceNameList { get { return m_faceNameList; } } /// /// Store all face instances for convenience to create a face-based family instance /// public List FaceList { get { return m_faceList; } } #endregion #region Construtor /// /// Constructor, Store the Revit application /// /// public FamilyInstanceCreator(Autodesk.Revit.UI.UIApplication app) { m_revitDoc = app.ActiveUIDocument; m_appCreator = app.Application.Create; } #endregion #region Public methods /// /// 1. Find all family symbols in current Revit document and store them /// 2. Find the index of default family symbol /// Point("Point-based"); Line("Line-based") /// public void CheckFamilySymbol(FileInfo fiFamilypath, string defaultSymbolName) { Autodesk.Revit.DB.FilteredElementIterator familySymbolItor = new FilteredElementCollector(m_revitDoc.Document).OfClass(typeof(FamilySymbol)).GetElementIterator(); bool hasDefaultSymbol = false; int ii = 0; while (familySymbolItor.MoveNext()) { FamilySymbol symbol = (FamilySymbol)familySymbolItor.Current; if (null == symbol) { continue; } if (!hasDefaultSymbol && 0 == String.Compare(defaultSymbolName, symbol.Name, true)) { hasDefaultSymbol = true; m_symbol = symbol; break; } } if (!hasDefaultSymbol) { FamilySymbol loadedfamilySymbol = null; try { m_revitDoc.Document.LoadFamilySymbol(fiFamilypath.FullName, defaultSymbolName, out loadedfamilySymbol); } catch (Exception ex) { MessageBox.Show(ex.Message); } if (null == loadedfamilySymbol) { return; } m_symbol = loadedfamilySymbol; } return; } public FamilyInstance CreatePipeAnnotation(XYZ origin, Autodesk.Revit.DB.View view) { FamilyInstance instance = m_revitDoc.Document.Create.NewFamilyInstance(origin, m_symbol, view); m_revitDoc.Selection.GetElementIds().Clear(); m_revitDoc.Selection.GetElementIds().Add(instance.Id); return instance; } public FamilyInstance CreateOpening(Reference linkedface, XYZ position, XYZ refDir) { Autodesk.Revit.DB.FamilyInstance instance = null; if (!m_symbol.IsActive) m_symbol.Activate(); instance = m_revitDoc.Document.Create.NewFamilyInstance(linkedface, position, refDir, m_symbol); return instance; } public FamilyInstance CreateOpening(Face face, Line position) { Autodesk.Revit.DB.FamilyInstance instance = null; if (!m_symbol.IsActive) m_symbol.Activate(); instance = m_revitDoc.Document.Create.NewFamilyInstance(face, position, m_symbol); return instance; } public FamilyInstance CreateWallOpening(XYZ origin, Wall wall) { Autodesk.Revit.DB.FamilyInstance instance = null; instance = m_revitDoc.Document.Create.NewFamilyInstance(origin, m_symbol, wall, Autodesk.Revit.DB.Structure.StructuralType.NonStructural); return instance; } public FamilyInstance CreateFloorOpening(XYZ origin, Floor floor) { Autodesk.Revit.DB.FamilyInstance instance = null; instance = m_revitDoc.Document.Create.NewFamilyInstance(origin, m_symbol, floor, Autodesk.Revit.DB.Structure.StructuralType.NonStructural); //m_revitDoc.Selection.Elements.Clear(); //m_revitDoc.Selection.Elements.Add(instance); return instance; } /// /// Create a based-point family instance by face /// /// the location point /// the direction /// the index of the selected face /// the index of the selected family symbol /// public bool CreatePointFamilyInstance(Autodesk.Revit.DB.XYZ locationP, Autodesk.Revit.DB.XYZ directionP, int faceIndex , int familySymbolIndex) { Face face = m_faceList[faceIndex]; FamilyInstance instance = m_revitDoc.Document.Create.NewFamilyInstance(face , locationP, directionP, m_symbol); m_revitDoc.Selection.GetElementIds().Clear(); m_revitDoc.Selection.GetElementIds().Add(instance.Id); return true; } /// /// Create a based-line family instance by face /// /// the start point /// the end point /// the index of the selected face /// the index of the selected family symbol /// public bool CreateLineFamilyInstance(Autodesk.Revit.DB.XYZ startP, Autodesk.Revit.DB.XYZ endP, int faceIndex , int familySymbolIndex) { Face face = m_faceList[faceIndex]; Autodesk.Revit.DB.XYZ projectedStartP = Project(face.Triangulate().Vertices as List, startP); Autodesk.Revit.DB.XYZ projectedEndP = Project(face.Triangulate().Vertices as List, endP); if (projectedStartP.IsAlmostEqualTo(projectedEndP)) { return false; } Line line = Line.CreateBound(projectedStartP, projectedEndP); FamilyInstance instance = m_revitDoc.Document.Create.NewFamilyInstance(face, line, m_symbol); m_revitDoc.Selection.GetElementIds().Clear(); m_revitDoc.Selection.GetElementIds().Add(instance.Id); return true; } /// /// Judge whether the selected elementSet has face geometry /// /// true is having face geometry, false is having no face geometry public bool CheckSelectedElementSet() { // judge whether an or more element is selected if (1 != m_revitDoc.Selection.GetElementIds().Count) { return false; } m_faceList.Clear(); m_faceNameList.Clear(); // judge whether the selected element has face geometry foreach (var elm_id in m_revitDoc.Selection.GetElementIds()) { var elem = m_revitDoc.Document.GetElement(elm_id); CheckSelectedElement(elem); break; } if (0 >= m_faceList.Count) { return false; } return true; } #endregion #region Private Methods /// /// Get the bounding box of a face, the BoundingBoxXYZ will be set in UI as default value /// /// the index of face /// the bounding box public BoundingBoxXYZ GetFaceBoundingBox(int indexFace) { Mesh mesh = m_faceList[indexFace].Triangulate(); Autodesk.Revit.DB.XYZ maxP = new Autodesk.Revit.DB.XYZ(double.MinValue, double.MinValue, double.MinValue); Autodesk.Revit.DB.XYZ minP = new Autodesk.Revit.DB.XYZ(double.MaxValue, double.MaxValue, double.MaxValue); foreach (Autodesk.Revit.DB.XYZ tempXYZ in mesh.Vertices) { minP = new XYZ( Math.Min(minP.X, tempXYZ.X), Math.Min(minP.Y, tempXYZ.Y), Math.Min(minP.Z, tempXYZ.Z)); maxP = new XYZ( Math.Max(maxP.X, tempXYZ.X), Math.Max(maxP.Y, tempXYZ.Y), Math.Max(maxP.Z, tempXYZ.Z)); } BoundingBoxXYZ retBounding = new BoundingBoxXYZ(); retBounding.Max = maxP; retBounding.Min = minP; return retBounding; } /// /// Judge whether an element has face geometry /// /// the element to be checked /// true is having face geometry, false is having no face geometry private bool CheckSelectedElement(RevitElement elem) { if (null == elem) { return false; } // Options opt = app.Application.Create.NewGeometryOptions(); Autodesk.Revit.DB.Options opts = new Autodesk.Revit.DB.Options(); opts.View = m_revitDoc.Document.ActiveView; opts.ComputeReferences = true; // Get geometry of the element GeometryElement geoElement = elem.get_Geometry(opts); InquireGeometry(geoElement, elem); return true; } /// /// Inquire an geometry element to get all face instances /// /// the geometry element /// the element, it provides the prefix of face name /// private bool InquireGeometry(GeometryElement geoElement, RevitElement elem) { if (null == geoElement || null == elem) { return false; } foreach (GeometryObject obj in geoElement) { if (obj is GeoInstance) { GeoInstance instance = (GeoInstance)obj; InquireGeometry(instance.SymbolGeometry, elem); } else if (!(obj is Solid)) { // is not Solid instance continue; } // continue when obj is Solid instance Solid solid = obj as Solid; if (null == solid) { continue; } FaceArray faces = solid.Faces; if (faces.IsEmpty) { continue; } // get the face name list String category = String.Empty; if (null != elem.Category && null != elem.Name) { category = elem.Category.Name; } int ii = 0; foreach (Face tempFace in faces) { if (tempFace is PlanarFace) { m_faceNameList.Add( String.Format("{0} : {1} ({2})", category, elem.Name, ii)); m_faceList.Add(tempFace); ii++; } } } return true; } /// /// Project a point on a face /// /// the face points, them fix a face /// the point /// the projected point on this face static private Autodesk.Revit.DB.XYZ Project(List xyzArray, Autodesk.Revit.DB.XYZ point) { Autodesk.Revit.DB.XYZ a = xyzArray[0] - xyzArray[1]; Autodesk.Revit.DB.XYZ b = xyzArray[0] - xyzArray[2]; Autodesk.Revit.DB.XYZ c = point - xyzArray[0]; Autodesk.Revit.DB.XYZ normal = (a.CrossProduct(b)); try { normal = normal.Normalize(); } catch (Exception) { normal = Autodesk.Revit.DB.XYZ.Zero; } Autodesk.Revit.DB.XYZ retProjectedPoint = point - (normal.DotProduct(c)) * normal; return retProjectedPoint; } #endregion } }