// // (C) Copyright 2003-2019 by Autodesk, Inc. // // Permission to use, copy, modify, and distribute this software in // object code form for any purpose and without fee is hereby granted, // provided that the above copyright notice appears in all copies and // that both that copyright notice and the limited warranty and // restricted rights notice below appear in all supporting // documentation. // // AUTODESK PROVIDES THIS PROGRAM "AS IS" AND WITH ALL FAULTS. // AUTODESK SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTY OF // MERCHANTABILITY OR FITNESS FOR A PARTICULAR USE. AUTODESK, INC. // DOES NOT WARRANT THAT THE OPERATION OF THE PROGRAM WILL BE // UNINTERRUPTED OR ERROR FREE. // // Use, duplication, or disclosure by the U.S. Government is subject to // restrictions set forth in FAR 52.227-19 (Commercial Computer // Software - Restricted Rights) and DFAR 252.227-7013(c)(1)(ii) // (Rights in Technical Data and Computer Software), as applicable. // using System; using System.Collections; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Text; using System.Text.RegularExpressions; using System.Windows.Forms; using Autodesk.Revit; using Autodesk.Revit.DB; using Autodesk.Revit.UI; using Autodesk.Revit.DB.Electrical; using Autodesk.Revit.UI.Selection; namespace Revit.SDK.Samples.PowerCircuit.CS { /// /// Data class which stores the information of electrical circuit operation /// public class CircuitOperationData { #region Fields /// /// Active document of Revit /// UIDocument m_revitDoc; /// /// Selection of active document /// Selection m_selection; /// /// Operation on selected elements /// private Operation m_operation; /// /// Option of editing circuit /// private EditOption m_editOption; /// /// Whether new circuit can be created with selected elements /// private bool m_canCreateCircuit; /// /// Whether there is a circuit in selected elements /// private bool m_hasCircuit; /// /// Whether the circuit in selected elements has panel /// private bool m_hasPanel; /// /// All electrical systems contain selected element /// private ElectricalSystemSet m_electricalSystemSet; /// /// All electrical system items which will be displayed in circuit selecting form /// private List m_electricalSystemItems; /// /// The electrical system chosen to operate /// private ElectricalSystem m_selectedElectricalSystem; #endregion #region Properties /// /// Operation type /// public Operation Operation { get { return m_operation; } set { m_operation = value; } } /// /// Get the information whether new circuit can be created /// public bool CanCreateCircuit { get { return m_canCreateCircuit; } } /// /// Get the value of whether there are circuits in selected elements /// public bool HasCircuit { get { return m_hasCircuit; } } /// /// Get the information whether the circuit in selected elements has panel /// public bool HasPanel { get { return m_hasPanel; } } /// /// Edit options /// public EditOption EditOption { get { return m_editOption; } set { m_editOption = value; } } /// /// All electrical system items which will be displayed in circuit selecting form /// public ReadOnlyCollection ElectricalSystemItems { get { foreach (ElectricalSystem es in m_electricalSystemSet) { ElectricalSystemItem esi = new ElectricalSystemItem(es); m_electricalSystemItems.Add(esi); } return new ReadOnlyCollection(m_electricalSystemItems); } } /// /// Number of electrical systems contain selected elements /// public int ElectricalSystemCount { get { return m_electricalSystemSet.Size; } } #endregion #region Methods /// /// Constructor /// /// Revit's external commandData public CircuitOperationData(ExternalCommandData commandData) { m_revitDoc = commandData.Application.ActiveUIDocument; m_selection = m_revitDoc.Selection; m_electricalSystemSet = new ElectricalSystemSet(); m_electricalSystemItems = new List(); CollectConnectorInfo(); CollectCircuitInfo(); } /// /// Verify if all selected elements have unused connectors /// private void CollectConnectorInfo() { m_canCreateCircuit = true; // Flag to check if all selected elements are lighting devices bool allLightingDevices = true; foreach (ElementId elementId in m_selection.GetElementIds()) { Element element = m_revitDoc.Document.GetElement(elementId); FamilyInstance fi = element as FamilyInstance; if (null == fi) { m_canCreateCircuit = false; return; } if (!String.Equals(fi.Category.Name, "Lighting Devices")) { allLightingDevices = false; } // Verify if the family instance has usable connectors if (!VerifyUnusedConnectors(fi)) { m_canCreateCircuit = false; return; } } if (allLightingDevices) { m_canCreateCircuit = false; } } /// /// Verify if the family instance has usable connectors /// /// The family instance to be verified /// True if the family instance has usable connecotors, /// otherwise false static private bool VerifyUnusedConnectors(FamilyInstance fi) { bool hasUnusedElectricalConnector = false; try { MEPModel mepModel = fi.MEPModel; if (null == mepModel) { return hasUnusedElectricalConnector; } ConnectorManager cm = mepModel.ConnectorManager; ConnectorSet unusedConnectors = cm.UnusedConnectors; if (null == unusedConnectors || unusedConnectors.IsEmpty) { return hasUnusedElectricalConnector; } foreach (Connector connector in unusedConnectors) { if (connector.Domain == Domain.DomainElectrical) { hasUnusedElectricalConnector = true; break; } } } catch (Exception) { return hasUnusedElectricalConnector; } return hasUnusedElectricalConnector; } /// /// Get common circuits contain all selected elements /// private void CollectCircuitInfo() { //bool isElectricalSystem = false; bool bInitilzedElectricalSystemSet = false; // // Get common circuits of selected elements // ElectricalSystem tempElectricalSystem = null; foreach (ElementId elementId in m_selection.GetElementIds()) { Element element = m_revitDoc.Document.GetElement(elementId); FamilyInstance fi = element as FamilyInstance; MEPModel mepModel; ElectricalSystemSet ess; if (fi != null && (mepModel = fi.MEPModel) != null) { // // If the element is a family instance and its MEP model is not null, // retrieve its circuits // Then compare the circuits with circuits of other selected elements // to get the common ones // // Get all electrical systems ess = mepModel.ElectricalSystems; if (null == ess) { m_hasCircuit = false; m_hasPanel = false; return; } // Remove systems which are not power circuits foreach (ElectricalSystem es in ess) { if (es.SystemType != ElectricalSystemType.PowerCircuit) { ess.Erase(es); } } if (ess.IsEmpty) { m_hasCircuit = false; m_hasPanel = false; return; } // If m_electricalSystemSet is not set before, set it // otherwise compare the circuits with circuits of other selected elements // to get the common ones if (!bInitilzedElectricalSystemSet) { m_electricalSystemSet = ess; bInitilzedElectricalSystemSet = true; continue; } else { foreach (ElectricalSystem es in m_electricalSystemSet) { if (!ess.Contains(es)) { m_electricalSystemSet.Erase(es); } } if (m_electricalSystemSet.IsEmpty) { m_hasCircuit = false; m_hasPanel = false; return; } } } else if ((tempElectricalSystem = element as ElectricalSystem) != null) { // // If the element is an electrical system, verify if it is a power circuit // If not, compare with circuits of other selected elements // to get the common ones // //verify if it is a power circuit if (tempElectricalSystem.SystemType != ElectricalSystemType.PowerCircuit) { m_hasCircuit = false; m_hasPanel = false; return; } // If m_electricalSystemSet is not set before, set it // otherwise compare with circuits of other selected elements // to get the common ones if (!bInitilzedElectricalSystemSet) { m_electricalSystemSet.Insert(tempElectricalSystem); bInitilzedElectricalSystemSet = true; continue; } if (!m_electricalSystemSet.Contains(tempElectricalSystem)) { m_hasCircuit = false; m_hasPanel = false; return; } m_electricalSystemSet.Clear(); m_electricalSystemSet.Insert(tempElectricalSystem); } else { m_hasCircuit = false; m_hasPanel = false; return; } } // Verify if there is any common power circuit if (!m_electricalSystemSet.IsEmpty) { m_hasCircuit = true; if (m_electricalSystemSet.Size == 1) { foreach (ElectricalSystem es in m_electricalSystemSet) { m_selectedElectricalSystem = es; break; } } foreach (ElectricalSystem es in m_electricalSystemSet) { if (!String.IsNullOrEmpty(es.PanelName)) { m_hasPanel = true; break; } } } } /// /// Dispatch operations /// public void Operate() { Transaction transaction = new Transaction(m_revitDoc.Document, m_operation.ToString()); transaction.Start(); switch (m_operation) { case Operation.CreateCircuit: CreatePowerCircuit(); break; case Operation.EditCircuit: EditCircuit(); break; case Operation.SelectPanel: SelectPanel(); break; case Operation.DisconnectPanel: DisconnectPanel(); break; default: break; } transaction.Commit(); // Select the modified circuit if (m_operation != Operation.CreateCircuit) { SelectCurrentCircuit(); } } /// /// Create a power circuit with selected elements /// public void CreatePowerCircuit() { List selectionElementId = new List(); ElementSet elements = new ElementSet(); foreach (ElementId elementId in m_selection.GetElementIds()) { elements.Insert(m_revitDoc.Document.GetElement(elementId)); } foreach (Element e in elements) { selectionElementId.Add(e.Id); } try { // Creation ElectricalSystem es = ElectricalSystem.Create(m_revitDoc.Document, selectionElementId, ElectricalSystemType.PowerCircuit); // Select the newly created power system m_selection.GetElementIds().Clear(); m_selection.GetElementIds().Add(es.Id); } catch (Exception) { ShowErrorMessage("FailedToCreateCircuit"); } } /// /// Dispatch operations of editing circuit /// public void EditCircuit() { switch (m_editOption) { case EditOption.Add: AddElementToCircuit(); break; case EditOption.Remove: RemoveElementFromCircuit(); break; case EditOption.SelectPanel: SelectPanel(); break; default: break; } } /// /// Add an element to circuit /// public void AddElementToCircuit() { // Clear selection before selecting the panel m_selection.GetElementIds().Clear(); // Interact with UI to select a panel if (m_revitDoc.Selection.PickObject(ObjectType.Element) == null) { return; } // // Verify if the selected element can be added to the circuit // // Get selected element Element selectedElement = null; foreach (ElementId elementId in m_selection.GetElementIds()) { Element element = m_revitDoc.Document.GetElement(elementId); selectedElement = element; } // Get the MEP model of selected element MEPModel mepModel = null; FamilyInstance fi = selectedElement as FamilyInstance; if (null == fi || null == (mepModel = fi.MEPModel)) { ShowErrorMessage("SelectElectricalComponent"); return; } // Verify if the element has usable connector if (!VerifyUnusedConnectors(fi)) { ShowErrorMessage("NoUsableConnector"); return; } if (IsElementBelongsToCircuit(mepModel, m_selectedElectricalSystem)) { ShowErrorMessage("ElementInCircuit"); return; } try { ElementSet es = new ElementSet(); foreach (ElementId elementId in m_selection.GetElementIds()) { es.Insert(m_revitDoc.Document.GetElement(elementId)); } if (!m_selectedElectricalSystem.AddToCircuit(es)) { ShowErrorMessage("FailedToAddElement"); return; } } catch (Exception) { ShowErrorMessage("FailedToAddElement"); } } /// /// Remove an element from selected circuit /// public void RemoveElementFromCircuit() { // Clear selection before selecting the panel m_selection.GetElementIds().Clear(); // Interact with UI to select a panel if (m_revitDoc.Selection.PickObject(ObjectType.Element) == null) { return; } // Get the selected element Element selectedElement = null; foreach (ElementId elementId in m_revitDoc.Selection.GetElementIds()) { Element element = m_revitDoc.Document.GetElement(elementId); selectedElement = element; } // Get the MEP model of selected element MEPModel mepModel = null; FamilyInstance fi = selectedElement as FamilyInstance; if (null == fi || null == (mepModel = fi.MEPModel)) { ShowErrorMessage("SelectElectricalComponent"); return; } // Check whether the selected element belongs to the circuit if (!IsElementBelongsToCircuit(mepModel, m_selectedElectricalSystem)) { ShowErrorMessage("ElementNotInCircuit"); return; } try { // Remove the selected element from circuit ElementSet es = new ElementSet(); foreach (ElementId elementId in m_revitDoc.Selection.GetElementIds()) { es.Insert(m_revitDoc.Document.GetElement(elementId)); } m_selectedElectricalSystem.RemoveFromCircuit(es); } catch (Exception) { ShowErrorMessage("FailedToRemoveElement"); } } static private bool IsElementBelongsToCircuit(MEPModel mepModel, ElectricalSystem selectedElectricalSystem) { ElectricalSystemSet ess = mepModel.ElectricalSystems; if (null == ess || !ess.Contains(selectedElectricalSystem)) { return false; } return true; } /// /// Select a panel for selected circuit /// public void SelectPanel() { // Clear selection before selecting the panel m_selection.GetElementIds().Clear(); // Interact with UI to select a panel if (m_revitDoc.Selection.PickObject(ObjectType.Element) == null) { return; } try { FamilyInstance fi; foreach (ElementId elementId in m_selection.GetElementIds()) { Element element = m_revitDoc.Document.GetElement(elementId); fi = element as FamilyInstance; if (fi != null) { m_selectedElectricalSystem.SelectPanel(fi); } } } catch (Exception) { ShowErrorMessage("FailedToSelectPanel"); } } /// /// Disconnect panel for selected circuit /// public void DisconnectPanel() { try { m_selectedElectricalSystem.DisconnectPanel(); } catch (Exception) { ShowErrorMessage("FailedToDisconnectPanel"); } } /// /// Get selected index from circuit selecting form and locate expected circuit /// /// Index of selected item in circuit selecting form public void SelectCircuit(int index) { // Locate ElectricalSystemItem by index ElectricalSystemItem esi = m_electricalSystemItems[index] as ElectricalSystemItem; Autodesk.Revit.DB.ElementId ei = esi.Id; // Locate expected electrical system m_selectedElectricalSystem = m_revitDoc.Document.GetElement(ei) as ElectricalSystem; // Select the electrical system SelectCurrentCircuit(); } /// /// Select created/modified/selected electrical system /// public void SelectCurrentCircuit() { m_selection.GetElementIds().Clear(); m_selection.GetElementIds().Add(m_selectedElectricalSystem.Id); } /// /// Get selected index from circuit selecting form and show the circuit in the center of /// screen by moving the view. /// /// Index of selected item in circuit selecting form public void ShowCircuit(int index) { ElectricalSystemItem esi = m_electricalSystemItems[index] as ElectricalSystemItem; Autodesk.Revit.DB.ElementId ei = esi.Id; m_revitDoc.ShowElements(ei); } /// /// Show message box with specified string /// /// specified string to show static private void ShowErrorMessage(String message) { TaskDialog.Show(Properties.Resources.ResourceManager.GetString("OperationFailed"), Properties.Resources.ResourceManager.GetString(message), TaskDialogCommonButtons.Ok); } #endregion } }