/// <summary> /// create the extrusions of the air handler system /// </summary> private void CreateExtrusions() { Autodesk.Revit.Creation.Application app = m_application.Create; CurveArray curves = null; CurveArrArray profile = null; Plane plane = null; SketchPlane sketchPlane = null; #region Create the cuboid extrusions for (int i = 0; i <= 2; ++i) { // create the profile curves = app.NewCurveArray(); curves.Append(Line.CreateBound(profileData[i, 0], profileData[i, 1])); curves.Append(Line.CreateBound(profileData[i, 1], profileData[i, 2])); curves.Append(Line.CreateBound(profileData[i, 2], profileData[i, 3])); curves.Append(Line.CreateBound(profileData[i, 3], profileData[i, 0])); profile = app.NewCurveArrArray(); profile.Append(curves); // create the sketch plane plane = Plane.CreateByNormalAndOrigin(sketchPlaneData[i, 0], sketchPlaneData[i, 1]); sketchPlane = SketchPlane.Create(m_document, plane); // create the extrusion extrusions[i] = f.NewExtrusion(isSolid[i], profile, sketchPlane, extrusionOffsets[i, 1]); extrusions[i].StartOffset = extrusionOffsets[i, 0]; m_combineElements.Append(extrusions[i]); } #endregion #region Create the round extrusions for (int i = 3; i <= 4; ++i) { // create the profile profile = app.NewCurveArrArray(); curves = app.NewCurveArray(); plane = Plane.CreateByNormalAndOrigin(profileData[i, 0], profileData[i, 1]); curves.Append(Arc.Create(plane, arcRadius, 0, Math.PI * 2)); profile.Append(curves); // create the sketch plane plane = Plane.CreateByNormalAndOrigin(sketchPlaneData[i, 0], sketchPlaneData[i, 1]); sketchPlane = SketchPlane.Create(m_document, plane); // create the extrusion extrusions[i] = f.NewExtrusion(isSolid[i], profile, sketchPlane, extrusionOffsets[i, 1]); extrusions[i].StartOffset = extrusionOffsets[i, 0]; m_combineElements.Append(extrusions[i]); } #endregion }
/// <summary> /// Implement this method as an external command for Revit. /// </summary> /// <param name="commandData">An object that is passed to the external application /// which contains data related to the command, /// such as the application object and active view.</param> /// <param name="message">A message that can be set by the external application /// which will be displayed if a failure or cancellation is returned by /// the external command.</param> /// <param name="elements">A set of elements to which the external application /// can add elements that are to be highlighted in case of failure or cancellation.</param> /// <returns>Return the status of the external command. /// A result of Succeeded means that the API external method functioned as expected. /// Cancelled can be used to signify that the user cancelled the external operation /// at some point. Failure should be returned if the application is unable to proceed with /// the operation.</returns> public virtual Autodesk.Revit.UI.Result Execute(ExternalCommandData commandData , ref string message, Autodesk.Revit.DB.ElementSet elements) { if (null == s_appCreation) { // share for class Intersection. s_appCreation = commandData.Application.Application.Create; } UIDocument doc = commandData.Application.ActiveUIDocument; CombinableElementArray solids = new CombinableElementArray(); ElementSet es = new ElementSet(); foreach (ElementId elemId in es) { es.Insert(doc.Document.GetElement(elemId)); } if (0 < es.Size) { foreach (Autodesk.Revit.DB.ElementId elementId in doc.Selection.GetElementIds()) { Autodesk.Revit.DB.Element element = doc.Document.GetElement(elementId); System.Diagnostics.Trace.WriteLine(element.GetType().ToString()); GenericForm gf = element as GenericForm; if (null != gf && !gf.IsSolid) { continue; } CombinableElement ce = element as CombinableElement; if (null != ce) { solids.Append(ce); } } if (solids.Size < 2) { message = "At least 2 combinable elements should be selected."; return(Autodesk.Revit.UI.Result.Failed); } doc.Document.CombineElements(solids); //The selected generic forms are joined, whether or not they overlap. return(Autodesk.Revit.UI.Result.Succeeded); } AutoJoin autojoin = new AutoJoin(); autojoin.Join(doc.Document); //All overlapping generic forms are joined. return(Autodesk.Revit.UI.Result.Succeeded); }
public Result Execute(ExternalCommandData commandData, ref string message, ElementSet elements) { var uidoc = commandData.Application.ActiveUIDocument; var doc = uidoc.Document; var connForm = new ConnectElmFrm(uidoc); if (connForm.ShowDialog() != DialogResult.OK) { return(Result.Cancelled); } doc.AutoTransaction(() => { var combins = new CombinableElementArray(); var elms = connForm.Elms; elms.OfType <CombinableElement>().ToList().ForEach(f => combins.Append(f)); if (doc.IsFamilyDocument && combins.Size >= 2) { doc.CombineElements(combins); } else if (!doc.IsFamilyDocument && elms.Count >= 2) { elms.ForEach(f1 => elms.ForEach(f2 => { ExceptionUtil.AutoTry(() => { if (f1 == f2) { return; } if (!doc.CrossSpaceBox(f1, f2)) { return; } JoinGeometryUtils.JoinGeometry(doc, f1, f2); }); })); } }); return(Result.Succeeded); }
/// <summary> /// Join the overlapped elements in the list. /// </summary> /// <param name="elements">the element list may includes overlapping.</param> /// <param name="document">the active document</param> /// <returns>the joined geometry combination, the joined elements is removed from the list.</returns> public GeomCombination JoinOverlapping(List <CombinableElement> elements, Document document) { CombinableElementArray joinedElements = new CombinableElementArray(); // try to find the first overlapping. foreach (CombinableElement aElement in elements) { foreach (CombinableElement xElement in elements) { if (IsOverlapped(aElement, xElement)) { joinedElements.Append(aElement); break; } } if (1 == joinedElements.Size) { break; } } if (0 == joinedElements.Size) { return(null);//Can not find any overlapping. } // try to find all elements overlapped the first element. foreach (CombinableElement aElement in elements) { if (IsOverlapped(aElement, joinedElements.get_Item(0))) { joinedElements.Append(aElement); } } List <CombinableElement> allCanJoin = new List <CombinableElement>(); bool isNew = false; do { allCanJoin.Clear(); isNew = false; // try to find all elements overlapped joinedElements foreach (CombinableElement aElement in joinedElements) { foreach (CombinableElement xElement in elements) { if (IsOverlapped(aElement, xElement)) { allCanJoin.Add(xElement); } } } foreach (CombinableElement aElement in allCanJoin) { bool isContained = false; for (int ii = 0; ii < joinedElements.Size; ii++) { if (aElement.Id.IntegerValue == joinedElements.get_Item(ii).Id.IntegerValue) { isContained = true; break; } } if (!isContained) { isNew = true; joinedElements.Append(aElement); } } } while (isNew);// find all elements which overlapped with joined geometry combination. // removed the joined elements from the input list. foreach (CombinableElement aElement in joinedElements) { elements.Remove(aElement); } return(document.CombineElements(joinedElements)); }
/// <summary> /// Join the overlapped elements in the list. /// </summary> /// <param name="elements">the element list may includes overlapping.</param> /// <param name="document">the active document</param> /// <returns>the joined geometry combination, the joined elements is removed from the list.</returns> public GeomCombination JoinOverlapping(List<CombinableElement> elements, Document document) { CombinableElementArray joinedElements = new CombinableElementArray(); // try to find the first overlapping. foreach (CombinableElement aElement in elements) { foreach (CombinableElement xElement in elements) { if (IsOverlapped(aElement, xElement)) { joinedElements.Append(aElement); break; } } if (1 == joinedElements.Size) break; } if (0 == joinedElements.Size) { return null;//Can not find any overlapping. } // try to find all elements overlapped the first element. foreach (CombinableElement aElement in elements) { if (IsOverlapped(aElement, joinedElements.get_Item(0))) { joinedElements.Append(aElement); } } List<CombinableElement> allCanJoin = new List<CombinableElement>(); bool isNew = false; do { allCanJoin.Clear(); isNew = false; // try to find all elements overlapped joinedElements foreach (CombinableElement aElement in joinedElements) { foreach (CombinableElement xElement in elements) { if (IsOverlapped(aElement, xElement)) { allCanJoin.Add(xElement); } } } foreach (CombinableElement aElement in allCanJoin) { bool isContained = false; for (int ii = 0; ii < joinedElements.Size; ii++) { if (aElement.Id.IntegerValue == joinedElements.get_Item(ii).Id.IntegerValue) { isContained = true; break; } } if (!isContained) { isNew = true; joinedElements.Append(aElement); } } } while (isNew);// find all elements which overlapped with joined geometry combination. // removed the joined elements from the input list. foreach (CombinableElement aElement in joinedElements) { elements.Remove(aElement); } return document.CombineElements(joinedElements); }
/// <summary> /// Implement this method as an external command for Revit. /// </summary> /// <param name="commandData">An object that is passed to the external application /// which contains data related to the command, /// such as the application object and active view.</param> /// <param name="message">A message that can be set by the external application /// which will be displayed if a failure or cancellation is returned by /// the external command.</param> /// <param name="elements">A set of elements to which the external application /// can add elements that are to be highlighted in case of failure or cancellation.</param> /// <returns>Return the status of the external command. /// A result of Succeeded means that the API external method functioned as expected. /// Cancelled can be used to signify that the user cancelled the external operation /// at some point. Failure should be returned if the application is unable to proceed with /// the operation.</returns> public virtual Autodesk.Revit.UI.Result Execute(ExternalCommandData commandData , ref string message, Autodesk.Revit.DB.ElementSet elements) { if (null == s_appCreation) { // share for class Intersection. s_appCreation = commandData.Application.Application.Create; } UIDocument doc = commandData.Application.ActiveUIDocument; CombinableElementArray solids = new CombinableElementArray(); if (0 < doc.Selection.Elements.Size) { foreach (Autodesk.Revit.DB.Element element in doc.Selection.Elements) { System.Diagnostics.Trace.WriteLine(element.GetType().ToString()); GenericForm gf = element as GenericForm; if (null != gf && !gf.IsSolid) continue; CombinableElement ce = element as CombinableElement; if (null != ce) solids.Append(ce); } if (solids.Size < 2) { message = "At least 2 combinable elements should be selected."; return Autodesk.Revit.UI.Result.Failed; } doc.Document.CombineElements(solids); //The selected generic forms are joined, whether or not they overlap. return Autodesk.Revit.UI.Result.Succeeded; } AutoJoin autojoin = new AutoJoin(); autojoin.Join(doc.Document); //All overlapping generic forms are joined. return Autodesk.Revit.UI.Result.Succeeded; }
public static Dictionary <string, object> ByRoom(string familyTemplatePath, global::Revit.Elements.Room room, string materialName, global::Revit.Elements.Category category, string subcategory = "") { //variables global::Revit.Elements.Element famInstance = null; Autodesk.Revit.DB.FamilyInstance internalFam = null; bool fileFound = false; //the current document Autodesk.Revit.DB.Document doc = DocumentManager.Instance.CurrentDBDocument; UIApplication uiapp = new UIApplication(doc.Application); //convert the room to an Autodesk.Revit.DB representation Autodesk.Revit.DB.Architecture.Room internalRoom = (Autodesk.Revit.DB.Architecture.Room)room.InternalElement; string name = internalRoom.Name; //we close all of the families because we need to swap documents foreach (Document d in uiapp.Application.Documents) { if (d.IsFamilyDocument) { d.Close(false); } } //create the new family document in the background and store it in memory Document familyDocument = uiapp.Application.NewFamilyDocument(familyTemplatePath); //instantiate a material element id and try to get the material that was specified ElementId material = null; FilteredElementCollector materialCollector = new FilteredElementCollector(familyDocument).OfClass(typeof(Autodesk.Revit.DB.Material)); foreach (var m in materialCollector) { if (m.Name.ToLower().Replace(" ", "") == materialName.ToLower().Replace(" ", "")) { material = m.Id; } } //close Dynamo's open transaction, we need to do this because we open a new Revit API transaction in the family document (This is document switching) TransactionManager.Instance.ForceCloseTransaction(); //start creating the families. Transaction trans = new Transaction(familyDocument, "Generate Families Ya'll"); trans.Start(); //set the family category Autodesk.Revit.DB.Category familyCategory = familyDocument.Settings.Categories.get_Item(category.Name); familyDocument.OwnerFamily.FamilyCategory = familyCategory; //get the subcategory for the solids Autodesk.Revit.DB.Category subCategory = null; foreach (Autodesk.Revit.DB.Category c in familyCategory.SubCategories) { if (c.Name.ToLower() == subcategory.ToLower()) { subCategory = c; } } //get the height of the thing double height = room.Height; //get the curves IList <IList <BoundarySegment> > boundary = internalRoom.GetBoundarySegments(new SpatialElementBoundaryOptions()); //generate a plane Autodesk.Revit.DB.Plane revitPlane = Autodesk.Revit.DB.Plane.CreateByNormalAndOrigin(Vector.ZAxis().ToXyz(), new XYZ(0, 0, 0)); Autodesk.Revit.DB.SketchPlane sketchPlane = SketchPlane.Create(familyDocument, revitPlane); //the curve arrays to generate solids and voids in family CurveArray curveArray = new CurveArray(); CurveArrArray curveArrArray = new CurveArrArray(); CurveArray curveArrayVoid = new CurveArray(); CurveArrArray curveArrArrayVoid = new CurveArrArray(); //to perform the cut action on the solid with the voids CombinableElementArray ceArray = new CombinableElementArray(); //transform bizness Point roomCentroid = room.BoundingBox.ToCuboid().Centroid(); Point locationPoint = Point.ByCoordinates(roomCentroid.X, roomCentroid.Y, 0); CoordinateSystem oldCS = CoordinateSystem.ByOrigin(locationPoint); CoordinateSystem newCS = CoordinateSystem.ByOrigin(0, 0, 0); //flag to step through the boundaries. int flag = 0; while (flag < boundary.Count) { //the first set of curves is the solid's boundary if (flag == 0) { //generate the solid form which is the first item in the boundary segments. foreach (BoundarySegment b in boundary[flag]) { Autodesk.DesignScript.Geometry.Curve c = b.GetCurve().ToProtoType(); Autodesk.DesignScript.Geometry.Curve movedCurve = c.Transform(oldCS, newCS) as Autodesk.DesignScript.Geometry.Curve; curveArray.Append(movedCurve.ToRevitType()); } curveArrArray.Append(curveArray); Extrusion solidExtrusion = familyDocument.FamilyCreate.NewExtrusion(true, curveArrArray, sketchPlane, height); if (material != null) { //Set the material Autodesk.Revit.DB.Parameter matParam = solidExtrusion.get_Parameter(BuiltInParameter.MATERIAL_ID_PARAM); matParam.Set(material); } //try to set the subcategory if (subCategory != null) { solidExtrusion.Subcategory = subCategory; } } //subsequent lists of curves are representative of the voids else { //clear the curves from the collection for all items after the second one. (index 2+) if (!curveArrayVoid.IsEmpty) { curveArrayVoid.Clear(); curveArrArrayVoid.Clear(); ceArray.Clear(); } //generate the void form foreach (BoundarySegment b in boundary[flag]) { Autodesk.DesignScript.Geometry.Curve c = b.GetCurve().ToProtoType(); Autodesk.DesignScript.Geometry.Curve movedCurve = c.Transform(oldCS, newCS) as Autodesk.DesignScript.Geometry.Curve; curveArrayVoid.Append(movedCurve.ToRevitType()); } curveArrArrayVoid.Append(curveArrayVoid); Extrusion voidExtrusion = familyDocument.FamilyCreate.NewExtrusion(false, curveArrArrayVoid, sketchPlane, height); //try to combine things foreach (Extrusion genericForm in new FilteredElementCollector(familyDocument).OfClass(typeof(Extrusion)) .Cast <Extrusion>()) { ceArray.Append(genericForm); } //to add the void to the solid familyDocument.CombineElements(ceArray); } flag++; } familyDocument.Regenerate(); trans.Commit(); Autodesk.Revit.DB.Family fam = null; //build the temporary path string familyFilePath = Path.GetTempPath() + name + ".rfa"; SaveAsOptions opt = new SaveAsOptions(); opt.OverwriteExistingFile = true; familyDocument.SaveAs(familyFilePath, opt); familyDocument.Close(false); TransactionManager.Instance.ForceCloseTransaction(); Transaction trans2 = new Transaction(doc, "Attempting to place or update Room family instances."); trans2.Start(); IFamilyLoadOptions loadOptions = new FamilyImportOptions(); bool variable = true; loadOptions.OnFamilyFound(true, out variable); doc.LoadFamily(familyFilePath, loadOptions, out fam); FamilySymbol familySymbol = (FamilySymbol)doc.GetElement(fam.GetFamilySymbolIds().First()); //try to find if it is placed already FilteredElementCollector col = new FilteredElementCollector(doc); //get built in category from user viewable category BuiltInCategory myCatEnum = (BuiltInCategory)Enum.Parse(typeof(BuiltInCategory), category.Id.ToString()); foreach (Autodesk.Revit.DB.Element e in col.WhereElementIsNotElementType().OfCategory(myCatEnum).ToElements()) { Autodesk.Revit.DB.FamilySymbol type = (FamilySymbol)doc.GetElement(e.GetTypeId()); if (type.FamilyName.Equals(name)) { fileFound = true; internalFam = e as Autodesk.Revit.DB.FamilyInstance; } } //place families that are not placed if (fileFound == false) { if (!familySymbol.IsActive) { familySymbol.Activate(); } internalFam = doc.Create.NewFamilyInstance(new XYZ(roomCentroid.X, roomCentroid.Y, 0), familySymbol, internalRoom.Level, StructuralType.NonStructural); } trans2.Commit(); //delete the temp file File.Delete(familyFilePath); //cast to Dynamo type for output and location updating (if necessary) famInstance = internalFam.ToDSType(true); if (fileFound) { famInstance.SetLocation(locationPoint); } //returns the outputs var outInfo = new Dictionary <string, object> { { "familyInstance", famInstance } }; return(outInfo); }