public Result Execute( ExternalCommandData commandData, ref string message, ElementSet elements) { UIApplication app = commandData.Application; UIDocument uidoc = app.ActiveUIDocument; Document doc = uidoc.Document; FamilyInstance inst = LabUtils.GetSingleSelectedElementOrPrompt( uidoc, typeof(FamilyInstance)) as FamilyInstance; if (null == inst) { LabUtils.ErrorMsg( "Selected element is not a " + "standard family instance."); return(Result.Cancelled); } // determine selected instance category: Category instCat = inst.Category; Dictionary <string, List <FamilySymbol> > mapFamilyToSymbols = new Dictionary <string, List <FamilySymbol> >(); { WaitCursor waitCursor = new WaitCursor(); // Collect all types applicable to this category and sort them into // a dictionary mapping the family name to a list of its types. // // We create a collection of all loaded families for this category // and for each one, the list of all loaded types (symbols). // // There are many ways how to store the matching objects, but we choose // whatever is most suitable for the relevant UI. We could use Revit's // generic Map class, but it is probably more efficient to use the .NET // strongly-typed Dictionary with // KEY = Family name (String) // VALUE = list of corresponding FamilySymbol objects // // find all corresponding families and types: FilteredElementCollector families = new FilteredElementCollector(doc); families.OfClass(typeof(Family)); foreach (Family f in families) { bool categoryMatches = false; ISet <ElementId> ids = f.GetFamilySymbolIds(); // 2015 // we cannot trust f.Category or // f.FamilyCategory, so grab the category // from first family symbol instead: //foreach( FamilySymbol sym in f.Symbols ) // 2014 foreach (ElementId id in ids) // 2015 { Element symbol = doc.GetElement(id); categoryMatches = symbol.Category.Id.Equals( instCat.Id); break; } if (categoryMatches) { List <FamilySymbol> symbols = new List <FamilySymbol>(); //foreach( FamilySymbol sym in f.Symbols ) // 2014 foreach (ElementId id in ids) // 2015 { FamilySymbol symbol = doc.GetElement(id) as FamilySymbol; symbols.Add(symbol); } mapFamilyToSymbols.Add(f.Name, symbols); } } } // display the form allowing the user to select // a family and a type, and assign this type // to the instance. Lab3_4_Form form = new Lab3_4_Form(mapFamilyToSymbols); if (System.Windows.Forms.DialogResult.OK == form.ShowDialog()) { using (Transaction t = new Transaction(doc)) { t.Start("Change Selected Instance Type"); inst.Symbol = form.cmbType.SelectedItem as FamilySymbol; t.Commit(); } LabUtils.InfoMsg( "Successfully changed family : type to " + form.cmbFamily.Text + " : " + form.cmbType.Text); } return(Result.Succeeded); }
public Result Execute( ExternalCommandData commandData, ref string message, ElementSet elements) { try { WaitCursor waitCursor = new WaitCursor(); UIApplication app = commandData.Application; Document doc = app.ActiveUIDocument.Document; Autodesk.Revit.Creation.Application createApp = app.Application.Create; Autodesk.Revit.Creation.Document createDoc = doc.Create; using (Transaction t = new Transaction(doc)) { t.Start("Create Little House"); // Determine the four corners of the rectangular house: double width = 7 * LabConstants.MeterToFeet; double depth = 4 * LabConstants.MeterToFeet; List <XYZ> corners = new List <XYZ>(4); corners.Add(XYZ.Zero); corners.Add(new XYZ(width, 0, 0)); corners.Add(new XYZ(width, depth, 0)); corners.Add(new XYZ(0, depth, 0)); #region Test creating two levels #if CREATE_TWO_LEVELS Level levelBottom = null; Level levelMiddle = null; Level levelTop = null; List <Element> levels = new List <Element>(); Filter filterType = createApp.Filter.NewTypeFilter( typeof(Level)); doc.get_Elements(filterType, levels); foreach (Element e in levels) { if (null == levelBottom) { levelBottom = e as Level; } else if (null == levelMiddle) { levelMiddle = e as Level; } else if (null == levelTop) { levelTop = e as Level; } else { break; } } BuiltInParameter topLevelParam = BuiltInParameter.WALL_HEIGHT_TYPE; Line line; Wall wall; Parameter param; ElementId topId = levelMiddle.Id; List <Wall> walls = new List <Wall>(8); for (int i = 0; i < 4; ++i) { line = createApp.NewLineBound( corners[i], corners[3 == i ? 0 : i + 1]); wall = createDoc.NewWall( line, levelBottom, false); param = wall.get_Parameter(topLevelParam); param.Set(ref topId); walls.Add(wall); } topId = levelTop.Id; for (int i = 0; i < 4; ++i) { line = createApp.NewLineBound( corners[i], corners[3 == i ? 0 : i + 1]); wall = createDoc.NewWall( line, levelMiddle, false); param = wall.get_Parameter(topLevelParam); param.Set(ref topId); walls.Add(wall); } List <Element> doorSymbols = LabUtils.GetAllFamilySymbols( app, BuiltInCategory.OST_Doors); Debug.Assert( 0 < doorSymbols.Count, "expected at least one door symbol" + " to be loaded into project"); FamilySymbol door = doorSymbols[0] as FamilySymbol; XYZ midpoint = LabUtils.Midpoint( corners[0], corners[1]); FamilyInstance inst0 = createDoc.NewFamilyInstance( midpoint, door, walls[0], levelBottom, StructuralType.NonStructural); midpoint.Z = levelMiddle.Elevation; FamilyInstance inst1 = createDoc.NewFamilyInstance( midpoint, door, walls[4], levelMiddle, StructuralType.NonStructural); #endif // CREATE_TWO_LEVELS #endregion // Test creating two levels // Determine the levels where the walls will be located: Level levelBottom = null; Level levelTop = null; if (!LabUtils.GetBottomAndTopLevels(doc, ref levelBottom, ref levelTop)) { message = "Unable to determine wall bottom and top levels"; return(Result.Failed); } Debug.Print(string.Format("Drawing walls on '{0}' up to '{1}'", levelBottom.Name, levelTop.Name)); // Create the walls: BuiltInParameter topLevelParam = BuiltInParameter.WALL_HEIGHT_TYPE; ElementId levelBottomId = levelBottom.Id; ElementId topLevelId = levelTop.Id; List <Wall> walls = new List <Wall>(4); for (int i = 0; i < 4; ++i) { Line line = Line.CreateBound(corners[i], corners[3 == i ? 0 : i + 1]); //Wall wall = createDoc.NewWall( line, levelBottom, false ); // 2012 Wall wall = Wall.Create(doc, line, levelBottomId, false); // 2013 Parameter param = wall.get_Parameter(topLevelParam); param.Set(topLevelId); walls.Add(wall); } // Determine wall thickness for tag offset and profile growth: //double wallThickness = walls[0].WallType.CompoundStructure.Layers.get_Item( 0 ).Thickness; // 2011 //double wallThickness = walls[0].WallType.GetCompoundStructure().GetLayers()[0].Width; // 2012 double wallThickness = walls[0].WallType.Width; // simpler and more direct property available in 2012 // Add door and windows to the first wall; // note that the NewFamilyInstance() api method does not automatically add door // and window tags, like the ui command does. we add tags here by making additional calls // to NewTag(): FamilySymbol door = LabUtils.GetFirstFamilySymbol(doc, BuiltInCategory.OST_Doors); if (null == door) { LabUtils.InfoMsg("No door symbol found."); return(Result.Failed); } FamilySymbol window = LabUtils.GetFirstFamilySymbol( doc, BuiltInCategory.OST_Windows); if (null == window) { LabUtils.InfoMsg("No window symbol found."); return(Result.Failed); } XYZ midpoint = LabUtils.Midpoint(corners[0], corners[1]); XYZ p = LabUtils.Midpoint(corners[0], midpoint); XYZ q = LabUtils.Midpoint(midpoint, corners[1]); double tagOffset = 3 * wallThickness; //double windowHeight = 1 * LabConstants.MeterToFeet; double windowHeight = levelBottom.Elevation + 0.3 * ( levelTop.Elevation - levelBottom.Elevation); p = new XYZ(p.X, p.Y, windowHeight); q = new XYZ(q.X, q.Y, windowHeight); View view = doc.ActiveView; door.Activate(); // 2016 FamilyInstance inst = createDoc.NewFamilyInstance( midpoint, door, walls[0], levelBottom, StructuralType.NonStructural); midpoint += tagOffset * XYZ.BasisY; //IndependentTag tag = createDoc.NewTag( // view, inst, false, TagMode.TM_ADDBY_CATEGORY, // TagOrientation.Horizontal, midpoint ); // 2017 IndependentTag tag = IndependentTag.Create( doc, view.Id, new Reference(inst), false, TagMode.TM_ADDBY_CATEGORY, TagOrientation.Horizontal, midpoint); // 2018 IList <FamilyPointPlacementReference> fpprefs = inst.GetFamilyPointPlacementReferences(); IList <Reference> refs = inst.GetReferences(FamilyInstanceReferenceType.CenterLeftRight); //IndependentTag tag = IndependentTag.Create( doc, // view.Id, refs[0], false, TagMode.TM_ADDBY_CATEGORY, // TagOrientation.Horizontal, midpoint ); // 2018 window.Activate(); // 2016 inst = createDoc.NewFamilyInstance(p, window, walls[0], levelBottom, StructuralType.NonStructural); p += tagOffset * XYZ.BasisY; //tag = createDoc.NewTag( view, inst, // false, TagMode.TM_ADDBY_CATEGORY, // TagOrientation.Horizontal, p ); // 2017 tag = IndependentTag.Create( doc, view.Id, new Reference(inst), false, TagMode.TM_ADDBY_CATEGORY, TagOrientation.Horizontal, p); // 2018 inst = createDoc.NewFamilyInstance(q, window, walls[0], levelBottom, StructuralType.NonStructural); q += tagOffset * XYZ.BasisY; //tag = createDoc.NewTag( view, inst, // false, TagMode.TM_ADDBY_CATEGORY, // TagOrientation.TAG_HORIZONTAL, q ); // 2011 //tag = createDoc.NewTag( view, inst, // false, TagMode.TM_ADDBY_CATEGORY, // TagOrientation.Horizontal, q ); // 2012 tag = IndependentTag.Create( doc, view.Id, new Reference(inst), false, TagMode.TM_ADDBY_CATEGORY, TagOrientation.Horizontal, p); // 2018 // Grow the profile out by half the wall thickness, // so the floor and roof do not stop halfway through the wall: double w = 0.5 * wallThickness; corners[0] -= w * (XYZ.BasisX + XYZ.BasisY); corners[1] += w * (XYZ.BasisX - XYZ.BasisY); corners[2] += w * (XYZ.BasisX + XYZ.BasisY); corners[3] -= w * (XYZ.BasisX - XYZ.BasisY); CurveArray profile = new CurveArray(); for (int i = 0; i < 4; ++i) { //Line line = createApp.NewLineBound( // 2013 Line line = Line.CreateBound( // 2014 corners[i], corners[3 == i ? 0 : i + 1]); profile.Append(line); } // Add a floor, a roof and the roof slope: bool structural = false; Floor floor = createDoc.NewFloor( profile, structural); List <Element> roofTypes = new List <Element>( LabUtils.GetElementsOfType( doc, typeof(RoofType), BuiltInCategory.OST_Roofs)); Debug.Assert(0 < roofTypes.Count, "expected at least one roof type" + " to be loaded into project"); // Ensure that we get a valid roof type. // In Revit 2013, the first one encountered // is sloped glazing with zero entries in // its compound layers; actually, the entire // compound structure is null: //RoofType roofType = null; //foreach( RoofType rt in roofTypes ) //{ // CompoundStructure cs = rt.GetCompoundStructure(); // if( null != cs // && 0 < cs.GetLayers().Count ) // { // roofType = rt; // break; // } //} RoofType roofType = roofTypes .Cast <RoofType>() .FirstOrDefault <RoofType>(typ => null != typ.GetCompoundStructure()); ModelCurveArray modelCurves = new ModelCurveArray(); FootPrintRoof roof = createDoc.NewFootPrintRoof(profile, levelTop, roofType, out modelCurves); // Regenerate the model after roof creation, // otherwise the calls to set_DefinesSlope and // set_SlopeAngle throw the exception "Unable // to access curves from the roof sketch." doc.Regenerate(); // The argument to set_SlopeAngle is NOT an // angle, it is really a slope, i.e. relation // of height to distance, e.g. 0.5 = 6" / 12", // 0.75 = 9" / 12", etc. double slope = 0.3; foreach (ModelCurve curve in modelCurves) { roof.set_DefinesSlope(curve, true); roof.set_SlopeAngle(curve, slope); } // Add a room and a room tag: Room room = createDoc.NewRoom(levelBottom, new UV(0.5 * width, 0.5 * depth)); //RoomTag roomTag = createDoc.NewRoomTag( // room, new UV( 0.5 * width, 0.7 * depth ), // null ); // 2014 RoomTag roomTag = createDoc.NewRoomTag( new LinkElementId(room.Id), new UV(0.5 * width, 0.7 * depth), null); // 2015 //doc.AutoJoinElements(); // todo: remove this, the transaction should perform this automatically //LabUtils.InfoMsg( "Little house was created successfully." ); //#region Test setting BaseOffset and LimitOffset //// 11334196 [Failed to set Room.BaseOffset and Room.LimitOffset properties] //double h = 0.123; //room.BaseOffset = -h; //room.LimitOffset = h + h; //#endregion // Test setting BaseOffset and LimitOffset t.Commit(); return(Result.Succeeded); } } catch (Exception ex) { message = ex.Message; return(Result.Failed); } }
/// <summary> /// Revit external command to list all valid built-in parameters for a given selected element. /// </summary> public Result Execute( ExternalCommandData commandData, ref string message, ElementSet elements) { UIDocument uidoc = commandData.Application.ActiveUIDocument; Document doc = uidoc.Document; Element e = LabUtils.GetSingleSelectedElementOrPrompt( uidoc); if (null == e) { return(Result.Cancelled); } bool isSymbol = false; #region Check for FamilyInstance #if CHECK_FOR_FAMILY_INSTANCE // // for a family instance, ask user whether to // display instance or type parameters; // in a similar manner, we could add dedicated // switches for Wall --> WallType, // Floor --> FloorType etc. ... // if (e is FamilyInstance) { FamilyInstance inst = e as FamilyInstance; if (null != inst.Symbol) { string symbol_name = LabUtils.ElementDescription( inst.Symbol, true); string family_name = LabUtils.ElementDescription( inst.Symbol.Family, true); string msg = "This element is a family instance, so it " + "has both type and instance parameters. " + "By default, the instance parameters are " + "displayed. If you select 'No', the type " + "parameters will be displayed instead. " + "Would you like to see the instance " + "parameters?"; if (!LabUtils.QuestionMsg(msg)) { e = inst.Symbol; isSymbol = true; } } } #endif // CHECK_FOR_FAMILY_INSTANCE #endregion // Check for FamilyInstance #region Check for element type #if CHECK_GET_TYPE_ID ElementId idType = e.GetTypeId(); if (ElementId.InvalidElementId != idType) { // The selected element has a type; ask user // whether to display instance or type // parameters. ElementType typ = doc.GetElement(idType) as ElementType; Debug.Assert(null != typ, "expected to retrieve a valid element type"); string type_name = LabUtils.ElementDescription( typ, true); string msg = "This element has an ElementType, so it has " + "both type and instance parameters. By " + "default, the instance parameters are " + "displayed. If you select 'No', the type " + "parameters will be displayed instead. " + "Would you like to see the instance " + "parameters?"; if (!LabUtils.QuestionMsg(msg)) { e = typ; isSymbol = true; } } #endif // CHECK_GET_TYPE_ID #endregion // Check for element type SortableBindingList <ParameterData> data = new SortableBindingList <ParameterData>(); { WaitCursor waitCursor = new WaitCursor(); Array bips = Enum.GetValues(typeof(BuiltInParameter)); int n = bips.Length; Parameter p; foreach (BuiltInParameter a in bips) { try { p = e.get_Parameter(a); #region Check for external definition #if CHECK_FOR_EXTERNAL_DEFINITION Definition d = p.Definition; ExternalDefinition e = d as ExternalDefinition; // this is never possible string guid = (null == e) ? null : e.GUID.ToString(); #endif // CHECK_FOR_EXTERNAL_DEFINITION #endregion // Check for external definition if (null != p) { //string value = LabUtils.GetParameterValue2( p, doc ); string valueString = (StorageType.ElementId == p.StorageType) ? LabUtils.GetParameterValue2(p, doc) : p.AsValueString(); data.Add(new ParameterData(a, p, valueString)); } } catch (Exception ex) { Debug.Print("Exception retrieving built-in parameter {0}: {1}", a, ex); } } } string description = LabUtils.ElementDescription(e, true) + (isSymbol ? " Type" : " Instance"); using (BuiltInParamsCheckerForm form = new BuiltInParamsCheckerForm(description, data)) { form.ShowDialog(); } return(Result.Succeeded); }
public Result Execute( ExternalCommandData commandData, ref string message, ElementSet elements) { #region 2.1.a. Access Revit doc and open output file: UIApplication app = commandData.Application; Document doc = app.ActiveUIDocument.Document; // .NET exception handling should be done everywhere, // but will sometimes be omitted for clarity in the // following labs unless we expect exceptions: StreamWriter sw; try { sw = new StreamWriter(LabConstants.FilePath); } catch (Exception e) { LabUtils.ErrorMsg(string.Format("Cannot open '{0}': {1}", LabConstants.FilePath, e.Message)); return(Result.Failed); } #endregion // 2.1.a. Access Revit doc and open output file try { WaitCursor waitCursor = new WaitCursor(); #region 2.1.b. Set up element collector to retrieve all elements: // the Revit API does not expect an application // ever to need to iterate over all elements. // To do so, we need to use a trick: ask for all // elements fulfilling a specific criteria and // unite them with all elements NOT fulfilling // the same criteria: FilteredElementCollector collector = new FilteredElementCollector(doc) .WhereElementIsElementType(); FilteredElementCollector collector2 = new FilteredElementCollector(doc) .WhereElementIsNotElementType(); collector.UnionWith(collector2); #endregion // 2.1.b. Set up element collector to retrieve all elements #region 2.1.c. Loop over the elements, list their data, and close the file: string s, line; foreach (Element e in collector) { line = "Id=" + e.Id.IntegerValue.ToString(); // element id line += "; Class=" + e.GetType().Name; // element class, i.e. System.Type // The element category is not implemented for all classes, // and may return null; for Family elements, one can sometimes // use the FamilyCategory property instead. s = string.Empty; if (null != e.Category) { s = e.Category.Name; } if (0 == s.Length && e is Family && null != ((Family)e).FamilyCategory) { s = ((Family)e).FamilyCategory.Name; } if (0 == s.Length) { s = "?"; } line += "; Category=" + s; // The element Name has a different meaning for different classes, // but is mostly implemented "logically". More precise info on elements // can be obtained in class-specific ways. line += "; Name=" + e.Name; line += "; UniqueId=" + e.UniqueId; //line += "; Guid=" + GetGuid( e.UniqueId ); sw.WriteLine(line); } sw.Close(); LabUtils.InfoMsg("Element list has been written to " + LabConstants.FilePath + "."); #endregion // 2.1.c. Loop over the elements, list their data, and close the output file } catch (Exception e) { message = e.Message; } return(Result.Failed); }