mirror of
https://github.com/jeremytammik/RevitSdkSamples.git
synced 2026-08-11 07:26:16 +00:00
copied Revit 2024 SDK
This commit is contained in:
@@ -0,0 +1,133 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Autodesk.Revit.DB;
|
||||
using Autodesk.Revit.DB.Analysis;
|
||||
|
||||
namespace Revit.SDK.Samples.NetworkPressureLossReport
|
||||
{
|
||||
public class AVFViewer
|
||||
{
|
||||
private bool? m_isItemzied;
|
||||
private View m_view;
|
||||
private SpatialFieldManager m_sfm;
|
||||
private int m_schemaIdx;
|
||||
private XYZ m_maxCorner;
|
||||
const string DisplayStyleName = "NetworkFlowDisplayStyle";
|
||||
const String SchemaName = "NetworkFlowSchema";
|
||||
|
||||
public AVFViewer(View view, bool? isItemized)
|
||||
{
|
||||
m_view = view;
|
||||
m_isItemzied = isItemized;
|
||||
|
||||
m_sfm = SpatialFieldManager.GetSpatialFieldManager(view);
|
||||
if (m_sfm == null)
|
||||
{
|
||||
m_sfm = SpatialFieldManager.CreateSpatialFieldManager(view, 1);
|
||||
}
|
||||
m_sfm.Clear();
|
||||
m_maxCorner = new XYZ(-Double.MaxValue, -Double.MaxValue, -Double.MaxValue);
|
||||
}
|
||||
public Document Document
|
||||
{
|
||||
get { return m_view.Document; }
|
||||
}
|
||||
public double Scale
|
||||
{
|
||||
get { return m_view.Scale; }
|
||||
}
|
||||
public bool IsItemized
|
||||
{
|
||||
get { return m_isItemzied == true; }
|
||||
}
|
||||
public void InitAVF()
|
||||
{
|
||||
m_view.EnableTemporaryViewPropertiesMode(m_view.Id);
|
||||
m_view.TemporaryViewModes.RemoveCustomization();
|
||||
m_view.TemporaryViewModes.CustomTitle = "Network Flow Analysis";
|
||||
|
||||
AnalysisResultSchema resultSchema = new AnalysisResultSchema(SchemaName, "");
|
||||
m_sfm.SetMeasurementNames(new List<string>() { SchemaName });
|
||||
m_schemaIdx = m_sfm.RegisterResult(resultSchema);
|
||||
}
|
||||
public int AddData(List<XYZ> points, List<VectorAtPoint> valList)
|
||||
{
|
||||
int idx = m_sfm.AddSpatialFieldPrimitive();
|
||||
FieldDomainPointsByXYZ pnts = new FieldDomainPointsByXYZ(points);
|
||||
FieldValues vals = new FieldValues(valList);
|
||||
m_sfm.UpdateSpatialFieldPrimitive(idx, pnts, vals, m_schemaIdx);
|
||||
return idx;
|
||||
}
|
||||
public void AddCorner(double maxX, double maxY, double maxZ)
|
||||
{
|
||||
double xx = Math.Max(m_maxCorner.X, maxX);
|
||||
double yy = Math.Max(m_maxCorner.Y, maxY);
|
||||
double zz = Math.Max(m_maxCorner.Z, maxZ);
|
||||
m_maxCorner = new XYZ(xx, yy, zz);
|
||||
}
|
||||
private AnalysisDisplayStyle getStyleByName(string name)
|
||||
{
|
||||
FilteredElementCollector collector = new FilteredElementCollector(Document);
|
||||
ICollection<Element> collection = collector.OfClass(typeof(AnalysisDisplayStyle)).ToElements();
|
||||
var displayStyle = from element in collection
|
||||
where element.Name == name
|
||||
select element;
|
||||
AnalysisDisplayStyle analysisDisplayStyle = null;
|
||||
if (displayStyle.Count() != 0)
|
||||
analysisDisplayStyle = displayStyle.Cast<AnalysisDisplayStyle>().ElementAt<AnalysisDisplayStyle>(0);
|
||||
return analysisDisplayStyle;
|
||||
}
|
||||
public void FinishDisplayStyle()
|
||||
{
|
||||
// set the legend to the top right corner so it is close to the AVF display
|
||||
m_sfm.LegendPosition = m_maxCorner;
|
||||
|
||||
AnalysisDisplayStyle analysisDisplayStyle = getStyleByName(DisplayStyleName);
|
||||
|
||||
// If display style does not already exist in the document, create it
|
||||
AnalysisDisplayColorSettings colorSettings = new AnalysisDisplayColorSettings();
|
||||
if (analysisDisplayStyle == null)
|
||||
{
|
||||
colorSettings.MaxColor = new Color(255, 0, 0);
|
||||
colorSettings.MinColor = new Color(0, 255, 0);
|
||||
|
||||
AnalysisDisplayVectorSettings vectorSettings = new AnalysisDisplayVectorSettings();
|
||||
vectorSettings.VectorOrientation = AnalysisDisplayStyleVectorOrientation.Linear;
|
||||
vectorSettings.ArrowheadScale = AnalysisDisplayStyleVectorArrowheadScale.NoScaling;
|
||||
vectorSettings.ArrowLineWeight = 4;
|
||||
vectorSettings.VectorTextType = AnalysisDisplayStyleVectorTextType.ShowNone;
|
||||
|
||||
AnalysisDisplayLegendSettings legendSettings = new AnalysisDisplayLegendSettings();
|
||||
legendSettings.ShowLegend = false;
|
||||
|
||||
analysisDisplayStyle = AnalysisDisplayStyle.CreateAnalysisDisplayStyle(Document, DisplayStyleName, vectorSettings, colorSettings, legendSettings);
|
||||
}
|
||||
|
||||
m_view.AnalysisDisplayStyleId = analysisDisplayStyle.Id;
|
||||
|
||||
m_view.TemporaryViewModes.CustomColor = analysisDisplayStyle.GetColorSettings().MaxColor;
|
||||
|
||||
// Transparent everything so we can see the flow vector.
|
||||
ElementId rasterId = new ElementId(BuiltInCategory.OST_RasterImages);
|
||||
foreach (Category c in m_view.Document.Settings.Categories)
|
||||
{
|
||||
if (!m_view.GetCategoryHidden(c.Id))
|
||||
{
|
||||
if (c.Id != rasterId && m_view.IsCategoryOverridable(c.Id))
|
||||
{
|
||||
OverrideGraphicSettings ogs = m_view.GetCategoryOverrides(c.Id);
|
||||
if (!ogs.Halftone)
|
||||
{
|
||||
m_view.SetCategoryOverrides(c.Id, ogs.SetHalftone(true));
|
||||
m_view.SetCategoryOverrides(c.Id, ogs.SetSurfaceTransparency(50));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,190 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Autodesk.Revit.DB;
|
||||
|
||||
namespace Revit.SDK.Samples.NetworkPressureLossReport
|
||||
{
|
||||
public class CSVExporter : IDisposable
|
||||
{
|
||||
private Document m_doc;
|
||||
private bool? m_isItemized;
|
||||
private ConnectorDomainType m_connType;
|
||||
private StreamWriter m_streamWriter;
|
||||
|
||||
public StreamWriter Writer
|
||||
{
|
||||
get { return m_streamWriter; }
|
||||
}
|
||||
public bool? IsItemized
|
||||
{
|
||||
get { return m_isItemized; }
|
||||
}
|
||||
public Document Document
|
||||
{
|
||||
set { m_doc = value; }
|
||||
}
|
||||
public ConnectorDomainType DomainType
|
||||
{
|
||||
set { m_connType = value; }
|
||||
}
|
||||
public CSVExporter(string csvFilePath, bool? isItemized)
|
||||
{
|
||||
if(!string.IsNullOrEmpty(csvFilePath))
|
||||
{
|
||||
m_streamWriter = new StreamWriter(csvFilePath, false, System.Text.Encoding.Unicode);
|
||||
}
|
||||
m_isItemized = isItemized;
|
||||
}
|
||||
~CSVExporter() => Dispose(false);
|
||||
public void Dispose()
|
||||
{
|
||||
Dispose(true);
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
protected virtual void Dispose(bool disposing)
|
||||
{
|
||||
if(m_streamWriter != null)
|
||||
{
|
||||
// Dispose/Close the stream writer.
|
||||
m_streamWriter.Dispose();
|
||||
m_streamWriter = null;
|
||||
}
|
||||
}
|
||||
private string SafeGetUnitLabel(FormatOptions opt)
|
||||
{
|
||||
string msg = null;
|
||||
string unitLabel = null;
|
||||
try
|
||||
{
|
||||
unitLabel = LabelUtils.GetLabelForSymbol(opt.GetSymbolTypeId());
|
||||
}
|
||||
catch (Autodesk.Revit.Exceptions.ArgumentException ex)
|
||||
{
|
||||
// The unit symbol is None.
|
||||
msg = ex.Message;
|
||||
}
|
||||
if(string.IsNullOrEmpty(unitLabel))
|
||||
{
|
||||
try
|
||||
{
|
||||
unitLabel = LabelUtils.GetLabelForUnit(opt.GetUnitTypeId());
|
||||
}
|
||||
catch (Autodesk.Revit.Exceptions.ArgumentException ex)
|
||||
{
|
||||
// The unit symbol is None.
|
||||
msg = ex.Message;
|
||||
}
|
||||
}
|
||||
return unitLabel;
|
||||
}
|
||||
private ForgeTypeId GetFlowTypeId()
|
||||
{
|
||||
ForgeTypeId typeId = null;
|
||||
if (m_connType == ConnectorDomainType.Piping)
|
||||
typeId = SpecTypeId.Flow;
|
||||
else if (m_connType == ConnectorDomainType.Hvac)
|
||||
typeId = SpecTypeId.AirFlow;
|
||||
return typeId;
|
||||
}
|
||||
public double ConvertFromInternalFlow(double flow)
|
||||
{
|
||||
FormatOptions formatOption = m_doc.GetUnits().GetFormatOptions(GetFlowTypeId());
|
||||
return UnitUtils.ConvertFromInternalUnits(flow, formatOption.GetUnitTypeId());
|
||||
}
|
||||
public string GetFlowUnitSymbol()
|
||||
{
|
||||
FormatOptions formatOption = m_doc.GetUnits().GetFormatOptions(GetFlowTypeId());
|
||||
return SafeGetUnitLabel(formatOption);
|
||||
}
|
||||
private ForgeTypeId GetSizeTypeId()
|
||||
{
|
||||
ForgeTypeId typeId = null;
|
||||
if (m_connType == ConnectorDomainType.Piping)
|
||||
typeId = SpecTypeId.PipeSize;
|
||||
else if (m_connType == ConnectorDomainType.Hvac)
|
||||
typeId = SpecTypeId.DuctSize;
|
||||
return typeId;
|
||||
}
|
||||
public double ConvertFromInternalSize(double value)
|
||||
{
|
||||
FormatOptions formatOption = m_doc.GetUnits().GetFormatOptions(GetSizeTypeId());
|
||||
return UnitUtils.ConvertFromInternalUnits(value, formatOption.GetUnitTypeId());
|
||||
}
|
||||
public string GetSizeUnitSymbol()
|
||||
{
|
||||
FormatOptions formatOption = m_doc.GetUnits().GetFormatOptions(GetSizeTypeId());
|
||||
return SafeGetUnitLabel(formatOption);
|
||||
}
|
||||
private ForgeTypeId GetVelocityTypeId()
|
||||
{
|
||||
ForgeTypeId typeId = null;
|
||||
if (m_connType == ConnectorDomainType.Piping)
|
||||
typeId = SpecTypeId.PipingVelocity;
|
||||
else if (m_connType == ConnectorDomainType.Hvac)
|
||||
typeId = SpecTypeId.HvacVelocity;
|
||||
return typeId;
|
||||
}
|
||||
public double ConvertFromInternalVelocity(double value)
|
||||
{
|
||||
FormatOptions formatOption = m_doc.GetUnits().GetFormatOptions(GetVelocityTypeId());
|
||||
return UnitUtils.ConvertFromInternalUnits(value, formatOption.GetUnitTypeId());
|
||||
}
|
||||
public string GetVelocityUnitSymbol()
|
||||
{
|
||||
FormatOptions formatOption = m_doc.GetUnits().GetFormatOptions(GetVelocityTypeId());
|
||||
return SafeGetUnitLabel(formatOption);
|
||||
}
|
||||
private ForgeTypeId GetPressureTypeId()
|
||||
{
|
||||
ForgeTypeId typeId = null;
|
||||
if (m_connType == ConnectorDomainType.Piping)
|
||||
typeId = SpecTypeId.PipingPressure;
|
||||
else if (m_connType == ConnectorDomainType.Hvac)
|
||||
typeId = SpecTypeId.HvacPressure;
|
||||
return typeId;
|
||||
}
|
||||
public double ConvertFromInternalPressure(double value)
|
||||
{
|
||||
FormatOptions formatOption = m_doc.GetUnits().GetFormatOptions(GetPressureTypeId());
|
||||
return UnitUtils.ConvertFromInternalUnits(value, formatOption.GetUnitTypeId());
|
||||
}
|
||||
public string GetPressureUnitSymbol()
|
||||
{
|
||||
FormatOptions formatOption = m_doc.GetUnits().GetFormatOptions(GetPressureTypeId());
|
||||
return SafeGetUnitLabel(formatOption);
|
||||
}
|
||||
private ForgeTypeId GetFrictionTypeId()
|
||||
{
|
||||
ForgeTypeId typeId = null;
|
||||
if (m_connType == ConnectorDomainType.Piping)
|
||||
typeId = SpecTypeId.PipingFriction;
|
||||
else if (m_connType == ConnectorDomainType.Hvac)
|
||||
typeId = SpecTypeId.HvacFriction;
|
||||
return typeId;
|
||||
}
|
||||
public double ConvertFromInternalFriction(double value)
|
||||
{
|
||||
FormatOptions formatOption = m_doc.GetUnits().GetFormatOptions(GetFrictionTypeId());
|
||||
return UnitUtils.ConvertFromInternalUnits(value, formatOption.GetUnitTypeId());
|
||||
}
|
||||
public string GetFrictionUnitSymbol()
|
||||
{
|
||||
FormatOptions formatOption = m_doc.GetUnits().GetFormatOptions(GetFrictionTypeId());
|
||||
return SafeGetUnitLabel(formatOption);
|
||||
}
|
||||
public double ConvertFromInternalLength(double value)
|
||||
{
|
||||
FormatOptions formatOption = m_doc.GetUnits().GetFormatOptions(SpecTypeId.Length);
|
||||
return UnitUtils.ConvertFromInternalUnits(value, formatOption.GetUnitTypeId());
|
||||
}
|
||||
public string GetLengthUnitSymbol()
|
||||
{
|
||||
FormatOptions formatOption = m_doc.GetUnits().GetFormatOptions(SpecTypeId.Length);
|
||||
return SafeGetUnitLabel(formatOption);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
//
|
||||
// (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.Collections.Generic;
|
||||
using Autodesk.Revit.DB;
|
||||
using Autodesk.Revit.UI;
|
||||
|
||||
namespace Revit.SDK.Samples.NetworkPressureLossReport
|
||||
{
|
||||
/// <summary>
|
||||
/// Demonstrate how to find all networks available in the active document.
|
||||
/// </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
|
||||
{
|
||||
#region IExternalCommand Members
|
||||
|
||||
public Autodesk.Revit.UI.Result Execute(ExternalCommandData commandData, ref string message, Autodesk.Revit.DB.ElementSet elements)
|
||||
{
|
||||
|
||||
// Get the application and document from external command data.
|
||||
Document activeDoc = commandData.Application.ActiveUIDocument.Document;
|
||||
|
||||
NetworkDialog dlg = new NetworkDialog(activeDoc);
|
||||
dlg.ShowDialog();
|
||||
|
||||
return Autodesk.Revit.UI.Result.Succeeded;
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
<Window x:Class="Revit.SDK.Samples.NetworkPressureLossReport.NetworkDialog"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:local="clr-namespace:Revit.SDK.Samples.NetworkPressureLossReport"
|
||||
Title="Network Flow and Pressure Loss Report"
|
||||
mc:Ignorable="d"
|
||||
Height="450"
|
||||
Width="600"
|
||||
MinHeight="250"
|
||||
MinWidth="400">
|
||||
<Grid>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="*" />
|
||||
</Grid.RowDefinitions>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="*" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<Label Grid.Column="0" Grid.Row="0" Content="Networks:" Margin="7,5" HorizontalAlignment="Left" VerticalAlignment="Top"/>
|
||||
<ListView Grid.Column="0"
|
||||
Grid.Row="1"
|
||||
Margin="7,0,0,7"
|
||||
SelectionMode="Multiple"
|
||||
x:Name="NetworkList" >
|
||||
<ListView.View>
|
||||
<GridView AllowsColumnReorder="true" ColumnHeaderToolTip="Network Information">
|
||||
<GridViewColumn DisplayMemberBinding="{Binding Path=Name}" Header="Name" Width="300"/>
|
||||
<GridViewColumn DisplayMemberBinding="{Binding Path=NumberOfSections}" Header="Sections" Width="60"/>
|
||||
<GridViewColumn DisplayMemberBinding="{Binding Path=FlowDisplay}" Header="Flow" Width="Auto"/>
|
||||
</GridView>
|
||||
</ListView.View>
|
||||
</ListView>
|
||||
|
||||
<StackPanel Grid.Column="1" Grid.Row="1">
|
||||
<CheckBox Content="Itemized" x:Name="ChxItemized" HorizontalAlignment="Left" Margin='16,10, 14,20' VerticalAlignment="Top" Height="Auto" Width="110" />
|
||||
<Button Content="Export..." HorizontalAlignment="Left" Margin='16,0, 14,10' VerticalAlignment="Top" Height="35" Width="110" IsDefault="True" Click="Report_Click"/>
|
||||
<Button Content="View" HorizontalAlignment="Left" Margin='16,12, 14,10' VerticalAlignment="Top" Height="35" Width="110" Click="View_Click"/>
|
||||
<Button Content="Cancel" HorizontalAlignment="Left" Margin='16,12, 14,5' VerticalAlignment="Top" Height="35" Width="110" Click="Cancel_Click" IsCancel="True"/>
|
||||
</StackPanel>
|
||||
|
||||
</Grid>
|
||||
|
||||
</Window>
|
||||
@@ -0,0 +1,92 @@
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Windows;
|
||||
using System.Windows.Forms;
|
||||
using Autodesk.Revit.DB;
|
||||
|
||||
namespace Revit.SDK.Samples.NetworkPressureLossReport
|
||||
{
|
||||
/// <summary>
|
||||
/// Interaction logic for NetworkDialog.xaml
|
||||
/// </summary>
|
||||
public partial class NetworkDialog : Window
|
||||
{
|
||||
private Document m_doc;
|
||||
private IList<NetworkInfo> m_networks;
|
||||
public NetworkDialog(Document doc)
|
||||
{
|
||||
m_doc = doc;
|
||||
InitializeComponent();
|
||||
|
||||
refreshNetworkList();
|
||||
}
|
||||
|
||||
private void refreshNetworkList()
|
||||
{
|
||||
m_networks = NetworkInfo.FindValidNetworks(m_doc);
|
||||
|
||||
NetworkList.ItemsSource = m_networks;
|
||||
if(m_networks.Count > 0)
|
||||
{
|
||||
NetworkList.SelectedIndex = 0;
|
||||
}
|
||||
}
|
||||
public void Cancel_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
Close();
|
||||
}
|
||||
public void View_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (NetworkList.SelectedItems.Count <= 0)
|
||||
return;
|
||||
|
||||
using (Transaction tran = new Transaction(m_doc))
|
||||
{
|
||||
tran.Start("Create Analysis View");
|
||||
|
||||
AVFViewer viewer = new AVFViewer(m_doc.ActiveView, ChxItemized.IsChecked);
|
||||
viewer.InitAVF();
|
||||
|
||||
foreach (var item in NetworkList.SelectedItems)
|
||||
{
|
||||
NetworkInfo net = item as NetworkInfo;
|
||||
if (net != null)
|
||||
{
|
||||
net.UpdateView(viewer);
|
||||
}
|
||||
}
|
||||
viewer.FinishDisplayStyle();
|
||||
|
||||
tran.Commit();
|
||||
}
|
||||
|
||||
Close();
|
||||
}
|
||||
public void Report_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
int idx = NetworkList.SelectedIndex;
|
||||
if (idx < 0 || m_networks.Count <= 0)
|
||||
return;
|
||||
|
||||
SaveFileDialog saveFileDialog1 = new SaveFileDialog();
|
||||
|
||||
saveFileDialog1.FileName = "PressureReport.csv";
|
||||
saveFileDialog1.Filter = "CSV Files | *.csv";
|
||||
saveFileDialog1.DefaultExt = "csv";
|
||||
saveFileDialog1.FilterIndex = 2;
|
||||
saveFileDialog1.RestoreDirectory = true;
|
||||
|
||||
if(saveFileDialog1.ShowDialog() == System.Windows.Forms.DialogResult.OK)
|
||||
{
|
||||
using (CSVExporter ex = new CSVExporter(saveFileDialog1.FileName, ChxItemized.IsChecked))
|
||||
{
|
||||
// Pass over the document and domain type to the exporter.
|
||||
NetworkInfo netInfo = m_networks[idx];
|
||||
ex.Document = netInfo.Document;
|
||||
ex.DomainType = netInfo.DomainType;
|
||||
netInfo.ExportCSV(ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,270 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using Autodesk.Revit.DB;
|
||||
using Autodesk.Revit.DB.Analysis;
|
||||
|
||||
namespace Revit.SDK.Samples.NetworkPressureLossReport
|
||||
{
|
||||
public class NetworkInfo
|
||||
{
|
||||
private Document m_doc;
|
||||
private string m_name; // A recognizable name from design system or fabrication service.
|
||||
private double m_maxFlow; // The maximum flow value of any segment on the entire network.
|
||||
private string m_flow;
|
||||
private ConnectorDomainType m_domainType;
|
||||
private IDictionary<int, SectionInfo> m_sections;
|
||||
|
||||
public NetworkInfo(Document doc)
|
||||
{
|
||||
m_doc = doc;
|
||||
m_maxFlow = 0.0;
|
||||
m_flow = null;
|
||||
m_domainType = ConnectorDomainType.Undefined;
|
||||
m_sections = new SortedDictionary<int, SectionInfo>();
|
||||
}
|
||||
public int NumberOfSections
|
||||
{
|
||||
get { return m_sections.Count; }
|
||||
}
|
||||
public Document Document
|
||||
{
|
||||
get { return m_doc; }
|
||||
}
|
||||
public string Name
|
||||
{
|
||||
get { return m_name; }
|
||||
set { m_name = value; }
|
||||
}
|
||||
|
||||
public string FlowDisplay
|
||||
{
|
||||
get { return m_flow; }
|
||||
}
|
||||
|
||||
public ConnectorDomainType DomainType
|
||||
{
|
||||
get { return m_domainType; }
|
||||
set { m_domainType = value; }
|
||||
}
|
||||
|
||||
public static IList<NetworkInfo> FindValidNetworks(Document doc)
|
||||
{
|
||||
IList<NetworkInfo> validNetworks = new List<NetworkInfo>();
|
||||
|
||||
HashSet<MEPNetworkSegmentId> visitedSegments = new HashSet<MEPNetworkSegmentId>(new CompareNetworkSegmentId());
|
||||
|
||||
// Find all elements that may drive the pipe or duct flow calculations.
|
||||
List<BuiltInCategory> categories = new List<BuiltInCategory>();
|
||||
categories.Add(BuiltInCategory.OST_MechanicalEquipment);
|
||||
categories.Add(BuiltInCategory.OST_PlumbingEquipment);
|
||||
categories.Add(BuiltInCategory.OST_DuctTerminal);
|
||||
|
||||
ElementMulticategoryFilter multiCatFilter = new ElementMulticategoryFilter(categories);
|
||||
FilteredElementCollector elemCollector = new FilteredElementCollector(doc).WherePasses(multiCatFilter).WhereElementIsNotElementType();
|
||||
foreach (Element elem in elemCollector.ToElements())
|
||||
{
|
||||
MEPAnalyticalModelData data = MEPAnalyticalModelData.GetMEPAnalyticalModelData(elem);
|
||||
if (data == null)
|
||||
continue;
|
||||
|
||||
int nSeg = data.GetNumberOfSegments();
|
||||
for (int ii = 0; ii < nSeg; ii++)
|
||||
{
|
||||
MEPAnalyticalSegment seg = data.GetSegmentByIndex(ii);
|
||||
MEPNetworkSegmentId idSegment = new MEPNetworkSegmentId(elem.Id, seg.Id);
|
||||
if (visitedSegments.Contains(idSegment))
|
||||
continue;
|
||||
|
||||
// Start from this analytical segment to traverse the entire network.
|
||||
NetworkInfo newNetwork = new NetworkInfo(doc);
|
||||
newNetwork.DomainType = seg.DomainType;
|
||||
|
||||
// First start from the side of the start node.
|
||||
MEPAnalyticalNode startNode = data.GetNodeById(seg.StartNode);
|
||||
MEPNetworkIterator iter = new MEPNetworkIterator(doc, startNode, seg);
|
||||
for (iter.Start(); !iter.End(); iter.Next())
|
||||
{
|
||||
MEPAnalyticalSegment currentSegment = iter.GetAnalyticalSegment();
|
||||
if (currentSegment == null)
|
||||
continue;
|
||||
|
||||
MEPAnalyticalModelData currentModelData = iter.GetAnalyticalModelData();
|
||||
if (currentModelData == null)
|
||||
continue;
|
||||
|
||||
// Mark this segment so not to create the duplicate network.
|
||||
MEPNetworkSegmentId currentSegmentId = new MEPNetworkSegmentId(currentSegment.RevitElementId, currentSegment.Id);
|
||||
visitedSegments.Add(currentSegmentId);
|
||||
|
||||
MEPNetworkSegmentData segFlowData = currentModelData.GetSegmentData(currentSegment.Id);
|
||||
// Grow the network information by filling in one segment.
|
||||
newNetwork.AddSegment(currentSegment, segFlowData);
|
||||
|
||||
// Refine the network name based on the straight segments.
|
||||
if (currentSegment.SegmentType == MEPAnalyticalSegmentType.Segment)
|
||||
newNetwork.RefineName(currentSegment.RevitElementId);
|
||||
}
|
||||
|
||||
// If this is not a close loop, we must include the other side as well!
|
||||
MEPAnalyticalNode endNode = data.GetNodeById(seg.EndNode);
|
||||
iter = new MEPNetworkIterator(doc, endNode, seg);
|
||||
for (iter.Start(); !iter.End(); iter.Next())
|
||||
{
|
||||
MEPAnalyticalSegment currentSegment = iter.GetAnalyticalSegment();
|
||||
if (currentSegment == null)
|
||||
continue;
|
||||
MEPNetworkSegmentId currentSegmentId = new MEPNetworkSegmentId(currentSegment.RevitElementId, currentSegment.Id);
|
||||
// Check if the segment was already visited.
|
||||
if (visitedSegments.Contains(currentSegmentId))
|
||||
continue;
|
||||
visitedSegments.Add(currentSegmentId);
|
||||
|
||||
MEPAnalyticalModelData currentModelData = iter.GetAnalyticalModelData();
|
||||
if (currentModelData == null)
|
||||
continue;
|
||||
MEPNetworkSegmentData segFlowData = currentModelData.GetSegmentData(currentSegment.Id);
|
||||
newNetwork.AddSegment(currentSegment, segFlowData);
|
||||
if (currentSegment.SegmentType == MEPAnalyticalSegmentType.Segment)
|
||||
newNetwork.RefineName(currentSegment.RevitElementId);
|
||||
}
|
||||
|
||||
// Collect this new network
|
||||
if (newNetwork.NumberOfSections > 0)
|
||||
{
|
||||
newNetwork.ResetFlowDisplay();
|
||||
validNetworks.Add(newNetwork);
|
||||
}
|
||||
}
|
||||
}
|
||||
return validNetworks;
|
||||
}
|
||||
|
||||
public void AddSegment(MEPAnalyticalSegment segment, MEPNetworkSegmentData segmentData)
|
||||
{
|
||||
int sectionNumber = segmentData.SectionNumber;
|
||||
// The equipment segment may not belong to any section. Skip those?!
|
||||
if (sectionNumber < 0)
|
||||
return;
|
||||
|
||||
double segmentFlow = Math.Abs(segmentData.Flow);
|
||||
if (segmentFlow > m_maxFlow)
|
||||
m_maxFlow = segmentFlow;
|
||||
|
||||
if (!m_sections.ContainsKey(sectionNumber))
|
||||
{
|
||||
m_sections.Add(sectionNumber, new SectionInfo());
|
||||
}
|
||||
SegmentInfo newSegmentInfo = m_sections[sectionNumber].AddSegment(m_doc, segment, segmentData);
|
||||
}
|
||||
|
||||
private void RefineName(ElementId idElem)
|
||||
{
|
||||
Element elem = m_doc.GetElement(idElem);
|
||||
MEPCurve aCurve = elem as MEPCurve;
|
||||
if (aCurve != null)
|
||||
{
|
||||
MEPSystem sys = aCurve.MEPSystem;
|
||||
if (sys != null)
|
||||
{
|
||||
AppendName(sys.Name);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
FabricationPart aPart = elem as FabricationPart;
|
||||
if (aPart != null)
|
||||
{
|
||||
string serviceName = aPart.ServiceName;
|
||||
// Get the full name of fabrication service by its id.
|
||||
FabricationConfiguration fabConfig = FabricationConfiguration.GetFabricationConfiguration(m_doc);
|
||||
if (fabConfig != null)
|
||||
{
|
||||
FabricationService fabService = fabConfig.GetService(aPart.ServiceId);
|
||||
if (fabService != null)
|
||||
{
|
||||
serviceName = fabService.Name;
|
||||
}
|
||||
}
|
||||
AppendName(serviceName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void AppendName(string name)
|
||||
{
|
||||
if (string.IsNullOrEmpty(m_name))
|
||||
{
|
||||
m_name = name;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!m_name.Contains(name))
|
||||
{
|
||||
m_name += " + " + name;
|
||||
}
|
||||
}
|
||||
}
|
||||
private void ResetFlowDisplay()
|
||||
{
|
||||
ForgeTypeId specId = SpecTypeId.Flow;
|
||||
if (DomainType == ConnectorDomainType.Hvac)
|
||||
specId = SpecTypeId.AirFlow;
|
||||
|
||||
// Reset the flow display value based on the maximum number after adding all segments.
|
||||
m_flow = UnitFormatUtils.Format(m_doc.GetUnits(), specId, m_maxFlow, false);
|
||||
}
|
||||
|
||||
public void ExportCSV(CSVExporter ex)
|
||||
{
|
||||
// Export the header line.
|
||||
string str = string.Format("Section, Type/No, Element, Flow ({0}), Size/Hydraulic Diameter ({1}), Velocity ({2}), Velocity Pressure ({3}), Length ({4}), Coefficients, Friction ({5}), Pressure Loss ({3}), Section Pressure Loss ({3})",
|
||||
ex.GetFlowUnitSymbol(), ex.GetSizeUnitSymbol(), ex.GetVelocityUnitSymbol(), ex.GetPressureUnitSymbol(), ex.GetLengthUnitSymbol(), ex.GetFrictionUnitSymbol());
|
||||
ex.Writer.WriteLine(str);
|
||||
foreach (var item in m_sections)
|
||||
{
|
||||
item.Value.ExportCSV(ex, item.Key);
|
||||
}
|
||||
// Critical path if available
|
||||
double dCriticalLoss = 0.0;
|
||||
string path = null;
|
||||
foreach(var item in m_sections)
|
||||
{
|
||||
if(item.Value.IsCriticalPath)
|
||||
{
|
||||
dCriticalLoss += item.Value.TotalPressureLoss;
|
||||
if(string.IsNullOrEmpty(path))
|
||||
{
|
||||
path = item.Key.ToString();
|
||||
}
|
||||
else
|
||||
{
|
||||
path += @" - " + item.Key.ToString();
|
||||
}
|
||||
}
|
||||
}
|
||||
ex.Writer.WriteLine(string.Format("Critical Pressure Loss: {0}, {1}", path, dCriticalLoss));
|
||||
}
|
||||
public void UpdateView(AVFViewer viewer)
|
||||
{
|
||||
List<XYZ> points = new List<XYZ>();
|
||||
List<VectorAtPoint> valList = new List<VectorAtPoint>();
|
||||
|
||||
// Safety check.
|
||||
if (m_maxFlow < 0.0000001)
|
||||
return;
|
||||
|
||||
foreach (var item in m_sections)
|
||||
{
|
||||
int sectionNum = item.Key;
|
||||
item.Value.UpdateView(viewer, points, valList, m_maxFlow);
|
||||
}
|
||||
|
||||
if(points.Count > 0)
|
||||
{
|
||||
viewer.AddData(points, valList);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<RevitAddIns>
|
||||
<AddIn Type="Command">
|
||||
<Assembly>D:\git\revit\RevitAdditions\RevitSDK\Software Development Kit\Samples\NetworkPressureLossReport\CS\bin\Debug\NetworkPressureLossReport.dll</Assembly>
|
||||
<ClientId>a000b64b-a718-48e7-bf5c-7f1f7452490b</ClientId>
|
||||
<FullClassName>Revit.SDK.Samples.NetworkPressureLossReport.Command</FullClassName>
|
||||
<Text>Pressure Loss Report</Text>
|
||||
<Description>Report the pressure loss for the network flow calculation.</Description>
|
||||
<VisibilityMode>AlwaysVisible</VisibilityMode>
|
||||
<VendorId>ADSK</VendorId>
|
||||
<VendorDescription>Autodesk, www.autodesk.com</VendorDescription>
|
||||
</AddIn>
|
||||
</RevitAddIns>
|
||||
@@ -0,0 +1,105 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProductVersion>9.0.30729</ProductVersion>
|
||||
<SchemaVersion>2.0</SchemaVersion>
|
||||
<ProjectGuid>{D9F2AB5B-1348-421A-9B08-9B4ED74A82CE}</ProjectGuid>
|
||||
<OutputType>Library</OutputType>
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>Revit.SDK.Samples.NetworkPressureLossReport.CS</RootNamespace>
|
||||
<AssemblyName>NetworkPressureLossReport</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.8</TargetFrameworkVersion>
|
||||
<TargetFrameworkProfile />
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>bin\Debug\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<Prefer32Bit>false</Prefer32Bit>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>bin\Release\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<Prefer32Bit>false</Prefer32Bit>
|
||||
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<OutputPath>bin\x64\Debug\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<DebugType>full</DebugType>
|
||||
<PlatformTarget>x64</PlatformTarget>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
|
||||
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'">
|
||||
<OutputPath>bin\x64\Release\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<Optimize>true</Optimize>
|
||||
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<PlatformTarget>x64</PlatformTarget>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<RunPostBuildEvent>OnOutputUpdated</RunPostBuildEvent>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="PresentationCore" />
|
||||
<Reference Include="PresentationFramework" />
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Data" />
|
||||
<Reference Include="System.Windows.Forms" />
|
||||
<Reference Include="System.Xaml" />
|
||||
<Reference Include="System.Xml" />
|
||||
<Reference Include="System.Core">
|
||||
<RequiredTargetFramework>3.5</RequiredTargetFramework>
|
||||
</Reference>
|
||||
<Reference Include="WindowsBase" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="AVFViewer.cs" />
|
||||
<Compile Include="Command.cs" />
|
||||
<Compile Include="CSVExporter.cs" />
|
||||
<Compile Include="NetworkInfo.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="SectionInfo.cs" />
|
||||
<Compile Include="SegmentInfo.cs" />
|
||||
<Compile Include="NetworkDialog.xaml.cs">
|
||||
<DependentUpon>NetworkDialog.xaml</DependentUpon>
|
||||
</Compile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Page Include="NetworkDialog.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
</ItemGroup>
|
||||
<Import Project="$(SolutionDir)VSProps\SDKSamples.targets" />
|
||||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||
Other similar extension points exist, see Microsoft.Common.targets.
|
||||
<Target Name="BeforeBuild">
|
||||
</Target>
|
||||
<Target Name="AfterBuild">
|
||||
</Target>
|
||||
-->
|
||||
<PropertyGroup>
|
||||
<PostBuildEvent>set FILEFORSAMPLEREG="$(SolutionDir)..\..\..\..\Regression\API\SDKSamples\UpdateSampleDllForRegression.py"
|
||||
if exist %25FILEFORSAMPLEREG%25 py -3 %25FILEFORSAMPLEREG%25 "$(ProjectPath)" "$(TargetPath)" "$(SolutionDir)"</PostBuildEvent>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<ResolveAssemblyWarnOrErrorOnTargetArchitectureMismatch>None</ResolveAssemblyWarnOrErrorOnTargetArchitectureMismatch>
|
||||
</PropertyGroup>
|
||||
</Project>
|
||||
@@ -0,0 +1,58 @@
|
||||
//
|
||||
// (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.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
// General Information about an assembly is controlled through the following
|
||||
// set of attributes. Change these attribute values to modify the information
|
||||
// associated with an assembly.
|
||||
[assembly: AssemblyTitle("NetworkPressureLossReport")]
|
||||
[assembly: AssemblyDescription("Report the pressure loss in the network flow calculation")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("Autodesk")]
|
||||
[assembly: AssemblyProduct("NetworkPressureLossReport")]
|
||||
[assembly: AssemblyCopyright("Copyright © Autodesk, Inc. 2022")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
|
||||
// Setting ComVisible to false makes the types in this assembly not visible
|
||||
// to COM components. If you need to access a type in this assembly from
|
||||
// COM, set the ComVisible attribute to true on that type.
|
||||
[assembly: ComVisible(false)]
|
||||
|
||||
// The following GUID is for the ID of the typelib if this project is exposed to COM
|
||||
[assembly: Guid("72ce761f-210a-40ce-ae47-e75e1356af1f")]
|
||||
|
||||
// Version information for an assembly consists of the following four values:
|
||||
//
|
||||
// Major Version
|
||||
// Minor Version
|
||||
// Build Number
|
||||
// Revision
|
||||
//
|
||||
// You can specify all the values or you can default the Revision and Build Numbers
|
||||
// by using the '*' as shown below:
|
||||
[assembly: AssemblyVersion("1.0.0.0")]
|
||||
[assembly: AssemblyFileVersion("1.0.0.0")]
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,169 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Autodesk.Revit.DB;
|
||||
using Autodesk.Revit.DB.Analysis;
|
||||
|
||||
namespace Revit.SDK.Samples.NetworkPressureLossReport
|
||||
{
|
||||
internal class SectionInfo
|
||||
{
|
||||
private double m_totalLoss;
|
||||
private IList<SegmentInfo> m_segments;
|
||||
const double Epsilon = 0.0001; // The small tolerance within which two flow values may be considered equal.
|
||||
|
||||
public SectionInfo()
|
||||
{
|
||||
m_totalLoss = 0.0;
|
||||
m_segments = new List<SegmentInfo>();
|
||||
}
|
||||
public double TotalPressureLoss
|
||||
{
|
||||
get { return m_totalLoss; }
|
||||
set { m_totalLoss = value; }
|
||||
}
|
||||
public int NumberOfSegments
|
||||
{
|
||||
get { return m_segments.Count; }
|
||||
}
|
||||
public int NumberOfStraights
|
||||
{
|
||||
get { return m_segments.Count(x => x.SegmentType == MEPAnalyticalSegmentType.Segment); }
|
||||
}
|
||||
public int NumberOfFittingsOrAccessories
|
||||
{
|
||||
get { return m_segments.Count(x => x.SegmentType == MEPAnalyticalSegmentType.Fitting); }
|
||||
}
|
||||
public double Flow
|
||||
{
|
||||
get { return m_segments.FirstOrDefault().Flow; }
|
||||
}
|
||||
public double Size
|
||||
{
|
||||
get { return m_segments.FirstOrDefault().Size; }
|
||||
}
|
||||
public double Velocity
|
||||
{
|
||||
get { return m_segments.FirstOrDefault().Velocity; }
|
||||
}
|
||||
public double VelocityPressure
|
||||
{
|
||||
get { return m_segments.FirstOrDefault().VelocityPressure; }
|
||||
}
|
||||
public double Friction
|
||||
{
|
||||
get { return m_segments.FirstOrDefault().Friction; }
|
||||
}
|
||||
public bool IsCriticalPath
|
||||
{
|
||||
get { return m_segments.FirstOrDefault().IsCriticalPath; }
|
||||
}
|
||||
|
||||
public SegmentInfo AddSegment(Document doc, MEPAnalyticalSegment segment, MEPNetworkSegmentData segmentData)
|
||||
{
|
||||
SegmentInfo newSegmentInfo = new SegmentInfo(doc, segment, segmentData);
|
||||
m_segments.Add(newSegmentInfo);
|
||||
return newSegmentInfo;
|
||||
}
|
||||
|
||||
public void ExportCSV(CSVExporter ex, int sectionNumber)
|
||||
{
|
||||
// "Section, Type/No, Element, Flow, Size, Velocity, Velocity Pressure, Length, Coefficients, Friction, Pressure Loss, Section Pressure Loss");
|
||||
string sNull = null;
|
||||
int straightCount = 0, fittingCount = 0;
|
||||
double totalStraightLength = 0.0;
|
||||
double totalFittingCoeff = 0.0;
|
||||
double totalStraightLoss = 0.0;
|
||||
double totalFittingLoss = 0.0;
|
||||
|
||||
foreach (SegmentInfo segInfo in m_segments)
|
||||
{
|
||||
if (ex.IsItemized == true)
|
||||
{
|
||||
ex.Writer.WriteLine(string.Format("{0}, {1}, {2}, {3}, {4}, {5}, {6}, {7}, {8}, {9}, {10}, {11}",
|
||||
sectionNumber, segInfo.SegmentType, segInfo.Id, ex.ConvertFromInternalFlow(segInfo.Flow), ex.ConvertFromInternalSize(segInfo.Size),
|
||||
ex.ConvertFromInternalVelocity(segInfo.Velocity), ex.ConvertFromInternalPressure(segInfo.VelocityPressure), ex.ConvertFromInternalLength(segInfo.Length),
|
||||
segInfo.Coefficients, ex.ConvertFromInternalFriction(segInfo.Friction), ex.ConvertFromInternalPressure(segInfo.PressureDrop), sNull));
|
||||
}
|
||||
if (segInfo.SegmentType == MEPAnalyticalSegmentType.Segment)
|
||||
{
|
||||
straightCount++;
|
||||
totalStraightLength += segInfo.Length;
|
||||
totalStraightLoss += segInfo.PressureDrop;
|
||||
}
|
||||
else if (segInfo.SegmentType == MEPAnalyticalSegmentType.Fitting)
|
||||
{
|
||||
fittingCount++;
|
||||
totalFittingCoeff += segInfo.Coefficients;
|
||||
totalFittingLoss = segInfo.PressureDrop;
|
||||
}
|
||||
}
|
||||
TotalPressureLoss = totalStraightLoss + totalFittingLoss;
|
||||
|
||||
// "Section, Type/No, Element, Flow, Size, Velocity, Velocity Pressure, Length, Coefficients, Friction, Pressure Loss, Section Pressure Loss");
|
||||
ex.Writer.WriteLine(string.Format("{0}, {1}, Straights, {2}, {3}, {4}, {5}, {6}, {7}, {8}, {9}, {10}",
|
||||
sectionNumber, straightCount, ex.ConvertFromInternalFlow(Flow), ex.ConvertFromInternalSize(Size),
|
||||
ex.ConvertFromInternalVelocity(Velocity), sNull, ex.ConvertFromInternalLength(totalStraightLength), sNull,
|
||||
ex.ConvertFromInternalFriction(Friction), ex.ConvertFromInternalPressure(totalStraightLoss), sNull));
|
||||
|
||||
ex.Writer.WriteLine(string.Format("{0}, {1}, Fittings, {2}, {3}, {4}, {5}, {6}, {7}, {8}, {9}, {10}",
|
||||
sectionNumber, fittingCount, ex.ConvertFromInternalFlow(Flow), ex.ConvertFromInternalSize(Size),
|
||||
ex.ConvertFromInternalVelocity(Velocity), ex.ConvertFromInternalPressure(VelocityPressure), sNull,
|
||||
totalFittingCoeff, sNull, ex.ConvertFromInternalPressure(totalFittingLoss), ex.ConvertFromInternalPressure(TotalPressureLoss)));
|
||||
}
|
||||
public void UpdateView(AVFViewer viewer, List<XYZ> points, List<VectorAtPoint> valList, double maxFlow)
|
||||
{
|
||||
double coeff = viewer.Scale / 12.0;
|
||||
|
||||
double maxX = -Double.MaxValue;
|
||||
double maxY = -Double.MaxValue;
|
||||
double maxZ = -Double.MaxValue;
|
||||
|
||||
foreach (SegmentInfo seg in m_segments)
|
||||
{
|
||||
// With the flow value being the scaled vector length, the fittings typically get much longer vector than its actual length.
|
||||
// As such, we skip the fitting flow display.
|
||||
if (seg.SegmentType != MEPAnalyticalSegmentType.Segment)
|
||||
continue;
|
||||
|
||||
// Skip the zero flow segments.
|
||||
if (seg.Flow < 0.0000001)
|
||||
continue;
|
||||
|
||||
XYZ p0 = seg.Start;
|
||||
XYZ p1 = seg.End;
|
||||
|
||||
maxX = Math.Max(Math.Max(maxX, p0.X), p1.X);
|
||||
maxY = Math.Max(Math.Max(maxY, p0.Y), p1.Y);
|
||||
maxZ = Math.Max(Math.Max(maxZ, p0.Z), p1.Z);
|
||||
|
||||
points.Add(p1);
|
||||
|
||||
List<XYZ> xyzList = new List<XYZ>();
|
||||
XYZ vec = (p1 - p0) / coeff; // This is the exact segment length at the current view scale.
|
||||
|
||||
// Convert the vector length to the flow value in scale.
|
||||
vec = vec.Normalize();
|
||||
vec *= seg.Flow / maxFlow;
|
||||
|
||||
xyzList.Add(vec) ;
|
||||
|
||||
valList.Add(new VectorAtPoint(xyzList));
|
||||
|
||||
if (points.Count >= 1000) // 1000 is the limit on the number of points for one spatial field primitive
|
||||
viewer.AddData(points, valList);
|
||||
|
||||
// Only display the first segment in the section unless checked "Itemized", since the flow value and direction are the same in one section.
|
||||
if (!viewer.IsItemized)
|
||||
break;
|
||||
}
|
||||
|
||||
viewer.AddCorner(maxX, maxY, maxZ);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,136 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Autodesk.Revit.DB;
|
||||
using Autodesk.Revit.DB.Analysis;
|
||||
|
||||
namespace Revit.SDK.Samples.NetworkPressureLossReport
|
||||
{
|
||||
internal class SegmentInfo
|
||||
{
|
||||
private MEPNetworkSegmentId m_id;
|
||||
private MEPAnalyticalSegmentType m_segmentType;
|
||||
private bool m_isCriticalPath;
|
||||
private double m_length;
|
||||
private double m_size;
|
||||
private double m_flow;
|
||||
private double m_velocity;
|
||||
private double m_velocityPressure;
|
||||
private double m_coefficients;
|
||||
private double m_pressureDrop;
|
||||
private double m_reynolds;
|
||||
private XYZ m_startPt;
|
||||
private XYZ m_endPt;
|
||||
const double Tolerance = 0.0000001;
|
||||
|
||||
public double Flow
|
||||
{
|
||||
get { return m_flow; }
|
||||
}
|
||||
public double PressureDrop
|
||||
{
|
||||
get { return m_pressureDrop; }
|
||||
}
|
||||
public MEPAnalyticalSegmentType SegmentType
|
||||
{
|
||||
get { return m_segmentType; }
|
||||
}
|
||||
public bool IsCriticalPath
|
||||
{
|
||||
get { return m_isCriticalPath; }
|
||||
}
|
||||
public string Id
|
||||
{
|
||||
get { return m_id.ElementId.ToString() + @"_" + m_id.SegmentId.ToString(); }
|
||||
}
|
||||
public ElementId RevitElementId
|
||||
{
|
||||
get { return m_id.ElementId; }
|
||||
}
|
||||
public double Length
|
||||
{
|
||||
get { return m_length; }
|
||||
}
|
||||
public double Size
|
||||
{
|
||||
get { return m_size; }
|
||||
}
|
||||
public double Velocity
|
||||
{
|
||||
get { return m_velocity; }
|
||||
}
|
||||
public double VelocityPressure
|
||||
{
|
||||
get { return m_velocityPressure; }
|
||||
}
|
||||
public double Coefficients
|
||||
{
|
||||
get { return m_coefficients; }
|
||||
}
|
||||
public double Friction
|
||||
{
|
||||
get { return m_length < Tolerance ? 0.0 : m_pressureDrop / m_length; }
|
||||
}
|
||||
public double ReynoldsNumber
|
||||
{
|
||||
get { return m_reynolds; }
|
||||
}
|
||||
public XYZ Start
|
||||
{
|
||||
get { return m_startPt; }
|
||||
}
|
||||
public XYZ End
|
||||
{
|
||||
get { return m_endPt; }
|
||||
}
|
||||
public SegmentInfo(Document doc, MEPAnalyticalSegment seg, MEPNetworkSegmentData data)
|
||||
{
|
||||
m_id = new MEPNetworkSegmentId(seg.RevitElementId, seg.Id);
|
||||
|
||||
// Be aware that the flow and pressure may be negative.
|
||||
// It means the flow is from the end node to the start node.
|
||||
m_segmentType = seg.SegmentType;
|
||||
m_size = seg.InnerDiameter; // Hydraulic diameter for rectangular or oval profile.
|
||||
m_flow = Math.Abs(data.Flow);
|
||||
m_pressureDrop = data.Flow > 0 ? data.PressureDrop : -1 * data.PressureDrop;
|
||||
|
||||
m_velocity = Math.Abs(data.Velocity);
|
||||
m_velocityPressure = Math.Abs(data.VelocityPressure);
|
||||
m_coefficients = data.Coefficient;
|
||||
m_isCriticalPath = data.IsCriticalPath;
|
||||
m_reynolds = data.ReynoldsNumber;
|
||||
|
||||
m_length = 0.0;
|
||||
Element thisElem = doc.GetElement(seg.RevitElementId);
|
||||
if (thisElem != null)
|
||||
{
|
||||
MEPAnalyticalModelData thisModel = MEPAnalyticalModelData.GetMEPAnalyticalModelData(thisElem);
|
||||
MEPAnalyticalNode start = thisModel.GetNodeById(seg.StartNode);
|
||||
MEPAnalyticalNode end = thisModel.GetNodeById(seg.EndNode);
|
||||
if (start != null && end != null)
|
||||
{
|
||||
m_startPt = data.Flow > 0 ? start.Location : end.Location;
|
||||
m_endPt = data.Flow > 0 ? end.Location : start.Location;
|
||||
m_length = m_startPt.DistanceTo(m_endPt);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal class CompareNetworkSegmentId : IEqualityComparer<MEPNetworkSegmentId>
|
||||
{
|
||||
public bool Equals(MEPNetworkSegmentId left, MEPNetworkSegmentId right)
|
||||
{
|
||||
return left.ElementId == right.ElementId
|
||||
&& left.SegmentId == right.SegmentId;
|
||||
}
|
||||
|
||||
public int GetHashCode(MEPNetworkSegmentId idSeg)
|
||||
{
|
||||
// A simple way to combine the element id and segment id into one hash code.
|
||||
int hash = 17;
|
||||
hash = hash * 31 + idSeg.ElementId.GetHashCode();
|
||||
hash = hash * 31 + idSeg.SegmentId.GetHashCode();
|
||||
return hash;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user