bool ChangeDiffuserSize( Document doc ) { // // iterate over all air terminal families and determine // the min and max flow assigned to each type. // // for each family, create a list of all its symbols // with their respective min and max flows. collect // these lists in a map keyed by family name: // Dictionary<string, List<SymbMinMax>> dictFamilyToSymbols = new Dictionary<string, List<SymbMinMax>>(); { WaitCursor waitCursor = new WaitCursor(); //Category categoryAirTerminal = doc.Settings.Categories.get_Item( BuiltInCategory.OST_DuctTerminal ); //ElementId categoryId = categoryAirTerminal.Id; //ElementIterator it = doc.get_Elements( typeof( Family ) ); FilteredElementCollector collector = new FilteredElementCollector( doc ) .OfClass( typeof( Family ) ); foreach( Family family in collector ) { ISet<ElementId> symbolIds = family.GetFamilySymbolIds(); // Family category is not implemented, // so check the symbols instead: bool categoryMatches = false; foreach( ElementId id in symbolIds ) { Element symbol = doc.GetElement( id ); // in 2008 and even 2009 beta 1, // you could compare categories directly: //categoryMatches = ( null != symbol.Category // && symbol.Category.Equals( categoryAirTerminal ) ); // in 2009, check the category id instead: categoryMatches = ( null != symbol.Category && symbol.Category.Id.IntegerValue.Equals( (int) BuiltInCategory.OST_DuctTerminal ) ); break; // we only need to check the first one } if( categoryMatches ) { List<SymbMinMax> familySymbols = new List<SymbMinMax>(); foreach( ElementId id in symbolIds ) { FamilySymbol symbol = doc.GetElement( id ) as FamilySymbol; SymbMinMax a = new SymbMinMax(); a.Symbol = symbol; a.Min = Util.GetParameterValueFromName( symbol, ParameterName.MinFlow ); a.Max = Util.GetParameterValueFromName( symbol, ParameterName.MaxFlow ); familySymbols.Add( a ); } dictFamilyToSymbols.Add( family.Name, familySymbols ); } } } // // prompt user to select which families to process: // //List<string> familyNames = new List<string>( dictFamilyToSymbols.Count ); //foreach( string s in dictFamilyToSymbols.Keys ) //{ // familyNames.Add( string.Format( "{0}({1})", s, dictFamilyToSymbols[s].Count ) ); //} List<string> familyNames = new List<string>( dictFamilyToSymbols.Keys ); familyNames.Sort(); FamilySelector fs = new FamilySelector( familyNames ); if( W.DialogResult.OK == fs.ShowDialog() ) { WaitCursor waitCursor = new WaitCursor(); FilteredElementCollector collector = Util.GetSupplyAirTerminals( doc ); IList<Element> terminals = collector.ToElements(); int n = terminals.Count; string s = "{0} of " + n.ToString() + " terminals processed..."; string caption = "Change Diffuser Size"; using( ProgressForm pf = new ProgressForm( caption, s, n ) ) { foreach( FamilyInstance terminal in terminals ) { string familyName = terminal.Symbol.Family.Name; if( fs.IsChecked( familyName ) ) { bool found = false; List<SymbMinMax> familySymbols = dictFamilyToSymbols[familyName]; double flow = Util.GetTerminalFlowParameter( terminal ).AsDouble(); foreach( SymbMinMax a in familySymbols ) { // // pick the first symbol found which matches our flow; // todo: this could be improved: // 1. we could sort the symbols by flow, and that would speed up the search // 2. we could report an error if multiple possible assignments are availabe // 3. we could improve the handling of borderline cases ... tend towards the smaller or bigger? // 4. we could build in a check after building each familySymbols ArrayList to ensure // that there is no ovelap in the flows and that the entire required flow spectrum is covered // if( a.Min <= flow && flow <= a.Max ) { terminal.Symbol = a.Symbol; found = true; break; } } if( !found ) { double flowInCfm = flow * Const.SecondsPerMinute; Util.ErrorMsg( string.Format( "No matching flow found for {0} with flow {1}.", Util.ElementDescription( terminal ), flowInCfm ) ); } } pf.Increment(); } } } return true; }
bool ChangeDiffuserSize(Document doc) { // // iterate over all air terminal families and determine // the min and max flow assigned to each type. // // for each family, create a list of all its symbols // with their respective min and max flows. collect // these lists in a map keyed by family name: // Dictionary <string, List <SymbMinMax> > dictFamilyToSymbols = new Dictionary <string, List <SymbMinMax> >(); { WaitCursor waitCursor = new WaitCursor(); //Category categoryAirTerminal = doc.Settings.Categories.get_Item( BuiltInCategory.OST_DuctTerminal ); //ElementId categoryId = categoryAirTerminal.Id; //ElementIterator it = doc.get_Elements( typeof( Family ) ); FilteredElementCollector collector = new FilteredElementCollector(doc) .OfClass(typeof(Family)); foreach (Family family in collector) { ISet <ElementId> symbolIds = family.GetFamilySymbolIds(); // Family category is not implemented, // so check the symbols instead: bool categoryMatches = false; foreach (ElementId id in symbolIds) { Element symbol = doc.GetElement(id); // in 2008 and even 2009 beta 1, // you could compare categories directly: //categoryMatches = ( null != symbol.Category // && symbol.Category.Equals( categoryAirTerminal ) ); // in 2009, check the category id instead: categoryMatches = (null != symbol.Category && symbol.Category.Id.IntegerValue.Equals( (int)BuiltInCategory.OST_DuctTerminal)); break; // we only need to check the first one } if (categoryMatches) { List <SymbMinMax> familySymbols = new List <SymbMinMax>(); foreach (ElementId id in symbolIds) { FamilySymbol symbol = doc.GetElement(id) as FamilySymbol; SymbMinMax a = new SymbMinMax(); a.Symbol = symbol; a.Min = Util.GetParameterValueFromName( symbol, ParameterName.MinFlow); a.Max = Util.GetParameterValueFromName( symbol, ParameterName.MaxFlow); familySymbols.Add(a); } dictFamilyToSymbols.Add( family.Name, familySymbols); } } } // // prompt user to select which families to process: // //List<string> familyNames = new List<string>( dictFamilyToSymbols.Count ); //foreach( string s in dictFamilyToSymbols.Keys ) //{ // familyNames.Add( string.Format( "{0}({1})", s, dictFamilyToSymbols[s].Count ) ); //} List <string> familyNames = new List <string>(dictFamilyToSymbols.Keys); familyNames.Sort(); FamilySelector fs = new FamilySelector(familyNames); if (W.DialogResult.OK == fs.ShowDialog()) { WaitCursor waitCursor = new WaitCursor(); FilteredElementCollector collector = Util.GetSupplyAirTerminals(doc); IList <Element> terminals = collector.ToElements(); int n = terminals.Count; string s = "{0} of " + n.ToString() + " terminals processed..."; string caption = "Change Diffuser Size"; using (ProgressForm pf = new ProgressForm(caption, s, n)) { foreach (FamilyInstance terminal in terminals) { string familyName = terminal.Symbol.Family.Name; if (fs.IsChecked(familyName)) { bool found = false; List <SymbMinMax> familySymbols = dictFamilyToSymbols[familyName]; double flow = Util.GetTerminalFlowParameter(terminal).AsDouble(); foreach (SymbMinMax a in familySymbols) { // // pick the first symbol found which matches our flow; // todo: this could be improved: // 1. we could sort the symbols by flow, and that would speed up the search // 2. we could report an error if multiple possible assignments are availabe // 3. we could improve the handling of borderline cases ... tend towards the smaller or bigger? // 4. we could build in a check after building each familySymbols ArrayList to ensure // that there is no ovelap in the flows and that the entire required flow spectrum is covered // if (a.Min <= flow && flow <= a.Max) { terminal.Symbol = a.Symbol; found = true; break; } } if (!found) { double flowInCfm = flow * Const.SecondsPerMinute; Util.ErrorMsg(string.Format("No matching flow found for {0} with flow {1}.", Util.ElementDescription(terminal), flowInCfm)); } } pf.Increment(); } } } return(true); }