private void ResetSupplyAirTerminals(Document doc) { 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 reset..."; string caption = "Resetting Supply Air Termainal Flows and Sizes"; using (ProgressForm pf = new ProgressForm(caption, s, n)) { foreach (FamilyInstance terminal in terminals) { // Reset flow Parameter p = Util.GetTerminalFlowParameter(terminal); p.Set(0); // Reset size ISet <ElementId> symbolIds = terminal.Symbol.Family .GetFamilySymbolIds(); foreach (ElementId id in symbolIds) { FamilySymbol sym = doc.GetElement(id) as FamilySymbol; terminal.Symbol = sym; // simply set to first symbol found break; // done after getting the first symbol } pf.Increment(); } } }
public Result Execute( ExternalCommandData commandData, ref string message, ElementSet elements) { try { WaitCursor waitCursor = new WaitCursor(); UIApplication app = commandData.Application; Document doc = app.ActiveUIDocument.Document; //ElementIterator it = doc.get_Elements( typeof( Room ) ); //ElementIterator it = doc.get_Elements( typeof( Space ) ); // changed Room to Space //FilteredElementCollector spaces = new FilteredElementCollector( doc ); //spaces.OfClass( typeof( Space ) ); using (Transaction tx = new Transaction(doc)) { tx.Start("Set Air Flow per SqFt on Spaces"); List <Space> spaces = Util.GetSpaces(doc); foreach (Space space in spaces) { SetCfmPerSf(space); // set CFM/SF on the space AFTER assigning flow to the terminals } tx.Commit(); } return(Result.Succeeded); } catch (Exception ex) { message = ex.Message; return(Result.Failed); } }
static public Result Execute2( ExternalCommandData commandData, ref String message, ElementSet elements, bool populateFullHierarchy) { try { WaitCursor waitCursor = new WaitCursor(); UIApplication app = commandData.Application; Document doc = app.ActiveUIDocument.Document; // // display electrical equipment instance data, // i.e. equipment_name:system_name, and convert it to // a map from key = panel:circuit --> equipment: // List <Element> equipment = Util.GetElectricalEquipment(doc); int n = equipment.Count; Debug.WriteLine(string.Format("Retrieved {0} electrical equipment instance{1}{2}", n, Util.PluralSuffix(n), Util.DotOrColon(n))); Dictionary <string, List <Element> > mapPanelAndSystemToEquipment = new Dictionary <string, List <Element> >(); foreach (FamilyInstance elecEqip in equipment) { ListEquipment(elecEqip, mapPanelAndSystemToEquipment); } // // determine mapping from panel to circuit == electrical system: // Dictionary <string, ElectricalSystemSet> mapPanelToSystems = new Dictionary <string, ElectricalSystemSet>(); IList <Element> systems = Util.GetElectricalSystems(doc); n = systems.Count; Debug.WriteLine(string.Format("Retrieved {0} electrical system{1}.", n, Util.PluralSuffix(n))); // // all circuits which are fed from the same family instance have // the same panel name, so you can retrieve all of these circuits. // // todo: there is an issue here if there are several different panels // with the same name! they will get merged in the tree view, // but they should stay separate. possible workaround: add the // element id to keep them separate, and then remove it again // when displaying in tree view. // foreach (ElectricalSystem system in systems) { string panelName = system.PanelName; Debug.WriteLine(" system " + system.Name + ": panel " + panelName + " load classifications " + system.LoadClassifications); if (!mapPanelToSystems.ContainsKey(panelName)) { mapPanelToSystems.Add(panelName, new ElectricalSystemSet()); } mapPanelToSystems[panelName].Insert(system); } n = mapPanelToSystems.Count; //Debug.WriteLine( string.Format( "Mapping from the {0} panel{1} to systems, system name :circuit name(connectors/unused connectors):", n, Util.PluralSuffix( n ) ) ); Debug.WriteLine(string.Format("Mapping from the {0} panel{1} to electrical systems == circuits:", n, Util.PluralSuffix(n))); List <string> keys = new List <string>(mapPanelToSystems.Keys); keys.Sort(); string s; foreach (string panelName in keys) { s = string.Empty; foreach (ElectricalSystem system in mapPanelToSystems[panelName]) { ConnectorManager cmgr = system.ConnectorManager; // the connector manager does not include any logical connectors // in the Revit 2009 fcs and wu1 API, only physical ones: //Debug.Assert( 0 == cmgr.Connectors.Size, // "electrical connector count is always zero" ); Debug.Assert(cmgr.UnusedConnectors.Size <= cmgr.Connectors.Size, "unused connectors is a subset of connectors"); Debug.Assert(system.Name.Equals(system.CircuitNumber), "ElectricalSystem Name and CircuitNumber properties are always identical"); //s += ( 0 < s.Length ? ", " : ": " ) + system.Name; s += (0 < s.Length ? ", " : ": ") + system.Name // + ":" + system.CircuitNumber + "(" + cmgr.Connectors.Size.ToString() + "/" + cmgr.UnusedConnectors.Size.ToString() + ")"; } Debug.WriteLine(" " + panelName + s); } /* * Debug.WriteLine( "Mapping from panels to systems to connected elements:" ); * foreach( string panelName in keys ) * { * Debug.WriteLine( " panel " + panelName + ":" ); * foreach( ElectricalSystem system in mapPanelToSystems[panelName] ) * { * ConnectorManager cmgr = system.ConnectorManager; * n = cmgr.Connectors.Size; * Debug.WriteLine( string.Format( " system {0} has {1} connector{2}{3}", system.Name, n, Util.PluralSuffix( n ), Util.DotOrColon( n ) ) ); * foreach( Connector connector in system.ConnectorManager.Connectors ) * { * Element owner = connector.Owner; * Debug.WriteLine( string.Format( " owner {0} {1}, domain {2}", owner.Name, owner.Id.IntegerValue, connector.Domain ) ); * } * } * } */ // // list all circuit elements: // // this captures all elements in circuits H-2: 2, 4, 6 etc, // but not the element T2 in H-2:1,3,5, because it has no circuit number, // just a panel number. // BuiltInParameter bipPanel = BuiltInParameter.RBS_ELEC_CIRCUIT_PANEL_PARAM; BuiltInParameter bipCircuit = BuiltInParameter.RBS_ELEC_CIRCUIT_NUMBER; IList <Element> circuitElements = Util.GetCircuitElements(doc); n = circuitElements.Count; Debug.WriteLine(string.Format("Retrieved {0} circuit element{1}{2}", n, Util.PluralSuffix(n), Util.DotOrColon(n))); Dictionary <string, List <Element> > mapPanelAndCircuitToElements = new Dictionary <string, List <Element> >(); foreach (Element e in circuitElements) { string circuitName = e.get_Parameter(bipCircuit).AsString(); // // do not map an electrical system to itself: // if (!(e is ElectricalSystem && e.Name.Equals(circuitName))) { string panelName = e.get_Parameter(bipPanel).AsString(); string key = panelName + ":" + circuitName; Debug.WriteLine(string.Format(" {0} <{1} {2}> panel:circuit {3}", e.GetType().Name, e.Name, e.Id.IntegerValue, key)); if (!mapPanelAndCircuitToElements.ContainsKey(key)) { mapPanelAndCircuitToElements.Add(key, new List <Element>()); } mapPanelAndCircuitToElements[key].Add(e); } } n = mapPanelAndCircuitToElements.Count; Debug.WriteLine(string.Format("Mapped circuit elements to {0} panel:circuit{1}{2}", n, Util.PluralSuffix(n), Util.DotOrColon(n))); keys.Clear(); keys.AddRange(mapPanelAndCircuitToElements.Keys); keys.Sort(new PanelCircuitComparer()); foreach (string panelAndCircuit in keys) { List <string> a = new List <string>(mapPanelAndCircuitToElements[panelAndCircuit].Count); foreach (Element e in mapPanelAndCircuitToElements[panelAndCircuit]) { FamilyInstance inst = e as FamilyInstance; a.Add((null == inst ? e.Category.Name : inst.Symbol.Family.Name) + " " + e.Name); } a.Sort(); s = string.Join(", ", a.ToArray()); Debug.WriteLine(" " + panelAndCircuit + ": " + s); } #region Aborted attempt to use RBS_ELEC_CIRCUIT_PANEL_PARAM #if USE_RBS_ELEC_CIRCUIT_PANEL_PARAM // // list all panel elements: // // selecting all elements with a BuiltInParameter.RBS_ELEC_CIRCUIT_NUMBER // captures all elements in circuits H-2: 2, 4, 6 etc, but not the element // T2 in H-2:1,3,5, because it has no circuit number, just a panel number. // // so grab everything with a panel number instead. // // all this added to the selection was lots of wires, so forget it again. // BuiltInParameter bipCircuit = BuiltInParameter.RBS_ELEC_CIRCUIT_NUMBER; BuiltInParameter bipPanel = BuiltInParameter.RBS_ELEC_CIRCUIT_PANEL_PARAM; List <Element> circuitElements = new List <Element>(); Util.GetElementsWithParameter(circuitElements, bipPanel, app); n = circuitElements.Count; Debug.WriteLine(string.Format("Retrieved {0} circuit element{1}{2}", n, Util.PluralSuffix(n), Util.DotOrColon(n))); Dictionary <string, List <Element> > mapCircuitToElements = new Dictionary <string, List <Element> >(); foreach (Element e in circuitElements) { string panelName = e.get_Parameter(bipPanel).AsString(); Parameter p = e.get_Parameter(bipCircuit); if (null == p) { Debug.WriteLine(string.Format(" {0} <{1} {2}> panel:circuit {3}:null", e.GetType().Name, e.Name, e.Id.IntegerValue, panelName)); } else { string circuitName = p.AsString(); // // do not map an electrical system to itself: // if (!(e is ElectricalSystem && e.Name.Equals(circuitName))) { string key = panelName + ":" + circuitName; Debug.WriteLine(string.Format(" {0} <{1} {2}> panel:circuit {3}", e.GetType().Name, e.Name, e.Id.IntegerValue, key)); if (!mapCircuitToElements.ContainsKey(key)) { mapCircuitToElements.Add(key, new List <Element>()); } mapCircuitToElements[key].Add(e); } } } n = mapCircuitToElements.Count; Debug.WriteLine(string.Format("Mapped circuit elements to {0} panel:circuit{1}{2}", n, Util.PluralSuffix(n), Util.DotOrColon(n))); keys.Clear(); keys.AddRange(mapCircuitToElements.Keys); keys.Sort(new PanelCircuitComparer()); foreach (string circuitName in keys) { List <string> a = new List <string>(mapCircuitToElements[circuitName].Count); foreach (Element e in mapCircuitToElements[circuitName]) { FamilyInstance inst = e as FamilyInstance; a.Add((null == inst ? e.Category.Name : inst.Symbol.Family.Name) + " " + e.Name); } a.Sort(); s = string.Join(", ", a.ToArray()); Debug.WriteLine(" " + circuitName + ": " + s); } #endif // USE_RBS_ELEC_CIRCUIT_PANEL_PARAM #endregion // Aborted attempt to use RBS_ELEC_CIRCUIT_PANEL_PARAM // // merge the two trees of equipment and circuit elements // to reproduce the content of the system browser ... the // hardest part of this is setting up the PanelSystemComparer // to generate the same sort order as the system browser: // //n = mapPanelAndSystemToEquipment.Count + mapPanelAndCircuitToElements.Count; //Dictionary<string, List<Element>> mapSystemBrowser = new Dictionary<string, List<Element>>( n ); Dictionary <string, List <Element> > mapSystemBrowser = new Dictionary <string, List <Element> >(mapPanelAndCircuitToElements); foreach (KeyValuePair <string, List <Element> > pair in mapPanelAndSystemToEquipment) { mapSystemBrowser[pair.Key] = pair.Value; } n = mapSystemBrowser.Count; Debug.WriteLine(string.Format("Mapped equipment + circuit elements to {0} panel:system{1}{2}", n, Util.PluralSuffix(n), Util.DotOrColon(n))); keys.Clear(); keys.AddRange(mapSystemBrowser.Keys); keys.Sort(new PanelSystemComparer()); foreach (string panelAndSystem in keys) { List <string> a = new List <string>(mapSystemBrowser[panelAndSystem].Count); foreach (Element e in mapSystemBrowser[panelAndSystem]) { a.Add(Util.BrowserDescription(e)); } a.Sort(); s = string.Join(", ", a.ToArray()); Debug.WriteLine(string.Format(" {0}({1}): ", panelAndSystem, a.Count) + s); } // // get the electrical equipment category id: // Categories categories = doc.Settings.Categories; ElementId electricalEquipmentCategoryId = categories.get_Item(BuiltInCategory.OST_ElectricalEquipment).Id; // // we have assembled the required information and structured it // sufficiently for the tree view, so now let us go ahead and display it: // CmdInspectElectricalForm dialog = new CmdInspectElectricalForm(mapSystemBrowser, electricalEquipmentCategoryId, populateFullHierarchy); dialog.Show(); return(Result.Succeeded); } catch (Exception ex) { message = ex.Message; return(Result.Failed); } }
public Result Execute( ExternalCommandData commandData, ref String message, ElementSet elements) { try { // // dictionary defining tree view info displayed in modeless // dialogue mapping parent node to all its circuit elements: // null --> root panels // panel --> systems // system --> circuit elements, panels, ... // MapParentToChildren mapParentToChildren = new MapParentToChildren(); ElementId electricalEquipmentCategoryId = ElementId.InvalidElementId; List <Element> equipment; { // // run the analysis in its own scope, so the wait cursor // disappears before we display the modeless dialogue: // WaitCursor waitCursor = new WaitCursor(); UIApplication app = commandData.Application; Document doc = app.ActiveUIDocument.Document; ElementId nullId = ElementId.InvalidElementId; // // retrieve electrical equipment instances: // equipment = Util.GetElectricalEquipment(doc); int n = equipment.Count; Debug.WriteLine(string.Format("Retrieved {0} electrical equipment instance{1}{2}", n, Util.PluralSuffix(n), Util.DotOrColon(n))); Dictionary <string, FamilyInstance> mapPanel = new Dictionary <string, FamilyInstance>(); foreach (FamilyInstance e in equipment) { // // ensure that every panel shows up in the list, // even if it does not have children: // mapParentToChildren.Add(e.Id, null); mapPanel[e.Name] = e; MEPModel mepModel = e.MEPModel; ElectricalSystemSet systems2 = mepModel.ElectricalSystems; string panelAndSystem = string.Empty; if (null == systems2) { panelAndSystem = CmdElectricalSystemBrowser.Unassigned; // this is a root node } else { Debug.Assert(1 == systems2.Size, "expected equipment to belong to one single panel and system"); foreach (ElectricalSystem system in systems2) { if (0 < panelAndSystem.Length) { panelAndSystem += ", "; } panelAndSystem += system.PanelName + ":" + system.Name + ":" + system.Id.IntegerValue.ToString(); } } Debug.WriteLine(" " + Util.ElementDescriptionAndId(e) + " " + panelAndSystem); } // // retrieve electrical systems: // these are also returned by Util.GetCircuitElements(), by the way, // since they have the parameters RBS_ELEC_CIRCUIT_PANEL_PARAM and // RBS_ELEC_CIRCUIT_NUMBER that we use to identify those. // FilteredElementCollector c = new FilteredElementCollector(doc); IList <Element> systems = c.OfClass(typeof(ElectricalSystem)).ToElements(); n = systems.Count; Debug.WriteLine(string.Format("Retrieved {0} electrical system{1}{2}", n, Util.PluralSuffix(n), Util.DotOrColon(n))); foreach (ElectricalSystem system in systems) { string panelName = system.PanelName; if (0 == panelName.Length) { panelName = CmdElectricalSystemBrowser.Unassigned; // will not appear in tree } else { // // todo: is there a more direct way to identify // what panel a system belongs to? this seems error // prone ... what if a panel name occurs multiple times? // how do we identify which one to use? // FamilyInstance panel = mapPanel[panelName]; mapParentToChildren.Add(panel.Id, system); } string panelAndSystem = panelName + ":" + system.Name + ":" + system.Id.IntegerValue.ToString(); Debug.WriteLine(" " + Util.ElementDescriptionAndId(system) + " " + panelAndSystem); Debug.Assert(system.ConnectorManager.Owner.Id.Equals(system.Id), "expected electrical system's connector manager owner to be system itself"); } // // now we have the equipment and systems, // we can build the non-leaf levels of the tree: // foreach (FamilyInstance e in equipment) { MEPModel mepModel = e.MEPModel; ElectricalSystemSet systems2 = mepModel.ElectricalSystems; if (null == systems2) { mapParentToChildren.Add(nullId, e); // root node } else { Debug.Assert(1 == systems2.Size, "expected equipment to belong to one single panel and system"); foreach (ElectricalSystem system in systems2) { mapParentToChildren.Add(system.Id, e); } } } // // list all circuit elements: // BuiltInParameter bipPanel = BuiltInParameter.RBS_ELEC_CIRCUIT_PANEL_PARAM; BuiltInParameter bipCircuit = BuiltInParameter.RBS_ELEC_CIRCUIT_NUMBER; IList <Element> circuitElements = Util.GetCircuitElements(doc); n = circuitElements.Count; Debug.WriteLine(string.Format("Retrieved {0} circuit element{1}...", n, Util.PluralSuffix(n))); n = 0; foreach (Element e in circuitElements) { if (e is ElectricalSystem) { ++n; } else { string circuitName = e.get_Parameter(bipCircuit).AsString(); string panelName = e.get_Parameter(bipPanel).AsString(); string key = panelName + ":" + circuitName; string panelAndSystem = string.Empty; FamilyInstance inst = e as FamilyInstance; Debug.Assert(null != inst, "expected all circuit elements to be family instances"); MEPModel mepModel = inst.MEPModel; ElectricalSystemSet systems2 = mepModel.ElectricalSystems; Debug.Assert(null != systems2, "expected circuit element to belong to an electrical system"); // this fails in "2341_MEP - 2009 Central.rvt", says martin: // // a circuit element can belong to several systems ... imagine // a piece of telephone equipment which hooks up to a phone line // and also requires power ... so i removed this assertion: // //Debug.Assert( 1 == systems2.Size, "expected circuit element to belong to one single system" ); foreach (ElectricalSystem system in systems2) { if (0 < panelAndSystem.Length) { panelAndSystem += ", "; } panelAndSystem += system.PanelName + ":" + system.Name + ":" + system.Id.IntegerValue.ToString(); Debug.Assert(system.PanelName == panelName, "expected same panel name in parameter and electrical system"); // this fails in "2341_MEP - 2009 Central.rvt", says martin: //Debug.Assert( system.Name == circuitName, "expected same name in circuit parameter and system" ); mapParentToChildren.Add(system.Id, e); } Debug.WriteLine(string.Format(" {0} panel:circuit {1}", Util.ElementDescriptionAndId(e), panelAndSystem)); } } Debug.WriteLine(string.Format("{0} circuit element{1} were the electrical systems.", n, Util.PluralSuffix(n))); // // get the electrical equipment category id: // Categories categories = doc.Settings.Categories; electricalEquipmentCategoryId = categories.get_Item(BuiltInCategory.OST_ElectricalEquipment).Id; } // // we have assembled the entire required tree view structure, so let us display it: // CmdInspectElectricalForm2 dialog = new CmdInspectElectricalForm2(mapParentToChildren, electricalEquipmentCategoryId, equipment); dialog.Show(); return(Result.Succeeded); } catch (Exception ex) { message = ex.Message; return(Result.Failed); } }
/// <summary> /// Determine unhosted elements. /// </summary> static bool DetermineUnhostedElements(Document doc) { int nHosted = 0; int nUnhosted = 0; bool needHeader = true; List <string> unhosted = new List <string>(); { WaitCursor waitCursor = new WaitCursor(); FilteredElementCollector collector = new FilteredElementCollector(doc); collector.OfClass(typeof(FamilyInstance)); //int j = 0; // temporary problem: running this in rac_basic_sample_project.rvt throws an exception // Unable to cast object of type 'Autodesk.Revit.DB.Panel' to type 'Autodesk.Revit.DB.FamilyInstance'. // fixed in http://srd.autodesk.com/srdapp/ReportForm.asp?number=176141 foreach (FamilyInstance inst in collector) { //Debug.WriteLine( ++j ); Parameter p = inst.get_Parameter(Bip.Host); if (null != p) { if (needHeader) { Debug.WriteLine("\nHosted and unhosted elements:"); needHeader = false; } string description = Util.ElementDescriptionAndId(inst); string hostValue = p.AsString(); bool hosted = IsValidHost(hostValue); if (hosted) { ++nHosted; } else { ++nUnhosted; //if( null == unhosted ) //{ // unhosted = new string[1]; // unhosted[0] = description; //} //else //{ // unhosted.se //} unhosted.Add(description); } Debug.WriteLine(string.Format("{0} {1} host is '{2}' --> {3}hosted", description, inst.Id.IntegerValue, hostValue, hosted ? "" : "un")); } } } if (0 < nHosted + nUnhosted) { Debug.WriteLine(string.Format("{0} hosted and {1} unhosted elements.", nHosted, nUnhosted)); } if (0 < nUnhosted) { string[] a = new string[unhosted.Count]; int i = 0; foreach (string s in unhosted) { a[i++] = s; } // todo: present the element ids in a separete edit box for easier copy and paste: string msg = string.Format("{0} unhosted element{1}:\n\n", nUnhosted, Util.PluralSuffix(nUnhosted)) + string.Join("\n", a); Util.InfoMsg(msg); } 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); }