应用程序:TraverseSystem

Revit平台:MEP

Revit版本:2011.0

首次发布时间:2010.0

编程语言:C#

技能水平:中级

类别:MEP

类型:ExternalCommand

主题:按照流向遍历连接良好的机械或管道系统。

摘要:

此示例展示了如何在流动方向上遍历连接良好的机械或管道系统,并将遍历结果转储到XML文件中。

相关类:

Autodesk.Revit.UI.IExternalCommand

Autodesk.Revit.DB

项目文件:

Command.cs

它包含了从IExternalCommand接口继承并实现Execute方法的Command类。它还从用户选择中检索良好连接的机械或管道系统。

TraversalTree.cs

它包含两个类:TreeNodeTraversalTreeTreeNode对象表示系统中的一个元素,它包含遍历的连接线索。TraversalTree类通过生成一种基于树的TreeNode对象结构,按照流向遍历指定的系统。

描述:

此示例提供以下功能。

- 从所选元素中检索良好连接的机械或管道系统,该元素可以是系统本身或系统中的任何元素。如果所选元素属于多个连接良好的系统,则选择元素最多的系统。

- 从系统的基本设备开始遍历系统。如果系统没有基本设备,则它将有一个开放连接器,这是唯一可以连接到基本设备的点。开放连接器的所有者将被选择为起点。

- 通过连接器流动方向分析系统中连接元素的关系,并生成遍历树形结构。

- 将遍历转储到XML文件中。

说明:

1. 打开Revit MEP应用程序,然后打开包含连接良好的系统的项目或在新项目中绘制连接良好的系统;选择连接良好的机械或管道系统或系统中的元素。然后执行命令。

2. 示例将按照流向遍历系统。最后,将在与文件“TraverseSystem.dll”相同的文件夹中将遍历转储到XML文件“traversal.xml”中。

源代码:
完整的源代码请加入QQ群649037449,在群文件中下载RevitSDK.exe,解压后在文件夹中搜索本文中应用程序名称即可获得完整源码

Command.cs

//
// (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.Windows.Forms;
using System.Collections;
using System.Reflection;
using System.IO;
using System.Collections.Generic;

using Autodesk.Revit;
using Autodesk.Revit.DB;
using Autodesk.Revit.UI;
using Autodesk.Revit.DB.Mechanical;
using Autodesk.Revit.DB.Plumbing;
using Autodesk.Revit.UI.Selection;
using Application = Autodesk.Revit.ApplicationServices.Application;
using Element = Autodesk.Revit.DB.Element;

namespace Revit.SDK.Samples.TraverseSystem.CS
{
/// <summary>
/// Implements the Revit add-in interface IExternalCommand
/// </summary>
[Autodesk.Revit.Attributes.Transaction(Autodesk.Revit.Attributes.TransactionMode.Manual)]
[Autodesk.Revit.Attributes.Regeneration(Autodesk.Revit.Attributes.RegenerationOption.Manual)]
[Autodesk.Revit.Attributes.Journaling(Autodesk.Revit.Attributes.JournalingMode.NoCommandData)]
public class Command : IExternalCommand
{
/// <summary>
/// Implement this method as an external command for Revit.
/// </summary>
/// <param name="commandData">An object that is passed to the external application
/// which contains data related to the command,
/// such as the application object and active view.</param>
/// <param name="message">A message that can be set by the external application
/// which will be displayed if a failure or cancellation is returned by
/// the external command.</param>
/// <param name="elements">A set of elements to which the external application
/// can add elements that are to be highlighted in case of failure or cancellation.</param>
/// <returns>Return the status of the external command.
/// A result of Succeeded means that the API external method functioned as expected.
/// Cancelled can be used to signify that the user cancelled the external operation
/// at some point. Failure should be returned if the application is unable to proceed with
/// the operation.</returns>
public virtual Autodesk.Revit.UI.Result Execute(ExternalCommandData commandData
, ref string message, Autodesk.Revit.DB.ElementSet elements)
{
try
{
// Verify if the active document is null
UIDocument activeDoc = commandData.Application.ActiveUIDocument;
if (activeDoc == null)
{
TaskDialog.Show("No Active Document", "There's no active document in Revit.", TaskDialogCommonButtons.Ok);
return Autodesk.Revit.UI.Result.Failed;
}

// Verify the number of selected elements
ElementSet selElements = new ElementSet();
foreach (ElementId elementId in activeDoc.Selection.GetElementIds())
{
selElements.Insert(activeDoc.Document.GetElement(elementId));
}
if (selElements.Size != 1)
{
message = "Please select ONLY one element from current project.";
return Autodesk.Revit.UI.Result.Failed;
}

// Get the selected element
Element selectedElement = null;
foreach (Element element in selElements)
{
selectedElement = element;
break;
}

// Get the expected mechanical or piping system from selected element
// Some elements in a non-well-connected system may get lost when traversing
//the system in the direction of flow; and
// flow direction of elements in a non-well-connected system may not be right,
// therefore the sample will only support well-connected system.
MEPSystem system = ExtractMechanicalOrPipingSystem(selectedElement);
if (system == null)
{
message = "The selected element does not belong to any well-connected mechanical or piping system. " +
"The sample will not support well-connected systems for the following reasons: " +
Environment.NewLine +
"- Some elements in a non-well-connected system may get lost when traversing the system in the " +
"direction of flow" + Environment.NewLine +
"- Flow direction of elements in a non-well-connected system may not be right";
return Autodesk.Revit.UI.Result.Failed;
}

// Traverse the system and dump the traversal into an XML file
TraversalTree tree = new TraversalTree(activeDoc.Document, system);
tree.Traverse();
String fileName;
fileName = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "traversal.xml");
tree.DumpIntoXML(fileName);

return Autodesk.Revit.UI.Result.Succeeded;
}
catch (Exception ex)
{
message = ex.Message;
return Autodesk.Revit.UI.Result.Failed;
}
}

/// <summary>
/// Get the mechanical or piping system from selected element
/// </summary>
/// <param name="selectedElement">Selected element</param>
/// <returns>The extracted mechanical or piping system. Null if no expected system is found.</returns>
private MEPSystem ExtractMechanicalOrPipingSystem(Element selectedElement)
{
MEPSystem system = null;

if (selectedElement is MEPSystem)
{
if (selectedElement is MechanicalSystem || selectedElement is PipingSystem)
{
system = selectedElement as MEPSystem;
return system;
}
}
else // Selected element is not a system
{
FamilyInstance fi = selectedElement as FamilyInstance;
//
// If selected element is a family instance, iterate its connectors and get the expected system
if (fi != null)
{
MEPModel mepModel = fi.MEPModel;
ConnectorSet connectors = null;
try
{
connectors = mepModel.ConnectorManager.Connectors;
}
catch (System.Exception)
{
system = null;
}

system = ExtractSystemFromConnectors(connectors);
}
else
{
//
// If selected element is a MEPCurve (e.g. pipe or duct),
// iterate its connectors and get the expected system
MEPCurve mepCurve = selectedElement as MEPCurve;
if (mepCurve != null)
{
ConnectorSet connectors = null;
connectors = mepCurve.ConnectorManager.Connectors;
system = ExtractSystemFromConnectors(connectors);
}
}
}

return system;
}

/// <summary>
/// Get the mechanical or piping system from the connectors of selected element
/// </summary>
/// <param name="connectors">Connectors of selected element</param>
/// <returns>The found mechanical or piping system</returns>
static private MEPSystem ExtractSystemFromConnectors(ConnectorSet connectors)
{
MEPSystem system = null;

if (connectors == null || connectors.Size == 0)
{
return null;
}

// Get well-connected mechanical or piping systems from each connector
List<MEPSystem> systems = new List<MEPSystem>();
foreach (Connector connector in connectors)
{
MEPSystem tmpSystem = connector.MEPSystem;
if (tmpSystem == null)
{
continue;
}

MechanicalSystem ms = tmpSystem as MechanicalSystem;
if (ms != null)
{
if (ms.IsWellConnected)
{
systems.Add(tmpSystem);
}
}
else
{
PipingSystem ps = tmpSystem as PipingSystem;
if (ps != null && ps.IsWellConnected)
{
systems.Add(tmpSystem);
}
}
}

// If more than one system is found, get the system contains the most elements
int countOfSystem = systems.Count;
if (countOfSystem != 0)
{
int countOfElements = 0;
foreach (MEPSystem sys in systems)
{
if (sys.Elements.Size > countOfElements)
{
system = sys;
countOfElements = sys.Elements.Size;
}
}
}

return system;
}
}
}

TraversalTree.cs

//
// (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.Generic;
using System.Text;
using System.Xml;

using Autodesk.Revit;
using Autodesk.Revit.DB;
using Autodesk.Revit.DB.Mechanical;
using Autodesk.Revit.DB.Plumbing;

namespace Revit.SDK.Samples.TraverseSystem.CS
{
/// <summary>
/// A TreeNode object represents an element in the system
/// </summary>
public class TreeNode
{
#region Member variables
/// <summary>
/// Id of the element
/// </summary>
private Autodesk.Revit.DB.ElementId m_Id;
/// <summary>
/// Flow direction of the node
/// For the starting element of the traversal, the direction will be the same as the connector
/// connected to its following element; Otherwise it will be the direction of the connector connected to
/// its previous element
/// </summary>
private FlowDirectionType m_direction;
/// <summary>
/// The parent node of the current node.
/// </summary>
private TreeNode m_parent;
/// <summary>
/// The connector of the previous element to which current element is connected
/// </summary>
private Connector m_inputConnector;
/// <summary>
/// The first-level child nodes of the current node
/// </summary>
private List<TreeNode> m_childNodes;
/// <summary>
/// Active document of Revit
/// </summary>
private Document m_document;
#endregion

#region Properties
/// <summary>
/// Id of the element
/// </summary>
public Autodesk.Revit.DB.ElementId Id
{
get
{
return m_Id;
}
}

/// <summary>
/// Flow direction of the node
/// </summary>
public FlowDirectionType Direction
{
get
{
return m_direction;
}
set
{
m_direction = value;
}
}

/// <summary>
/// Gets and sets the parent node of the current node.
/// </summary>
public TreeNode Parent
{
get
{
return m_parent;
}
set
{
m_parent = value;
}
}

/// <summary>
/// Gets and sets the first-level child nodes of the current node
/// </summary>
public List<TreeNode> ChildNodes
{
get
{
return m_childNodes;
}
set
{
m_childNodes = value;
}
}

/// <summary>
/// The connector of the previous element to which current element is connected
/// </summary>
public Connector InputConnector
{
get
{
return m_inputConnector;
}
set
{
m_inputConnector = value;
}
}
#endregion

#region Methods
/// <summary>
/// Constructor
/// </summary>
/// <param name="doc">Revit document</param>
/// <param name="id">Element's Id</param>
public TreeNode(Document doc, Autodesk.Revit.DB.ElementId id)
{
m_document = doc;
m_Id = id;
m_childNodes = new List<TreeNode>();
}

/// <summary>
/// Get Element by its Id
/// </summary>
/// <param name="eid">Element's Id</param>
/// <returns>Element</returns>
private Element GetElementById(Autodesk.Revit.DB.ElementId eid)
{
return m_document.GetElement(eid);
}

/// <summary>
/// Dump the node into XML file
/// </summary>
/// <param name="writer">XmlWriter object</param>
public void DumpIntoXML(XmlWriter writer)
{
// Write node information
Element element = GetElementById(m_Id);
FamilyInstance fi = element as FamilyInstance;
if (fi != null)
{
MEPModel mepModel = fi.MEPModel;
String type = String.Empty;
if (mepModel is MechanicalEquipment)
{
type = "MechanicalEquipment";
writer.WriteStartElement(type);
}
else if (mepModel is MechanicalFitting)
{
MechanicalFitting mf = mepModel as MechanicalFitting;
type = "MechanicalFitting";
writer.WriteStartElement(type);
writer.WriteAttributeString("Category", element.Category.Name);
writer.WriteAttributeString("PartType", mf.PartType.ToString());
}
else
{
type = "FamilyInstance";
writer.WriteStartElement(type);
writer.WriteAttributeString("Category", element.Category.Name);
}

writer.WriteAttributeString("Name", element.Name);
writer.WriteAttributeString("Id", element.Id.IntegerValue.ToString());
writer.WriteAttributeString("Direction", m_direction.ToString());
writer.WriteEndElement();
}
else
{
String type = element.GetType().Name;

writer.WriteStartElement(type);
writer.WriteAttributeString("Name", element.Name);
writer.WriteAttributeString("Id", element.Id.IntegerValue.ToString());
writer.WriteAttributeString("Direction", m_direction.ToString());
writer.WriteEndElement();
}

foreach (TreeNode node in m_childNodes)
{
if (m_childNodes.Count > 1)
{
writer.WriteStartElement("Path");
}

node.DumpIntoXML(writer);

if (m_childNodes.Count > 1)
{
writer.WriteEndElement();
}
}
}
#endregion
}

/// <summary>
/// Data structure of the traversal
/// </summary>
public class TraversalTree
{
#region Member variables
// Active document of Revit
private Document m_document;
// The MEP system of the traversal
private MEPSystem m_system;
// The flag whether the MEP system of the traversal is a mechanical system or piping system
private Boolean m_isMechanicalSystem;
// The starting element node
private TreeNode m_startingElementNode;
#endregion

#region Methods
/// <summary>
/// Constructor
/// </summary>
/// <param name="activeDocument">Revit document</param>
/// <param name="system">The MEP system to traverse</param>
public TraversalTree(Document activeDocument, MEPSystem system)
{
m_document = activeDocument;
m_system = system;
m_isMechanicalSystem = (system is MechanicalSystem);
}

/// <summary>
/// Traverse the system
/// </summary>
public void Traverse()
{
// Get the starting element node
m_startingElementNode = GetStartingElementNode();

// Traverse the system recursively
Traverse(m_startingElementNode);
}

/// <summary>
/// Get the starting element node.
/// If the system has base equipment then get it;
/// Otherwise get the owner of the open connector in the system
/// </summary>
/// <returns>The starting element node</returns>
private TreeNode GetStartingElementNode()
{
TreeNode startingElementNode = null;

FamilyInstance equipment = m_system.BaseEquipment;
//
// If the system has base equipment then get it;
// Otherwise get the owner of the open connector in the system
if (equipment != null)
{
startingElementNode = new TreeNode(m_document, equipment.Id);
}
else
{
startingElementNode = new TreeNode(m_document, GetOwnerOfOpenConnector().Id);
}

startingElementNode.Parent = null;
startingElementNode.InputConnector = null;

return startingElementNode;
}

/// <summary>
/// Get the owner of the open connector as the starting element
/// </summary>
/// <returns>The owner</returns>
private Element GetOwnerOfOpenConnector()
{
Element element = null;

//
// Get an element from the system's terminals
ElementSet elements = m_system.Elements;
foreach (Element ele in elements)
{
element = ele;
break;
}

// Get the open connector recursively
Connector openConnector = GetOpenConnector(element, null);

return openConnector.Owner;
}

/// <summary>
/// Get the open connector of the system if the system has no base equipment
/// </summary>
/// <param name="element">An element in the system</param>
/// <param name="inputConnector">The connector of the previous element
/// to which the element is connected </param>
/// <returns>The found open connector</returns>
private Connector GetOpenConnector(Element element, Connector inputConnector)
{
Connector openConnector = null;
ConnectorManager cm = null;
//
// Get the connector manager of the element
if (element is FamilyInstance)
{
FamilyInstance fi = element as FamilyInstance;
cm = fi.MEPModel.ConnectorManager;
}
else
{
MEPCurve mepCurve = element as MEPCurve;
cm = mepCurve.ConnectorManager;
}

foreach (Connector conn in cm.Connectors)
{
// Ignore the connector does not belong to any MEP System or belongs to another different MEP system
if (conn.MEPSystem == null || !conn.MEPSystem.Id.IntegerValue.Equals(m_system.Id.IntegerValue))
{
continue;
}

// If the connector is connected to the input connector, they will have opposite flow directions.
if (inputConnector != null && conn.IsConnectedTo(inputConnector))
{
continue;
}

// If the connector is not connected, it is the open connector
if (!conn.IsConnected)
{
openConnector = conn;
break;
}

//
// If open connector not found, then look for it from elements connected to the element
foreach (Connector refConnector in conn.AllRefs)
{
// Ignore non-EndConn connectors and connectors of the current element
if (refConnector.ConnectorType != ConnectorType.End ||
refConnector.Owner.Id.IntegerValue.Equals(conn.Owner.Id.IntegerValue))
{
continue;
}

// Ignore connectors of the previous element
if (inputConnector != null && refConnector.Owner.Id.IntegerValue.Equals(inputConnector.Owner.Id.IntegerValue))
{
continue;
}

openConnector = GetOpenConnector(refConnector.Owner, conn);
if (openConnector != null)
{
return openConnector;
}
}
}

return openConnector;
}

/// <summary>
/// Traverse the system recursively by analyzing each element
/// </summary>
/// <param name="elementNode">The element to be analyzed</param>
private void Traverse(TreeNode elementNode)
{
//
// Find all child nodes and analyze them recursively
AppendChildren(elementNode);
foreach (TreeNode node in elementNode.ChildNodes)
{
Traverse(node);
}
}

/// <summary>
/// Find all child nodes of the specified element node
/// </summary>
/// <param name="elementNode">The specified element node to be analyzed</param>
private void AppendChildren(TreeNode elementNode)
{
List<TreeNode> nodes = elementNode.ChildNodes;
ConnectorSet connectors;
//
// Get connector manager
Element element = GetElementById(elementNode.Id);
FamilyInstance fi = element as FamilyInstance;
if (fi != null)
{
connectors = fi.MEPModel.ConnectorManager.Connectors;
}
else
{
MEPCurve mepCurve = element as MEPCurve;
connectors = mepCurve.ConnectorManager.Connectors;
}

// Find connected connector for each connector
foreach (Connector connector in connectors)
{
MEPSystem mepSystem = connector.MEPSystem;
// Ignore the connector does not belong to any MEP System or belongs to another different MEP system
if (mepSystem == null || !mepSystem.Id.IntegerValue.Equals(m_system.Id.IntegerValue))
{
continue;
}

//
// Get the direction of the TreeNode object
if (elementNode.Parent == null)
{
if (connector.IsConnected)
{
elementNode.Direction = connector.Direction;
}
}
else
{
// If the connector is connected to the input connector, they will have opposite flow directions.
// Then skip it.
if (connector.IsConnectedTo(elementNode.InputConnector))
{
elementNode.Direction = connector.Direction;
continue;
}
}

// Get the connector connected to current connector
Connector connectedConnector = GetConnectedConnector(connector);
if (connectedConnector != null)
{
TreeNode node = new TreeNode(m_document, connectedConnector.Owner.Id);
node.InputConnector = connector;
node.Parent = elementNode;
nodes.Add(node);
}
}

nodes.Sort(delegate(TreeNode t1, TreeNode t2)
{
return t1.Id.IntegerValue > t2.Id.IntegerValue ? 1 : (t1.Id.IntegerValue < t2.Id.IntegerValue ? -1 : 0);
}
);
}

/// <summary>
/// Get the connected connector of one connector
/// </summary>
/// <param name="connector">The connector to be analyzed</param>
/// <returns>The connected connector</returns>
static private Connector GetConnectedConnector(Connector connector)
{
Connector connectedConnector = null;
ConnectorSet allRefs = connector.AllRefs;
foreach (Connector conn in allRefs)
{
// Ignore non-EndConn connectors and connectors of the current element
if (conn.ConnectorType != ConnectorType.End ||
conn.Owner.Id.IntegerValue.Equals(connector.Owner.Id.IntegerValue))
{
continue;
}

connectedConnector = conn;
break;
}

return connectedConnector;
}

/// <summary>
/// Get element by its id
/// </summary>
private Element GetElementById(Autodesk.Revit.DB.ElementId eid)
{
return m_document.GetElement(eid);
}

/// <summary>
/// Dump the traversal into an XML file
/// </summary>
/// <param name="fileName">Name of the XML file</param>
public void DumpIntoXML(String fileName)
{
XmlWriterSettings settings = new XmlWriterSettings();
settings.Indent = true;
settings.IndentChars = " ";
XmlWriter writer = XmlWriter.Create(fileName, settings);

// Write the root element
String mepSystemType = String.Empty;
mepSystemType = (m_system is MechanicalSystem ? "MechanicalSystem" : "PipingSystem");
writer.WriteStartElement(mepSystemType);

// Write basic information of the MEP system
WriteBasicInfo(writer);
// Write paths of the traversal
WritePaths(writer);

// Close the root element
writer.WriteEndElement();

writer.Flush();
writer.Close();
}

/// <summary>
/// Write basic information of the MEP system into the XML file
/// </summary>
/// <param name="writer">XMLWriter object</param>
private void WriteBasicInfo(XmlWriter writer)
{
MechanicalSystem ms = null;
PipingSystem ps = null;
if (m_isMechanicalSystem)
{
ms = m_system as MechanicalSystem;
}
else
{
ps = m_system as PipingSystem;
}

// Write basic information of the system
writer.WriteStartElement("BasicInformation");

// Write Name property
writer.WriteStartElement("Name");
writer.WriteString(m_system.Name);
writer.WriteEndElement();

// Write Id property
writer.WriteStartElement("Id");
writer.WriteValue(m_system.Id.IntegerValue);
writer.WriteEndElement();

// Write UniqueId property
writer.WriteStartElement("UniqueId");
writer.WriteString(m_system.UniqueId);
writer.WriteEndElement();

// Write SystemType property
writer.WriteStartElement("SystemType");
if (m_isMechanicalSystem)
{
writer.WriteString(ms.SystemType.ToString());
}
else
{
writer.WriteString(ps.SystemType.ToString());
}
writer.WriteEndElement();

// Write Category property
writer.WriteStartElement("Category");
writer.WriteAttributeString("Id", m_system.Category.Id.IntegerValue.ToString());
writer.WriteAttributeString("Name", m_system.Category.Name);
writer.WriteEndElement();

// Write IsWellConnected property
writer.WriteStartElement("IsWellConnected");
if (m_isMechanicalSystem)
{
writer.WriteValue(ms.IsWellConnected);
}
else
{
writer.WriteValue(ps.IsWellConnected);
}
writer.WriteEndElement();

// Write HasBaseEquipment property
writer.WriteStartElement("HasBaseEquipment");
bool hasBaseEquipment = ((m_system.BaseEquipment == null) ? false : true);
writer.WriteValue(hasBaseEquipment);
writer.WriteEndElement();

// Write TerminalElementsCount property
writer.WriteStartElement("TerminalElementsCount");
writer.WriteValue(m_system.Elements.Size);
writer.WriteEndElement();

// Write Flow property
writer.WriteStartElement("Flow");
if (m_isMechanicalSystem)
{
writer.WriteValue(ms.GetFlow());
}
else
{
writer.WriteValue(ps.GetFlow());
}
writer.WriteEndElement();

// Close basic information
writer.WriteEndElement();
}

/// <summary>
/// Write paths of the traversal into the XML file
/// </summary>
/// <param name="writer">XMLWriter object</param>
private void WritePaths(XmlWriter writer)
{
writer.WriteStartElement("Path");
m_startingElementNode.DumpIntoXML(writer);
writer.WriteEndElement();
}
#endregion
}
}