├── CypherToPowerBI.pbix ├── HLApps.MEPGraph ├── packages.config ├── Model │ ├── MEPEdgeTypes.cs │ ├── Edge.cs │ ├── Node.cs │ └── pocos.cs ├── IGraphDBClient.cs ├── Properties │ └── AssemblyInfo.cs ├── HLApps.MEPGraph.csproj └── Neo4j │ └── Neo4jClient.cs ├── README.md ├── HLApps.Revit.Graph ├── Parameters │ ├── IHLPeramiter.cs │ ├── HLRevitElementName.cs │ ├── HLRevitElementProperty.cs │ ├── HLRevitReadonlyTextData.cs │ └── HLRevitParameter.cs ├── Graph │ ├── ConnectorPointGeometrySegment.cs │ ├── MEPConnector.cs │ ├── Parsers │ │ ├── IMEPGraphElementScanner.cs │ │ ├── MEPGraphParserBase.cs │ │ ├── FaceIntersectRay.cs │ │ ├── MEPGraphParserElectrical.cs │ │ └── SpaceToDoorPathScanner.cs │ ├── MEPPathWriteCache.cs │ ├── MEPPathDirectionEnum.cs │ ├── MEPPathSection.cs │ ├── MEPGraphUtils.cs │ ├── MEPRevitGraphWriter.cs │ ├── MEPNodeEdge.cs │ ├── MEPPathNode.cs │ └── MEPGraphWriter.cs ├── Utils │ ├── MEPUtils.cs │ ├── DocUtils.cs │ ├── RevitElementExtensions.cs │ └── GeoUtils.cs ├── Geometry │ ├── GeometrySegment.cs │ ├── SolidGeometrySegment.cs │ ├── PointGeometrySegment.cs │ ├── CurveGeometrySegment.cs │ ├── Octree │ │ ├── PointOctreeElementWriter.cs │ │ ├── BoundsOctreeElementWriter.cs │ │ ├── PointOctree.cs │ │ └── BoundsOctree.cs │ └── HLBoundingBoxXYZ.cs ├── RevitToGraphPublisherSettings.cs ├── Properties │ └── AssemblyInfo.cs ├── RevitToGraphPublisher.cs └── HLApps.Revit.Graph.csproj ├── HLApps.Revit.Graph.UIAddin ├── HLApps.Revit.Graph.addin ├── UI │ ├── GraphAppWindow.xaml.cs │ ├── ViewModel │ │ ├── BaseViewModel.cs │ │ ├── GraphAppViewModel.cs │ │ └── Command.cs │ └── GraphAppWindow.xaml ├── GraphAppShowCommand.cs ├── Properties │ └── AssemblyInfo.cs ├── GraphApp.cs └── HLApps.Revit.Graph.UIAddin.csproj ├── HLApps.RevitBuildConfigurations ├── RevitBuildConfigurations.projitems ├── HLApps.RevitBuildConfigurations.shproj ├── Imports.targets ├── LocalDebugAddin.targets └── BuildConfigurations.targets ├── LICENSE ├── .gitignore └── RevitToGraphDB.sln /CypherToPowerBI.pbix: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/willhl/GraphData-MEP/HEAD/CypherToPowerBI.pbix -------------------------------------------------------------------------------- /HLApps.MEPGraph/packages.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | # SUPERSEDED 4 | 5 | **This repository has been superseded by the Building Graph:** 6 | 7 | https://github.com/willhl/BuildingGraph-Client-Revit 8 | 9 | This is a new(er) initiative which includes a GraphQL server built using GRANDstack, as well as the same direct Neo4j connections from this project. 10 | 11 | -------------------------------------------------------------------------------- /HLApps.Revit.Graph/Parameters/IHLPeramiter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | 6 | namespace HLApps.Revit.Parameters 7 | { 8 | public interface IHLPeramiter 9 | { 10 | 11 | string Name { get; } 12 | 13 | object Value { get; set; } 14 | 15 | Type ExpectedType { get; } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /HLApps.MEPGraph/Model/MEPEdgeTypes.cs: -------------------------------------------------------------------------------- 1 | namespace HLApps.MEPGraph.Model 2 | { 3 | public enum MEPEdgeTypes 4 | { 5 | IS_IN, 6 | IS_IN_SPACE, 7 | IS_OF, 8 | IS_ON, 9 | CABLETRAY_FLOW_TO, 10 | ELECTRICAL_FLOW_TO, 11 | AIR_FLOW_TO, 12 | HYDRONIC_FLOW_TO, 13 | FLOWS_TO, 14 | FLOWS_TO_SPACE, 15 | BOUNDED_BY, 16 | DERIVED_BY, 17 | REALIZED_BY, 18 | ABSTRACTED_BY 19 | 20 | } 21 | 22 | } 23 | -------------------------------------------------------------------------------- /HLApps.MEPGraph/IGraphDBClient.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using HLApps.MEPGraph.Model; 3 | 4 | namespace HLApps.MEPGraph 5 | { 6 | public interface IGraphDBClient 7 | { 8 | void Dispose(); 9 | long Push(Node node, Dictionary variables); 10 | void Relate(long fromNodeId, long toNodeId, MEPEdgeTypes relType, Dictionary variables); 11 | void Relate(Node fromNode, Node toNode, string relType, Dictionary variables); 12 | } 13 | } -------------------------------------------------------------------------------- /HLApps.Revit.Graph.UIAddin/HLApps.Revit.Graph.addin: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Revit To Graph 5 | HLApps.Revit\HLApps.Revit.Graph.UIAddin.dll 6 | 5EE88C10-F682-4A48-8975-CB5652917F6B 7 | HLApps.Revit.Graph.UIAddin.GraphApp 8 | HLEA 9 | Will Reynolds @ Hoare Lea 10 | 11 | -------------------------------------------------------------------------------- /HLApps.Revit.Graph/Graph/ConnectorPointGeometrySegment.cs: -------------------------------------------------------------------------------- 1 | 2 | using Autodesk.Revit.DB; 3 | using HLApps.Revit.Geometry; 4 | 5 | namespace HLApps.Revit.Graph 6 | { 7 | 8 | public class ConnectorPointGeometrySegment : PointGeometrySegment 9 | { 10 | public ConnectorPointGeometrySegment(ElementId element, XYZ point, int Connectorindex) : base(element, point) 11 | { 12 | ConnectorIndex = Connectorindex; 13 | } 14 | 15 | public int ConnectorIndex { get; set; } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /HLApps.Revit.Graph/Graph/MEPConnector.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | using Autodesk.Revit.DB; 8 | 9 | namespace HLApps.Revit.Graph 10 | { 11 | public abstract class MEPConnector 12 | { 13 | 14 | public XYZ Origin { get; set; } 15 | 16 | } 17 | 18 | 19 | 20 | public class RevitConnector : MEPConnector 21 | { 22 | 23 | 24 | } 25 | 26 | public class VirtualConnector : MEPConnector 27 | { 28 | 29 | 30 | } 31 | 32 | } 33 | -------------------------------------------------------------------------------- /HLApps.Revit.Graph/Graph/Parsers/IMEPGraphElementScanner.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using Autodesk.Revit.DB; 3 | using HLApps.Revit.Geometry; 4 | using HLApps.Revit.Geometry.Octree; 5 | 6 | namespace HLApps.Revit.Graph.Parsers 7 | { 8 | public interface IMEPGraphElementScanner 9 | { 10 | void Initialise(ICollection geoSerchElements, BoundsOctree geo); 11 | void ScanFromDocument(Document doc, MEPRevitGraph graph, int maxDepth); 12 | void ScanFromElement(Element elm, MEPRevitGraph graph, int maxDepth); 13 | } 14 | } -------------------------------------------------------------------------------- /HLApps.Revit.Graph/Graph/Parsers/MEPGraphParserBase.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using Autodesk.Revit.DB; 3 | 4 | namespace HLApps.Revit.Graph.Parsers 5 | { 6 | public interface IRevitGraphParser 7 | { 8 | bool CanParse(Element elm); 9 | ElementFilter GetFilter(); 10 | 11 | void ParseFrom(Element elm, MEPRevitGraphWriter writer); 12 | void ParseFrom(ICollection elm, MEPRevitGraphWriter writer); 13 | 14 | void FinalizeGraph(MEPRevitGraphWriter writer); 15 | void InitializeGraph(MEPRevitGraphWriter writer); 16 | } 17 | 18 | } 19 | -------------------------------------------------------------------------------- /HLApps.Revit.Graph/Graph/MEPPathWriteCache.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using HLApps.Revit.Geometry.Octree; 3 | using HLApps.Revit.Geometry; 4 | using HLApps.Revit.Graph.Parsers; 5 | 6 | namespace HLApps.Revit.Graph 7 | { 8 | 9 | public class MEPPathWriteCache 10 | { 11 | public BoundsOctree geoCache; 12 | public BoundsOctreeElementWriter geoCacheWriter; 13 | public PointOctree connectorsCache; 14 | public PointOctree rayhitCache; 15 | public HashSet ParsedElements; 16 | public double MaxDepth; 17 | } 18 | } 19 | 20 | -------------------------------------------------------------------------------- /HLApps.Revit.Graph/Utils/MEPUtils.cs: -------------------------------------------------------------------------------- 1 | using Autodesk.Revit.DB; 2 | 3 | namespace HLApps.Revit.Utils 4 | { 5 | class MEPUtils 6 | { 7 | public static ConnectorManager GetConnectionManager(Element elm) 8 | { 9 | if (elm is FamilyInstance) 10 | { 11 | return (elm as FamilyInstance).MEPModel.ConnectorManager; 12 | } 13 | else if (elm is MEPCurve) 14 | { 15 | return (elm as MEPCurve).ConnectorManager; 16 | } 17 | else 18 | { 19 | return null; 20 | } 21 | } 22 | 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /HLApps.Revit.Graph/Graph/Parsers/FaceIntersectRay.cs: -------------------------------------------------------------------------------- 1 | using Autodesk.Revit.DB; 2 | 3 | using HLApps.Revit.Geometry; 4 | 5 | namespace HLApps.Revit.Graph.Parsers 6 | { 7 | public class FaceIntersectRay 8 | { 9 | public string IntermediatDocIdent; 10 | public ElementId IntermeidateElement; 11 | public SolidGeometrySegment HittingSegment; 12 | public Element SourceElement; 13 | public Face SourceFace; 14 | public Face HittingFace; 15 | public XYZ RayVecotor; 16 | public UV SourceUV; 17 | public UV HittingUV; 18 | public XYZ SourceXYZ; 19 | public XYZ HittingXYZ; 20 | public SubfaceType SubFaceType; 21 | public double AreaWeight; 22 | public double Distance; 23 | public bool Ignore; 24 | } 25 | 26 | } 27 | -------------------------------------------------------------------------------- /HLApps.Revit.Graph/Geometry/GeometrySegment.cs: -------------------------------------------------------------------------------- 1 | using Autodesk.Revit.DB; 2 | 3 | 4 | namespace HLApps.Revit.Geometry 5 | { 6 | 7 | public abstract class GeometrySegment 8 | { 9 | 10 | public HLBoundingBoxXYZ Bounds { get; set; } 11 | 12 | public string OriginatingDocIdent { get; set; } 13 | public ElementId OriginatingElement { get; set; } 14 | public ElementId OriginatingElementCategory { get; set; } 15 | 16 | public bool Removed { get; set; } 17 | 18 | protected string segId = string.Empty; 19 | public string SegmentId 20 | { 21 | get 22 | { 23 | return segId.ToString(); 24 | } 25 | } 26 | public virtual void Invalidate() 27 | { 28 | Removed = true; 29 | } 30 | } 31 | 32 | } -------------------------------------------------------------------------------- /HLApps.Revit.Graph.UIAddin/UI/GraphAppWindow.xaml.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Windows; 6 | 7 | using HLApps.Revit.Graph.UIAddin.ViewModel; 8 | 9 | namespace HLApps.Revit.Graph.UIAddin 10 | { 11 | internal partial class GraphAppWindow : Window 12 | { 13 | GraphAppViewModel _gappVM; 14 | public GraphAppWindow(GraphAppViewModel gappVM) 15 | { 16 | InitializeComponent(); 17 | 18 | _gappVM = gappVM; 19 | this.DataContext = gappVM; 20 | 21 | pwBox.PasswordChanged += PwBox_PasswordChanged; 22 | } 23 | 24 | private void PwBox_PasswordChanged(object sender, RoutedEventArgs e) 25 | { 26 | _gappVM.Password = pwBox.Password; 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /HLApps.Revit.Graph.UIAddin/UI/ViewModel/BaseViewModel.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.ComponentModel; 5 | 6 | namespace HLApps.Revit.Graph.UIAddin.ViewModel 7 | { 8 | class BaseViewModel : INotifyPropertyChanged 9 | { 10 | 11 | public event PropertyChangedEventHandler PropertyChanged; 12 | 13 | /// 14 | /// Raises the property changed event. 15 | /// 16 | /// Name of the property. 17 | public virtual void NotifyPropertyChanged(string propertyName) 18 | { 19 | // If the event has been subscribed to, fire it. 20 | if (PropertyChanged != null) PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); 21 | } 22 | 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /HLApps.RevitBuildConfigurations/RevitBuildConfigurations.projitems: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | $(MSBuildAllProjects);$(MSBuildThisFileFullPath) 5 | true 6 | 59589e76-d411-4579-810d-a08074e453e7 7 | 8 | 9 | HLApps.RevitBuildConfigurations 10 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /HLApps.MEPGraph/Model/Edge.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace HLApps.MEPGraph.Model 4 | { 5 | public class Edge 6 | { 7 | public virtual string TypeLabel 8 | { 9 | get; set; 10 | } 11 | 12 | public MEPEdgeTypes EdgeType { get; set; } 13 | 14 | 15 | Dictionary _extendedProperties = new Dictionary(); 16 | public Dictionary ExtendedProperties { get => _extendedProperties; } 17 | public virtual Dictionary GetAllProperties() 18 | { 19 | var allProps = new Dictionary(); 20 | 21 | foreach (var kvp in ExtendedProperties) 22 | { 23 | allProps.Add(kvp.Key, kvp.Value); 24 | } 25 | 26 | return allProps; 27 | 28 | } 29 | } 30 | 31 | } 32 | -------------------------------------------------------------------------------- /HLApps.Revit.Graph/RevitToGraphPublisherSettings.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace HLApps.Revit.Graph 8 | { 9 | public class RevitToGraphPublisherSettings 10 | { 11 | public RevitToGraphPublisherSettings() 12 | { 13 | IncludeElectrical = true; 14 | IncludeMechanical = true; 15 | DBHost = "localhost"; 16 | DBPort = 7687; 17 | DBUsername = "neo4j"; 18 | } 19 | 20 | public bool IncludeBoundaries { get; set; } 21 | public bool IncludeMechanical { get; set; } 22 | public bool IncludeElectrical { get; set; } 23 | 24 | public string DBPassword { get; set; } 25 | public string DBUsername { get; set; } 26 | public string DBHost { get; set; } 27 | public int DBPort { get; set; } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /HLApps.Revit.Graph/Geometry/SolidGeometrySegment.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using HLApps.Revit.Utils; 3 | using Autodesk.Revit.DB; 4 | 5 | 6 | namespace HLApps.Revit.Geometry 7 | { 8 | public class SolidGeometrySegment : GeometrySegment 9 | { 10 | public SolidGeometrySegment(Solid geo, Element element, HLBoundingBoxXYZ bounds) 11 | { 12 | Geometry = geo; 13 | OriginatingElement = element.Id; 14 | OriginatingDocIdent = DocUtils.GetDocumentIdent(element.Document); 15 | if (element.Category != null) OriginatingElementCategory = element.Category.Id; 16 | 17 | Bounds = bounds; 18 | 19 | Removed = false; 20 | segId = Guid.NewGuid().ToString(); 21 | } 22 | 23 | public Solid Geometry { get; set; } 24 | public override void Invalidate() 25 | { 26 | Geometry = null; 27 | Removed = true; 28 | } 29 | } 30 | 31 | } -------------------------------------------------------------------------------- /HLApps.Revit.Graph/Graph/MEPPathDirectionEnum.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace HLApps.Revit.Graph 8 | { 9 | public enum MEPPathDirection 10 | { 11 | Indeterminate, 12 | In, 13 | Out, 14 | 15 | } 16 | 17 | 18 | public enum MEPPathConnectionType 19 | { 20 | Phyiscal, 21 | Proximity, 22 | Analytical, 23 | ProximityNoConnector, 24 | SectionOf, 25 | } 26 | 27 | 28 | public enum MEPPathSectionType 29 | { 30 | Section, 31 | Equipment, 32 | Terminal, 33 | Transition, 34 | Accessory, 35 | Space, 36 | Wall, 37 | Window, 38 | Door, 39 | Floor, 40 | Roof, 41 | Lighting, 42 | Electrical, 43 | Data, 44 | Security, 45 | Safety, 46 | 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /HLApps.Revit.Graph/Geometry/PointGeometrySegment.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Autodesk.Revit.DB; 3 | 4 | 5 | namespace HLApps.Revit.Geometry 6 | { 7 | public class PointGeometrySegment : GeometrySegment 8 | { 9 | public PointGeometrySegment(ElementId element, XYZ point) 10 | { 11 | OriginatingElement = element; 12 | Point = point; 13 | Removed = false; 14 | segId = Guid.NewGuid().ToString(); 15 | } 16 | 17 | public PointGeometrySegment(ElementId element, XYZ point, XYZ facing, XYZ hand, bool fflip, bool hflip) : this(element, point) 18 | { 19 | Facing = facing; 20 | Hand = hand; 21 | FacingFlipped = fflip; 22 | HandFlipped = hflip; 23 | } 24 | 25 | public XYZ Point { get; set; } 26 | public XYZ Facing { get; set; } 27 | public XYZ Hand { get; set; } 28 | public bool FacingFlipped { get; private set; } 29 | public bool HandFlipped { get; private set; } 30 | } 31 | 32 | } -------------------------------------------------------------------------------- /HLApps.Revit.Graph.UIAddin/GraphAppShowCommand.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Autodesk.Revit.DB; 3 | using Autodesk.Revit.UI; 4 | 5 | using HLApps.Revit.Graph.UIAddin.ViewModel; 6 | 7 | 8 | namespace HLApps.Revit.Graph.UIAddin 9 | { 10 | [Autodesk.Revit.Attributes.Transaction(Autodesk.Revit.Attributes.TransactionMode.Manual)] 11 | [Autodesk.Revit.Attributes.Regeneration(Autodesk.Revit.Attributes.RegenerationOption.Manual)] 12 | public class GraphAppShowCommand : IExternalCommand 13 | { 14 | public Result Execute(ExternalCommandData cmdData, ref string message, ElementSet elements) 15 | { 16 | Document rDoc = cmdData.Application.ActiveUIDocument.Document; 17 | var gdApp = GraphApp.Instance; 18 | var publisher = new RevitToGraphPublisher(rDoc); 19 | GraphAppViewModel gvm = new GraphAppViewModel(publisher, gdApp); 20 | gdApp.GraphAppWindow = new GraphAppWindow(gvm); 21 | gdApp.GraphAppWindow.ShowDialog(); 22 | 23 | return Result.Succeeded; 24 | } 25 | } 26 | } -------------------------------------------------------------------------------- /HLApps.MEPGraph/Model/Node.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace HLApps.MEPGraph.Model 4 | { 5 | public class Node 6 | { 7 | 8 | public string UniqueId { get; set; } 9 | 10 | public virtual string Label 11 | { 12 | get 13 | { 14 | return GetType().Name; 15 | } 16 | } 17 | 18 | public string Name { get; set; } 19 | 20 | Dictionary _extendedProperties = new Dictionary(); 21 | public Dictionary ExtendedProperties { get => _extendedProperties; } 22 | 23 | 24 | public virtual Dictionary GetAllProperties() 25 | { 26 | var allProps = new Dictionary(); 27 | 28 | foreach(var kvp in ExtendedProperties) 29 | { 30 | allProps.Add(kvp.Key, kvp.Value); 31 | } 32 | 33 | if(!allProps.ContainsKey("Name")) allProps.Add("Name", Name); 34 | 35 | return allProps; 36 | 37 | } 38 | 39 | } 40 | 41 | } 42 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) [year] [fullname] 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /HLApps.RevitBuildConfigurations/HLApps.RevitBuildConfigurations.shproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 59589e76-d411-4579-810d-a08074e453e7 5 | 14.0 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /HLApps.Revit.Graph/Utils/DocUtils.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Linq; 3 | using Autodesk.Revit.DB; 4 | 5 | namespace HLApps.Revit.Utils 6 | { 7 | class DocUtils 8 | { 9 | public static string GetDocumentIdent(Document doc) 10 | { 11 | if (doc.IsFamilyDocument) 12 | { 13 | return doc.PathName; 14 | } 15 | else 16 | { 17 | return string.Format("{0}:{1}", doc.ProjectInformation != null ? doc.ProjectInformation.UniqueId.ToString() : "", doc.PathName); 18 | } 19 | } 20 | 21 | public static Document GetDocument(string docIdent, Autodesk.Revit.ApplicationServices.Application revitApp) 22 | { 23 | Document doc = null; 24 | if (!string.IsNullOrEmpty(docIdent)) 25 | { 26 | doc = revitApp.Documents.OfType() 27 | .FirstOrDefault(dc => GetDocumentIdent(dc) == docIdent); 28 | 29 | } 30 | 31 | return doc; 32 | } 33 | 34 | public static IEnumerable GetLinkInstances(Document _document) 35 | { 36 | var liColl = new FilteredElementCollector(_document); 37 | return liColl.OfClass(typeof(RevitLinkInstance)).ToElements().OfType(); 38 | 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /HLApps.MEPGraph/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("MEPGraphToNeo4j")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("Hoare Lea")] 12 | [assembly: AssemblyProduct("MEPGraphToNeo4j")] 13 | [assembly: AssemblyCopyright("Copyright © Hoare Lea 2018")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("400e1964-b716-4ea4-b21e-15c1f2135888")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /HLApps.Revit.Graph/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("RevitToGraphDB")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("Hoare Lea")] 12 | [assembly: AssemblyProduct("RevitToGraphDB")] 13 | [assembly: AssemblyCopyright("Copyright © Hoare Lea 2018")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("93280ff6-c2cc-4ece-8c26-d6794f7121d3")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /HLApps.Revit.Graph.UIAddin/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("RevitToGraphAddin")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("Hoare Lea")] 12 | [assembly: AssemblyProduct("RevitToGraphAddin")] 13 | [assembly: AssemblyCopyright("Copyright © Hoare Lea 2018")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("f5fecc1a-9803-43ea-a217-e9d321a7c2d2")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /HLApps.Revit.Graph.UIAddin/GraphApp.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using Autodesk.Revit.UI; 7 | using Autodesk.Revit.DB; 8 | 9 | namespace HLApps.Revit.Graph.UIAddin 10 | { 11 | 12 | [Autodesk.Revit.Attributes.Regeneration(Autodesk.Revit.Attributes.RegenerationOption.Manual)] 13 | public class GraphApp : IExternalApplication 14 | { 15 | public static GraphApp Instance; 16 | 17 | public GraphApp() 18 | { 19 | Instance = this; 20 | } 21 | 22 | public Result OnShutdown(UIControlledApplication application) 23 | { 24 | 25 | return Result.Succeeded; 26 | } 27 | 28 | public Result OnStartup(UIControlledApplication application) 29 | { 30 | 31 | var appPanel = application.CreateRibbonPanel(Tab.AddIns, "HLApps"); 32 | var showAppBtn = new PushButtonData("hleaPublishToGraph", "Publish to Graph", System.Reflection.Assembly.GetExecutingAssembly().Location, typeof(GraphAppShowCommand).FullName); 33 | showAppBtn.ToolTip = "Publish the current Revit model to a graph database"; 34 | appPanel.AddItem(showAppBtn); 35 | 36 | //TODO: persist settings with local storage 37 | SessionSettings = new RevitToGraphPublisherSettings(); 38 | 39 | return Result.Succeeded; 40 | } 41 | 42 | public System.Windows.Window GraphAppWindow { get; set; } 43 | public RevitToGraphPublisherSettings SessionSettings { get; private set; } 44 | } 45 | } -------------------------------------------------------------------------------- /HLApps.RevitBuildConfigurations/Imports.targets: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | C:\Program Files\Autodesk\Revit 2018\RevitAPI.dll 8 | False 9 | 10 | 11 | 12 | C:\Program Files\Autodesk\Revit 2019\RevitAPI.dll 13 | False 14 | 15 | 16 | 17 | C:\Program Files\Autodesk\Revit 2018\RevitAPIUI.dll 18 | False 19 | 20 | 21 | 22 | C:\Program Files\Autodesk\Revit 2019\RevitAPIUI.dll 23 | False 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | # Created by https://www.gitignore.io/api/visualstudio 3 | # Edit at https://www.gitignore.io/?templates=visualstudio 4 | 5 | ### VisualStudio ### 6 | ## Ignore Visual Studio temporary files, build results, and 7 | ## files generated by popular Visual Studio add-ons. 8 | ## 9 | ## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore 10 | 11 | # User-specific files 12 | *.rsuser 13 | *.suo 14 | *.user 15 | *.userosscache 16 | *.sln.docstates 17 | 18 | # User-specific files (MonoDevelop/Xamarin Studio) 19 | *.userprefs 20 | 21 | # Build results 22 | [Dd]ebug/ 23 | [Dd]ebugPublic/ 24 | [Rr]elease/ 25 | [Rr]eleases/ 26 | x64/ 27 | x86/ 28 | bld/ 29 | [Bb]in/ 30 | [Oo]bj/ 31 | [Ll]og/ 32 | 33 | # Visual Studio 2015/2017 cache/options directory 34 | .vs/ 35 | # Uncomment if you have tasks that create the project's static files in wwwroot 36 | #wwwroot/ 37 | 38 | # Visual Studio 2017 auto generated files 39 | Generated\ Files/ 40 | 41 | # Files built by Visual Studio 42 | *_i.c 43 | *_p.c 44 | *_h.h 45 | *.ilk 46 | *.meta 47 | *.obj 48 | *.iobj 49 | *.pch 50 | *.pdb 51 | *.ipdb 52 | *.pgc 53 | *.pgd 54 | *.rsp 55 | *.sbr 56 | *.tlb 57 | *.tli 58 | *.tlh 59 | *.tmp 60 | *.tmp_proj 61 | *_wpftmp.csproj 62 | *.log 63 | *.vspscc 64 | *.vssscc 65 | .builds 66 | *.pidb 67 | *.svclog 68 | *.scc 69 | 70 | # NuGet Packages 71 | *.nupkg 72 | # The packages folder can be ignored because of Package Restore 73 | **/[Pp]ackages/* 74 | # except build/, which is used as an MSBuild target. 75 | !**/[Pp]ackages/build/ 76 | # Uncomment if necessary however generally it will be regenerated when needed 77 | #!**/[Pp]ackages/repositories.config 78 | # NuGet v3's project.json files produces more ignorable files 79 | *.nuget.props 80 | *.nuget.targets 81 | 82 | # Visual Studio cache files 83 | # files ending in .cache can be ignored 84 | *.[Cc]ache 85 | # but keep track of directories ending in .cache 86 | !*.[Cc]ache/ 87 | 88 | # Local History for Visual Studio 89 | .localhistory/ 90 | 91 | # End of https://www.gitignore.io/api/visualstudio -------------------------------------------------------------------------------- /HLApps.Revit.Graph/Utils/RevitElementExtensions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using Autodesk.Revit.DB; 5 | 6 | namespace HLApps.Revit.Utils 7 | { 8 | static class RevitElementExtensions 9 | { 10 | 11 | 12 | public static Parameter HLGetParameter(this Element elm, string name) 13 | { 14 | 15 | var foundPramams = elm.GetParameters(name); 16 | 17 | if (foundPramams.Count == 0) 18 | { 19 | foundPramams = elm.Parameters.OfType().Where(p => string.Equals(p.Definition.Name, name, StringComparison.CurrentCultureIgnoreCase)).ToList(); 20 | } 21 | 22 | 23 | var firstValidParam = foundPramams.FirstOrDefault(p => p.HasValue); 24 | 25 | return firstValidParam != null ? firstValidParam : foundPramams.FirstOrDefault(); 26 | 27 | } 28 | 29 | public static Parameter HLGetParameter(this Element elm, BuiltInParameter bip) 30 | { 31 | 32 | return elm.get_Parameter(bip); 33 | 34 | } 35 | 36 | 37 | public static Parameter HLGetParameter(this Element elm, Guid Id) 38 | { 39 | 40 | return elm.get_Parameter(Id); 41 | 42 | } 43 | 44 | 45 | public static Parameter HLGetParameter(this Element elm, ElementId parameterId) 46 | { 47 | if (parameterId.IntegerValue == -1) return null; 48 | 49 | Parameter param = null; 50 | if (parameterId.IntegerValue < -1) 51 | { 52 | param = elm.get_Parameter((BuiltInParameter)parameterId.IntegerValue); 53 | } 54 | else 55 | { 56 | param = elm.Parameters.OfType().FirstOrDefault(pr => GetParameterId(pr).IntegerValue == parameterId.IntegerValue); 57 | } 58 | 59 | return param; 60 | } 61 | 62 | public static ElementId GetParameterId(Parameter param) 63 | { 64 | return param.Id; 65 | } 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /HLApps.Revit.Graph/RevitToGraphPublisher.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using Autodesk.Revit.DB; 7 | 8 | namespace HLApps.Revit.Graph 9 | { 10 | public class RevitToGraphPublisher 11 | { 12 | Document _rdoc; 13 | public RevitToGraphPublisher(Document doc) 14 | { 15 | _rdoc = doc; 16 | } 17 | 18 | public void Publish(RevitToGraphPublisherSettings settings, MEPGraph.IGraphDBClient client) 19 | { 20 | var meGraph = new MEPRevitGraph(); 21 | MEPRevitGraphWriter mps = new MEPRevitGraphWriter(meGraph); 22 | 23 | if (settings.IncludeElectrical) mps.Parsers.Add(new Parsers.MEPGraphParserElectrical()); 24 | if (settings.IncludeMechanical) mps.Parsers.Add(new Parsers.MEPGraphParserConnectors()); 25 | if (settings.IncludeBoundaries) mps.Parsers.Add(new Parsers.MEPGraphParserSpaces()); 26 | 27 | if (mps.Parsers.Count == 0) return; 28 | 29 | var mecFEc = new FilteredElementCollector(_rdoc); 30 | var mecFilter = mps.GetFilterForAllParsers; 31 | var mecElements = mecFEc.WherePasses(mecFilter).WhereElementIsNotElementType().ToElements(); 32 | 33 | var wfic = new FilteredElementCollector(_rdoc); 34 | var geoElementsFilter = new ElementMulticategoryFilter(new BuiltInCategory[] { BuiltInCategory.OST_Floors, BuiltInCategory.OST_Roofs, BuiltInCategory.OST_Windows, BuiltInCategory.OST_Doors, BuiltInCategory.OST_MEPSpaces, BuiltInCategory.OST_Rooms }); 35 | var geoElements = wfic.WherePasses(geoElementsFilter).WhereElementIsNotElementType().ToElements(); 36 | 37 | 38 | using (Transaction tx = new Transaction(_rdoc, "Build graph")) 39 | { 40 | tx.Start("Build graph"); 41 | mps.Write(mecElements, geoElements, -1, true, _rdoc); 42 | tx.Commit(); 43 | } 44 | 45 | MEPGraphWriter wre = new MEPGraphWriter(client); 46 | wre.Write(meGraph, _rdoc); 47 | 48 | } 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /HLApps.RevitBuildConfigurations/LocalDebugAddin.targets: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 8 | 9 | 10 | 11 | 15 | 16 | 17 | 18 | 19 | xcopy /y "$(TargetDir)*.dll" "C:\ProgramData\Autodesk\Revit\Addins\2018\HLApps.Revit\" 20 | 21 | 22 | 23 | xcopy /y "$(TargetDir)*.dll" "C:\ProgramData\Autodesk\Revit\Addins\2019\HLApps.Revit\" 24 | 25 | 26 | 27 | 28 | xcopy /y/S "$(SolutionDir)HLApps.Revit.Graph.UIAddin\HLApps.Revit.Graph.addin" "C:\ProgramData\Autodesk\Revit\Addins\2018\" 29 | 30 | 31 | 32 | xcopy /y/S "$(SolutionDir)HLApps.Revit.Graph.UIAddin\HLApps.Revit.Graph.addin" "C:\ProgramData\Autodesk\Revit\Addins\2019\" 33 | 34 | 35 | 36 | 37 | Program 38 | C:\Program Files\Autodesk\Revit 2018\Revit.exe 39 | 40 | 41 | C:\Program Files\Autodesk\Revit 2019\Revit.exe 42 | Program 43 | 44 | 45 | -------------------------------------------------------------------------------- /HLApps.Revit.Graph/Geometry/CurveGeometrySegment.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using HLApps.Revit.Utils; 3 | using Autodesk.Revit.DB; 4 | 5 | 6 | namespace HLApps.Revit.Geometry 7 | { 8 | public class CurveGeometrySegment : GeometrySegment 9 | { 10 | public CurveGeometrySegment(Curve curve, Element element) 11 | { 12 | Geometry = curve; 13 | 14 | OriginatingElement = element.Id; 15 | OriginatingDocIdent = DocUtils.GetDocumentIdent(element.Document); 16 | if (element.Category != null) OriginatingElementCategory = element.Category.Id; 17 | 18 | var min = curve.GetEndPoint(0); 19 | var max = curve.GetEndPoint(1); 20 | MidPoint = (min + max) / 2; 21 | Bounds = new HLBoundingBoxXYZ(min, max, false); 22 | Removed = false; 23 | segId = Guid.NewGuid().ToString(); 24 | 25 | if (element is MEPCurve) 26 | { 27 | var dParam = element.get_Parameter(BuiltInParameter.RBS_CURVE_DIAMETER_PARAM); 28 | if (dParam != null) 29 | { 30 | Radius = dParam.AsDouble() * 0.5; 31 | } 32 | else 33 | { 34 | var wParam = element.get_Parameter(BuiltInParameter.RBS_CURVE_WIDTH_PARAM); 35 | if (wParam != null) Width = wParam.AsDouble(); 36 | var hParam = element.get_Parameter(BuiltInParameter.RBS_CURVE_HEIGHT_PARAM); 37 | if (hParam != null) Height = hParam.AsDouble(); 38 | } 39 | 40 | } 41 | } 42 | 43 | public double MaxDimension 44 | { 45 | get 46 | { 47 | if (Radius > Height) return Radius; 48 | if (Radius > Width) return Radius; 49 | if (Height > Width) return Height; 50 | return Width; 51 | } 52 | } 53 | 54 | public Curve Geometry { get; set; } 55 | 56 | public override void Invalidate() 57 | { 58 | Geometry = null; 59 | Removed = true; 60 | } 61 | 62 | public double Width { private set; get; } 63 | public double Height { private set; get; } 64 | public double Radius { private set; get; } 65 | 66 | public XYZ MidPoint { get; private set; } 67 | } 68 | 69 | } -------------------------------------------------------------------------------- /HLApps.Revit.Graph/Parameters/HLRevitElementName.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Autodesk.Revit.DB; 3 | 4 | namespace HLApps.Revit.Parameters 5 | { 6 | public class HLRevitElementName : HLRevitElementData 7 | { 8 | Element _elm; 9 | 10 | public HLRevitElementName(Element elm) 11 | { 12 | _elm = elm; 13 | } 14 | 15 | public override string Name 16 | { 17 | get { return "Name"; } 18 | } 19 | 20 | public override object Value 21 | { 22 | get 23 | { 24 | return _elm.Name; 25 | } 26 | set 27 | { 28 | if (value != null) 29 | { 30 | _elm.Name = value.ToString(); 31 | } 32 | } 33 | } 34 | 35 | public override Type ExpectedType 36 | { 37 | get { return typeof(string); } 38 | } 39 | 40 | public override string StringValue 41 | { 42 | get 43 | { 44 | return _elm.Name; 45 | } 46 | set 47 | { 48 | if (!string.IsNullOrEmpty(value)) _elm.Name = value; 49 | } 50 | } 51 | 52 | public override StorageType StorageType 53 | { 54 | get { return Autodesk.Revit.DB.StorageType.String; } 55 | } 56 | 57 | public override bool IsReadOnly 58 | { 59 | get { return false; } 60 | } 61 | 62 | public override int IntElementId 63 | { 64 | get 65 | { 66 | return _elm.Id.IntegerValue; 67 | } 68 | } 69 | 70 | protected override void OnDisposing() 71 | { 72 | 73 | } 74 | } 75 | 76 | /* 77 | *Name property on element has no Get?? this soultion didn't work 78 | public static class ObjectExtensions 79 | { 80 | public static Object GetPropertyValue(this Object obj, String propertyName) 81 | { 82 | if (obj == null) throw new ArgumentNullException("obj", "`obj` cannot be null"); 83 | 84 | var fields = from f in obj.GetType().GetFields(BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public) 85 | where f.Name.Contains(String.Format("<{0}>", propertyName)) 86 | select f; 87 | 88 | if (fields.Any()) 89 | { 90 | return fields.First().GetValue(obj); 91 | } 92 | 93 | return null; 94 | } 95 | } */ 96 | 97 | 98 | } 99 | -------------------------------------------------------------------------------- /HLApps.Revit.Graph/Geometry/Octree/PointOctreeElementWriter.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | using Autodesk.Revit.DB; 4 | 5 | 6 | namespace HLApps.Revit.Geometry.Octree 7 | { 8 | public class PointOctreeElementWriter 9 | { 10 | PointOctree _pointStree; 11 | Dictionary> SegmentCache = new Dictionary>(); 12 | 13 | 14 | public PointOctreeElementWriter(PointOctree pointStree) 15 | { 16 | _pointStree = pointStree; 17 | } 18 | 19 | public void AddElement(ICollection elements) 20 | { 21 | foreach (var elm in elements) 22 | { 23 | AddElement(elm); 24 | } 25 | } 26 | 27 | public void AddElement(Element elm) 28 | { 29 | 30 | if (_pointStree == null) return; 31 | 32 | var elmid = elm.Id.IntegerValue; 33 | 34 | HashSet segList; 35 | 36 | if (SegmentCache.ContainsKey(elmid)) 37 | { 38 | segList = SegmentCache[elmid]; 39 | } 40 | else 41 | { 42 | segList = new HashSet(); 43 | } 44 | 45 | if (elm.Location is LocationPoint) 46 | { 47 | var lpoint = elm.Location as LocationPoint; 48 | PointGeometrySegment psg = null; 49 | if (elm is FamilyInstance) 50 | { 51 | var fi = elm as FamilyInstance; 52 | psg = new PointGeometrySegment(elm.Id, lpoint.Point, fi.FacingOrientation, fi.HandOrientation, fi.FacingFlipped, fi.HandFlipped); 53 | } 54 | else 55 | { 56 | psg = new PointGeometrySegment(elm.Id, lpoint.Point); 57 | } 58 | 59 | _pointStree.Add(psg, lpoint.Point); 60 | } 61 | else if (elm.Location is LocationCurve) 62 | { 63 | var curve = elm.Location as LocationCurve; 64 | if (curve == null) return; 65 | 66 | var cseg = new CurveGeometrySegment(curve.Curve, elm); 67 | segList.Add(cseg); 68 | _pointStree.Add(cseg, cseg.MidPoint); 69 | } 70 | 71 | 72 | if (!SegmentCache.ContainsKey(elmid)) 73 | { 74 | SegmentCache.Add(elmid, segList); 75 | } 76 | 77 | 78 | } 79 | 80 | public PointOctree OcTree 81 | { 82 | get 83 | { 84 | return _pointStree; 85 | } 86 | } 87 | 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /HLApps.RevitBuildConfigurations/BuildConfigurations.targets: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | true 6 | bin\x64\Debug\2018 7 | TRACE;DEBUG;REVIT2012,REVIT2013,REVIT2014,REVIT2015,REVIT2016,REVIT2017,REVIT2018 8 | full 9 | x64 10 | prompt 11 | MinimumRecommendedRules.ruleset 12 | $(MSBuildProjectName) 13 | false 14 | v4.6.1 15 | 16 | 17 | bin\x64\Release\2018 18 | TRACE;REVIT2012,REVIT2013,REVIT2014,REVIT2015,REVIT2016,REVIT2017,REVIT2018 19 | true 20 | pdbonly 21 | x64 22 | prompt 23 | MinimumRecommendedRules.ruleset 24 | $(MSBuildProjectName) 25 | false 26 | v4.6.1 27 | 28 | 29 | 30 | true 31 | bin\x64\Debug\2019\ 32 | TRACE;DEBUG;REVIT2012,REVIT2013,REVIT2014,REVIT2015,REVIT2016,REVIT2017,REVIT2018,REVIT2019 33 | full 34 | x64 35 | prompt 36 | MinimumRecommendedRules.ruleset 37 | $(MSBuildProjectName) 38 | v4.7 39 | 40 | 41 | bin\x64\Release\2019\ 42 | TRACE;REVIT2012,REVIT2013,REVIT2014,REVIT2015,REVIT2016,REVIT2017,REVIT2018,REVIT2019 43 | true 44 | pdbonly 45 | x64 46 | prompt 47 | MinimumRecommendedRules.ruleset 48 | $(MSBuildProjectName) 49 | v4.7 50 | 51 | 52 | -------------------------------------------------------------------------------- /HLApps.Revit.Graph/Graph/Parsers/MEPGraphParserElectrical.cs: -------------------------------------------------------------------------------- 1 | using System.Linq; 2 | 3 | using Autodesk.Revit.DB; 4 | 5 | 6 | namespace HLApps.Revit.Graph.Parsers 7 | { 8 | public class MEPGraphParserElectrical : MEPGraphParserConnectors 9 | { 10 | public override bool CanParse(Element elm) 11 | { 12 | var cats = new BuiltInCategory[] {BuiltInCategory.OST_ElectricalEquipment, BuiltInCategory.OST_ElectricalFixtures, BuiltInCategory.OST_LightingDevices, BuiltInCategory.OST_LightingFixtures, BuiltInCategory.OST_SecurityDevices, BuiltInCategory.OST_DataDevices, BuiltInCategory.OST_FireAlarmDevices, BuiltInCategory.OST_CommunicationDevices, BuiltInCategory.OST_NurseCallDevices, BuiltInCategory.OST_TelephoneDevices }; 13 | return elm.Category != null ? cats.Contains((BuiltInCategory)elm.Category.Id.IntegerValue) : false; 14 | } 15 | 16 | public override ElementFilter GetFilter() 17 | { 18 | var cats = new BuiltInCategory[] {BuiltInCategory.OST_ElectricalEquipment, BuiltInCategory.OST_ElectricalFixtures, BuiltInCategory.OST_LightingDevices, BuiltInCategory.OST_LightingFixtures, BuiltInCategory.OST_SecurityDevices, BuiltInCategory.OST_DataDevices, BuiltInCategory.OST_FireAlarmDevices, BuiltInCategory.OST_CommunicationDevices, BuiltInCategory.OST_NurseCallDevices, BuiltInCategory.OST_TelephoneDevices }; 19 | var emcf = new ElementMulticategoryFilter(cats); 20 | return emcf; 21 | } 22 | 23 | public override void ParseFrom(Element elm, MEPRevitGraphWriter writer) 24 | { 25 | 26 | //connect db panels to their circuits 27 | if (elm is FamilyInstance) 28 | { 29 | var fi = elm as FamilyInstance; 30 | var sysElm = fi.MEPModel; 31 | if (sysElm != null && sysElm.ElectricalSystems != null) 32 | { 33 | var panleSystems = sysElm.ElectricalSystems.OfType().Where(sy => sy.BaseEquipment != null && sy.BaseEquipment.Id == elm.Id); 34 | 35 | foreach (var sys in panleSystems) 36 | { 37 | writer.Graph.AddConnection(elm, sys, MEPPathConnectionType.Analytical, MEPGraph.Model.MEPEdgeTypes.ELECTRICAL_FLOW_TO); 38 | 39 | try 40 | { 41 | var elmsINSys = sys.Elements.OfType(); 42 | 43 | foreach (var emms in elmsINSys) 44 | { 45 | writer.Graph.AddConnection(sys, emms, MEPPathConnectionType.Analytical, MEPGraph.Model.MEPEdgeTypes.ELECTRICAL_FLOW_TO); 46 | 47 | ParseFrom(emms, writer); 48 | } 49 | } 50 | catch 51 | { 52 | //log exception 53 | } 54 | } 55 | } 56 | } 57 | 58 | base.ParseFrom(elm, writer); 59 | 60 | } 61 | 62 | } 63 | 64 | } 65 | -------------------------------------------------------------------------------- /HLApps.Revit.Graph.UIAddin/HLApps.Revit.Graph.UIAddin.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {F5FECC1A-9803-43EA-A217-E9D321A7C2D2} 8 | Library 9 | Properties 10 | HLApps.Revit.Graph.UIAddin 11 | HLApps.Revit.Graph.UIAddin 12 | v4.6.1 13 | 512 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | GraphAppWindow.xaml 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | {400e1964-b716-4ea4-b21e-15c1f2135888} 48 | HLApps.MEPGraph 49 | 50 | 51 | {93280ff6-c2cc-4ece-8c26-d6794f7121d3} 52 | HLApps.Revit.Graph 53 | 54 | 55 | 56 | 57 | 58 | MSBuild:Compile 59 | Designer 60 | 61 | 62 | 63 | 64 | -------------------------------------------------------------------------------- /HLApps.Revit.Graph/Graph/MEPPathSection.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.ObjectModel; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | 8 | using Autodesk.Revit.DB; 9 | 10 | 11 | namespace HLApps.Revit.Graph 12 | { 13 | 14 | 15 | 16 | 17 | public class MEPPathSection 18 | { 19 | 20 | public MEPPathSection() 21 | { 22 | 23 | } 24 | 25 | public MEPPathSection(int orgId) 26 | { 27 | 28 | } 29 | 30 | public MEPPathSection(int orgId, double pathlength, MEPPathSection parent) 31 | { 32 | _ordId = orgId; 33 | _In = parent; 34 | _pathLength = pathlength; 35 | } 36 | 37 | public MEPPathSection(Element elm, double pathlength, MEPPathSection parent) : this(elm, pathlength) 38 | { 39 | _In = parent; 40 | } 41 | 42 | 43 | public MEPPathSection(Element elm, double pathlength) 44 | { 45 | _ordId = elm.Id.IntegerValue; 46 | _pathLength = pathlength; 47 | _name = elm.Name; 48 | 49 | if (elm.Category.Id.IntegerValue == (int)BuiltInCategory.OST_DuctTerminal) _sectionType = MEPPathSectionType.Terminal; 50 | if (elm.Category.Id.IntegerValue == (int)BuiltInCategory.OST_MechanicalEquipment) _sectionType = MEPPathSectionType.Equipment; 51 | 52 | } 53 | 54 | string _name; 55 | public string Name 56 | { 57 | get 58 | { 59 | return _name; 60 | } 61 | } 62 | 63 | MEPPathSectionType _sectionType = MEPPathSectionType.Section; 64 | public MEPPathSectionType SectionType 65 | { 66 | get { return _sectionType; } 67 | } 68 | 69 | double _pathLength = 0; 70 | public double PathLength 71 | { 72 | get { return _pathLength; } 73 | } 74 | 75 | public double TotalPathLeghth 76 | { 77 | get 78 | { 79 | return PathLength + (_In != null ? _In.TotalPathLeghth : 0); 80 | } 81 | } 82 | 83 | int _ordId = -1; 84 | int OriginId 85 | { 86 | get { return _ordId; } 87 | } 88 | 89 | MEPPathSection _In; 90 | public MEPPathSection In 91 | { 92 | get { return _In; } 93 | } 94 | 95 | List _out = new List(); 96 | public IEnumerable Out { get { return _out; } } 97 | 98 | public void Connect(MEPPathSection section, MEPPathDirection direction) 99 | { 100 | if (direction == MEPPathDirection.Out) _out.Add(section); 101 | if (direction == MEPPathDirection.In) _In = section; 102 | } 103 | 104 | public double GetLengthTo(string search) 105 | { 106 | if (_In != null && !_In.Name.Contains(search)) 107 | { 108 | return _In.PathLength + _In.GetLengthTo(search); 109 | } 110 | 111 | return 0; 112 | } 113 | 114 | } 115 | 116 | 117 | 118 | } 119 | -------------------------------------------------------------------------------- /HLApps.Revit.Graph/Graph/MEPGraphUtils.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Linq; 3 | using Autodesk.Revit.DB; 4 | using HLApps.MEPGraph.Model; 5 | using HLApps.Revit.Parameters; 6 | 7 | namespace HLApps.Revit.Graph 8 | { 9 | public static class MEPGraphUtils 10 | { 11 | public static object RevitToGraphValue(HLRevitElementData elmData) 12 | { 13 | var val = elmData.Value; 14 | if (val is ElementId) return (val as ElementId).IntegerValue; 15 | 16 | if (val is Element) return (val as Element).Name; 17 | 18 | return val; 19 | } 20 | 21 | public static Dictionary GetNodePropsWithElementProps(Node node, Element elm) 22 | { 23 | var elmParms = node.GetAllProperties(); 24 | 25 | 26 | if (elm != null && elm.Location is Autodesk.Revit.DB.LocationPoint) 27 | { 28 | var lpt = (elm.Location as Autodesk.Revit.DB.LocationPoint); 29 | var insPt = lpt.Point; 30 | if (!elmParms.ContainsKey("LocationX")) elmParms.Add("LocationX", insPt.X); 31 | if (!elmParms.ContainsKey("LocationY")) elmParms.Add("LocationY", insPt.Y); 32 | if (!elmParms.ContainsKey("LocationZ")) elmParms.Add("LocationZ", insPt.Z); 33 | //if (!elmParms.ContainsKey("LocationRotation")) elmParms.Add("LocationRotation", lpt.Rotation); 34 | } 35 | else if (elm != null && elm.Location is Autodesk.Revit.DB.LocationCurve) 36 | { 37 | //just start and end points for now 38 | var insPt = (elm.Location as Autodesk.Revit.DB.LocationCurve).Curve.GetEndPoint(0); 39 | if (!elmParms.ContainsKey("LocationX")) elmParms.Add("LocationX", insPt.X); 40 | if (!elmParms.ContainsKey("LocationY")) elmParms.Add("LocationY", insPt.Y); 41 | if (!elmParms.ContainsKey("LocationZ")) elmParms.Add("LocationZ", insPt.Z); 42 | 43 | insPt = (elm.Location as Autodesk.Revit.DB.LocationCurve).Curve.GetEndPoint(1); 44 | if (!elmParms.ContainsKey("LocationX2")) elmParms.Add("LocationX2", insPt.X); 45 | if (!elmParms.ContainsKey("LocationY2")) elmParms.Add("LocationY2", insPt.Y); 46 | if (!elmParms.ContainsKey("LocationZ2")) elmParms.Add("LocationZ2", insPt.Z); 47 | } 48 | 49 | 50 | foreach (var param in elm.Parameters.OfType()) 51 | { 52 | var hp = new HLRevitParameter(param); 53 | var val = RevitToGraphValue(hp); 54 | 55 | if (!elmParms.ContainsKey(param.Definition.Name)) 56 | { 57 | elmParms.Add(param.Definition.Name, val); 58 | } 59 | 60 | if (!elmParms.ContainsKey(param.Definition.Name)) 61 | { 62 | elmParms.Add(param.Definition.Name, val); 63 | } 64 | } 65 | 66 | return elmParms; 67 | } 68 | 69 | public static Dictionary GetEdgeProps(Element elm) 70 | { 71 | var eprops = new Dictionary(); 72 | if (elm != null) 73 | { 74 | eprops.Add("UniqueId", elm.UniqueId); 75 | eprops.Add("ModelId", elm.Id.IntegerValue); 76 | } 77 | 78 | return eprops; 79 | 80 | } 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /HLApps.MEPGraph/HLApps.MEPGraph.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {400E1964-B716-4EA4-B21E-15C1F2135888} 8 | Library 9 | Properties 10 | HLApps.MEPGraph 11 | HLApps.MEPGraph 12 | v4.6.1 13 | 512 14 | 15 | 16 | true 17 | full 18 | false 19 | bin\Debug\ 20 | DEBUG;TRACE 21 | prompt 22 | 4 23 | x64 24 | 25 | 26 | pdbonly 27 | true 28 | bin\Release\ 29 | TRACE 30 | prompt 31 | 4 32 | 33 | 34 | true 35 | bin\x64\Debug\ 36 | DEBUG;TRACE 37 | full 38 | x64 39 | prompt 40 | MinimumRecommendedRules.ruleset 41 | 42 | 43 | bin\x64\Release\ 44 | TRACE 45 | true 46 | pdbonly 47 | x64 48 | prompt 49 | MinimumRecommendedRules.ruleset 50 | 51 | 52 | 53 | ..\packages\Neo4j.Driver.1.7.0\lib\net452\Neo4j.Driver.dll 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | -------------------------------------------------------------------------------- /RevitToGraphDB.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 15 4 | VisualStudioVersion = 15.0.27130.2027 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HLApps.Revit.Graph", "HLApps.Revit.Graph\HLApps.Revit.Graph.csproj", "{93280FF6-C2CC-4ECE-8C26-D6794F7121D3}" 7 | EndProject 8 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HLApps.MEPGraph", "HLApps.MEPGraph\HLApps.MEPGraph.csproj", "{400E1964-B716-4EA4-B21E-15C1F2135888}" 9 | EndProject 10 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HLApps.Revit.Graph.UIAddin", "HLApps.Revit.Graph.UIAddin\HLApps.Revit.Graph.UIAddin.csproj", "{F5FECC1A-9803-43EA-A217-E9D321A7C2D2}" 11 | EndProject 12 | Project("{D954291E-2A0B-460D-934E-DC6B0785DB48}") = "HLApps.RevitBuildConfigurations", "HLApps.RevitBuildConfigurations\HLApps.RevitBuildConfigurations.shproj", "{59589E76-D411-4579-810D-A08074E453E7}" 13 | EndProject 14 | Global 15 | GlobalSection(SharedMSBuildProjectFiles) = preSolution 16 | HLApps.RevitBuildConfigurations\RevitBuildConfigurations.projitems*{59589e76-d411-4579-810d-a08074e453e7}*SharedItemsImports = 13 17 | EndGlobalSection 18 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 19 | Debug2018|x64 = Debug2018|x64 20 | Debug2019|x64 = Debug2019|x64 21 | Release2018|x64 = Release2018|x64 22 | Release2019|x64 = Release2019|x64 23 | EndGlobalSection 24 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 25 | {93280FF6-C2CC-4ECE-8C26-D6794F7121D3}.Debug2018|x64.ActiveCfg = RV2018DBDebug|x64 26 | {93280FF6-C2CC-4ECE-8C26-D6794F7121D3}.Debug2018|x64.Build.0 = RV2018DBDebug|x64 27 | {93280FF6-C2CC-4ECE-8C26-D6794F7121D3}.Debug2019|x64.ActiveCfg = RV2019DBDebug|x64 28 | {93280FF6-C2CC-4ECE-8C26-D6794F7121D3}.Debug2019|x64.Build.0 = RV2019DBDebug|x64 29 | {93280FF6-C2CC-4ECE-8C26-D6794F7121D3}.Release2018|x64.ActiveCfg = RV2018DBRelease|x64 30 | {93280FF6-C2CC-4ECE-8C26-D6794F7121D3}.Release2018|x64.Build.0 = RV2018DBRelease|x64 31 | {93280FF6-C2CC-4ECE-8C26-D6794F7121D3}.Release2019|x64.ActiveCfg = RV2019DBRelease|x64 32 | {93280FF6-C2CC-4ECE-8C26-D6794F7121D3}.Release2019|x64.Build.0 = RV2019DBRelease|x64 33 | {400E1964-B716-4EA4-B21E-15C1F2135888}.Debug2018|x64.ActiveCfg = Debug|x64 34 | {400E1964-B716-4EA4-B21E-15C1F2135888}.Debug2018|x64.Build.0 = Debug|x64 35 | {400E1964-B716-4EA4-B21E-15C1F2135888}.Debug2019|x64.ActiveCfg = Debug|x64 36 | {400E1964-B716-4EA4-B21E-15C1F2135888}.Debug2019|x64.Build.0 = Debug|x64 37 | {400E1964-B716-4EA4-B21E-15C1F2135888}.Release2018|x64.ActiveCfg = Release|x64 38 | {400E1964-B716-4EA4-B21E-15C1F2135888}.Release2018|x64.Build.0 = Release|x64 39 | {400E1964-B716-4EA4-B21E-15C1F2135888}.Release2019|x64.ActiveCfg = Release|x64 40 | {400E1964-B716-4EA4-B21E-15C1F2135888}.Release2019|x64.Build.0 = Release|x64 41 | {F5FECC1A-9803-43EA-A217-E9D321A7C2D2}.Debug2018|x64.ActiveCfg = RV2018Debug|x64 42 | {F5FECC1A-9803-43EA-A217-E9D321A7C2D2}.Debug2018|x64.Build.0 = RV2018Debug|x64 43 | {F5FECC1A-9803-43EA-A217-E9D321A7C2D2}.Debug2019|x64.ActiveCfg = RV2019Debug|x64 44 | {F5FECC1A-9803-43EA-A217-E9D321A7C2D2}.Debug2019|x64.Build.0 = RV2019Debug|x64 45 | {F5FECC1A-9803-43EA-A217-E9D321A7C2D2}.Release2018|x64.ActiveCfg = RV2018Release|x64 46 | {F5FECC1A-9803-43EA-A217-E9D321A7C2D2}.Release2018|x64.Build.0 = RV2018Release|x64 47 | {F5FECC1A-9803-43EA-A217-E9D321A7C2D2}.Release2019|x64.ActiveCfg = RV2019Release|x64 48 | {F5FECC1A-9803-43EA-A217-E9D321A7C2D2}.Release2019|x64.Build.0 = RV2019Release|x64 49 | EndGlobalSection 50 | GlobalSection(SolutionProperties) = preSolution 51 | HideSolutionNode = FALSE 52 | EndGlobalSection 53 | GlobalSection(ExtensibilityGlobals) = postSolution 54 | SolutionGuid = {D56EF679-D1D3-4CB1-BE53-7981591D6E5E} 55 | EndGlobalSection 56 | EndGlobal 57 | -------------------------------------------------------------------------------- /HLApps.MEPGraph/Model/pocos.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq; 3 | using System.Text; 4 | using System.Threading.Tasks; 5 | 6 | namespace HLApps.MEPGraph.Model 7 | { 8 | 9 | public class ElementType : Node 10 | { 11 | public string Category { get; set; } 12 | 13 | 14 | 15 | } 16 | 17 | public class ModelElement : Node 18 | { 19 | public string Category { get; set; } 20 | 21 | } 22 | 23 | public class Space : Node 24 | { 25 | 26 | } 27 | 28 | public class Project : Node 29 | { 30 | public string number { get; set; } 31 | } 32 | 33 | public class RevitModel : Node 34 | { 35 | public string uri { get; set; } 36 | } 37 | 38 | public class ForgeModel : Node 39 | { 40 | public string uri { get; set; } 41 | } 42 | 43 | public class Surface : Node 44 | { 45 | public double area { get; set; } 46 | } 47 | 48 | public class VoidVolume : Node 49 | { 50 | 51 | } 52 | 53 | public class Wall : Node 54 | { 55 | 56 | } 57 | 58 | public class Door : Node 59 | { 60 | 61 | } 62 | 63 | public class Window : Node 64 | { 65 | 66 | } 67 | 68 | public class Ceiling : Node 69 | { 70 | 71 | } 72 | 73 | public class Column : Node 74 | { 75 | 76 | } 77 | 78 | 79 | public class Roof : Node 80 | { 81 | 82 | } 83 | 84 | public class Floor : Node 85 | { 86 | 87 | } 88 | 89 | public class Section : Node 90 | { 91 | 92 | } 93 | 94 | public class Duct : Section 95 | { 96 | 97 | } 98 | 99 | public class Pipe : Section 100 | { 101 | 102 | } 103 | 104 | public class CableTray : Section 105 | { 106 | 107 | } 108 | 109 | public class Transition : Node 110 | { 111 | 112 | } 113 | 114 | public class DuctTransition : Transition 115 | { 116 | 117 | } 118 | public class PipeTransition : Transition 119 | { 120 | 121 | } 122 | 123 | public class CableTrayTransition : Transition 124 | { 125 | 126 | } 127 | 128 | public class Terminal : Node 129 | { 130 | 131 | } 132 | 133 | public class Accessory : Node 134 | { 135 | 136 | } 137 | 138 | public class DuctAccessory : Accessory 139 | { 140 | 141 | } 142 | public class PipeAccessory : Accessory 143 | { 144 | 145 | } 146 | public class Equipment : Node 147 | { 148 | 149 | } 150 | 151 | public class Level : Node 152 | { 153 | 154 | } 155 | 156 | 157 | public class System : Node 158 | { 159 | 160 | } 161 | 162 | public class Circuit : Node 163 | { 164 | 165 | } 166 | 167 | 168 | public class DBPanel : Node 169 | { 170 | 171 | } 172 | 173 | public class ElectricalLoad : Node 174 | { 175 | 176 | } 177 | 178 | public class ElectricalSource : Node 179 | { 180 | 181 | } 182 | 183 | public class ElectricalDevice : Node 184 | { 185 | 186 | } 187 | 188 | public class Data : Node 189 | { 190 | 191 | } 192 | 193 | public class Security : Node 194 | { 195 | 196 | } 197 | 198 | public class Safety : Node 199 | { 200 | 201 | } 202 | 203 | public class Sprinkler : Safety 204 | { 205 | 206 | } 207 | 208 | public class FireAlarm : Safety 209 | { 210 | 211 | } 212 | 213 | 214 | public class Lighting : Node 215 | { 216 | 217 | } 218 | public class Environment : Node 219 | { 220 | 221 | } 222 | 223 | 224 | public class Realisable : Node 225 | { 226 | 227 | } 228 | 229 | 230 | public class RealisableType : Node 231 | { 232 | 233 | } 234 | 235 | } 236 | -------------------------------------------------------------------------------- /HLApps.Revit.Graph/Graph/Parsers/SpaceToDoorPathScanner.cs: -------------------------------------------------------------------------------- 1 | 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using Autodesk.Revit.DB; 5 | using HLApps.Revit.Geometry; 6 | using HLApps.Revit.Geometry.Octree; 7 | using HLApps.Revit.Utils; 8 | 9 | namespace HLApps.Revit.Graph.Parsers 10 | { 11 | public class SpaceNetworkPathScanner : IMEPGraphElementScanner 12 | { 13 | BoundsOctree _geoTree; 14 | 15 | public void Initialise(ICollection geoSerchElements, BoundsOctree geo) 16 | { 17 | _geoTree = geo; 18 | 19 | 20 | } 21 | 22 | 23 | public void ScanFromDocument(Document doc, MEPRevitGraph graph, int maxDepth) 24 | { 25 | Dictionary> spaceToDoors = new Dictionary>(); 26 | 27 | scanFromDocument(graph, doc, Transform.Identity, doc); 28 | 29 | //get linked documents 30 | foreach (RevitLinkInstance linkedInstance in DocUtils.GetLinkInstances(doc)) 31 | { 32 | 33 | //RevitLinkType linkType = (RevitLinkType)doc.GetElement(linkedInstance.GetTypeId()) as RevitLinkType; 34 | 35 | //ExternalFileReference exfRef = linkType.GetExternalFileReference(); 36 | 37 | //if (exfRef.GetLinkedFileStatus() != LinkedFileStatus.Loaded) continue; 38 | 39 | 40 | var ldoc = linkedInstance.GetLinkDocument(); 41 | if (ldoc == null) continue; 42 | scanFromDocument(graph, ldoc, linkedInstance.GetTotalTransform().Inverse, doc); 43 | } 44 | 45 | } 46 | 47 | public void ScanFromElement(Element elm, MEPRevitGraph graph, int maxDepth) 48 | { 49 | //TODO: actually scan from the supplied element 50 | ScanFromDocument(elm.Document, graph, maxDepth); 51 | 52 | } 53 | 54 | void scanFromDocument(MEPRevitGraph graph, Document doc, Transform tr, Document spaceSourceDoc) 55 | { 56 | var doorCol = new FilteredElementCollector(doc); 57 | var doors = doorCol.OfCategory(BuiltInCategory.OST_Doors).WhereElementIsNotElementType().ToElements().OfType(); 58 | 59 | foreach (var door in doors) 60 | { 61 | if (door.Location == null) continue; 62 | 63 | var ho = door.FacingFlipped ? door.FacingOrientation.Negate() : door.FacingOrientation; 64 | //var bbox = door.get_BoundingBox(null); 65 | var midPoint = (door.Location as LocationPoint).Point + new XYZ(0, 0, 1); 66 | //if (bbox != null) 67 | //{ 68 | // midPoint = (bbox.Min + bbox.Max) / 2; 69 | //} 70 | 71 | //get point in front 72 | var hfOrt = ho.Normalize(); 73 | var frontPos = midPoint + hfOrt.Multiply(1.64042); //stub is 1.64042 feet (0.5 meters) 74 | var lpFrontPoint = tr.OfPoint(frontPos); 75 | var spFront = spaceSourceDoc.GetSpaceAtPoint(lpFrontPoint);//, phase); 76 | 77 | 78 | //get point behind 79 | var hbOrt = ho.Negate().Normalize(); 80 | var behindPos = midPoint + hbOrt.Multiply(1.64042); //stub is 1.64042 feet (0.5 meters) 81 | var lpBehindPoint = tr.OfPoint(behindPos); 82 | var spBehind = spaceSourceDoc.GetSpaceAtPoint(lpBehindPoint);//, phase); 83 | 84 | 85 | 86 | if (spFront != null) 87 | { 88 | var edges = graph.AddConnection(spFront, door, midPoint, MEPPathConnectionType.Phyiscal, MEPGraph.Model.MEPEdgeTypes.FLOWS_TO); 89 | edges.ThisNode.OrginTransform = tr; 90 | } 91 | 92 | if (spBehind != null) 93 | { 94 | var edges = graph.AddConnection(door, spBehind, midPoint, MEPPathConnectionType.Phyiscal, MEPGraph.Model.MEPEdgeTypes.FLOWS_TO); 95 | edges.ThisNode.OrginTransform = tr; 96 | } 97 | 98 | 99 | } 100 | } 101 | 102 | 103 | 104 | } 105 | 106 | } 107 | 108 | -------------------------------------------------------------------------------- /HLApps.Revit.Graph/HLApps.Revit.Graph.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {93280FF6-C2CC-4ECE-8C26-D6794F7121D3} 8 | Library 9 | Properties 10 | HLApps.Revit.Graph 11 | HLApps.Revit.Graph 12 | v4.5.1 13 | 512 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | {400e1964-b716-4ea4-b21e-15c1f2135888} 76 | HLApps.MEPGraph 77 | 78 | 79 | 80 | -------------------------------------------------------------------------------- /HLApps.Revit.Graph.UIAddin/UI/ViewModel/GraphAppViewModel.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | 8 | namespace HLApps.Revit.Graph.UIAddin.ViewModel 9 | { 10 | class GraphAppViewModel : BaseViewModel 11 | { 12 | GraphApp _app; 13 | RevitToGraphPublisherSettings _settings; 14 | RevitToGraphPublisher _publisher; 15 | public GraphAppViewModel(RevitToGraphPublisher pubisher, GraphApp app) 16 | { 17 | _publishToGraphCommand = new Command(PublishToGraph); 18 | _cancelCommand = new Command(Close); 19 | _publisher = pubisher; 20 | _settings = app.SessionSettings; 21 | _app = app; 22 | } 23 | 24 | public string Username 25 | { 26 | get 27 | { 28 | return _settings.DBUsername; 29 | } 30 | set 31 | { 32 | _settings.DBUsername = value; 33 | NotifyPropertyChanged("Username"); 34 | } 35 | } 36 | 37 | 38 | public string Password 39 | { 40 | get 41 | { 42 | return _settings.DBPassword; 43 | } 44 | set 45 | { 46 | _settings.DBPassword = value; 47 | NotifyPropertyChanged("Password"); 48 | } 49 | } 50 | 51 | public string Host 52 | { 53 | get 54 | { 55 | return _settings.DBHost; 56 | } 57 | set 58 | { 59 | _settings.DBHost = value; 60 | NotifyPropertyChanged("Host"); 61 | } 62 | } 63 | public int Port 64 | { 65 | get 66 | { 67 | return _settings.DBPort; 68 | } 69 | set 70 | { 71 | _settings.DBPort = value; 72 | NotifyPropertyChanged("Port"); 73 | } 74 | } 75 | 76 | public bool IncludeBoundaries 77 | { 78 | get 79 | { 80 | return _settings.IncludeBoundaries; 81 | } 82 | set 83 | { 84 | _settings.IncludeBoundaries = value; 85 | NotifyPropertyChanged("IncludeBoundaries"); 86 | NotifyPropertyChanged("CanPublish"); 87 | } 88 | } 89 | public bool IncludeMechanical 90 | { 91 | get 92 | { 93 | return _settings.IncludeMechanical; 94 | } 95 | set 96 | { 97 | _settings.IncludeMechanical = value; 98 | NotifyPropertyChanged("IncludeMechanical"); 99 | NotifyPropertyChanged("CanPublish"); 100 | } 101 | } 102 | public bool IncludeElectrical 103 | { 104 | get 105 | { 106 | return _settings.IncludeElectrical; 107 | } 108 | set 109 | { 110 | _settings.IncludeElectrical = value; 111 | NotifyPropertyChanged("IncludeElectrical"); 112 | NotifyPropertyChanged("CanPublish"); 113 | } 114 | } 115 | 116 | public bool CanPublish 117 | { 118 | get 119 | { 120 | return IncludeBoundaries || IncludeMechanical || IncludeElectrical; 121 | } 122 | } 123 | 124 | Command _publishToGraphCommand; 125 | public Command PublishToGraphCommand 126 | { 127 | get 128 | { 129 | return _publishToGraphCommand; 130 | } 131 | } 132 | 133 | Command _cancelCommand; 134 | public Command CancelCommand 135 | { 136 | get 137 | { 138 | return _cancelCommand; 139 | } 140 | } 141 | 142 | void PublishToGraph() 143 | { 144 | var client = new MEPGraph.Neo4jClient(new Uri(string.Format("bolt://{0}:{1}", Host, Port)), Username, Password); 145 | _publisher.Publish(_settings, client); 146 | Autodesk.Revit.UI.TaskDialog.Show("Publish complete", "The current revit model has been successfully published to the graph database."); 147 | Close(); 148 | } 149 | 150 | void Close() 151 | { 152 | var appWindow = _app.GraphAppWindow; 153 | if (appWindow != null && appWindow.IsVisible) appWindow.Close(); 154 | } 155 | } 156 | } 157 | -------------------------------------------------------------------------------- /HLApps.Revit.Graph/Graph/MEPRevitGraphWriter.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Linq; 3 | 4 | using Autodesk.Revit.DB; 5 | using HLApps.Revit.Geometry; 6 | using HLApps.Revit.Geometry.Octree; 7 | using HLApps.Revit.Graph.Parsers; 8 | using HLApps.Revit.Utils; 9 | 10 | namespace HLApps.Revit.Graph 11 | { 12 | public class MEPRevitGraphWriter 13 | { 14 | MEPRevitGraph graph = new MEPRevitGraph(); 15 | 16 | public MEPRevitGraphWriter(MEPRevitGraph graph) 17 | { 18 | Cache = new MEPPathWriteCache(); 19 | Graph = graph; 20 | Parsers = new List(); 21 | 22 | } 23 | 24 | public List Parsers { get; private set; } 25 | public MEPPathWriteCache Cache { get; private set; } 26 | 27 | public MEPRevitGraph Graph { get; private set; } 28 | 29 | public ElementFilter GetFilterForAllParsers 30 | { 31 | get 32 | { 33 | var orFlre = new LogicalOrFilter(Parsers.Select(p => p.GetFilter()).ToList()); 34 | return orFlre; 35 | } 36 | } 37 | 38 | public void Write(ICollection scanElements, ICollection geoSerchElements, int maxDepth, bool doGeometryMatch, Document doc) 39 | { 40 | 41 | Cache.connectorsCache = new PointOctree(6.56168F, XYZ.Zero, 2F); 42 | Cache.MaxDepth = maxDepth; 43 | Cache.geoCache = new BoundsOctree(2, XYZ.Zero, 2F, 1.001f); 44 | Cache.geoCacheWriter = new BoundsOctreeElementWriter(Cache.geoCache); 45 | Cache.ParsedElements = new HashSet(); 46 | Cache.rayhitCache = new PointOctree(2, XYZ.Zero, 2F); 47 | 48 | var dsCount = geoSerchElements.Count; 49 | 50 | foreach (var elm in geoSerchElements) 51 | { 52 | var cmn = MEPUtils.GetConnectionManager(elm); 53 | if (cmn != null) 54 | { 55 | 56 | foreach (var conn in cmn.Connectors.OfType()) 57 | { 58 | #if REVIT2016 59 | var gesseg = new ConnectorPointGeometrySegment(elm.Id, conn.Origin, conn.Id); 60 | Cache.connectorsCache.Add(gesseg, conn.Origin); 61 | #else 62 | throw new Exception("Only supported in Revit 2016 onwards"); 63 | #endif 64 | } 65 | 66 | 67 | } 68 | 69 | if (doGeometryMatch) Cache.geoCacheWriter.AddElement(elm, true); 70 | } 71 | 72 | if (doGeometryMatch) 73 | { 74 | var li = DocUtils.GetLinkInstances(doc); 75 | dsCount = li.Count(); 76 | //cache geometry in linked documents. The geometry is expected to remain static, or changed as a block, so we don't need to keep track of each element. 77 | foreach (var linkedInstance in li) 78 | { 79 | Transform docTransform = linkedInstance.GetTotalTransform(); 80 | Transform docTransformInverse = docTransform.Inverse; 81 | 82 | //RevitLinkType linkType = (RevitLinkType)rDoc.GetElement(linkedInstance.GetTypeId()) as RevitLinkType; 83 | var ldoc = linkedInstance.GetLinkDocument();// HLRevitUtilities.GetLinkedDocumentFromType(_rdoc.Application, linkType); 84 | if (ldoc == null) continue; 85 | 86 | var lnGeoCol = new FilteredElementCollector(ldoc); 87 | var lnGeoFilter = new ElementMulticategoryFilter(new BuiltInCategory[] { BuiltInCategory.OST_Floors, BuiltInCategory.OST_Roofs }); 88 | 89 | foreach (var lnelm in lnGeoCol.WherePasses(lnGeoFilter).WhereElementIsNotElementType().ToElements()) 90 | { 91 | Cache.geoCacheWriter.AddElement(lnelm, true, docTransformInverse); 92 | } 93 | } 94 | } 95 | 96 | 97 | var elmcache = new HashSet(); 98 | var parserCount = Parsers.Count; 99 | 100 | foreach (var parser in Parsers) 101 | { 102 | parser.InitializeGraph(this); 103 | var elms = scanElements.Where(el => parser.CanParse(el)).ToList(); 104 | dsCount = elms.Count(); 105 | 106 | foreach (var elm in elms) 107 | { 108 | parser.ParseFrom(elm, this); 109 | } 110 | parser.FinalizeGraph(this); 111 | } 112 | 113 | } 114 | 115 | 116 | } 117 | } 118 | 119 | -------------------------------------------------------------------------------- /HLApps.Revit.Graph/Utils/GeoUtils.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using Autodesk.Revit.DB; 5 | using HLApps.Revit.Geometry; 6 | 7 | namespace HLApps.Revit.Utils 8 | { 9 | class GeoUtils 10 | { 11 | public static IEnumerable GetAllSolidsInGeometry(GeometryObject geo) 12 | { 13 | if (geo != null) 14 | { 15 | if (geo is GeometryElement) 16 | { 17 | var geoElm = geo as GeometryElement; 18 | foreach (var geoObj in geoElm.OfType()) 19 | { 20 | foreach (var recursiveCat in GetAllSolidsInGeometry(geoObj)) 21 | { 22 | yield return recursiveCat; 23 | } 24 | } 25 | } 26 | 27 | if (geo is GeometryInstance) 28 | { 29 | var geoInst = geo as GeometryInstance; 30 | GeometryElement geoElm = null; 31 | try 32 | { 33 | if (geoInst.Transform.IsConformal) 34 | { 35 | geoElm = geoInst.GetInstanceGeometry(); 36 | } 37 | } 38 | catch 39 | { 40 | //sometimes Revit throws an error unexpectedly, (e.g. "Trf is not conformal") 41 | //so we'll swallow it for now 42 | } 43 | 44 | if (geoElm != null) 45 | { 46 | foreach (var recursiveCat in GetAllSolidsInGeometry(geoElm)) 47 | { 48 | yield return recursiveCat; 49 | } 50 | } 51 | } 52 | 53 | if (geo is Solid) 54 | { 55 | yield return geo as Solid; 56 | } 57 | } 58 | 59 | } 60 | 61 | 62 | /// 63 | /// Returns an axis aligned box which for extents of only visible geometry 64 | /// Solid.GetBoundingBox method includes planes and non-visible geometry 65 | /// 66 | /// 67 | /// 68 | /// 69 | public static HLBoundingBoxXYZ GetGeoBoundingBox(Solid geoObj, Transform parentTransform) 70 | { 71 | HLBoundingBoxXYZ box = null; 72 | 73 | var sld = geoObj as Solid; 74 | foreach (var edge in sld.Edges.OfType()) 75 | { 76 | foreach (var pt in edge.Tessellate()) 77 | { 78 | var ptx = parentTransform.OfPoint(pt); 79 | if (box == null) 80 | { 81 | box = new HLBoundingBoxXYZ(ptx, new XYZ(0.01, 0.01, 0.01)); 82 | } 83 | else 84 | { 85 | box.ExpandToContain(ptx); 86 | } 87 | } 88 | } 89 | 90 | return box; 91 | } 92 | 93 | public static bool DoBoxesIntersect(HLBoundingBoxXYZ r1, HLBoundingBoxXYZ r2, double tolerance) 94 | { 95 | return r1.Min.X <= r2.Max.X && r1.Max.X >= r2.Min.X && r1.Min.Y <= r2.Max.Y && r1.Max.Y >= r2.Min.Y && r1.Min.Z <= r2.Max.Z && r1.Max.Z >= r2.Min.Z; 96 | } 97 | 98 | //Rotate the point (x,y,z) around the vector (u,v,w) 99 | public static XYZ RotateAboutVector(XYZ point, XYZ Vector, double angle) 100 | { 101 | 102 | double u = Vector.X; 103 | double v = Vector.Y; 104 | double w = Vector.Z; 105 | double x = point.X; 106 | double y = point.Y; 107 | double z = point.Z; 108 | 109 | double ux = Vector.X * point.X; 110 | double uy = Vector.X * point.Y; 111 | double uz = Vector.X * point.Z; 112 | double vx = Vector.Y * point.X; 113 | double vy = Vector.Y * point.Y; 114 | double vz = Vector.Y * point.Z; 115 | double wx = Vector.Z * point.X; 116 | double wy = Vector.Z * point.Y; 117 | double wz = Vector.Z * point.Z; 118 | double sa = Math.Sin(angle); 119 | double ca = Math.Cos(angle); 120 | x = u * (ux + vy + wz) + (x * (v * v + w * w) - u * (vy + wz)) * ca + (-wy + vz) * sa; 121 | y = v * (ux + vy + wz) + (y * (u * u + w * w) - v * (ux + wz)) * ca + (wx - uz) * sa; 122 | z = w * (ux + vy + wz) + (z * (u * u + v * v) - w * (ux + vy)) * ca + (-vx + uy) * sa; 123 | 124 | return new XYZ(x, y, z); 125 | } 126 | 127 | 128 | } 129 | } 130 | -------------------------------------------------------------------------------- /HLApps.Revit.Graph/Graph/MEPNodeEdge.cs: -------------------------------------------------------------------------------- 1 | //using Newtonsoft.Json.Serialization; 2 | using System.Collections.Generic; 3 | using HLApps.MEPGraph.Model; 4 | 5 | namespace HLApps.Revit.Graph 6 | { 7 | 8 | public class MEPRevitEdge 9 | { 10 | 11 | public MEPRevitEdge(int index, MEPRevitNode owner, MEPRevitNode next, MEPPathDirection direction) : this() 12 | { 13 | ThisConnectorIndex = index; 14 | NextNode = next; 15 | ThisNode = owner; 16 | Direction = direction; 17 | } 18 | 19 | public MEPRevitEdge(int index, int systemId, MEPRevitNode owner, MEPRevitNode next, MEPPathDirection direction) : this(index, owner, next, direction) 20 | { 21 | SystemId = SystemId; 22 | } 23 | 24 | public MEPRevitEdge() 25 | { 26 | Length = 0; 27 | } 28 | 29 | public int SystemId { get; set; } 30 | public int ThisConnectorIndex { get; set; } 31 | public int NextConnectorIndex { get; set; } 32 | 33 | string _Description; 34 | public string Description 35 | { 36 | get 37 | { 38 | return _Description; 39 | } 40 | set 41 | { 42 | _Description = value; 43 | SetWeight("Description", value); 44 | } 45 | 46 | } 47 | 48 | public MEPRevitNode NextNode { get; set; } 49 | 50 | public MEPRevitEdge Reverse { get; set; } 51 | 52 | public Autodesk.Revit.DB.XYZ ThisOrigin { get; set; } 53 | public Autodesk.Revit.DB.XYZ NextOrigin { get; set; } 54 | 55 | public MEPRevitNode ThisNode { get; set; } 56 | 57 | MEPPathConnectionType _ConnectionType = MEPPathConnectionType.Analytical; 58 | public MEPPathConnectionType ConnectionType 59 | { 60 | get 61 | { 62 | return _ConnectionType; 63 | } 64 | set 65 | { 66 | _ConnectionType = value; 67 | SetWeight("ConnectionType", value.ToString()); 68 | } 69 | 70 | } 71 | 72 | MEPPathDirection _Direction; 73 | public MEPPathDirection Direction { 74 | get 75 | { 76 | return _Direction; 77 | } 78 | set 79 | { 80 | _Direction = value; 81 | SetWeight("Direction", value.ToString()); 82 | } 83 | } 84 | 85 | 86 | Dictionary _weights = new Dictionary(); 87 | public Dictionary Weights 88 | { 89 | get 90 | { 91 | return _weights; 92 | } 93 | 94 | } 95 | 96 | 97 | public object GetWeight(string name) 98 | { 99 | if (Weights.ContainsKey(name)) 100 | { 101 | return Weights[name]; 102 | } 103 | else 104 | { 105 | throw new System.Exception("Node does not contain weight: " + name); 106 | } 107 | } 108 | 109 | public void SetWeight(string name, object value) 110 | { 111 | if (Weights.ContainsKey(name)) 112 | { 113 | Weights[name] = value; 114 | } 115 | else 116 | { 117 | Weights.Add(name, value); 118 | } 119 | } 120 | 121 | public double Flow 122 | { 123 | get 124 | { 125 | return Weights.ContainsKey("Flow") ? (double)GetWeight("Flow") : 0; 126 | } 127 | set 128 | { 129 | SetWeight("Flow", value); 130 | } 131 | } 132 | 133 | public double Length 134 | { 135 | get 136 | { 137 | return Weights.ContainsKey("Length") ? (double)GetWeight("Length") : 0; 138 | } 139 | set 140 | { 141 | SetWeight("Length", value); 142 | } 143 | } 144 | 145 | 146 | Edge _edge; 147 | public Edge AsNodeEdge 148 | { 149 | get 150 | { 151 | if (_edge ==null) _edge = new Edge(); 152 | 153 | return _edge; 154 | } 155 | } 156 | 157 | 158 | } 159 | 160 | public class MEPConnectorNodeEdge : MEPRevitEdge 161 | { 162 | 163 | public MEPConnectorNodeEdge(int index, MEPRevitNode owner, MEPRevitNode next, MEPPathDirection direction) : base(index, owner, next, direction) 164 | { 165 | } 166 | 167 | public MEPConnectorNodeEdge(int index, int systemId, MEPRevitNode owner, MEPRevitNode next, MEPPathDirection direction) : base(index, systemId, owner, next, direction) 168 | { 169 | } 170 | 171 | 172 | 173 | } 174 | 175 | } 176 | -------------------------------------------------------------------------------- /HLApps.Revit.Graph/Geometry/Octree/BoundsOctreeElementWriter.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using Autodesk.Revit.DB; 3 | using HLApps.Revit.Utils; 4 | 5 | namespace HLApps.Revit.Geometry.Octree 6 | { 7 | 8 | public class BoundsOctreeElementWriter 9 | { 10 | 11 | BoundsOctree _boundsStree; 12 | Dictionary _geoOptionsOverrides; 13 | Options defaultGeomOptions; 14 | 15 | public BoundsOctreeElementWriter(BoundsOctree boundsStree) 16 | { 17 | _geoOptionsOverrides = new Dictionary(); 18 | _boundsStree = boundsStree; 19 | var fineGeoOp = new Options(); 20 | fineGeoOp.DetailLevel = ViewDetailLevel.Fine; 21 | 22 | var courseGeomOptions = new Options(); 23 | courseGeomOptions.DetailLevel = ViewDetailLevel.Coarse; 24 | 25 | 26 | _geoOptionsOverrides.Add((int)BuiltInCategory.OST_PipeCurves, fineGeoOp); 27 | _geoOptionsOverrides.Add((int)BuiltInCategory.OST_PipeSegments, fineGeoOp); 28 | _geoOptionsOverrides.Add((int)BuiltInCategory.OST_PipeFitting, fineGeoOp); 29 | _geoOptionsOverrides.Add((int)BuiltInCategory.OST_PipeAccessory, fineGeoOp); 30 | _geoOptionsOverrides.Add((int)BuiltInCategory.OST_FlexPipeCurves, fineGeoOp); 31 | _geoOptionsOverrides.Add((int)BuiltInCategory.OST_FlexDuctCurves, fineGeoOp); 32 | _geoOptionsOverrides.Add((int)BuiltInCategory.OST_Windows, fineGeoOp); 33 | _geoOptionsOverrides.Add((int)BuiltInCategory.OST_Doors, courseGeomOptions); 34 | _geoOptionsOverrides.Add((int)BuiltInCategory.OST_Roofs, fineGeoOp); 35 | _geoOptionsOverrides.Add((int)BuiltInCategory.OST_Floors, fineGeoOp); 36 | _geoOptionsOverrides.Add((int)BuiltInCategory.OST_Ceilings, fineGeoOp); 37 | 38 | 39 | defaultGeomOptions = new Options(); 40 | defaultGeomOptions.DetailLevel = ViewDetailLevel.Medium; 41 | 42 | } 43 | 44 | Dictionary> SegmentCache = new Dictionary>(); 45 | 46 | public void AddElement(ICollection elements, bool includeGeometry) 47 | { 48 | foreach (var elm in elements) 49 | { 50 | AddElement(elm, includeGeometry); 51 | } 52 | } 53 | 54 | public void AddElement(Element elm, bool includeGeometry, Transform tx = null) 55 | { 56 | if (_boundsStree == null || elm == null) 57 | { 58 | return; 59 | } 60 | 61 | 62 | var elmid = elm.Id.IntegerValue; 63 | 64 | HashSet segList; 65 | 66 | if (SegmentCache.ContainsKey(elmid)) 67 | { 68 | segList = SegmentCache[elmid]; 69 | } 70 | else 71 | { 72 | segList = new HashSet(); 73 | } 74 | 75 | if (includeGeometry || elm is FamilyInstance) 76 | { 77 | var gop = defaultGeomOptions; 78 | if (elm.Category != null && _geoOptionsOverrides.ContainsKey(elm.Category.Id.IntegerValue)) 79 | { 80 | gop = _geoOptionsOverrides[elm.Category.Id.IntegerValue]; 81 | } 82 | 83 | var egeo = elm.get_Geometry(gop); 84 | if (egeo == null) return; 85 | 86 | if (tx != null) egeo = egeo.GetTransformed(tx); 87 | 88 | var allSolids = GeoUtils.GetAllSolidsInGeometry(egeo); 89 | foreach (var sld in allSolids) 90 | { 91 | if (!solidIsValid(sld)) 92 | { 93 | continue; 94 | } 95 | 96 | var hlbbox = GeoUtils.GetGeoBoundingBox(sld, Transform.Identity); 97 | if (hlbbox == null) continue; 98 | var geoSegment = new SolidGeometrySegment(sld, elm, hlbbox); 99 | segList.Add(geoSegment); 100 | _boundsStree.Add(geoSegment, hlbbox); 101 | } 102 | } 103 | 104 | if (elm.Location is LocationCurve) 105 | { 106 | var curve = elm.Location as LocationCurve; 107 | if (curve == null) return; 108 | var acCurve = curve.Curve; 109 | 110 | if (tx != null) acCurve = acCurve.CreateTransformed(tx); 111 | 112 | var cseg = new CurveGeometrySegment(acCurve, elm); 113 | segList.Add(cseg); 114 | _boundsStree.Add(cseg, cseg.Bounds); 115 | } 116 | 117 | 118 | if (!SegmentCache.ContainsKey(elmid)) 119 | { 120 | SegmentCache.Add(elmid, segList); 121 | 122 | } 123 | 124 | 125 | 126 | } 127 | 128 | 129 | public BoundsOctree OcTree 130 | { 131 | get 132 | { 133 | return _boundsStree; 134 | } 135 | } 136 | 137 | 138 | 139 | double _minVolume = 0.1; 140 | private bool solidIsValid(Solid sld) 141 | { 142 | return sld != null && sld.Volume > _minVolume; 143 | } 144 | 145 | } 146 | } 147 | -------------------------------------------------------------------------------- /HLApps.Revit.Graph/Parameters/HLRevitElementProperty.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq; 3 | using Autodesk.Revit.DB; 4 | 5 | namespace HLApps.Revit.Parameters 6 | { 7 | public class HLRevitElementProperty : HLRevitElementData 8 | { 9 | string _name; 10 | object _value; 11 | Type _ExpectedType; 12 | StorageType _storageType; 13 | object _baseObj = null; 14 | bool _isReadOnly = true; 15 | int _elementdId = -1; 16 | 17 | public HLRevitElementProperty(int elmId, string name, object value, StorageType storageTyp) 18 | { 19 | _name = name; 20 | _value = value; 21 | _ExpectedType = value.GetType(); 22 | _storageType = storageTyp; 23 | _isValid = true; 24 | _elementdId = elmId; 25 | } 26 | 27 | public HLRevitElementProperty(int elmId, string name, object value, StorageType storageTyp, object baseObj) 28 | { 29 | _name = name; 30 | _value = value; 31 | _ExpectedType = value.GetType(); 32 | _storageType = storageTyp; 33 | _baseObj = baseObj; 34 | _isValid = true; 35 | _elementdId = elmId; 36 | } 37 | 38 | public HLRevitElementProperty(string name, object baseObj) 39 | { 40 | _name = name; 41 | _baseObj = baseObj; 42 | 43 | var prop = _baseObj.GetType().GetProperties().FirstOrDefault(pr => pr.Name == _name); 44 | 45 | var bt = _baseObj.GetType().BaseType; 46 | var propbt = bt.GetProperties().FirstOrDefault(pr => pr.Name == _name); 47 | 48 | var allProps = baseObj.GetType().GetProperties().Select(p => p.Name).ToList(); 49 | if (prop != null) 50 | { 51 | _ExpectedType = prop.PropertyType; 52 | _storageType = Autodesk.Revit.DB.StorageType.None; 53 | if (prop.GetGetMethod() != null) 54 | { 55 | _value = prop.GetValue(baseObj, null); 56 | _isValid = true; 57 | } 58 | else 59 | { 60 | // _value = baseObj.GetPropertyValue(name); 61 | } 62 | 63 | _isReadOnly = !prop.CanWrite; 64 | } 65 | } 66 | 67 | public override string Name 68 | { 69 | get 70 | { 71 | return _name; 72 | } 73 | } 74 | 75 | public override object Value 76 | { 77 | get 78 | { 79 | return _value; 80 | } 81 | set 82 | { 83 | if (_baseObj != null) 84 | { 85 | var prop = _baseObj.GetType().GetProperties().FirstOrDefault(pr => pr.Name == _name); 86 | 87 | if (prop != null) 88 | { 89 | prop.SetValue(_baseObj, value, null); 90 | } 91 | } 92 | } 93 | } 94 | 95 | public override Type ExpectedType 96 | { 97 | get 98 | { 99 | return _ExpectedType; 100 | } 101 | } 102 | 103 | public override string StringValue 104 | { 105 | get 106 | { 107 | if (_value is Category) 108 | { 109 | return (_value as Category).Name; 110 | } 111 | else if (_value is Element) 112 | { 113 | return (_value as Element).Name; 114 | } 115 | 116 | return _value.ToString(); 117 | } 118 | set 119 | { 120 | 121 | Value = value; 122 | } 123 | 124 | } 125 | 126 | public override StorageType StorageType 127 | { 128 | get 129 | { 130 | return _storageType; 131 | } 132 | } 133 | 134 | public override bool IsReadOnly 135 | { 136 | get 137 | { 138 | return _isReadOnly; 139 | } 140 | } 141 | 142 | bool _isValid = false; 143 | public bool IsValid 144 | { 145 | get { return _isValid; } 146 | } 147 | 148 | public override int IntElementId 149 | { 150 | get 151 | { 152 | return _elementdId; 153 | } 154 | } 155 | 156 | protected override void OnDisposing() 157 | { 158 | 159 | } 160 | } 161 | 162 | /* 163 | *Name property on element has no Get?? this soultion didn't work 164 | public static class ObjectExtensions 165 | { 166 | public static Object GetPropertyValue(this Object obj, String propertyName) 167 | { 168 | if (obj == null) throw new ArgumentNullException("obj", "`obj` cannot be null"); 169 | 170 | var fields = from f in obj.GetType().GetFields(BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public) 171 | where f.Name.Contains(String.Format("<{0}>", propertyName)) 172 | select f; 173 | 174 | if (fields.Any()) 175 | { 176 | return fields.First().GetValue(obj); 177 | } 178 | 179 | return null; 180 | } 181 | } */ 182 | 183 | 184 | } 185 | -------------------------------------------------------------------------------- /HLApps.Revit.Graph/Parameters/HLRevitReadonlyTextData.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Autodesk.Revit.DB; 3 | 4 | namespace HLApps.Revit.Parameters 5 | { 6 | public class HLRevitReadonlyTextData : HLRevitElementData 7 | { 8 | int _elmId; 9 | string _value; 10 | string _Name; 11 | 12 | public HLRevitReadonlyTextData(ElementId elementId, string value, string name) 13 | { 14 | _elmId = elementId.IntegerValue; 15 | _value = value; 16 | _Name = name; 17 | } 18 | 19 | public override Type ExpectedType 20 | { 21 | get 22 | { 23 | return typeof(string); 24 | } 25 | } 26 | 27 | public override int IntElementId 28 | { 29 | get 30 | { 31 | return _elmId; 32 | } 33 | } 34 | 35 | public override bool IsReadOnly 36 | { 37 | get 38 | { 39 | return true; 40 | } 41 | } 42 | 43 | public override string Name 44 | { 45 | get 46 | { 47 | return _Name; 48 | } 49 | } 50 | 51 | public override StorageType StorageType 52 | { 53 | get 54 | { 55 | return StorageType.String; 56 | } 57 | } 58 | 59 | public override string StringValue 60 | { 61 | get 62 | { 63 | return _value; 64 | } 65 | 66 | set 67 | { 68 | _value = value; 69 | } 70 | } 71 | 72 | public override object Value 73 | { 74 | get 75 | { 76 | return StringValue; 77 | } 78 | set 79 | { 80 | StringValue = value != null ? value.ToString() : string.Empty; 81 | } 82 | } 83 | 84 | protected override void OnDisposing() 85 | { 86 | 87 | } 88 | } 89 | 90 | 91 | public class HLRevitReadonlyData : HLRevitElementData 92 | { 93 | int _elmId; 94 | object _value; 95 | string _Name; 96 | 97 | public HLRevitReadonlyData(ElementId elementId, object value, string name) 98 | { 99 | _elmId = elementId.IntegerValue; 100 | _value = value; 101 | _Name = name; 102 | 103 | _storageType = StorageType.None; 104 | if (value is int) 105 | { 106 | _storageType = StorageType.Integer; 107 | } 108 | else if (value is double) 109 | { 110 | _storageType = StorageType.Double; 111 | } 112 | else if (value is string) 113 | { 114 | _storageType = StorageType.String; 115 | } 116 | else if (value is ElementId) 117 | { 118 | _storageType = StorageType.ElementId; 119 | } 120 | } 121 | 122 | 123 | public override Type ExpectedType 124 | { 125 | get 126 | { 127 | return typeof(string); 128 | } 129 | } 130 | 131 | public override int IntElementId 132 | { 133 | get 134 | { 135 | return _elmId; 136 | } 137 | } 138 | 139 | public override bool IsReadOnly 140 | { 141 | get 142 | { 143 | return true; 144 | } 145 | } 146 | 147 | public override string Name 148 | { 149 | get 150 | { 151 | return _Name; 152 | } 153 | } 154 | 155 | StorageType _storageType; 156 | public override StorageType StorageType 157 | { 158 | get 159 | { 160 | return _storageType; 161 | } 162 | } 163 | 164 | public override string StringValue 165 | { 166 | get 167 | { 168 | return _value != null ? _value.ToString() : string.Empty; 169 | } 170 | set 171 | { 172 | throw new Exception("Value is read only"); 173 | } 174 | } 175 | 176 | public override object Value 177 | { 178 | get 179 | { 180 | return _value; 181 | } 182 | set 183 | { 184 | _value = value; 185 | } 186 | } 187 | 188 | protected override void OnDisposing() 189 | { 190 | 191 | } 192 | } 193 | /* 194 | *Name property on element has no Get?? this soultion didn't work 195 | public static class ObjectExtensions 196 | { 197 | public static Object GetPropertyValue(this Object obj, String propertyName) 198 | { 199 | if (obj == null) throw new ArgumentNullException("obj", "`obj` cannot be null"); 200 | 201 | var fields = from f in obj.GetType().GetFields(BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public) 202 | where f.Name.Contains(String.Format("<{0}>", propertyName)) 203 | select f; 204 | 205 | if (fields.Any()) 206 | { 207 | return fields.First().GetValue(obj); 208 | } 209 | 210 | return null; 211 | } 212 | } */ 213 | 214 | 215 | } 216 | -------------------------------------------------------------------------------- /HLApps.MEPGraph/Neo4j/Neo4jClient.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | 5 | using Neo4j.Driver.V1; 6 | 7 | namespace HLApps.MEPGraph 8 | { 9 | public class Neo4jClient : IDisposable, IGraphDBClient 10 | { 11 | 12 | IDriver _driver; 13 | public Neo4jClient(Uri host, string userName, string password) 14 | { 15 | _driver = GraphDatabase.Driver(host, AuthTokens.Basic(userName, password)); 16 | } 17 | 18 | /// 19 | /// MATCH(a),(b) 20 | /// WHERE ID(a) = $fromNodeId AND ID(b) = $toNodeId 21 | /// CREATE (a)-[r: $relType $variables ]->(b) 22 | /// 23 | /// 24 | /// 25 | /// 26 | /// 27 | public void Relate(long fromNodeId, long toNodeId, Model.MEPEdgeTypes relType, Dictionary variables) 28 | { 29 | Dictionary props = new Dictionary(); 30 | props.Add("auid", fromNodeId); 31 | props.Add("buid", toNodeId); 32 | 33 | string query = string.Empty; 34 | if (variables != null && variables.Count > 0) 35 | { 36 | props.Add("cvar", variables); 37 | query = 38 | "MATCH(a),(b)" + 39 | "WHERE ID(a) = $auid AND ID(b) = $buid " + 40 | string.Format("CREATE (a)-[r: {0} $cvar]->(b) ", relType); 41 | } 42 | else 43 | { 44 | query = 45 | "MATCH(a),(b)" + 46 | "WHERE ID(a) = $auid AND ID(b) = $buid " + 47 | string.Format("CREATE (a)-[r: {0}]->(b) ", relType); 48 | } 49 | 50 | 51 | using (var session = _driver.Session()) 52 | { 53 | var greeting = session.WriteTransaction(tx => 54 | { 55 | var result = props.Count > 0 ? tx.Run(query, props) : tx.Run(query); 56 | return result; 57 | }); 58 | 59 | Console.WriteLine(greeting); 60 | } 61 | 62 | 63 | } 64 | 65 | 66 | public void Relate(Model.Node fromNode, Model.Node toNode, string relType, Dictionary variables) 67 | { 68 | Dictionary props = new Dictionary(); 69 | props.Add("auid", fromNode.UniqueId); 70 | props.Add("buid", toNode.UniqueId); 71 | 72 | string query = string.Empty; 73 | if (variables != null && variables.Count > 0) 74 | { 75 | props.Add("cvar", variables); 76 | query = 77 | string.Format("MATCH(a:{0}),(b:{1})", fromNode.Label, toNode.Label) + 78 | "WHERE a.UniqueId = $auid AND b.UniqueId = $buid " + 79 | string.Format("CREATE (a)-[r: {0} $cvar]->(b) ", relType); 80 | } 81 | else 82 | { 83 | query = 84 | string.Format("MATCH(a:{0}),(b:{1})", fromNode.Label, toNode.Label) + 85 | "WHERE a.UniqueId = $auid AND b.UniqueId = $buid " + 86 | string.Format("CREATE (a)-[r: {0}]->(b) ", relType); 87 | } 88 | 89 | 90 | using (var session = _driver.Session()) 91 | { 92 | var greeting = session.WriteTransaction(tx => 93 | { 94 | var result = props.Count > 0 ? tx.Run(query, props) : tx.Run(query); 95 | return result; 96 | }); 97 | 98 | Console.WriteLine(greeting); 99 | } 100 | 101 | } 102 | 103 | public long Push(Model.Node node, Dictionary variables) 104 | { 105 | Dictionary props = new Dictionary(); 106 | props.Add("props", variables); 107 | 108 | 109 | var nodeLabel = node.Label; 110 | var query = string.Format("CREATE (n:{0} $props) RETURN ID(n)", nodeLabel); 111 | 112 | IStatementResult retId; 113 | 114 | using (var session = _driver.Session()) 115 | { 116 | retId = session.WriteTransaction(tx => 117 | { 118 | var result = props.Count > 0 ? tx.Run(query, props) : tx.Run(query); 119 | return result; 120 | }); 121 | 122 | } 123 | 124 | if (retId != null) 125 | { 126 | var lr = retId.ToList(); 127 | if (lr.Count() == 1) 128 | { 129 | var rs = lr.First(); 130 | if (rs.Values.Count() == 1) 131 | { 132 | var rtval = rs.Values.First().Value; 133 | return (long)rtval; 134 | } 135 | } 136 | 137 | } 138 | return -1; 139 | 140 | } 141 | 142 | #region IDisposable Support 143 | private bool disposedValue = false; // To detect redundant calls 144 | 145 | protected virtual void Dispose(bool disposing) 146 | { 147 | if (!disposedValue) 148 | { 149 | if (disposing) 150 | { 151 | if (_driver != null) _driver.Dispose(); 152 | } 153 | disposedValue = true; 154 | } 155 | } 156 | 157 | // This code added to correctly implement the disposable pattern. 158 | public void Dispose() 159 | { 160 | // Do not change this code. Put cleanup code in Dispose(bool disposing) above. 161 | Dispose(true); 162 | } 163 | #endregion 164 | 165 | } 166 | } 167 | -------------------------------------------------------------------------------- /HLApps.Revit.Graph.UIAddin/UI/GraphAppWindow.xaml: -------------------------------------------------------------------------------- 1 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 95 | 96 | 97 | 98 | 99 | 102 | 105 | 106 | 107 | 108 | 109 | -------------------------------------------------------------------------------- /HLApps.Revit.Graph.UIAddin/UI/ViewModel/Command.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Windows.Input; 3 | 4 | namespace HLApps.Revit.Graph.UIAddin.ViewModel 5 | { 6 | 7 | /// 8 | /// The ViewModelCommand class - an ICommand that can fire a function. 9 | /// 10 | public class Command : ICommand 11 | { 12 | /// 13 | /// Initializes a new instance of the class. 14 | /// 15 | /// The action. 16 | /// if set to true [can execute]. 17 | public Command(Action action, bool canExecute = true) 18 | { 19 | // Set the action. 20 | this.action = action; 21 | this.canExecute = canExecute; 22 | } 23 | 24 | /// 25 | /// Initializes a new instance of the class. 26 | /// 27 | /// The parameterized action. 28 | /// if set to true [can execute]. 29 | public Command(Action parameterizedAction, bool canExecute = true) 30 | { 31 | // Set the action. 32 | this.parameterizedAction = parameterizedAction; 33 | this.canExecute = canExecute; 34 | } 35 | 36 | /// 37 | /// Executes the command. 38 | /// 39 | /// The param. 40 | public virtual void DoExecute(object param) 41 | { 42 | // Invoke the executing command, allowing the command to be cancelled. 43 | CancelCommandEventArgs args = new CancelCommandEventArgs() { Parameter = param, Cancel = false }; 44 | InvokeExecuting(args); 45 | 46 | // If the event has been cancelled, bail now. 47 | if (args.Cancel) 48 | return; 49 | 50 | // Call the action or the parameterized action, whichever has been set. 51 | InvokeAction(param); 52 | 53 | // Call the executed function. 54 | InvokeExecuted(new CommandEventArgs() { Parameter = param }); 55 | } 56 | 57 | protected void InvokeAction(object param) 58 | { 59 | Action theAction = action; 60 | Action theParameterizedAction = parameterizedAction; 61 | if (theAction != null) 62 | theAction(); 63 | else if (theParameterizedAction != null) 64 | theParameterizedAction(param); 65 | } 66 | 67 | protected void InvokeExecuted(CommandEventArgs args) 68 | { 69 | CommandEventHandler executed = Executed; 70 | 71 | // Call the executed event. 72 | if (executed != null) 73 | executed(this, args); 74 | } 75 | 76 | protected void InvokeExecuting(CancelCommandEventArgs args) 77 | { 78 | CancelCommandEventHandler executing = Executing; 79 | 80 | // Call the executed event. 81 | if (executing != null) 82 | executing(this, args); 83 | } 84 | 85 | 86 | /// 87 | /// The action (or parameterized action) that will be called when the command is invoked. 88 | /// 89 | protected Action action = null; 90 | protected Action parameterizedAction = null; 91 | 92 | /// 93 | /// Bool indicating whether the command can execute. 94 | /// 95 | private bool canExecute = false; 96 | 97 | /// 98 | /// Gets or sets a value indicating whether this instance can execute. 99 | /// 100 | /// 101 | /// true if this instance can execute; otherwise, false. 102 | /// 103 | public bool CanExecute 104 | { 105 | get { return canExecute; } 106 | set 107 | { 108 | if (canExecute != value) 109 | { 110 | canExecute = value; 111 | EventHandler canExecuteChanged = CanExecuteChanged; 112 | if (canExecuteChanged != null) 113 | canExecuteChanged(this, EventArgs.Empty); 114 | } 115 | } 116 | } 117 | 118 | #region ICommand Members 119 | 120 | /// 121 | /// Defines the method that determines whether the command can execute in its current state. 122 | /// 123 | /// Data used by the command. If the command does not require data to be passed, this object can be set to null. 124 | /// 125 | /// true if this command can be executed; otherwise, false. 126 | /// 127 | bool ICommand.CanExecute(object parameter) 128 | { 129 | return canExecute; 130 | } 131 | 132 | /// 133 | /// Defines the method to be called when the command is invoked. 134 | /// 135 | /// Data used by the command. If the command does not require data to be passed, this object can be set to null. 136 | void ICommand.Execute(object parameter) 137 | { 138 | this.DoExecute(parameter); 139 | 140 | } 141 | 142 | #endregion 143 | 144 | 145 | /// 146 | /// Occurs when can execute is changed. 147 | /// 148 | public event EventHandler CanExecuteChanged; 149 | 150 | /// 151 | /// Occurs when the command is about to execute. 152 | /// 153 | public event CancelCommandEventHandler Executing; 154 | 155 | /// 156 | /// Occurs when the command executed. 157 | /// 158 | public event CommandEventHandler Executed; 159 | } 160 | 161 | /// 162 | /// The CommandEventHandler delegate. 163 | /// 164 | public delegate void CommandEventHandler(object sender, CommandEventArgs args); 165 | 166 | /// 167 | /// The CancelCommandEvent delegate. 168 | /// 169 | public delegate void CancelCommandEventHandler(object sender, CancelCommandEventArgs args); 170 | 171 | /// 172 | /// CommandEventArgs - simply holds the command parameter. 173 | /// 174 | public class CommandEventArgs : EventArgs 175 | { 176 | /// 177 | /// Gets or sets the parameter. 178 | /// 179 | /// The parameter. 180 | public object Parameter { get; set; } 181 | } 182 | 183 | /// 184 | /// CancelCommandEventArgs - just like above but allows the event to 185 | /// be cancelled. 186 | /// 187 | public class CancelCommandEventArgs : CommandEventArgs 188 | { 189 | /// 190 | /// Gets or sets a value indicating whether this command should be cancelled. 191 | /// 192 | /// true if cancel; otherwise, false. 193 | public bool Cancel { get; set; } 194 | } 195 | 196 | 197 | } 198 | -------------------------------------------------------------------------------- /HLApps.Revit.Graph/Geometry/Octree/PointOctree.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Runtime; 3 | using Autodesk.Revit.DB; 4 | 5 | // A Dynamic Octree for storing any objects that can be described as a single point 6 | // See also: BoundsOctree, where objects are described by AABB bounds 7 | // Octree: An octree is a tree data structure which divides 3D space into smaller partitions (nodes) 8 | // and places objects into the appropriate nodes. This allows fast access to objects 9 | // in an area of interest without having to check every object. 10 | // Dynamic: The octree grows or shrinks as required when objects as added or removed 11 | // It also splits and merges nodes as appropriate. There is no maximum depth. 12 | // Nodes have a constant - numObjectsAllowed - which sets the amount of items allowed in a node before it splits. 13 | // T: The content of the octree can be anything, since the bounds data is supplied separately. 14 | 15 | // Originally written for my game Scraps (http://www.scrapsgame.com) but intended to be general-purpose. 16 | // Copyright 2014 Nition, BSD licence (see LICENCE file). http://nition.co 17 | // Unity-based, but could be adapted to work in pure C# 18 | namespace HLApps.Revit.Geometry.Octree 19 | { 20 | public class PointOctree where T : class 21 | { 22 | // The total amount of objects currently in the tree 23 | public int Count { get; private set; } 24 | 25 | // Root node of the octree 26 | PointOctreeNode rootNode; 27 | // Size that the octree was on creation 28 | readonly float initialSize; 29 | // Minimum side length that a node can be - essentially an alternative to having a max depth 30 | readonly float minSize; 31 | 32 | /// 33 | /// Constructor for the point octree. 34 | /// 35 | /// Size of the sides of the initial node. The octree will never shrink smaller than this. 36 | /// Position of the centre of the initial node. 37 | /// Nodes will stop splitting if the new nodes would be smaller than this. 38 | public PointOctree(float initialWorldSize, XYZ initialWorldPos, float minNodeSize) 39 | { 40 | if (minNodeSize > initialWorldSize) 41 | { 42 | //Debug.LogWarning("Minimum node size must be at least as big as the initial world size. Was: " + minNodeSize + " Adjusted to: " + initialWorldSize); 43 | minNodeSize = initialWorldSize; 44 | } 45 | Count = 0; 46 | initialSize = initialWorldSize; 47 | minSize = minNodeSize; 48 | rootNode = new PointOctreeNode(initialSize, minSize, initialWorldPos); 49 | } 50 | 51 | // #### PUBLIC METHODS #### 52 | 53 | /// 54 | /// Add an object. 55 | /// 56 | /// Object to add. 57 | /// Position of the object. 58 | public void Add(T obj, XYZ objPos) 59 | { 60 | // Add object or expand the octree until it can be added 61 | int count = 0; // Safety check against infinite/excessive growth 62 | while (!rootNode.Add(obj, objPos)) 63 | { 64 | Grow(objPos - rootNode.Center); 65 | if (++count > 20) 66 | { 67 | //Debug.LogError("Aborted Add operation as it seemed to be going on forever (" + (count - 1) + ") attempts at growing the octree."); 68 | return; 69 | } 70 | } 71 | Count++; 72 | } 73 | 74 | /// 75 | /// Remove an object. Makes the assumption that the object only exists once in the tree. 76 | /// 77 | /// Object to remove. 78 | /// True if the object was removed successfully. 79 | public bool Remove(T obj) 80 | { 81 | bool removed = rootNode.Remove(obj); 82 | 83 | // See if we can shrink the octree down now that we've removed the item 84 | if (removed) 85 | { 86 | Count--; 87 | Shrink(); 88 | } 89 | 90 | return removed; 91 | } 92 | 93 | /// 94 | /// Return objects that are within maxDistance of the specified ray. 95 | /// If none, returns an empty array (not null). 96 | /// 97 | /// The ray. Passing as ref to improve performance since it won't have to be copied. 98 | /// Maximum distance from the ray to consider. 99 | /// Objects within range. 100 | public T[] GetNearby(Line ray, float maxDistance) 101 | { 102 | List collidingWith = new List(); 103 | rootNode.GetNearby(ref ray, ref maxDistance, collidingWith); 104 | return collidingWith.ToArray(); 105 | } 106 | 107 | public T[] GetNearby(XYZ point, float maxDistance) 108 | { 109 | List collidingWith = new List(); 110 | rootNode.GetNearby(ref point, ref maxDistance, collidingWith); 111 | return collidingWith.ToArray(); 112 | } 113 | /* 114 | /// 115 | /// Draws node boundaries visually for debugging. 116 | /// Must be called from OnDrawGizmos externally. See also: DrawAllObjects. 117 | /// 118 | public void DrawAllBounds() 119 | { 120 | rootNode.DrawAllBounds(); 121 | } 122 | 123 | /// 124 | /// Draws the bounds of all objects in the tree visually for debugging. 125 | /// Must be called from OnDrawGizmos externally. See also: DrawAllBounds. 126 | /// 127 | public void DrawAllObjects() 128 | { 129 | rootNode.DrawAllObjects(); 130 | } 131 | */ 132 | // #### PRIVATE METHODS #### 133 | 134 | /// 135 | /// Grow the octree to fit in all objects. 136 | /// 137 | /// Direction to grow. 138 | void Grow(XYZ direction) 139 | { 140 | int xDirection = direction.X >= 0 ? 1 : -1; 141 | int yDirection = direction.Y >= 0 ? 1 : -1; 142 | int zDirection = direction.Z >= 0 ? 1 : -1; 143 | PointOctreeNode oldRoot = rootNode; 144 | float half = rootNode.SideLength / 2; 145 | float newLength = rootNode.SideLength * 2; 146 | var newCenter = rootNode.Center + new XYZ(xDirection * half, yDirection * half, zDirection * half); 147 | 148 | // Create a new, bigger octree root node 149 | rootNode = new PointOctreeNode(newLength, minSize, newCenter); 150 | 151 | // Create 7 new octree children to go with the old root as children of the new root 152 | int rootPos = GetRootPosIndex(xDirection, yDirection, zDirection); 153 | PointOctreeNode[] children = new PointOctreeNode[8]; 154 | for (int i = 0; i < 8; i++) 155 | { 156 | if (i == rootPos) 157 | { 158 | children[i] = oldRoot; 159 | } 160 | else 161 | { 162 | xDirection = i % 2 == 0 ? -1 : 1; 163 | yDirection = i > 3 ? -1 : 1; 164 | zDirection = (i < 2 || (i > 3 && i < 6)) ? -1 : 1; 165 | children[i] = new PointOctreeNode(rootNode.SideLength, minSize, newCenter + new XYZ(xDirection * half, yDirection * half, zDirection * half)); 166 | } 167 | } 168 | 169 | // Attach the new children to the new root node 170 | rootNode.SetChildren(children); 171 | } 172 | 173 | /// 174 | /// Shrink the octree if possible, else leave it the same. 175 | /// 176 | void Shrink() 177 | { 178 | rootNode = rootNode.ShrinkIfPossible(initialSize); 179 | } 180 | 181 | /// 182 | /// Used when growing the octree. Works out where the old root node would fit inside a new, larger root node. 183 | /// 184 | /// X direction of growth. 1 or -1. 185 | /// Y direction of growth. 1 or -1. 186 | /// Z direction of growth. 1 or -1. 187 | /// Octant where the root node should be. 188 | static int GetRootPosIndex(int xDir, int yDir, int zDir) 189 | { 190 | int result = xDir > 0 ? 1 : 0; 191 | if (yDir < 0) result += 4; 192 | if (zDir > 0) result += 2; 193 | return result; 194 | } 195 | } 196 | } -------------------------------------------------------------------------------- /HLApps.Revit.Graph/Geometry/Octree/BoundsOctree.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using Autodesk.Revit.DB; 3 | 4 | // A Dynamic, Loose Octree for storing any objects that can be described with AABB bounds 5 | // See also: PointOctree, where objects are stored as single points and some code can be simplified 6 | // Octree: An octree is a tree data structure which divides 3D space into smaller partitions (nodes) 7 | // and places objects into the appropriate nodes. This allows fast access to objects 8 | // in an area of interest without having to check every object. 9 | // Dynamic: The octree grows or shrinks as required when objects as added or removed 10 | // It also splits and merges nodes as appropriate. There is no maximum depth. 11 | // Nodes have a constant - numObjectsAllowed - which sets the amount of items allowed in a node before it splits. 12 | // Loose: The octree's nodes can be larger than 1/2 their parent's length and width, so they overlap to some extent. 13 | // This can alleviate the problem of even tiny objects ending up in large nodes if they're near boundaries. 14 | // A looseness value of 1.0 will make it a "normal" octree. 15 | // T: The content of the octree can be anything, since the bounds data is supplied separately. 16 | 17 | // Originally written for my game Scraps (http://www.scrapsgame.com) but intended to be general-purpose. 18 | // Copyright 2014 Nition, BSD licence (see LICENCE file). http://nition.co 19 | // Unity-based, but could be adapted to work in pure C# 20 | 21 | // Note: For loops are often used here since in some cases (e.g. the IsColliding method) 22 | // they actually give much better performance than using Foreach, even in the compiled build. 23 | // Using a LINQ expression is worse again than Foreach. 24 | namespace HLApps.Revit.Geometry.Octree 25 | { 26 | 27 | 28 | 29 | public class BoundsOctree 30 | { 31 | // The total amount of objects currently in the tree 32 | public int Count { get; private set; } 33 | 34 | // Root node of the octree 35 | BoundsOctreeNode rootNode; 36 | // Should be a value between 1 and 2. A multiplier for the base size of a node. 37 | // 1.0 is a "normal" octree, while values > 1 have overlap 38 | readonly float looseness; 39 | // Size that the octree was on creation 40 | readonly float initialSize; 41 | // Minimum side length that a node can be - essentially an alternative to having a max depth 42 | readonly float minSize; 43 | 44 | /// 45 | /// Constructor for the bounds octree. 46 | /// 47 | /// Size of the sides of the initial node, in metres. The octree will never shrink smaller than this. 48 | /// Position of the centre of the initial node. 49 | /// Nodes will stop splitting if the new nodes would be smaller than this (metres). 50 | /// Clamped between 1 and 2. Values > 1 let nodes overlap. 51 | public BoundsOctree(float initialWorldSize, XYZ initialWorldPos, float minNodeSize, float loosenessVal) 52 | { 53 | if (minNodeSize > initialWorldSize) 54 | { 55 | //Debug.LogWarning("Minimum node size must be at least as big as the initial world size. Was: " + minNodeSize + " Adjusted to: " + initialWorldSize); 56 | minNodeSize = initialWorldSize; 57 | } 58 | Count = 0; 59 | initialSize = initialWorldSize; 60 | minSize = minNodeSize; 61 | looseness = 1.0f; //Mathf.Clamp(loosenessVal, 1.0f, 2.0f); 62 | rootNode = new BoundsOctreeNode(initialSize, minSize, loosenessVal, initialWorldPos); 63 | } 64 | 65 | // #### PUBLIC METHODS #### 66 | 67 | /// 68 | /// Add an object. 69 | /// 70 | /// Object to add. 71 | /// 3D bounding box around the object. 72 | public void Add(T obj, HLBoundingBoxXYZ objBounds) 73 | { 74 | // Add object or expand the octree until it can be added 75 | int count = 0; // Safety check against infinite/excessive growth 76 | while (!rootNode.Add(obj, objBounds)) 77 | { 78 | Grow(objBounds.MidPoint - rootNode.Center); 79 | if (++count > 20) 80 | { 81 | //Debug.LogError("Aborted Add operation as it seemed to be going on forever (" + (count - 1) + ") attempts at growing the octree."); 82 | return; 83 | } 84 | } 85 | Count++; 86 | } 87 | 88 | /// 89 | /// Remove an object. Makes the assumption that the object only exists once in the tree. 90 | /// 91 | /// Object to remove. 92 | /// True if the object was removed successfully. 93 | public bool Remove(T obj) 94 | { 95 | bool removed = rootNode.Remove(obj); 96 | 97 | // See if we can shrink the octree down now that we've removed the item 98 | if (removed) 99 | { 100 | Count--; 101 | Shrink(); 102 | } 103 | 104 | return removed; 105 | } 106 | 107 | 108 | /// 109 | /// Check if the specified bounds intersect with anything in the tree. See also: GetColliding. 110 | /// 111 | /// bounds to check. 112 | /// True if there was a collision. 113 | public bool IsColliding(HLBoundingBoxXYZ checkBounds, Filter flt = null) 114 | { 115 | //#if UNITY_EDITOR 116 | // For debugging 117 | //AddCollisionCheck(checkBounds); 118 | //#endif 119 | 120 | 121 | return rootNode.IsColliding(ref checkBounds, flt); 122 | } 123 | 124 | 125 | /// 126 | /// Returns an array of objects that intersect with the specified bounds, if any. Otherwise returns an empty array. See also: IsColliding. 127 | /// 128 | /// bounds to check. 129 | /// Objects that intersect with the specified bounds. 130 | public T[] GetColliding(HLBoundingBoxXYZ checkBounds, Filter flt = null) 131 | { 132 | //#if UNITY_EDITOR 133 | // For debugging 134 | //AddCollisionCheck(checkBounds); 135 | //#endif 136 | List collidingWith = new List(); 137 | rootNode.GetColliding(ref checkBounds, collidingWith, flt); 138 | return collidingWith.ToArray(); 139 | } 140 | 141 | /// 142 | /// Returns an array of objects that intersect with the specified bounds, if any. Otherwise returns an empty array. See also: IsColliding. 143 | /// 144 | /// bounds to check. 145 | /// Objects that intersect with the specified bounds. 146 | public T[] GetColliding(Line ray, Filter flt = null) 147 | { 148 | //#if UNITY_EDITOR 149 | // For debugging 150 | //AddCollisionCheck(checkBounds); 151 | //#endif 152 | List collidingWith = new List(); 153 | rootNode.GetColliding(ref ray, collidingWith, flt); 154 | return collidingWith.ToArray(); 155 | } 156 | 157 | /// 158 | /// Grow the octree to fit in all objects. 159 | /// 160 | /// Direction to grow. 161 | void Grow(XYZ direction) 162 | { 163 | int xDirection = direction.X >= 0 ? 1 : -1; 164 | int yDirection = direction.Y >= 0 ? 1 : -1; 165 | int zDirection = direction.Z >= 0 ? 1 : -1; 166 | BoundsOctreeNode oldRoot = rootNode; 167 | float half = rootNode.BaseLength / 2; 168 | float newLength = rootNode.BaseLength * 2; 169 | var newCenter = rootNode.Center + new XYZ(xDirection * half, yDirection * half, zDirection * half); 170 | 171 | // Create a new, bigger octree root node 172 | rootNode = new BoundsOctreeNode(newLength, minSize, looseness, newCenter); 173 | 174 | // Create 7 new octree children to go with the old root as children of the new root 175 | int rootPos = GetRootPosIndex(xDirection, yDirection, zDirection); 176 | BoundsOctreeNode[] children = new BoundsOctreeNode[8]; 177 | for (int i = 0; i < 8; i++) 178 | { 179 | if (i == rootPos) 180 | { 181 | children[i] = oldRoot; 182 | } 183 | else 184 | { 185 | xDirection = i % 2 == 0 ? -1 : 1; 186 | yDirection = i > 3 ? -1 : 1; 187 | zDirection = (i < 2 || (i > 3 && i < 6)) ? -1 : 1; 188 | children[i] = new BoundsOctreeNode(rootNode.BaseLength, minSize, looseness, newCenter + new XYZ(xDirection * half, yDirection * half, zDirection * half)); 189 | } 190 | } 191 | 192 | // Attach the new children to the new root node 193 | rootNode.SetChildren(children); 194 | } 195 | 196 | /// 197 | /// Shrink the octree if possible, else leave it the same. 198 | /// 199 | void Shrink() 200 | { 201 | rootNode = rootNode.ShrinkIfPossible(initialSize); 202 | } 203 | 204 | /// 205 | /// Used when growing the octree. Works out where the old root node would fit inside a new, larger root node. 206 | /// 207 | /// X direction of growth. 1 or -1. 208 | /// Y direction of growth. 1 or -1. 209 | /// Z direction of growth. 1 or -1. 210 | /// Octant where the root node should be. 211 | static int GetRootPosIndex(int xDir, int yDir, int zDir) 212 | { 213 | int result = xDir > 0 ? 1 : 0; 214 | if (yDir < 0) result += 4; 215 | if (zDir > 0) result += 2; 216 | return result; 217 | } 218 | } 219 | } -------------------------------------------------------------------------------- /HLApps.Revit.Graph/Graph/MEPPathNode.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Collections; 3 | using System.Linq; 4 | 5 | using Autodesk.Revit.DB; 6 | using Autodesk.Revit.DB.Mechanical; 7 | using Autodesk.Revit.DB.Plumbing; 8 | 9 | using HLApps.Revit.Utils; 10 | using HLApps.Revit.Geometry; 11 | using gmdl = HLApps.MEPGraph.Model; 12 | 13 | 14 | 15 | namespace HLApps.Revit.Graph 16 | { 17 | 18 | public class MEPRevitNode 19 | { 20 | 21 | public MEPRevitNode() 22 | { 23 | Connections = new HashSet(); 24 | OrginTransform = Transform.Identity; 25 | } 26 | 27 | public MEPRevitNode(string name, string category, string sectionType, gmdl.Node analyticalNode) : this() 28 | { 29 | _name = name; 30 | _node = analyticalNode; 31 | OrginCategoryName = category; 32 | AsElementNode.Name = _name; 33 | AsAbstractNode.Name = sectionType; 34 | AsAbstractNode.ExtendedProperties.Add("Category", this.OrginCategoryName); 35 | } 36 | 37 | 38 | public MEPRevitNode(int orgId) : this() 39 | { 40 | _ordId = orgId; 41 | Connections = new HashSet(); 42 | 43 | } 44 | 45 | public MEPRevitNode(Element elm) : this() 46 | { 47 | if (elm == null) return; 48 | 49 | _ordId = elm.Id.IntegerValue; 50 | OrginIsInLinked = elm.Document.IsLinked; 51 | OrginDocIdent = DocUtils.GetDocumentIdent(elm.Document); 52 | 53 | _name = elm.Name; 54 | 55 | if (elm is FamilyInstance) 56 | { 57 | var fs = (elm as FamilyInstance); 58 | 59 | if (fs.MEPModel is MechanicalFitting) 60 | { 61 | _name = (fs.MEPModel as MechanicalFitting).PartType.ToString(); 62 | } 63 | else if (fs.Symbol != null) 64 | { 65 | #if REVIT2015 66 | if (_name != fs.Symbol.FamilyName) 67 | { 68 | _name = fs.Symbol.FamilyName + " : " + _name; 69 | 70 | } 71 | #else 72 | _name = fs.Symbol.Name; 73 | #endif 74 | } 75 | } 76 | else if (elm is Space) 77 | { 78 | var sp = (elm as Space); 79 | _name = sp.Number + " : " + sp.Name; 80 | } 81 | 82 | 83 | if (elm.Category.Id.IntegerValue == (int)BuiltInCategory.OST_MechanicalEquipment) _node = new gmdl.Equipment();//_sectionType = MEPPathSectionType.Equipment; 84 | if (elm.Category.Id.IntegerValue == (int)BuiltInCategory.OST_MEPSpaces) _node = new gmdl.Space(); //_sectionType = MEPPathSectionType.Space; 85 | 86 | if (elm.Category.Id.IntegerValue == (int)BuiltInCategory.OST_DuctFitting) _node = new gmdl.DuctTransition(); //_sectionType = MEPPathSectionType.Transition; 87 | if (elm.Category.Id.IntegerValue == (int)BuiltInCategory.OST_PipeFitting) _node = new gmdl.PipeTransition(); //_sectionType = MEPPathSectionType.Transition; 88 | if (elm.Category.Id.IntegerValue == (int)BuiltInCategory.OST_CableTrayFitting) _node = new gmdl.CableTrayTransition(); ;// _sectionType = MEPPathSectionType.Transition; 89 | 90 | if (elm.Category.Id.IntegerValue == (int)BuiltInCategory.OST_DuctAccessory) _node = new gmdl.DuctAccessory(); //_sectionType = MEPPathSectionType.Accessory; 91 | if (elm.Category.Id.IntegerValue == (int)BuiltInCategory.OST_PipeAccessory) _node = new gmdl.PipeAccessory(); //_sectionType = MEPPathSectionType.Accessory; 92 | 93 | if (elm.Category.Id.IntegerValue == (int)BuiltInCategory.OST_DuctCurves) _node = new gmdl.Duct(); //_sectionType = MEPPathSectionType.Section; 94 | if (elm.Category.Id.IntegerValue == (int)BuiltInCategory.OST_FlexDuctCurves) _node = new gmdl.Duct(); // _sectionType = MEPPathSectionType.Section; 95 | if (elm.Category.Id.IntegerValue == (int)BuiltInCategory.OST_PipeCurves) _node = new gmdl.Pipe(); // _sectionType = MEPPathSectionType.Section; 96 | if (elm.Category.Id.IntegerValue == (int)BuiltInCategory.OST_FlexPipeCurves) _node = new gmdl.Pipe(); // _sectionType = MEPPathSectionType.Section; 97 | if (elm.Category.Id.IntegerValue == (int)BuiltInCategory.OST_CableTray) _node = new gmdl.CableTray(); //_sectionType = MEPPathSectionType.Section; 98 | 99 | if (elm.Category.Id.IntegerValue == (int)BuiltInCategory.OST_DuctTerminal) _node = new gmdl.Terminal(); // _sectionType = MEPPathSectionType.Terminal; 100 | 101 | if (elm.Category.Id.IntegerValue == (int)BuiltInCategory.OST_ElectricalEquipment) _node = new gmdl.DBPanel(); 102 | if (elm.Category.Id.IntegerValue == (int)BuiltInCategory.OST_ElectricalFixtures) _node = new gmdl.ElectricalLoad(); 103 | if (elm.Category.Id.IntegerValue == (int)BuiltInCategory.OST_LightingDevices) _node = new gmdl.Lighting(); 104 | if (elm.Category.Id.IntegerValue == (int)BuiltInCategory.OST_LightingFixtures) _node = new gmdl.Lighting(); 105 | if (elm.Category.Id.IntegerValue == (int)BuiltInCategory.OST_DataDevices) _node = new gmdl.Data(); 106 | if (elm.Category.Id.IntegerValue == (int)BuiltInCategory.OST_SecurityDevices) _node = new gmdl.Security(); 107 | if (elm.Category.Id.IntegerValue == (int)BuiltInCategory.OST_NurseCallDevices) _node = new gmdl.Safety(); 108 | if (elm.Category.Id.IntegerValue == (int)BuiltInCategory.OST_Sprinklers) _node = new gmdl.Sprinkler(); 109 | if (elm.Category.Id.IntegerValue == (int)BuiltInCategory.OST_FireAlarmDevices) _node = new gmdl.FireAlarm(); 110 | if (elm.Category.Id.IntegerValue == (int)BuiltInCategory.OST_ElectricalCircuit) _node = new gmdl.Circuit(); 111 | 112 | if (elm.Category.Id.IntegerValue == (int)BuiltInCategory.OST_CurtainWallPanels) _node = new gmdl.Wall(); 113 | if (elm.Category.Id.IntegerValue == (int)BuiltInCategory.OST_Walls) _node = new gmdl.Wall(); 114 | if (elm.Category.Id.IntegerValue == (int)BuiltInCategory.OST_Ceilings) _node = new gmdl.Ceiling(); 115 | if (elm.Category.Id.IntegerValue == (int)BuiltInCategory.OST_Doors) _node = new gmdl.Door(); 116 | if (elm.Category.Id.IntegerValue == (int)BuiltInCategory.OST_Floors) _node = new gmdl.Floor(); 117 | if (elm.Category.Id.IntegerValue == (int)BuiltInCategory.OST_Windows) _node = new gmdl.Window(); 118 | if (elm.Category.Id.IntegerValue == (int)BuiltInCategory.OST_Roofs) _node = new gmdl.Roof(); 119 | if (elm.Category.Id.IntegerValue == (int)BuiltInCategory.OST_Columns) _node = new gmdl.Column(); 120 | 121 | if (elm.Category.Id.IntegerValue == (int)BuiltInCategory.OST_Levels) _node = new gmdl.Level(); 122 | 123 | if (elm.Category != null) 124 | { 125 | OrginCategoryId = elm.Category.Id.IntegerValue; 126 | OrginCategoryName = elm.Category.Name; 127 | } 128 | 129 | Level flevel = null; 130 | if (elm is FamilyInstance) 131 | { 132 | flevel = elm.Document.GetElement(elm.LevelId) as Level; 133 | } 134 | else if (elm is MEPCurve) 135 | { 136 | var mepc = elm as MEPCurve; 137 | flevel = mepc.ReferenceLevel; 138 | /* 139 | var mplc = mepc.Location as LocationCurve; 140 | var midPoint = (mplc.Curve.GetEndPoint(0) + mplc.Curve.GetEndPoint(1)) / 2; 141 | var levels = HLRevitUtilities.GetElements(elm.Document).OrderBy(lv => lv.ProjectElevation); 142 | 143 | flevel = levels.LastOrDefault(lv => lv.ProjectElevation < midPoint.Z);*/ 144 | } 145 | 146 | if (flevel != null) 147 | { 148 | this.LevelId = flevel.Id.IntegerValue; 149 | this.LevelName = flevel.Name; 150 | 151 | //var levels = HLRevitUtilities.GetElements(elm.Document).OrderBy(lv => lv.ProjectElevation).ToList(); 152 | //var lev = levels.First(l => l.Id.IntegerValue == flevel.Id.IntegerValue); 153 | //LevelIndex = levels.IndexOf(lev); 154 | } 155 | 156 | 157 | AsElementNode.ExtendedProperties.Add("UniqueId", elm.UniqueId); 158 | AsElementNode.ExtendedProperties.Add("Name", Name); 159 | AsElementNode.Name = this.Name; 160 | AsAbstractNode.Name = this.Name; 161 | AsAbstractNode.ExtendedProperties.Add("Category", this.OrginCategoryName); 162 | 163 | } 164 | 165 | string _name; 166 | public string Name 167 | { 168 | get 169 | { 170 | return _name; 171 | } 172 | } 173 | 174 | /*MEPPathSectionType _sectionType = MEPPathSectionType.Section; 175 | public MEPPathSectionType SectionType 176 | { 177 | get { return _sectionType; } 178 | }*/ 179 | 180 | 181 | int _ordId = -1; 182 | public int OriginId 183 | { 184 | get { return _ordId; } 185 | } 186 | 187 | 188 | public bool OrginIsInLinked { get; private set; } 189 | public string OrginDocIdent { get; private set; } 190 | public Transform OrginTransform { get; set; } 191 | public int OrginCategoryId { get; set; } 192 | public string OrginCategoryName { get; set; } 193 | 194 | public string LevelName { get; set; } 195 | public int LevelId { get; set; } 196 | public int LevelIndex { get; set; } 197 | 198 | 199 | public ICollection In 200 | { 201 | get 202 | { 203 | return Connections.Where(cn => cn.Direction == MEPPathDirection.In).Select(n => n.NextNode).ToList(); 204 | } 205 | } 206 | 207 | public ICollection Out 208 | { 209 | get 210 | { 211 | return Connections.Where(cn => cn.Direction == MEPPathDirection.Out).Select(n => n.NextNode).ToList(); 212 | } 213 | } 214 | 215 | 216 | public HashSet Connections { get; } 217 | 218 | public override string ToString() 219 | { 220 | return Name; 221 | } 222 | 223 | public Dictionary Properties = new Dictionary(); 224 | 225 | public object GetProperty(string name) 226 | { 227 | if (Properties.ContainsKey(name)) 228 | { 229 | return Properties[name]; 230 | } 231 | else 232 | { 233 | throw new System.Exception("Node does not contain property: " + name); 234 | } 235 | } 236 | 237 | public void SetProperty(string name, object value) 238 | { 239 | if (Properties.ContainsKey(name)) 240 | { 241 | Properties[name] = value; 242 | } 243 | else 244 | { 245 | Properties.Add(name, value); 246 | } 247 | } 248 | 249 | 250 | gmdl.ModelElement _modelNode; 251 | public virtual gmdl.ModelElement AsElementNode 252 | { 253 | get 254 | { 255 | if (_modelNode == null) _modelNode = new gmdl.ModelElement(); 256 | 257 | return _modelNode; 258 | 259 | } 260 | } 261 | 262 | 263 | gmdl.Node _node; 264 | public virtual gmdl.Node AsAbstractNode 265 | { 266 | get 267 | { 268 | if (_node != null) return _node; 269 | _node = new gmdl.Section(); 270 | return _node; 271 | } 272 | } 273 | 274 | public HLBoundingBoxXYZ BoundingBox { get; set; } 275 | 276 | } 277 | } 278 | -------------------------------------------------------------------------------- /HLApps.Revit.Graph/Graph/MEPGraphWriter.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Linq; 3 | 4 | using HLApps.Revit.Utils; 5 | using HLApps.MEPGraph; 6 | using HLApps.MEPGraph.Model; 7 | 8 | 9 | namespace HLApps.Revit.Graph 10 | { 11 | public class MEPGraphWriter 12 | { 13 | IGraphDBClient _gdbClient; 14 | public MEPGraphWriter(IGraphDBClient gdbClient) 15 | { 16 | _gdbClient = gdbClient; 17 | } 18 | 19 | 20 | public void Write(MEPRevitGraph mepGraph, Autodesk.Revit.DB.Document rootDoc) 21 | { 22 | 23 | var track = new Dictionary(); 24 | 25 | var models = new Dictionary(); 26 | var types = new Dictionary(); 27 | var levels = new Dictionary(); 28 | 29 | var rootModelNode = new RevitModel(); 30 | var rootModelIdent = DocUtils.GetDocumentIdent(rootDoc); 31 | rootModelNode.Name = rootDoc.PathName; 32 | rootModelNode.ExtendedProperties.Add("Identity", rootModelIdent); 33 | rootModelNode.ExtendedProperties.Add("DateTimeStamp", System.DateTime.Now); 34 | var rootparams = MEPGraphUtils.GetNodePropsWithElementProps(rootModelNode, rootDoc.ProjectInformation); 35 | var seid = _gdbClient.Push(rootModelNode, rootparams); 36 | models.Add(rootModelIdent, seid); 37 | 38 | 39 | 40 | //add the nodes 41 | foreach (var mepNode in mepGraph.Nodes) 42 | { 43 | 44 | var npNode = mepNode.AsAbstractNode; 45 | var elmAbParams = npNode.GetAllProperties(); 46 | 47 | 48 | if (!string.IsNullOrEmpty(mepNode.OrginDocIdent)) 49 | { 50 | var elmNode = mepNode.AsElementNode; 51 | var elmParms = elmNode.GetAllProperties(); 52 | 53 | var elmdoc = DocUtils.GetDocument(mepNode.OrginDocIdent, rootDoc.Application); 54 | var elm = elmdoc.GetElement(new Autodesk.Revit.DB.ElementId(mepNode.OriginId)); 55 | if (elm != null) 56 | { 57 | 58 | elmParms = MEPGraphUtils.GetNodePropsWithElementProps(elmNode, elm); 59 | elmAbParams = MEPGraphUtils.GetNodePropsWithElementProps(npNode, elm); 60 | } 61 | 62 | var atid = _gdbClient.Push(npNode, elmAbParams); 63 | track.Add(mepNode, atid); 64 | 65 | var elmid = _gdbClient.Push(elmNode, elmParms); 66 | 67 | //relate the element node to the abstracted model node 68 | _gdbClient.Relate(atid, elmid, MEPEdgeTypes.REALIZED_BY, null); 69 | 70 | 71 | var modelId = 0L; 72 | //create up model nodes 73 | if (models.ContainsKey(mepNode.OrginDocIdent)) 74 | { 75 | modelId = models[mepNode.OrginDocIdent]; 76 | } 77 | else 78 | { 79 | var modelNode = new RevitModel(); 80 | modelNode.ExtendedProperties.Add("Identity", mepNode.OrginDocIdent); 81 | var mparams = modelNode.GetAllProperties(); 82 | 83 | var ldoc = DocUtils.GetDocument(mepNode.OrginDocIdent, rootDoc.Application); 84 | if (ldoc != null) 85 | { 86 | mparams = MEPGraphUtils.GetNodePropsWithElementProps(modelNode, ldoc.ProjectInformation); 87 | } 88 | 89 | modelId = _gdbClient.Push(modelNode, mparams); 90 | models.Add(mepNode.OrginDocIdent, modelId); 91 | } 92 | 93 | var elmedgeProps = MEPGraphUtils.GetEdgeProps(elm); 94 | //connect up model node to element node 95 | _gdbClient.Relate(elmid, modelId, MEPEdgeTypes.IS_IN, elmedgeProps); 96 | 97 | Autodesk.Revit.DB.Element typeElm = null; 98 | 99 | 100 | if (elm is Autodesk.Revit.DB.FamilyInstance) 101 | { 102 | typeElm = (elm as Autodesk.Revit.DB.FamilyInstance).Symbol; 103 | 104 | } 105 | else 106 | { 107 | var mpType = elm.GetTypeId(); 108 | typeElm = elmdoc.GetElement(mpType); 109 | } 110 | 111 | /* 112 | if (elm is Autodesk.Revit.DB.MEPCurve) 113 | { 114 | var mpType = (elm as Autodesk.Revit.DB.MEPCurve).GetTypeId(); 115 | typeElm = elmdoc.GetElement(mpType); 116 | } 117 | else if (elm is Autodesk.Revit.DB.RoofBase) 118 | { 119 | var mpType = (elm as Autodesk.Revit.DB.RoofBase).GetTypeId(); 120 | typeElm = elmdoc.GetElement(mpType); 121 | } 122 | else if (elm is Autodesk.Revit.DB.Floor) 123 | { 124 | var mpType = (elm as Autodesk.Revit.DB.Floor).GetTypeId(); 125 | typeElm = elmdoc.GetElement(mpType); 126 | } 127 | else if (elm is Autodesk.Revit.DB.Ceiling) 128 | { 129 | var mpType = (elm as Autodesk.Revit.DB.Ceiling).GetTypeId(); 130 | typeElm = elmdoc.GetElement(mpType); 131 | } 132 | else if (elm is Autodesk.Revit.DB.Wall) 133 | { 134 | var mpType = (elm as Autodesk.Revit.DB.Wall).GetTypeId(); 135 | typeElm = elmdoc.GetElement(mpType); 136 | } 137 | else if (elm is Autodesk.Revit.DB.SpatialElement) 138 | { 139 | var mpType = (elm as Autodesk.Revit.DB.SpatialElement).GetTypeId(); 140 | typeElm = elmdoc.GetElement(mpType); 141 | } 142 | else if (elm is Autodesk.Revit.DB.Electrical.ElectricalSystem) 143 | { 144 | var mpType = (elm as Autodesk.Revit.DB.Electrical.ElectricalSystem).GetTypeId(); 145 | typeElm = elmdoc.GetElement(mpType); 146 | } 147 | */ 148 | 149 | //create type nodes 150 | if (typeElm != null) 151 | { 152 | var tsId = 0L; 153 | if (!types.ContainsKey(typeElm.UniqueId)) 154 | { 155 | var edgeProps = MEPGraphUtils.GetEdgeProps(typeElm); 156 | var tsNode = new ElementType(); 157 | tsNode.Name = typeElm.Name; 158 | var tsprops = MEPGraphUtils.GetNodePropsWithElementProps(tsNode, typeElm); 159 | 160 | tsId = _gdbClient.Push(tsNode, tsprops); 161 | types.Add(typeElm.UniqueId, tsId); 162 | 163 | var tselmNode = new ModelElement(); 164 | var tselmId = _gdbClient.Push(tselmNode, tsprops); 165 | 166 | _gdbClient.Relate(tsId, tselmId, MEPEdgeTypes.REALIZED_BY, null); 167 | _gdbClient.Relate(tselmId, modelId, MEPEdgeTypes.IS_IN, edgeProps); 168 | } 169 | else 170 | { 171 | tsId = types[typeElm.UniqueId]; 172 | } 173 | _gdbClient.Relate(atid, tsId, MEPEdgeTypes.IS_OF, null); 174 | 175 | } 176 | 177 | 178 | 179 | //create level nodes 180 | var lvl = elmdoc.GetElement(new Autodesk.Revit.DB.ElementId(mepNode.LevelId)); 181 | if (lvl != null) 182 | { 183 | var edgeProps = MEPGraphUtils.GetEdgeProps(lvl); 184 | var lvlId = 0L; 185 | if (!levels.ContainsKey(lvl.UniqueId)) 186 | { 187 | var lvlNode = new Level(); 188 | lvlNode.Name = lvl.Name; 189 | var lvlprops = MEPGraphUtils.GetNodePropsWithElementProps(lvlNode, lvl); 190 | lvlId = _gdbClient.Push(lvlNode, lvlprops); 191 | levels.Add(lvl.UniqueId, lvlId); 192 | _gdbClient.Relate(lvlId, modelId, MEPEdgeTypes.IS_IN, edgeProps); 193 | } 194 | else 195 | { 196 | lvlId = levels[lvl.UniqueId]; 197 | } 198 | 199 | _gdbClient.Relate(atid, lvlId, MEPEdgeTypes.IS_ON, null); 200 | 201 | } 202 | 203 | } 204 | else 205 | { 206 | var modelId = _gdbClient.Push(npNode, elmAbParams); 207 | track.Add(mepNode, modelId); 208 | } 209 | 210 | 211 | } 212 | 213 | //now add the adjacencies 214 | foreach (var mepEdge in mepGraph.Edges) 215 | { 216 | if (!track.ContainsKey(mepEdge.ThisNode)) 217 | { 218 | continue; 219 | } 220 | 221 | if (!track.ContainsKey(mepEdge.NextNode)) 222 | { 223 | continue; 224 | } 225 | 226 | var nid1 = track[mepEdge.ThisNode]; 227 | var nid2 = track[mepEdge.NextNode]; 228 | 229 | var edPArams = new Dictionary(); 230 | foreach (var wkvp in mepEdge.Weights) 231 | { 232 | edPArams.Add(wkvp.Key, wkvp.Value); 233 | } 234 | 235 | 236 | _gdbClient.Relate(nid1, nid2, mepEdge.AsNodeEdge.EdgeType, edPArams); 237 | } 238 | 239 | 240 | //add systems and connections 241 | foreach (var system in mepGraph.Systems) 242 | { 243 | 244 | var sysNode = new MEPGraph.Model.System(); 245 | 246 | var syselm = rootDoc.GetElement(new Autodesk.Revit.DB.ElementId(system)); 247 | var srops = MEPGraphUtils.GetNodePropsWithElementProps(sysNode, syselm); 248 | var sysNodeId = _gdbClient.Push(sysNode, srops); 249 | 250 | var tselmNode = new ModelElement(); 251 | tselmNode.ExtendedProperties.Add("UniqueId", syselm.UniqueId); 252 | 253 | var emprops = MEPGraphUtils.GetNodePropsWithElementProps(tselmNode, syselm); 254 | var tselmId = _gdbClient.Push(tselmNode, emprops); 255 | _gdbClient.Relate(sysNodeId, tselmId, MEPEdgeTypes.REALIZED_BY, null); 256 | var edgeProps = MEPGraphUtils.GetEdgeProps(syselm); 257 | _gdbClient.Relate(tselmId, seid, MEPEdgeTypes.IS_IN, edgeProps); 258 | 259 | 260 | var stypeId = syselm.GetTypeId(); 261 | var typeElm = rootDoc.GetElement(stypeId); 262 | if (typeElm != null) 263 | { 264 | var tsId = 0L; 265 | if (!types.ContainsKey(typeElm.UniqueId)) 266 | { 267 | var stypeedgeProps = MEPGraphUtils.GetEdgeProps(typeElm); 268 | var tsNode = new ElementType(); 269 | tsNode.Name = typeElm.Name; 270 | var tsprops = MEPGraphUtils.GetNodePropsWithElementProps(tsNode, typeElm); 271 | 272 | tsId = _gdbClient.Push(tsNode, tsprops); 273 | types.Add(typeElm.UniqueId, tsId); 274 | 275 | var sysTypeelmNode = new ModelElement(); 276 | var sysTypeelmId = _gdbClient.Push(sysTypeelmNode, tsprops); 277 | 278 | _gdbClient.Relate(tsId, sysTypeelmId, MEPEdgeTypes.REALIZED_BY, null); 279 | _gdbClient.Relate(tselmId, seid, MEPEdgeTypes.IS_IN, stypeedgeProps); 280 | } 281 | else 282 | { 283 | tsId = types[typeElm.UniqueId]; 284 | } 285 | 286 | _gdbClient.Relate(sysNodeId, tsId, MEPEdgeTypes.IS_OF, null); 287 | 288 | } 289 | 290 | var snodes = mepGraph.GetAllNodesForSystem(system); 291 | foreach (var snd in snodes) 292 | { 293 | if (!track.ContainsKey(snd)) 294 | { 295 | continue; 296 | } 297 | 298 | var rid = track[snd]; 299 | _gdbClient.Relate(rid, sysNodeId, MEPEdgeTypes.ABSTRACTED_BY, null); 300 | } 301 | 302 | } 303 | 304 | } 305 | 306 | 307 | 308 | } 309 | } 310 | -------------------------------------------------------------------------------- /HLApps.Revit.Graph/Geometry/HLBoundingBoxXYZ.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using Autodesk.Revit.DB; 5 | 6 | namespace HLApps.Revit.Geometry 7 | { 8 | public class HLBoundingBoxXYZ // : Tuple 9 | { 10 | public static HLBoundingBoxXYZ FromXYZPoints(IList points) 11 | { 12 | HLBoundingBoxXYZ bbox = new HLBoundingBoxXYZ(); 13 | 14 | foreach (XYZ point in points) 15 | { 16 | bbox.ExpandToContain(point); 17 | } 18 | 19 | return bbox; 20 | } 21 | 22 | 23 | /// 24 | /// Minimum and maximum X, Y and Z values. 25 | /// 26 | double xmin, ymin, zmin, xmax, ymax, zmax; 27 | 28 | /// 29 | /// Initialise to infinite values. 30 | /// 31 | public HLBoundingBoxXYZ() 32 | { 33 | xmin = ymin = zmin = double.MaxValue; 34 | xmax = ymax = zmax = double.MinValue; 35 | } 36 | 37 | public HLBoundingBoxXYZ(XYZ min, XYZ max, bool wibble) 38 | { 39 | xmin = ymin = zmin = double.MaxValue; 40 | xmax = ymax = zmax = double.MinValue; 41 | 42 | ExpandToContain(min); 43 | ExpandToContain(max); 44 | } 45 | 46 | /// 47 | /// Initialise to finiate values. 48 | /// 49 | public HLBoundingBoxXYZ(BoundingBoxXYZ rvBox) 50 | { 51 | xmin = rvBox.Min.X; 52 | xmax = rvBox.Max.X; 53 | 54 | ymin = rvBox.Min.Y; 55 | ymax = rvBox.Max.Y; 56 | 57 | zmin = rvBox.Min.Z; 58 | zmax = rvBox.Max.Z; 59 | } 60 | 61 | /// 62 | /// Initialise to finiate values. 63 | /// 64 | public HLBoundingBoxXYZ(XYZ center, XYZ size) 65 | { 66 | 67 | xmin = center.X - (size.X * 0.5); 68 | ymin = center.Y - (size.Y * 0.5); 69 | zmin = center.Z - (size.Z * 0.5); 70 | 71 | xmax = center.X + (size.X * 0.5); 72 | ymax = center.Y + (size.Y * 0.5); 73 | zmax = center.Z + (size.Z * 0.5); 74 | } 75 | 76 | /// 77 | /// Return current lower left corner. 78 | /// 79 | public XYZ Min 80 | { 81 | get { return new XYZ(xmin, ymin, zmin); } 82 | } 83 | 84 | /// 85 | /// Return current upper right corner. 86 | /// 87 | public XYZ Max 88 | { 89 | get { return new XYZ(xmax, ymax, zmax); } 90 | } 91 | 92 | public XYZ MidPoint 93 | { 94 | get { return 0.5 * (Min + Max); } 95 | } 96 | 97 | /// 98 | /// Expand bounding box to contain 99 | /// the given new point. 100 | /// 101 | public void ExpandToContain(XYZ p) 102 | { 103 | if (p.X < xmin) { xmin = p.X; } 104 | if (p.Y < ymin) { ymin = p.Y; } 105 | if (p.Z < zmin) { zmin = p.Z; } 106 | if (p.X > xmax) { xmax = p.X; } 107 | if (p.Y > ymax) { ymax = p.Y; } 108 | if (p.Z > zmax) { zmax = p.Z; } 109 | } 110 | 111 | public bool Intersects(HLBoundingBoxXYZ r2) 112 | { 113 | var r1 = this; 114 | 115 | return r1.Min.X <= r2.Max.X && r1.Max.X >= r2.Min.X && r1.Min.Y <= r2.Max.Y && r1.Max.Y >= r2.Min.Y && r1.Min.Z <= r2.Max.Z && r1.Max.Z >= r2.Min.Z; 116 | 117 | } 118 | 119 | public bool Contains(XYZ point) 120 | { 121 | return point.X <= xmax 122 | && point.Y <= ymax 123 | && point.Z <= zmax 124 | && point.X >= xmin 125 | && point.Y >= ymin 126 | && point.Z >= zmin; 127 | } 128 | 129 | public bool IntersectRay(Line Ray) 130 | { 131 | 132 | var bmin = this.Min; 133 | var bmax = this.Max; 134 | 135 | XYZ itx = XYZ.Zero; 136 | if (Ray.IsBound && CheckLineBoX(bmin, bmax, Ray.GetEndPoint(0), Ray.GetEndPoint(1), ref itx)) return true; 137 | 138 | 139 | //if (Ray.IsBound) 140 | { 141 | var mpointItx = Ray.Project(this.MidPoint); 142 | var mpx = getInteresct(Ray, this.MidPoint); 143 | if (this.Contains(mpointItx.XYZPoint)) return true; 144 | 145 | //mpointItx = Ray.Project(new XYZ(bmin.X, bmin.Y, bmin.Z)); 146 | mpx = getInteresct(Ray, new XYZ(bmin.X, bmin.Y, bmin.Z)); 147 | if (this.Contains(mpx)) return true;// mpointItx.XYZPoint)) return true; 148 | 149 | //mpointItx = Ray.Project(new XYZ(bmin.X, bmax.Y, bmin.Z)); 150 | mpx = getInteresct(Ray, new XYZ(bmin.X, bmax.Y, bmin.Z)); 151 | if (this.Contains(mpx)) return true;//mpointItx.XYZPoint)) return true; 152 | 153 | //mpointItx = Ray.Project(new XYZ(bmax.X, bmax.Y, bmin.Z)); 154 | mpx = getInteresct(Ray, new XYZ(bmax.X, bmax.Y, bmin.Z)); 155 | if (this.Contains(mpx)) return true;//mpointItx.XYZPoint)) return true; 156 | 157 | //mpointItx = Ray.Project(new XYZ(bmax.X, bmin.Y, bmin.Z)); 158 | mpx = getInteresct(Ray, new XYZ(bmax.X, bmin.Y, bmin.Z)); 159 | if (this.Contains(mpx)) return true;//mpointItx.XYZPoint)) return true; 160 | 161 | //mpointItx = Ray.Project(new XYZ(bmin.X, bmin.Y, bmax.Z)); 162 | mpx = getInteresct(Ray, new XYZ(bmin.X, bmin.Y, bmax.Z)); 163 | if (this.Contains(mpx)) return true;//mpointItx.XYZPoint)) return true; 164 | 165 | //mpointItx = Ray.Project(new XYZ(bmin.X, bmax.Y, bmax.Z)); 166 | mpx = getInteresct(Ray, new XYZ(bmin.X, bmax.Y, bmax.Z)); 167 | if (this.Contains(mpx)) return true;//mpointItx.XYZPoint)) return true; 168 | 169 | //mpointItx = Ray.Project(new XYZ(bmax.X, bmax.Y, bmax.Z)); 170 | mpx = getInteresct(Ray, new XYZ(bmax.X, bmax.Y, bmax.Z)); 171 | if (this.Contains(mpx)) return true;//mpointItx.XYZPoint)) return true; 172 | 173 | //mpointItx = Ray.Project(new XYZ(bmax.X, bmin.Y, bmax.Z)); 174 | mpx = getInteresct(Ray, new XYZ(bmax.X, bmin.Y, bmax.Z)); 175 | if (this.Contains(mpx)) return true;//mpointItx.XYZPoint)) return true; 176 | } 177 | 178 | 179 | var rx0 = Ray.Origin; 180 | var rn_inv = Ray.Direction.Negate(); 181 | 182 | double tx1 = (bmin.X - rx0.X) * rn_inv.X; 183 | double tx2 = (bmax.X - rx0.X) * rn_inv.X; 184 | 185 | var tmin = Math.Min(tx1, tx2); 186 | var tmax = Math.Max(tx1, tx2); 187 | 188 | double ty1 = (bmin.Y - rx0.Y) * rn_inv.Y; 189 | double ty2 = (bmax.Y - rx0.Y) * rn_inv.Y; 190 | 191 | tmin = Math.Max(tmin, Math.Min(ty1, ty2)); 192 | tmax = Math.Min(tmax, Math.Max(ty1, ty2)); 193 | 194 | double tz1 = (bmin.Z - rx0.Z) * rn_inv.Z; 195 | double tz2 = (bmax.Z - rx0.Z) * rn_inv.Z; 196 | 197 | tmin = Math.Max(tmin, Math.Min(tz1, tz2)); 198 | tmax = Math.Min(tmax, Math.Max(tz1, tz2)); 199 | 200 | return tmax >= tmin; 201 | } 202 | 203 | bool CheckLineBoX(XYZ B1, XYZ B2, XYZ L1, XYZ L2, ref XYZ Hit) 204 | { 205 | if (L2.X < B1.X && L1.X < B1.X) return false; 206 | if (L2.X > B2.X && L1.X > B2.X) return false; 207 | if (L2.Y < B1.Y && L1.Y < B1.Y) return false; 208 | if (L2.Y > B2.Y && L1.Y > B2.Y) return false; 209 | if (L2.Z < B1.Z && L1.Z < B1.Z) return false; 210 | if (L2.Z > B2.Z && L1.Z > B2.Z) return false; 211 | if (L1.X > B1.X && L1.X < B2.X && 212 | L1.Y > B1.Y && L1.Y < B2.Y && 213 | L1.Z > B1.Z && L1.Z < B2.Z) 214 | { 215 | Hit = L1; 216 | return true; 217 | } 218 | if ((GetIntersection(L1.X - B1.X, L2.X - B1.X, L1, L2, ref Hit) && InBoX(Hit, B1, B2, 1)) 219 | || (GetIntersection(L1.Y - B1.Y, L2.Y - B1.Y, L1, L2, ref Hit) && InBoX(Hit, B1, B2, 2)) 220 | || (GetIntersection(L1.Z - B1.Z, L2.Z - B1.Z, L1, L2, ref Hit) && InBoX(Hit, B1, B2, 3)) 221 | || (GetIntersection(L1.X - B2.X, L2.X - B2.X, L1, L2, ref Hit) && InBoX(Hit, B1, B2, 1)) 222 | || (GetIntersection(L1.Y - B2.Y, L2.Y - B2.Y, L1, L2, ref Hit) && InBoX(Hit, B1, B2, 2)) 223 | || (GetIntersection(L1.Z - B2.Z, L2.Z - B2.Z, L1, L2, ref Hit) && InBoX(Hit, B1, B2, 3))) 224 | return true; 225 | 226 | return false; 227 | } 228 | 229 | XYZ getInteresct(Line ln, XYZ P) 230 | { 231 | //A + dot(AP,AB) / dot(AB,AB) * AB 232 | 233 | var A = ln.GetEndPoint(0); 234 | var B = ln.GetEndPoint(1); 235 | var AP = P - A; 236 | var AB = B - A; 237 | 238 | var prjPmpointItxA = A + AP.DotProduct(AB) / AB.DotProduct(AB) * AB; 239 | 240 | return prjPmpointItxA; 241 | } 242 | 243 | bool GetIntersection(double fDst1, double fDst2, XYZ P1, XYZ P2, ref XYZ Hit) 244 | { 245 | if ((fDst1 * fDst2) >= 0.0f) return false; 246 | if (fDst1 == fDst2) return false; 247 | Hit = P1 + (P2 - P1) * (-fDst1 / (fDst2 - fDst1)); 248 | return true; 249 | } 250 | 251 | bool InBoX(XYZ Hit, XYZ B1, XYZ B2, int AXis) 252 | { 253 | if (AXis == 1 && Hit.Z > B1.Z && Hit.Z < B2.Z && Hit.Y > B1.Y && Hit.Y < B2.Y) return true; 254 | if (AXis == 2 && Hit.Z > B1.Z && Hit.Z < B2.Z && Hit.X > B1.X && Hit.X < B2.X) return true; 255 | if (AXis == 3 && Hit.X > B1.X && Hit.X < B2.X && Hit.Y > B1.Y && Hit.Y < B2.Y) return true; 256 | return false; 257 | } 258 | 259 | public bool IsInvalid 260 | { 261 | get 262 | { 263 | return double.IsInfinity(xmax) || double.IsInfinity(xmin) || double.IsInfinity(ymax) || double.IsInfinity(ymin) || double.IsInfinity(zmax) || double.IsInfinity(zmin) || double.IsNaN(xmax) || double.IsNaN(xmin) || double.IsNaN(ymax) || double.IsNaN(ymin) || double.IsNaN(zmax) || double.IsNaN(zmin); 264 | } 265 | } 266 | 267 | /// 268 | /// Set size of bbox from current center point 269 | /// 270 | public XYZ Size 271 | { 272 | get 273 | { 274 | if (double.IsInfinity(xmax) || double.IsInfinity(xmin) || double.IsInfinity(ymax) || double.IsInfinity(ymin) || double.IsInfinity(zmax) || double.IsInfinity(zmin)) return XYZ.Zero; 275 | if (double.IsNaN(xmax) || double.IsNaN(xmin) || double.IsNaN(ymax) || double.IsNaN(ymin) || double.IsNaN(zmax) || double.IsNaN(zmin)) return XYZ.Zero; 276 | return new XYZ(Math.Abs(xmax - xmin), Math.Abs(ymax - ymin), Math.Abs(zmax - zmin)); 277 | } 278 | set 279 | { 280 | var center = this.MidPoint; 281 | var size = value; 282 | 283 | xmin = center.X - (size.X * 0.5); 284 | ymin = center.Y - (size.Y * 0.5); 285 | zmin = center.Z - (size.Z * 0.5); 286 | 287 | xmax = center.X + (size.X * 0.5); 288 | ymax = center.Y + (size.Y * 0.5); 289 | zmax = center.Z + (size.Z * 0.5); 290 | } 291 | } 292 | } 293 | 294 | 295 | public class HLBoundingBoxUV // : Tuple 296 | { 297 | public static HLBoundingBoxUV FromXYZPoints(IList points) 298 | { 299 | HLBoundingBoxUV bbox = new HLBoundingBoxUV(); 300 | 301 | foreach (UV point in points) 302 | { 303 | bbox.ExpandToContain(point); 304 | } 305 | 306 | return bbox; 307 | } 308 | 309 | 310 | /// 311 | /// Minimum and maximum X, Y and Z values. 312 | /// 313 | double umin, vmin, umax, vmax; 314 | 315 | /// 316 | /// Initialise to infinite values. 317 | /// 318 | public HLBoundingBoxUV() 319 | { 320 | umin = vmin = double.MaxValue; 321 | umax = vmax = double.MinValue; 322 | } 323 | 324 | /// 325 | /// Return current lower left corner. 326 | /// 327 | public UV Min 328 | { 329 | get { return new UV(umin, vmin); } 330 | } 331 | 332 | /// 333 | /// Return current upper right corner. 334 | /// 335 | public UV Max 336 | { 337 | get { return new UV(umax, vmax); } 338 | } 339 | 340 | public UV MidPoint 341 | { 342 | get { return 0.5 * (Min + Max); } 343 | } 344 | 345 | public double Left 346 | { 347 | get 348 | { 349 | return umin; 350 | } 351 | } 352 | 353 | public double Right 354 | { 355 | get 356 | { 357 | return umax; 358 | } 359 | } 360 | 361 | public double Top 362 | { 363 | get 364 | { 365 | return vmax; 366 | } 367 | } 368 | 369 | public double Bottom 370 | { 371 | get 372 | { 373 | return vmin; 374 | } 375 | } 376 | 377 | /// 378 | /// Expand bounding box to contain 379 | /// the given new point. 380 | /// 381 | public void ExpandToContain(UV p) 382 | { 383 | if (p.U < umin) { umin = p.U; } 384 | if (p.V < vmin) { vmin = p.V; } 385 | if (p.U > umax) { umax = p.U; } 386 | if (p.V > vmax) { vmax = p.V; } 387 | } 388 | } 389 | } 390 | -------------------------------------------------------------------------------- /HLApps.Revit.Graph/Parameters/HLRevitParameter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq; 3 | using Autodesk.Revit.DB; 4 | 5 | namespace HLApps.Revit.Parameters 6 | { 7 | public class HLRevitParameter : HLRevitElementData 8 | { 9 | private Parameter _revitPerameter; 10 | private Guid definedGuid = new Guid(); 11 | 12 | public HLRevitParameter(Parameter revitParam) 13 | { 14 | _revitPerameter = revitParam; 15 | } 16 | 17 | public Guid GUID 18 | { 19 | get 20 | { 21 | if (_revitPerameter.IsShared) 22 | { 23 | return _revitPerameter.GUID; 24 | } 25 | else 26 | { 27 | return definedGuid; 28 | } 29 | } 30 | } 31 | 32 | public ElementId Id 33 | { 34 | get 35 | { 36 | return _revitPerameter.Id; 37 | } 38 | } 39 | 40 | public override int IntElementId 41 | { 42 | get 43 | { 44 | return Id.IntegerValue; 45 | } 46 | } 47 | 48 | 49 | public override string Name 50 | { 51 | get 52 | { 53 | 54 | return _revitPerameter.Definition.Name; ; 55 | } 56 | } 57 | 58 | public override object Value 59 | { 60 | get 61 | { 62 | object retVal = string.Empty; 63 | if (_revitPerameter != null) 64 | { 65 | var doc = _revitPerameter.Element.Document; 66 | 67 | switch (_revitPerameter.StorageType) 68 | { 69 | 70 | case Autodesk.Revit.DB.StorageType.Double: 71 | // append the type and value 72 | retVal = _revitPerameter.AsDouble(); 73 | break; 74 | case Autodesk.Revit.DB.StorageType.ElementId: 75 | if (Name == "Category") 76 | { 77 | retVal = _revitPerameter.AsValueString(); 78 | return retVal; 79 | } 80 | 81 | var elid = _revitPerameter.AsElementId(); 82 | if (PreserveIds) return elid; 83 | 84 | if (Name.ToLower().EndsWith("id")) 85 | { 86 | try 87 | { 88 | retVal = _revitPerameter.AsValueString(); 89 | } 90 | catch { retVal = doc.GetElement(elid); }//.IntegerValue; } 91 | } 92 | else 93 | { 94 | var vael = _revitPerameter.AsValueString(); 95 | var vaels = _revitPerameter.AsString(); 96 | retVal = doc.GetElement(elid);//.IntegerValue; 97 | if (retVal == null) retVal = string.IsNullOrEmpty(vaels) ? vael : vaels; 98 | return retVal; 99 | } 100 | 101 | break; 102 | case Autodesk.Revit.DB.StorageType.Integer: 103 | // append the type and value 104 | int retValAsInt = _revitPerameter.AsInteger(); 105 | 106 | if (_revitPerameter.Definition.ParameterType == ParameterType.YesNo) 107 | { 108 | retVal = (retValAsInt == 1); 109 | } 110 | else 111 | { 112 | retVal = retValAsInt; 113 | } 114 | 115 | return retVal; 116 | 117 | case Autodesk.Revit.DB.StorageType.String: 118 | // append the type and value 119 | retVal = _revitPerameter.AsString(); 120 | return retVal; 121 | 122 | case Autodesk.Revit.DB.StorageType.None: 123 | // append the type and value 124 | retVal = _revitPerameter.AsValueString(); 125 | return retVal; 126 | 127 | default: 128 | break; 129 | } 130 | } 131 | 132 | 133 | return retVal; 134 | } 135 | set 136 | { 137 | string valueAsString = value != null ? value.ToString() : string.Empty; 138 | bool wasSet = false; 139 | 140 | switch (_revitPerameter.StorageType) 141 | { 142 | case Autodesk.Revit.DB.StorageType.Double: 143 | // append the type and value 144 | double dval = 0; 145 | bool wasParsed = false; 146 | 147 | if (value is double) 148 | { 149 | dval = (double)value; 150 | wasParsed = true; 151 | } 152 | else 153 | { 154 | wasParsed = double.TryParse(valueAsString, out dval); 155 | 156 | if (!wasParsed && !_revitPerameter.SetValueString(valueAsString) && valueAsString.Contains(' ')) 157 | { 158 | var stl = valueAsString.Split(' '); 159 | wasParsed = double.TryParse(stl[0], out dval); 160 | } 161 | 162 | } 163 | 164 | if (wasParsed && _revitPerameter.DisplayUnitType == DisplayUnitType.DUT_PERCENTAGE && dval > 1) 165 | { 166 | dval = dval / 100; 167 | _revitPerameter.Set(dval); 168 | wasSet = true; 169 | } 170 | else if (wasParsed) 171 | { 172 | _revitPerameter.Set(dval); 173 | wasSet = true; 174 | } 175 | 176 | if (!wasSet || !wasParsed) 177 | { 178 | throw new Exception("Data type mismatch, could not parse \"" + valueAsString + "\" to a number"); 179 | } 180 | 181 | break; 182 | case Autodesk.Revit.DB.StorageType.ElementId: 183 | 184 | int eval; 185 | 186 | if (value is ElementId) 187 | { 188 | _revitPerameter.Set((ElementId)value); 189 | } 190 | else if (value is int) 191 | { 192 | _revitPerameter.Set(new ElementId((int)value)); 193 | } 194 | else 195 | { 196 | if (int.TryParse(valueAsString, out eval)) 197 | { 198 | _revitPerameter.Set(new ElementId(eval)); 199 | } 200 | else 201 | { 202 | //invalid value, raise error 203 | _revitPerameter.SetValueString(valueAsString); 204 | } 205 | } 206 | 207 | break; 208 | case Autodesk.Revit.DB.StorageType.Integer: 209 | // append the type and value 210 | 211 | if (_revitPerameter.Definition.ParameterType == ParameterType.YesNo) 212 | { 213 | bool valueAsBool = false; 214 | 215 | //use string as common ground, if value is bool it'll be reparsed. 216 | 217 | valueAsString = valueAsString.ToLower().Trim(); 218 | if (valueAsString == "yes" || valueAsString == "y") 219 | { 220 | valueAsBool = true; 221 | } 222 | else if (valueAsString == "no" || valueAsString == "n") 223 | { 224 | valueAsBool = false; 225 | } 226 | else if (!bool.TryParse(valueAsString, out valueAsBool)) 227 | { 228 | //perhaps value is an int or string expressed as 1 229 | valueAsBool = valueAsString == "1"; 230 | } 231 | 232 | _revitPerameter.Set(valueAsBool ? 1 : 0); 233 | wasSet = true; 234 | 235 | } 236 | else if (value is int) 237 | { 238 | _revitPerameter.Set((int)value); 239 | wasSet = true; 240 | } 241 | else 242 | { 243 | int ival; 244 | 245 | if (int.TryParse(valueAsString, out ival)) 246 | { 247 | _revitPerameter.Set(ival); 248 | wasSet = true; 249 | } 250 | else 251 | { 252 | if (!_revitPerameter.SetValueString(valueAsString) && valueAsString.Contains(" ")) 253 | { 254 | var stl = valueAsString.Split(' '); 255 | if (int.TryParse(stl[0], out ival)) 256 | { 257 | _revitPerameter.Set(ival); 258 | wasSet = true; 259 | } 260 | } 261 | } 262 | } 263 | 264 | if (!wasSet) 265 | { 266 | throw new Exception("Data type mismatch, could not parse \"" + valueAsString + "\" to an integer"); 267 | } 268 | 269 | 270 | break; 271 | case Autodesk.Revit.DB.StorageType.String: 272 | // append the type and value 273 | 274 | _revitPerameter.Set(valueAsString); 275 | 276 | break; 277 | case Autodesk.Revit.DB.StorageType.None: 278 | // append the type and value 279 | _revitPerameter.SetValueString(valueAsString); 280 | 281 | break; 282 | default: 283 | break; 284 | } 285 | 286 | } 287 | } 288 | 289 | public bool ReturnUnsetValuesAsEmptyString { get; set; } 290 | 291 | public override string StringValue 292 | { 293 | get 294 | { 295 | if (!_revitPerameter.HasValue && ReturnUnsetValuesAsEmptyString) return string.Empty; 296 | 297 | if (_revitPerameter.StorageType == StorageType.Double) 298 | { 299 | if (!_revitPerameter.HasValue) return "0"; 300 | 301 | return _revitPerameter != null ? _revitPerameter.AsValueString() : string.Empty; 302 | } 303 | else if (_revitPerameter.Definition.ParameterType == ParameterType.YesNo) 304 | { 305 | var bval = this.Value; 306 | if (bval != null && bval is bool) 307 | { 308 | return (bool)bval ? "Yes" : "No"; 309 | } 310 | else 311 | { 312 | return string.Empty; 313 | } 314 | } 315 | 316 | if (!_revitPerameter.HasValue) return string.Empty; 317 | 318 | var val = this.Value; 319 | 320 | if (val is Category) 321 | { 322 | return (val as Category).Name; 323 | 324 | } 325 | 326 | if (val is Element) 327 | { 328 | return (val as Element).Name; 329 | } 330 | 331 | return val != null ? val.ToString() : string.Empty; 332 | } 333 | set 334 | { 335 | if (_revitPerameter.StorageType == StorageType.Double) 336 | { 337 | string oringalValue = _revitPerameter.AsValueString(); 338 | if (oringalValue != value) 339 | { 340 | _revitPerameter.SetValueString(value); 341 | } 342 | } 343 | else 344 | { 345 | var thisStringVal = StringValue; 346 | if (string.IsNullOrEmpty(thisStringVal) && string.IsNullOrEmpty(value)) return; 347 | 348 | if (thisStringVal != value) 349 | { 350 | this.Value = value; 351 | } 352 | } 353 | } 354 | } 355 | 356 | public override Type ExpectedType 357 | { 358 | get 359 | { 360 | return Value != null ? Value.GetType() : typeof(string); 361 | } 362 | } 363 | 364 | public override bool IsReadOnly 365 | { 366 | get 367 | { 368 | return (_revitPerameter.IsReadOnly || Name.ToLower().Contains("specified")); 369 | } 370 | } 371 | 372 | public override StorageType StorageType 373 | { 374 | get 375 | { 376 | return _revitPerameter.StorageType; 377 | } 378 | } 379 | 380 | public Parameter Parameter 381 | { 382 | get 383 | { 384 | return _revitPerameter; 385 | } 386 | } 387 | 388 | public bool IsShared 389 | { 390 | get 391 | { 392 | return _revitPerameter != null ? _revitPerameter.IsShared : false; 393 | } 394 | } 395 | 396 | protected override void OnDisposing() 397 | { 398 | _revitPerameter.Dispose(); 399 | _revitPerameter = null; 400 | } 401 | 402 | } 403 | 404 | 405 | 406 | 407 | } 408 | --------------------------------------------------------------------------------