public Result Execute( ExternalCommandData commandData, ref string message, ElementSet elements) { UIApplication app = commandData.Application; Document doc = app.ActiveUIDocument.Document; List <string> a = new List <string>(); // list groups: FilteredElementCollector collector; collector = new FilteredElementCollector(doc); collector.OfClass(typeof(Group)); foreach (Group g in collector) { a.Add("Id=" + g.Id.IntegerValue.ToString() + "; Type=" + g.GroupType.Name); } LabUtils.InfoMsg("{0} group{1} in the document{2}", a); // list groups types: BuiltInParameter bic = BuiltInParameter.SYMBOL_FAMILY_NAME_PARAM; a.Clear(); collector = new FilteredElementCollector(doc); collector.OfClass(typeof(GroupType)); foreach (GroupType g in collector) { // determine the GroupType system family // (cf. Labs3 for standard symbols): Parameter p = g.get_Parameter(bic); string famName = (null == p) ? "?" : p.AsString(); a.Add("Name=" + g.Name + "; Id=" + g.Id.IntegerValue.ToString() + "; Family=" + famName); } LabUtils.InfoMsg("{0} group type{1} in the document{2}", a); // typically, only "Model" types will be needed. // create a filter by creating a provider and an evaluator. // we can reuse the collector we already set up for group // types, and just add another criteria to check to it: a.Clear(); #region Failed attempts /* * this returns zero elements: * * ParameterValueProvider provider * = new ParameterValueProvider( new ElementId( ( int ) bic ) ); * * FilterStringRuleEvaluator evaluator * = new FilterStringEquals(); * * string ruleString = _groupTypeModel; * bool caseSensitive = true; * * FilterRule rule = new FilterStringRule( provider, evaluator, ruleString, caseSensitive ); * * // Create an ElementParameter filter: * * ElementParameterFilter filter = new ElementParameterFilter( rule ); * * // Apply the filter to the elements in the active collector: * * collector.WherePasses( filter ).ToElements(); */ /* * this returns false: * * if( doc.Settings.Categories.Contains( _groupsTypeModel ) ) * { * Category cat = doc.Settings.Categories.get_Item( _groupsTypeModel ); * * foreach( GroupType g in collector ) * { * a.Add( "Name=" + g.Name + "; Id=" + g.Id.IntegerValue.ToString() ); * } * } */ #endregion // Failed attempts collector.OfCategory(BuiltInCategory.OST_IOSModelGroups); foreach (GroupType g in collector) { a.Add("Name=" + g.Name + "; Id=" + g.Id.IntegerValue.ToString()); } LabUtils.InfoMsg("{0} *model* group type{1} in the document{2}", a); return(Result.Failed); }
/// <summary> /// This method will run automatically when Revit start up. /// It shows a message box. Initiative task can be done in this function. /// </summary> public Result OnStartup( UIControlledApplication a) { LabUtils.InfoMsg("Hello World from an external application in C#."); return(Result.Succeeded); }
public Result Execute( ExternalCommandData commandData, ref string message, ElementSet elements) { UIApplication app = commandData.Application; UIDocument uidoc = app.ActiveUIDocument; Document doc = uidoc.Document; // Get all Group Types of Model Family: FilteredElementCollector modelGroupTypes = new FilteredElementCollector(doc); modelGroupTypes.OfClass(typeof(GroupType)); modelGroupTypes.OfCategory(BuiltInCategory.OST_IOSModelGroups); if (0 == modelGroupTypes.Count()) { message = "No model group types found in model."; return(Result.Failed); } FilteredElementCollector groups; groups = new FilteredElementCollector(doc); groups.OfClass(typeof(Group)); foreach (Group g in groups) { // Offer simple message box to swap the type // (one-by-one, stop if user confirms the change) foreach (GroupType gt in modelGroupTypes) { string msg = "Swap OLD Type=" + g.GroupType.Name + " with NEW Type=" + gt.Name + " for Group Id=" + g.Id.IntegerValue.ToString() + "?"; TaskDialogResult r = LabUtils.QuestionCancelMsg(msg); switch (r) { case TaskDialogResult.Yes: using (Transaction tx = new Transaction(doc)) { tx.Start("Swap Group Type"); g.GroupType = gt; tx.Commit(); } LabUtils.InfoMsg("Group type successfully swapped."); return(Result.Succeeded); case TaskDialogResult.Cancel: LabUtils.InfoMsg("Command cancelled."); return(Result.Cancelled); // else continue... } } } /* * // * // cannot modify group members after creation: * // * Element e = null; * ElementArray els = new ElementArray(); * els.Append( e ); * Group g = new Group(); * g.Members = els; // Property or indexer 'Autodesk.Revit.Elements.Group.Members' cannot be assigned to -- it is read only * Element e2 = null; * els.Append( e2 ); * g.Members = els; */ return(Result.Succeeded); }
public Result Execute( ExternalCommandData commandData, ref string message, ElementSet elements) { UIApplication app = commandData.Application; Document doc = app.ActiveUIDocument.Document; FilteredElementCollector rooms = new FilteredElementCollector(doc); // // this is one way of obtaining rooms ... but see below for a better solution: // //rooms.OfClass( typeof( Room ) ); // Input type is of an element type that exists in the API, but not in Revit's native object model. Try using Autodesk.Revit.DB.Enclosure instead, and then postprocessing the results to find the elements of interest. //rooms.OfClass( typeof( Enclosure ) ); // this works but returns all Enclosure elements RoomFilter filter = new RoomFilter(); rooms.WherePasses(filter); if (0 == rooms.Count()) { LabUtils.InfoMsg("There are no rooms in this model."); } else { List <string> a = new List <string>(); /* * foreach( Enclosure e in rooms ) // todo: remove this * { * Room room = e as Room; // todo: remove this * if( null != room ) // todo: remove this * { */ foreach (Room room in rooms) { string roomName = room.Name; string roomNumber = room.Number; string s = "Room Id=" + room.Id.IntegerValue.ToString() + " Name=" + roomName + " Number=" + roomNumber + "\n"; // Loop all boundaries of this room //BoundarySegmentArrayArray boundaries = room.Boundary; // 2011 IList <IList <BoundarySegment> > boundaries // 2012 = room.GetBoundarySegments( // 2012 new SpatialElementBoundaryOptions()); // 2012; passing in a null value throws an exception // Check to ensure room has boundary if (null != boundaries) { int iB = 0; //foreach( BoundarySegmentArray boundary in boundaries ) // 2011 foreach (IList <BoundarySegment> boundary in boundaries) // 2012 { ++iB; s += " Boundary " + iB + ":\n"; int iSeg = 0; foreach (BoundarySegment segment in boundary) { ++iSeg; // Segment's curve Curve crv = segment.GetCurve(); if (crv is Line) { Line line = crv as Line; XYZ ptS = line.GetEndPoint(0); XYZ ptE = line.GetEndPoint(1); s += " Segment " + iSeg + " is a LINE: " + LabUtils.PointString(ptS) + " ; " + LabUtils.PointString(ptE) + "\n"; } else if (crv is Arc) { Arc arc = crv as Arc; XYZ ptS = arc.GetEndPoint(0); XYZ ptE = arc.GetEndPoint(1); double r = arc.Radius; s += " Segment " + iSeg + " is an ARC:" + LabUtils.PointString(ptS) + " ; " + LabUtils.PointString(ptE) + " ; R=" + LabUtils.RealString(r) + "\n"; } } } a.Add(s); } LabUtils.InfoMsg("{0} room{1} in the model{2}", a); } } return(Result.Failed); }
public Result Execute( ExternalCommandData commandData, ref string message, ElementSet elements) { #region TEST_1 #if TEST_1 // // you cannot create your own parameter, because the // constuctor is for internal use only. This is due // to the fact that a parameter cannot live on its own, // it is linked to a definition and needs to be hooked // up properly in the Revit database system to work // ... case 1245614 [Formatting units strings]: // bool iReallyWantToCrash = false; if (iReallyWantToCrash) { Parameter p = new Parameter(); p.Set(1.0); string s = p.AsDouble().ToString(); string t = p.AsValueString(); Debug.WriteLine("Value " + s); Debug.WriteLine("Value string " + t); } #endif // TEST #endregion // TEST_1 UIDocument uidoc = commandData.Application.ActiveUIDocument; Document doc = uidoc.Document; // Loop through all pre-selected elements: foreach (ElementId id in uidoc.Selection.GetElementIds()) { Element e = doc.GetElement(id); string s = string.Empty; // set this variable to false to analyse the element's own parameters, // i.e. instance parameters for a family instance, and set it to true // to analyse a family instance's type parameters: bool analyseTypeParameters = false; if (analyseTypeParameters) { if (e is FamilyInstance) { FamilyInstance inst = e as FamilyInstance; if (null != inst.Symbol) { e = inst.Symbol; s = " type"; } } else if (e is Wall) { Wall wall = e as Wall; if (null != wall.WallType) { e = wall.WallType; s = " type"; } } // ... add support for other types if desired ... } // Loop through and list all UI-visible element parameters List <string> a = new List <string>(); #region 4.1.a Iterate over element parameters and retrieve their name, type and value: foreach (Parameter p in e.Parameters) { string name = p.Definition.Name; string type = p.StorageType.ToString(); string value = LabUtils.GetParameterValue2(p, uidoc.Document); //bool read_only = p.Definition.IsReadOnly; // 2013 bool read_only = p.IsReadOnly; // 2014 a.Add(string.Format( "Name={0}; Type={1}; Value={2}; ValueString={3}; read-{4}", name, type, value, p.AsValueString(), (read_only ? "only" : "write"))); } #endregion // 4.1.a string what = e.Category.Name + " (" + e.Id.IntegerValue.ToString() + ")"; LabUtils.InfoMsg(what + " has {0} parameter{1}{2}", a); // If we know which param we are looking for, then: // A) If a standard parameter, we can get it via BuiltInParam // signature of Parameter method: try { #region 4.1.b Retrieve a specific built-in parameter: Parameter p = e.get_Parameter( BuiltInParameter.FAMILY_BASE_LEVEL_OFFSET_PARAM); #endregion // 4.1.b if (null == p) { LabUtils.InfoMsg("FAMILY_BASE_LEVEL_OFFSET_PARAM is NOT available for this element."); } else { string name = p.Definition.Name; string type = p.StorageType.ToString(); string value = LabUtils.GetParameterValue2(p, doc); LabUtils.InfoMsg("FAMILY_BASE_LEVEL_OFFSET_PARAM: Name=" + name + "; Type=" + type + "; Value=" + value); } } catch (Exception) { LabUtils.InfoMsg("FAMILY_BASE_LEVEL_OFFSET_PARAM is NOT available for this element."); } // B) For a shared parameter, we can get it via "GUID" signature // of Parameter method ... this will be shown later in Labs 4 ... // C) or we can get the parameter by name: // alternatively, loop through all parameters and // search for the name (this works for either // standard or shared). Note that the same name // may occur multiple times: const string paramName = "Base Offset"; //Parameter parByName = e.get_Parameter( paramName ); // 2014 IList <Parameter> paramsByName = e.GetParameters(paramName); // 2015 if (0 == paramsByName.Count) { LabUtils.InfoMsg(paramName + " is NOT available for this element."); } else { foreach (Parameter p in paramsByName) { string parByNameName = p.Definition.Name; string parByNameType = p.StorageType.ToString(); string parByNameValue = LabUtils.GetParameterValue2(p, doc); LabUtils.InfoMsg(paramName + ": Name=" + parByNameName + "; Type=" + parByNameType + "; Value=" + parByNameValue); } } #region TEST_2 #if TEST_2 List <string> a = GetParameters(doc, e); foreach (string s2 in a) { Debug.WriteLine(s2); } #endif // TEST_2 #endregion // TEST_2 } return(Result.Failed); }
public Result Execute( ExternalCommandData commandData, ref string message, ElementSet elements) { #region 1.2.a. Examine command data input argument: // // access application, document, and current view: // UIApplication uiapp = commandData.Application; Application app = uiapp.Application; UIDocument uidoc = uiapp.ActiveUIDocument; Document doc = uidoc.Document; View view = commandData.View; LanguageType lt = app.Language; ProductType pt = app.Product; string s = "Application = " + app.VersionName + "\r\nLanguage = " + lt.ToString() + "\r\nProduct = " + pt.ToString() + "\r\nVersion = " + app.VersionNumber + "\r\nDocument path = " + doc.PathName // empty if not yet saved + "\r\nDocument title = " + doc.Title + "\r\nView name = " + view.Name; LabUtils.InfoMsg(s); #endregion // 1.2.a. Examine command data input argument #region 1.2.b. List selection set content: // // list the current selection set: // Selection sel = uidoc.Selection; List <string> a = new List <string>(); foreach (ElementId id in sel.GetElementIds()) { Element e = doc.GetElement(id); string name = (null == e.Category) ? e.GetType().Name : e.Category.Name; a.Add(name + " Id=" + e.Id.IntegerValue.ToString()); } LabUtils.InfoMsg( "There are {0} element{1} in the selection set{2}", a); #endregion // 1.2.b. List selection set content #region 1.2.c. Populate return arguments: // We pretend that something is wrong with the // first element in the selection. Pass an error // message back to the user and indicate the // error result: ICollection <ElementId> ids = sel.GetElementIds(); if (0 < ids.Count) { //ElementSetIterator iter = sel.Elements.ForwardIterator(); //iter.MoveNext(); //Element errElem = iter.Current as Element; Element errElem = doc.GetElement(ids.First()); elements.Clear(); elements.Insert(errElem); message = "We pretend something is wrong with this " + " element and pass back this message to user"; return(Result.Failed); } else { // We return failed here as well. // As long as the message string and element set are empty, // it makes no difference to the user. // If they are not empty, the message is displayed to the // user and/or the elements in the set are highlighted. // If an automatic transaction is open, it is aborted, // avoiding marking the database as dirty. return(Result.Failed); } #endregion // 1.2.c. Populate return arguments }
public Result Execute( ExternalCommandData commandData, ref string message, ElementSet elements) { UIApplication app = commandData.Application; Document doc = app.ActiveUIDocument.Document; #region 2.3.a Filter to retrieve and list all walls: // get all wall elements: // // we could also call // // FilteredElementCollector walls = LabUtils.GetElementsOfType( // doc, typeof( Wall ), BuiltInCategory.OST_Walls ); FilteredElementCollector walls = new FilteredElementCollector(doc); walls.OfClass(typeof(Wall)); List <string> a = new List <string>(); foreach (Wall wall in walls) { a.Add(string.Format("Id={0}; Kind={1}; Type={2}", wall.Id.IntegerValue, wall.WallType.Kind.ToString(), wall.WallType.Name)); } LabUtils.InfoMsg("{0} wall{1} in the model{2}", a); #endregion // 2.3.a Filter to retrieve and list all walls a.Clear(); #region 2.3.b Filter to retrieve and list all doors: // get all door family instances: // // we could also call // // FilteredElementCollector doors = LabUtils.GetElementsOfType( // doc, typeof( FamilyInstance ), BuiltInCategory.OST_Doors ); // // or // // FilteredElementCollector doors = LabUtils.GetFamilyInstances( // doc, BuiltInCategory.OST_Doors ); FilteredElementCollector doors = new FilteredElementCollector(doc); doors.OfCategory(BuiltInCategory.OST_Doors); doors.OfClass(typeof(FamilyInstance)); foreach (FamilyInstance door in doors) { // For family instances, the element name property // returns the type name: a.Add(string.Format("Id={0}; Type={1}", door.Id.IntegerValue, door.Name)); } LabUtils.InfoMsg("{0} door family instance{1} in the model{2}", a); #endregion // 2.3.b Filter to retrieve and list all doors return(Result.Failed); }
public Result Execute( ExternalCommandData commandData, ref string message, ElementSet elements) { UIApplication app = commandData.Application; UIDocument uidoc = app.ActiveUIDocument; Document doc = uidoc.Document; //ElementSet ss = uidoc.Selection.Elements; // 2014 ICollection <ElementId> ids = uidoc.Selection.GetElementIds(); Wall wall = null; if (0 < ids.Count) { // old pre-selection handling: // must be one single element only: if (1 != ids.Count) { message = "Please pre-select a single wall element."; return(Result.Failed); } // must be a wall: //ElementSetIterator it = ss.ForwardIterator(); //it.MoveNext(); //Element e = it.Current as Element; ElementId id = ids.First <ElementId>(); Element e = doc.GetElement(id); if (!(e is Wall)) { message = "Selected element is NOT a wall."; return(Result.Failed); } wall = e as Wall; } else { // new prompt for filtered selection allowing only walls: try { Reference r = uidoc.Selection.PickObject( ObjectType.Element, new WallSelectionFilter(), "Please pick a wall"); //wall = r.Element as Wall; // 2011 wall = uidoc.Document.GetElement(r) as Wall; // 2012 } catch (OperationCanceledException) { message = "Selection cancelled."; return(Result.Cancelled); } } // wall must be constrained to a level at the top (more on parameters later): Level topLev = null; try { ElementId id = wall.get_Parameter(BuiltInParameter.WALL_HEIGHT_TYPE).AsElementId(); topLev = doc.GetElement(id) as Level; } catch (Exception) { topLev = null; } if (null == topLev) { message = "Selected wall is not constrained to a level at the top."; return(Result.Failed); } // get the bottom level as well (this should never fail): Level botLev = null; try { ElementId id = wall.get_Parameter(BuiltInParameter.WALL_BASE_CONSTRAINT).AsElementId(); botLev = doc.GetElement(id) as Level; } catch (Exception) { botLev = null; } if (null == botLev) { message = "Selected wall is not constrained to a level at the bottom."; return(Result.Failed); } // Calculate the location points for the 3 columns (assuming straight wall) LocationCurve locCurve = wall.Location as LocationCurve; XYZ ptStart = locCurve.Curve.GetEndPoint(0); XYZ ptEnd = locCurve.Curve.GetEndPoint(1); XYZ ptMid = 0.5 * (ptStart + ptEnd); List <XYZ> locations = new List <XYZ>(3); locations.Add(ptStart); locations.Add(ptMid); locations.Add(ptEnd); string s = "{0} location{1} for the new columns in raw database coordinates, e.g. feet{2}"; List <string> a = new List <string>(); a.Add("Start: " + LabUtils.PointString(ptStart)); a.Add("Mid : " + LabUtils.PointString(ptMid)); a.Add("End : " + LabUtils.PointString(ptEnd)); LabUtils.InfoMsg(s, a); FilteredElementCollector collector = new FilteredElementCollector(doc); collector.OfCategory(BuiltInCategory.OST_Columns); collector.OfClass(typeof(FamilySymbol)); #if SEARCH_FOR_SPECIFIC_NAME // retrieve the family type for the new instances. // if needed, change the names to match a column // type available in the model: string family_name = "M_Wood Timber Column"; string type_name = "191 x 292mm"; // LINQ query to find element with given name: // // ... note that this could also be achieved by // filtering for the element name parameter value. var column_types = from element in collector //where ((FamilySymbol)element).Family.Name == family_name where element.Name == type_name select element; FamilySymbol symbol = null; try { symbol = column_types.Cast <FamilySymbol>().First <FamilySymbol>(); } catch { } if (null == symbol) { message = string.Format( "Cannot find type '{0}' in family '{1}' in the current model - please load it first.", type_name, family_name); return(Result.Failed); } #endif // SEARCH_FOR_SPECIFIC_NAME FamilySymbol symbol = collector.Cast <FamilySymbol>().First <FamilySymbol>(); if (null == symbol) { message = "Cannot find a suitable column type."; return(Result.Failed); } using (Transaction tx = new Transaction(doc)) { tx.Start("Insert Columns and Move Wall"); // insert column family instances: foreach (XYZ p in locations) { try { // Note: Currently there is a problem. // If we set the type as NonStructural, it is treated as Annotation instance, // and it shows only in plan view. // FamilyInstance column = doc.Create.NewFamilyInstance( p, symbol, botLev, StructuralType.NonStuctural ); FamilyInstance column = doc.Create.NewFamilyInstance( p, symbol, botLev, StructuralType.Column); Parameter paramTopLevel = column.get_Parameter( BuiltInParameter.FAMILY_TOP_LEVEL_PARAM); ElementId id = topLev.Id; paramTopLevel.Set(id); } catch (Exception) { LabUtils.ErrorMsg("Failed to create or adjust column."); } } // Finally, move the wall so the columns are visible. // We move the wall perpendicularly to its location // curve by one tenth of its length: XYZ v = new XYZ( -0.1 * (ptEnd.Y - ptStart.Y), 0.1 * (ptEnd.X - ptStart.X), 0); if (!wall.Location.Move(v)) { LabUtils.ErrorMsg("Failed to move the wall."); } tx.Commit(); } 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); }
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); } }
public Result Execute( ExternalCommandData commandData, ref string message, ElementSet elements) { UIApplication app = commandData.Application; Document doc = app.ActiveUIDocument.Document; List <string> a = new List <string>(); FilteredElementCollector families; #region 3.1.a Retrieve and iterate over all Family objects in document: // // retrieve all family elements in current document: // families = new FilteredElementCollector(doc); families.OfClass(typeof(Family)); foreach (Family f in families) { // Get its category name; notice that the Category property is not // implemented for the Family class; use FamilyCategory instead; // notice that that is also not always implemented; in that case, // use the workaround demonstrated below, looking at the contained // family symbols' category: a.Add(string.Format("Name={0}; Category={1}; FamilyCategory={2}", f.Name, ((null == f.Category) ? "?" : f.Category.Name), ((null == f.FamilyCategory) ? "?" : f.FamilyCategory.Name))); } #endregion // 3.1.a string msg = "{0} standard familie{1} are loaded in this model{2}"; LabUtils.InfoMsg(msg, a); // Loop through the collection of families, and now look at // the child symbols (types) as well. These symbols can be // used to determine the family category. foreach (Family f in families) { string catName; bool first = true; // Loop all contained symbols (types): //foreach( FamilySymbol s in f.Symbols ) // 2014 foreach (ElementId id in f.GetFamilySymbolIds()) // 2015 { FamilySymbol s = doc.GetElement(id) as FamilySymbol; // you can determine the family category from its first symbol. if (first) { first = false; #region 3.1.b Retrieve category name of first family symbol: catName = s.Category.Name; #endregion // 3.1.b msg = "Family: Name=" + f.Name + "; Id=" + f.Id.IntegerValue.ToString() + "; Category=" + catName + "\r\nContains Types:"; } msg += "\r\n " + s.Name + "; Id=" + s.Id.IntegerValue.ToString(); } // Show the symbols for this family and allow user to proceed // to the next family (OK) or cancel (Cancel) msg += "\r\nContinue?"; if (!LabUtils.QuestionMsg(msg)) { break; } } // // return all families whose name contains the substring "Round Duct": // IEnumerable <Family> round_duct_families = LabUtils.GetFamilies(doc, "Round Duct", true); int n = round_duct_families.Count(); return(Result.Failed); }
public Result Execute( ExternalCommandData commandData, ref string message, ElementSet elements) { UIApplication app = commandData.Application; UIDocument uidoc = app.ActiveUIDocument; Document doc = uidoc.Document; // Find all wall types and their system families (or kinds): WallType newWallType = null; string msg = "All wall types and families in the model:"; string content = string.Empty; FilteredElementCollector wallTypes = new FilteredElementCollector(doc) .OfClass(typeof(WallType)); foreach (WallType wt in wallTypes) { content += "\nType=" + wt.Name + " Family=" + wt.Kind.ToString(); newWallType = wt; } content += "\n\nStored WallType " + newWallType.Name + " (Id=" + newWallType.Id.IntegerValue.ToString() + ") for later use."; LabUtils.InfoMsg(msg, content); // Find all floor types: FloorType newFloorType = null; msg = "All floor types in the model:"; content = string.Empty; //foreach( FloorType ft in doc.FloorTypes ) // 2014 FilteredElementCollector floorTypes // 2015 = new FilteredElementCollector(doc) .OfClass(typeof(FloorType)); foreach (FloorType ft in floorTypes) // 2015 { content += "\nType=" + ft.Name + ", Id=" + ft.Id.IntegerValue.ToString(); // In 9.0, the "Foundation Slab" system family from "Structural // Foundations" category ALSO contains FloorType class instances. // Be careful to exclude those as choices for standard floor types. Parameter p = ft.get_Parameter(BuiltInParameter.SYMBOL_FAMILY_NAME_PARAM); string famName = null == p ? "?" : p.AsString(); Category cat = ft.Category; content += ", Family=" + famName + ", Category=" + cat.Name; // store for the new floor type only if it has the proper Floors category: if (cat.Id.Equals((int)BuiltInCategory.OST_Floors)) { newFloorType = ft; } } content += (null == newFloorType) ? "\n\nNo floor type found." : "\n\nStored FloorType " + newFloorType.Name + " (Id=" + newFloorType.Id.IntegerValue.ToString() + ") for later use"; LabUtils.InfoMsg(msg, content); // Change the type for selected walls and floors: using (Transaction t = new Transaction(doc)) { t.Start("Change Type of Walls and Floors"); msg = "{0} {1}: Id={2}" + "\r\n changed from old type={3}; Id={4}" + " to new type={5}; Id={6}."; //ElementSet sel = uidoc.Selection.Elements; // 2014 ICollection <ElementId> ids = uidoc.Selection.GetElementIds(); // 2015 int iWall = 0; int iFloor = 0; foreach (ElementId id in ids) { Element e = doc.GetElement(id); if (e is Wall) { ++iWall; Wall wall = e as Wall; WallType oldWallType = wall.WallType; // change wall type and report the old/new values wall.WallType = newWallType; LabUtils.InfoMsg(string.Format(msg, "Wall", iWall, wall.Id.IntegerValue, oldWallType.Name, oldWallType.Id.IntegerValue, wall.WallType.Name, wall.WallType.Id.IntegerValue)); } else if (null != newFloorType && e is Floor) { ++iFloor; Floor f = e as Floor; FloorType oldFloorType = f.FloorType; f.FloorType = newFloorType; LabUtils.InfoMsg(string.Format(msg, "Floor", iFloor, f.Id.IntegerValue, oldFloorType.Name, oldFloorType.Id.IntegerValue, f.FloorType.Name, f.FloorType.Id.IntegerValue)); } } t.Commit(); } return(Result.Succeeded); }
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) { UIApplication app = commandData.Application; UIDocument uidoc = app.ActiveUIDocument; Document doc = uidoc.Document; // retrieve all FamilySymbol objects of "Windows" category: BuiltInCategory bic = BuiltInCategory.OST_Windows; FilteredElementCollector symbols = LabUtils.GetFamilySymbols(doc, bic); List <string> a = new List <string>(); foreach (FamilySymbol s in symbols) { Family fam = s.Family; a.Add(s.Name + ", Id=" + s.Id.IntegerValue.ToString() + "; Family name=" + fam.Name + ", Family Id=" + fam.Id.IntegerValue.ToString()); } LabUtils.InfoMsg("{0} windows family symbol{1} loaded in the model{1}", a); // loop through the selection set and check for // standard family instances of "Windows" category: int iBic = (int)bic; string msg, content; ICollection <ElementId> ids = uidoc.Selection.GetElementIds(); foreach (ElementId id in ids) { Element e = doc.GetElement(id); if (e is FamilyInstance && null != e.Category && e.Category.Id.IntegerValue.Equals(iBic)) { msg = "Selected window Id=" + e.Id.IntegerValue.ToString(); FamilyInstance inst = e as FamilyInstance; #region 3.3 Retrieve the type of the family instance, and the family of the type: FamilySymbol fs = inst.Symbol; Family f = fs.Family; #endregion // 3.3 content = "FamilySymbol = " + fs.Name + "; Id=" + fs.Id.IntegerValue.ToString(); content += "\r\n Family = " + f.Name + "; Id=" + f.Id.IntegerValue.ToString(); LabUtils.InfoMsg(msg, content); } } return(Result.Succeeded); }
public Result Execute( ExternalCommandData commandData, ref string message, ElementSet elements) { UIApplication app = commandData.Application; Document doc = app.ActiveUIDocument.Document; bool rc; using (Transaction t = new Transaction(doc)) { #region 3.2.a Load an entire RFA family file: // Load a whole Family // // Example for a family WITH TXT file: rc = doc.LoadFamily(LabConstants.WholeFamilyFileToLoad1); #endregion // 3.2.a if (rc) { LabUtils.InfoMsg("Successfully loaded family " + LabConstants.WholeFamilyFileToLoad1 + "."); } else { LabUtils.ErrorMsg("ERROR loading family " + LabConstants.WholeFamilyFileToLoad1 + "."); } // Example for a family WITHOUT TXT file: rc = doc.LoadFamily(LabConstants.WholeFamilyFileToLoad2); if (rc) { LabUtils.InfoMsg("Successfully loaded family " + LabConstants.WholeFamilyFileToLoad2 + "."); } else { LabUtils.ErrorMsg("ERROR loading family " + LabConstants.WholeFamilyFileToLoad2 + "."); } #region 3.2.b Load an individual type from a RFA family file: // Load only a specific symbol (type): rc = doc.LoadFamilySymbol( LabConstants.FamilyFileToLoadSingleSymbol, LabConstants.SymbolName); #endregion // 3.2.b if (rc) { LabUtils.InfoMsg("Successfully loaded family symbol " + LabConstants.FamilyFileToLoadSingleSymbol + " : " + LabConstants.SymbolName + "."); } else { LabUtils.ErrorMsg("ERROR loading family symbol " + LabConstants.FamilyFileToLoadSingleSymbol + " : " + LabConstants.SymbolName + "."); } t.Commit(); } return(Result.Succeeded); }