├── .gitignore ├── .gitmodules ├── BuildConfigurations ├── BuildConfigurations.shproj ├── BuildConfigurations.targets ├── Imports.targets ├── LocalDebugAddin.targets └── RevitBuildConfigurations.projitems ├── BuildingGraph.Integration.Dynamo ├── BuildingGraph.Integration.Dynamo.csproj ├── Components │ ├── GraphQL │ │ ├── BGNode.cs │ │ ├── BuildingGraphAPIClient.cs │ │ ├── ClientMapping.cs │ │ ├── Mutations.cs │ │ └── Queries.cs │ └── Neo4j │ │ └── Neo4jCl.cs ├── Properties │ └── AssemblyInfo.cs ├── app.config └── packages.config ├── BuildingGraph.Integration.Revit.sln ├── BuildingGraph.Integration.Revit ├── BuildingGraph.Integration.Revit.csproj ├── Geometry │ ├── Convert.cs │ ├── CurveGeometrySegment.cs │ ├── GeometrySegment.cs │ ├── HLBoundingBoxXYZ.cs │ ├── Octree │ │ ├── BoundsOctree.cs │ │ ├── BoundsOctreeElementWriter.cs │ │ ├── BoundsOctreeNode.cs │ │ ├── PointOctree.cs │ │ ├── PointOctreeElementWriter.cs │ │ └── PointOctreeNode.cs │ ├── PointGeometrySegment.cs │ └── SolidGeometrySegment.cs ├── Graph │ ├── ConnectorPointGeometrySegment.cs │ ├── IMEPGraphWriter.cs │ ├── MEPConnector.cs │ ├── MEPGraph.cs │ ├── MEPGraphUtils.cs │ ├── MEPGraphWriter.cs │ ├── MEPGraphWriterGraphQL.cs │ ├── MEPNodeEdge.cs │ ├── MEPPathDirectionEnum.cs │ ├── MEPPathNode.cs │ ├── MEPPathSection.cs │ ├── MEPPathWriteCache.cs │ ├── MEPRevitGraphWriter.cs │ ├── Parsers │ │ ├── FaceIntersectRay.cs │ │ ├── IMEPGraphElementScanner.cs │ │ ├── IRevitGraphParser.cs │ │ ├── MEPGraphParserConnectors.cs │ │ ├── MEPGraphParserElectrical.cs │ │ ├── MEPGraphParserIoT.cs │ │ ├── MEPGraphParserSpaces.cs │ │ └── SpaceToDoorPathScanner.cs │ └── introspection │ │ └── EnumUtils.cs ├── Parameters │ ├── HLRevitElementData.cs │ ├── HLRevitElementName.cs │ ├── HLRevitElementProperty.cs │ ├── HLRevitParameter.cs │ ├── HLRevitReadonlyTextData.cs │ └── IHLPeramiter.cs ├── Properties │ └── AssemblyInfo.cs ├── RevitGraphApp.cs ├── RevitGraphSyncService.cs ├── RevitToGraphPublisher.cs ├── RevitToGraphPublisherSettings.cs ├── RevitToGraphQLMappings.json ├── Streams │ └── RevitStreamConsumer.cs ├── Units │ ├── Convert │ │ ├── HLDisplayUnitTypeConvert.cs │ │ ├── HLUnitSymbolTypeConvert.cs │ │ ├── HLUnitTypeEnumConvert.cs │ │ ├── LabelUtilsConvert.cs │ │ ├── NoForgeTypeFoundException.cs │ │ ├── StringToForgeTypeId.cs │ │ ├── UnitFormatUtilsConvert.cs │ │ └── UnitUtilsConvert.cs │ └── Mappings │ │ ├── HLDisplayUnitType.cs │ │ ├── HLDisplayUnitTypeEnum.cs │ │ ├── HLEnumForgeWrapper.cs │ │ ├── HLMEPSystem.cs │ │ ├── HLParameterType.cs │ │ ├── HLParameterTypeEnum.cs │ │ ├── HLUnitSymbolType.cs │ │ ├── HLUnitSymbolTypeEnum.cs │ │ ├── HLUnitType.cs │ │ └── HLUnitTypeEnum.cs ├── Utils │ ├── DocUtils.cs │ ├── GeoUtils.cs │ ├── MEPUtils.cs │ └── RevitElementExtensions.cs ├── app.config └── packages.config ├── BuildingGraph.Integration.RevitUI ├── BuildingGraph.Integration.RevitUI.csproj ├── BuildingGraph.addin ├── GraphApp.cs ├── GraphAppShowCommand.cs ├── Properties │ └── AssemblyInfo.cs ├── RevitEventDispatcher.cs ├── RevitGraphSyncCommand.cs ├── Streams │ ├── ElementStreamHandler.cs │ └── RevitStreamConsumer.cs ├── UI │ ├── GraphAppWindow.xaml │ ├── GraphAppWindow.xaml.cs │ └── ViewModel │ │ ├── BaseViewModel.cs │ │ ├── Command.cs │ │ └── GraphAppViewModel.cs └── app.config ├── LICENSE └── README.md /.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 -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "BuildingGraph-Client"] 2 | path = BuildingGraph-Client 3 | url = https://github.com/willhl/BuildingGraph-Client.git 4 | branch = master 5 | -------------------------------------------------------------------------------- /BuildConfigurations/BuildConfigurations.shproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 59589e76-d411-4579-810d-a08074e453e7 5 | 14.0 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /BuildConfigurations/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 | 53 | true 54 | bin\x64\Debug\2020\ 55 | TRACE;DEBUG;REVIT2012,REVIT2013,REVIT2014,REVIT2015,REVIT2016,REVIT2017,REVIT2018,REVIT2019,REVIT2020 56 | full 57 | x64 58 | prompt 59 | MinimumRecommendedRules.ruleset 60 | $(MSBuildProjectName) 61 | v4.7 62 | 63 | 64 | bin\x64\Release\2020\ 65 | TRACE;REVIT2012,REVIT2013,REVIT2014,REVIT2015,REVIT2016,REVIT2017,REVIT2018,REVIT2019,REVIT2020 66 | true 67 | pdbonly 68 | x64 69 | prompt 70 | MinimumRecommendedRules.ruleset 71 | $(MSBuildProjectName) 72 | v4.7 73 | 74 | 75 | 76 | 77 | true 78 | bin\x64\Debug\2021\ 79 | TRACE;DEBUG;REVIT2012,REVIT2013,REVIT2014,REVIT2015,REVIT2016,REVIT2017,REVIT2018,REVIT2019,REVIT2020,REVIT2021 80 | full 81 | x64 82 | prompt 83 | MinimumRecommendedRules.ruleset 84 | $(MSBuildProjectName) 85 | v4.8 86 | 87 | 88 | bin\x64\Release\2021\ 89 | TRACE;REVIT2012,REVIT2013,REVIT2014,REVIT2015,REVIT2016,REVIT2017,REVIT2018,REVIT2019,REVIT2020,REVIT2021 90 | true 91 | pdbonly 92 | x64 93 | prompt 94 | MinimumRecommendedRules.ruleset 95 | $(MSBuildProjectName) 96 | v4.8 97 | 98 | 99 | 100 | true 101 | bin\x64\Debug\2022\ 102 | TRACE;DEBUG;REVIT2012,REVIT2013,REVIT2014,REVIT2015,REVIT2016,REVIT2017,REVIT2018,REVIT2019,REVIT2020,REVIT2021,REVIT2022 103 | full 104 | x64 105 | prompt 106 | MinimumRecommendedRules.ruleset 107 | $(MSBuildProjectName) 108 | v4.8 109 | 110 | 111 | bin\x64\Release\2022\ 112 | TRACE;REVIT2012,REVIT2013,REVIT2014,REVIT2015,REVIT2016,REVIT2017,REVIT2018,REVIT2019,REVIT2020,REVIT2021,REVIT2022 113 | true 114 | pdbonly 115 | x64 116 | prompt 117 | MinimumRecommendedRules.ruleset 118 | $(MSBuildProjectName) 119 | v4.8 120 | 121 | 122 | 123 | -------------------------------------------------------------------------------- /BuildConfigurations/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 2018\RevitAPIUI.dll 13 | False 14 | 15 | 16 | 17 | 18 | C:\Program Files\Autodesk\Revit 2019\RevitAPI.dll 19 | False 20 | 21 | 22 | 23 | C:\Program Files\Autodesk\Revit 2019\RevitAPIUI.dll 24 | False 25 | 26 | 27 | 28 | 29 | C:\Program Files\Autodesk\Revit 2020\RevitAPI.dll 30 | False 31 | 32 | 33 | 34 | C:\Program Files\Autodesk\Revit 2020\RevitAPIUI.dll 35 | False 36 | 37 | 38 | 39 | C:\Program Files\Autodesk\Revit 2021\RevitAPI.dll 40 | False 41 | 42 | 43 | 44 | C:\Program Files\Autodesk\Revit 2021\RevitAPIUI.dll 45 | False 46 | 47 | 48 | 49 | C:\Program Files\Autodesk\Revit 2022\RevitAPI.dll 50 | False 51 | 52 | 53 | 54 | C:\Program Files\Autodesk\Revit 2022\RevitAPIUI.dll 55 | False 56 | 57 | 58 | 59 | 60 | 61 | -------------------------------------------------------------------------------- /BuildConfigurations/LocalDebugAddin.targets: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 8 | 9 | 10 | 11 | 15 | 16 | 17 | 18 | 19 | xcopy /y "*.dll" "%appdata%\Autodesk\Revit\Addins\2018\BuildingGraph\" 20 | 21 | 22 | 23 | xcopy /y "*.dll" "%appdata%\Autodesk\Revit\Addins\2019\BuildingGraph\" 24 | 25 | 26 | 27 | xcopy /y "*.dll" "%appdata%\Autodesk\Revit\Addins\2020\BuildingGraph\" 28 | 29 | 30 | 31 | xcopy /y "*.dll" "%appdata%\Autodesk\Revit\Addins\2021\BuildingGraph\" 32 | 33 | 34 | 35 | xcopy /y "*.dll" "%appdata%\Autodesk\Revit\Addins\2022\BuildingGraph\" 36 | 37 | 38 | 39 | xcopy /y/S "$(SolutionDir)BuildingGraph.Integration.RevitUI\BuildingGraph.addin" "%appdata%\Autodesk\Revit\Addins\2018\" 40 | 41 | 42 | 43 | xcopy /y/S "$(SolutionDir)BuildingGraph.Integration.RevitUI\BuildingGraph.addin" "%appdata%\Autodesk\Revit\Addins\2019\" 44 | 45 | 46 | 47 | xcopy /y/S "$(SolutionDir)BuildingGraph.Integration.RevitUI\BuildingGraph.addin" "%appdata%\Autodesk\Revit\Addins\2020\" 48 | 49 | 50 | 51 | xcopy /y/S "$(SolutionDir)BuildingGraph.Integration.RevitUI\BuildingGraph.addin" "%appdata%\Autodesk\Revit\Addins\2021\" 52 | 53 | 54 | 55 | xcopy /y/S "$(SolutionDir)BuildingGraph.Integration.RevitUI\BuildingGraph.addin" "%appdata%\Autodesk\Revit\Addins\2022\" 56 | 57 | 58 | 59 | Program 60 | C:\Program Files\Autodesk\Revit 2018\Revit.exe 61 | 62 | 63 | C:\Program Files\Autodesk\Revit 2019\Revit.exe 64 | Program 65 | 66 | 67 | C:\Program Files\Autodesk\Revit 2020\Revit.exe 68 | Program 69 | 70 | 71 | C:\Program Files\Autodesk\Revit 2021\Revit.exe 72 | Program 73 | 74 | 75 | C:\Program Files\Autodesk\Revit 2022\Revit.exe 76 | Program 77 | 78 | 79 | -------------------------------------------------------------------------------- /BuildConfigurations/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 | -------------------------------------------------------------------------------- /BuildingGraph.Integration.Dynamo/Components/GraphQL/BGNode.cs: -------------------------------------------------------------------------------- 1 | using BuildingGraph.Client; 2 | 3 | public class BGNode 4 | { 5 | 6 | internal BGNode() { } 7 | 8 | internal BGNode(PendingNode pendingNode) 9 | { 10 | intPendingNode = pendingNode; 11 | Name = pendingNode.NodeName; 12 | Id = pendingNode.Id; 13 | WasCommited = pendingNode.WasCommited; 14 | } 15 | 16 | public static BGNode FromNameAndId(string name, string id) 17 | { 18 | return new BGNode(new PendingNode(name, id)); 19 | } 20 | 21 | public static BGNode FromName(string name) 22 | { 23 | return new BGNode(new PendingNode(name)); 24 | } 25 | 26 | internal PendingNode intPendingNode { get; set; } 27 | 28 | public string Name { get; internal set; } 29 | 30 | public string Id { get; internal set; } 31 | 32 | public bool WasCommited { get; internal set; } 33 | } 34 | 35 | -------------------------------------------------------------------------------- /BuildingGraph.Integration.Dynamo/Components/GraphQL/BuildingGraphAPIClient.cs: -------------------------------------------------------------------------------- 1 | using BuildingGraph.Client; 2 | using System.Collections.Generic; 3 | 4 | public class BuildingGraphAPIClient 5 | { 6 | 7 | 8 | public BuildingGraphAPIClient(string endpointURL, ClientMapping clientMapping) 9 | { 10 | Endpoint = endpointURL; 11 | Mapping = clientMapping; 12 | 13 | Client = new BuildingGraphClient(Endpoint); 14 | } 15 | 16 | internal BuildingGraphClient Client { get; } 17 | public string Endpoint { get; } 18 | public ClientMapping Mapping { get; } 19 | 20 | public void Commit(List nodes) 21 | { 22 | Client.Commit(); 23 | } 24 | 25 | } 26 | 27 | -------------------------------------------------------------------------------- /BuildingGraph.Integration.Dynamo/Components/GraphQL/ClientMapping.cs: -------------------------------------------------------------------------------- 1 | using BuildingGraph.Client.Introspection; 2 | 3 | public class ClientMapping 4 | { 5 | public ClientMapping(string mappingJSON) 6 | { 7 | 8 | var clienMapping = new BuildingGraphMapping(mappingJSON); 9 | } 10 | 11 | } 12 | 13 | -------------------------------------------------------------------------------- /BuildingGraph.Integration.Dynamo/Components/GraphQL/Mutations.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using Dynamo.Graph.Nodes; 3 | using BuildingGraph.Client; 4 | 5 | public static class Mutations 6 | { 7 | 8 | 9 | 10 | [NodeName("Create/Update Node")] 11 | [NodeDescription("Creates or updates a node")] 12 | [NodeCategory("Mutations")] 13 | [NodeSearchTags("Graphql")] 14 | public static BGNode CreateNode(BuildingGraphAPIClient client, BGNode node, Dictionary vars) 15 | { 16 | 17 | var _client = client.Client; 18 | var elmId = node.Id; 19 | if (node.intPendingNode.WasCommited) return node; 20 | 21 | Dictionary mergeOn = null; 22 | if (!string.IsNullOrEmpty(elmId) && node.WasCommited) 23 | { 24 | mergeOn = new Dictionary(); 25 | mergeOn.Add("Id", elmId); 26 | } 27 | 28 | var result = _client.Push(node.Name, vars, mergeOn); 29 | _client.Commit(); 30 | 31 | if (result != null) 32 | { 33 | node.intPendingNode = result; 34 | node.Id = result.Id; 35 | node.WasCommited = result.WasCommited; 36 | } 37 | 38 | return node; 39 | } 40 | 41 | 42 | public static BGNode UpdateNode(BuildingGraphAPIClient client, BGNode node, Dictionary vars) 43 | { 44 | 45 | var _client = client.Client; 46 | var elmId = node.Id; 47 | Dictionary mergeOn = null; 48 | if (!string.IsNullOrEmpty(elmId) && node.WasCommited) 49 | { 50 | mergeOn = new Dictionary(); 51 | mergeOn.Add("Id", elmId); 52 | 53 | var result = _client.Push(node.Name, vars, mergeOn); 54 | _client.Commit(); 55 | 56 | } 57 | 58 | return node; 59 | } 60 | 61 | public static string RelateNode(BuildingGraphAPIClient client, BGNode fromNode, BGNode toNode, string relationshipType) 62 | { 63 | 64 | var _client = client.Client; 65 | 66 | 67 | if (string.IsNullOrEmpty(fromNode.Id)) return "From node must have an ID"; 68 | if (string.IsNullOrEmpty(toNode.Id)) return "To node must have an ID"; 69 | 70 | var fromPn = new PendingNode(fromNode.Name, fromNode.Id); 71 | var toPn = new PendingNode(toNode.Name, toNode.Id); 72 | fromNode.intPendingNode = fromPn; 73 | toNode.intPendingNode = toPn; 74 | 75 | //variables in relationships not supported yet 76 | _client.Relate(fromPn, toPn, relationshipType, null); 77 | _client.Commit(); 78 | 79 | return "OK"; 80 | } 81 | 82 | } 83 | 84 | -------------------------------------------------------------------------------- /BuildingGraph.Integration.Dynamo/Components/GraphQL/Queries.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.DesignScript.Runtime; 7 | 8 | public static class Queries 9 | { 10 | /// 11 | /// Queries the building graph API 12 | /// 13 | /// the building graph api client 14 | /// the GraphQL query 15 | /// Dictionary of key value pairs for variables in the GraphQL query 16 | /// 17 | [CanUpdatePeriodically(true)] 18 | public static string BGGraphQLQuery(BuildingGraphAPIClient client, string query, Dictionary inputVariables) 19 | { 20 | var _client = client.Client; 21 | var result = _client.ExecuteQuery(query, inputVariables); 22 | 23 | return result != null ? result.ToString() : string.Empty; 24 | } 25 | 26 | } 27 | 28 | -------------------------------------------------------------------------------- /BuildingGraph.Integration.Dynamo/Components/Neo4j/Neo4jCl.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using Dynamo.Graph.Nodes; 7 | using BuildingGraph.Client.Neo4j; 8 | using Nito.AsyncEx; 9 | 10 | public static class Neo4j 11 | { 12 | [NodeName("Create/Update Neo4jClient")] 13 | [NodeDescription("Creates Neo4jClient")] 14 | [NodeCategory("Neo4jClient")] 15 | [NodeSearchTags("Neo4j")] 16 | public static Neo4jClient CreateClient(string host, string username, string password) 17 | { 18 | var n4c = new Neo4jClient(new Uri(host), username, password); 19 | return n4c; 20 | } 21 | 22 | 23 | public static string RunCypherQuery(Neo4jClient client, string cypher, Dictionary vars) 24 | { 25 | 26 | var task = Task.Run(() => AsyncContext.Run(() => client.RunCypherQueryAsync(cypher, vars))); 27 | 28 | if (task.Exception != null) throw new Exception("Query failed: " + task.Exception.Message, task.Exception); 29 | 30 | return task.Result.AsJson; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /BuildingGraph.Integration.Dynamo/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("BuildingGraph.Integration.Dynamo")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("BuildingGraph.Integration.Dynamo")] 13 | [assembly: AssemblyCopyright("Copyright © 2019")] 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("86a8b497-bd80-4123-8c03-3468bdbca2a9")] 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 | -------------------------------------------------------------------------------- /BuildingGraph.Integration.Dynamo/app.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /BuildingGraph.Integration.Dynamo/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /BuildingGraph.Integration.Revit/BuildingGraph.Integration.Revit.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | Debug 7 | AnyCPU 8 | {93280FF6-C2CC-4ECE-8C26-D6794F7121D3} 9 | Library 10 | Properties 11 | BuildingGraph.Integration.Revit 12 | HLApps.Revit.Graph 13 | v4.6 14 | 512 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | False 24 | 25 | 26 | ..\packages\Nito.AsyncEx.Context.5.0.0\lib\netstandard2.0\Nito.AsyncEx.Context.dll 27 | 28 | 29 | ..\packages\Nito.AsyncEx.Coordination.5.0.0\lib\netstandard2.0\Nito.AsyncEx.Coordination.dll 30 | 31 | 32 | ..\packages\Nito.AsyncEx.Interop.WaitHandles.5.0.0\lib\netstandard2.0\Nito.AsyncEx.Interop.WaitHandles.dll 33 | 34 | 35 | ..\packages\Nito.AsyncEx.Oop.5.0.0\lib\netstandard2.0\Nito.AsyncEx.Oop.dll 36 | 37 | 38 | ..\packages\Nito.AsyncEx.Tasks.5.0.0\lib\netstandard2.0\Nito.AsyncEx.Tasks.dll 39 | 40 | 41 | ..\packages\Nito.Cancellation.1.0.5\lib\netstandard2.0\Nito.Cancellation.dll 42 | 43 | 44 | ..\packages\Nito.Collections.Deque.1.0.4\lib\netstandard2.0\Nito.Collections.Deque.dll 45 | 46 | 47 | ..\packages\Nito.Disposables.2.0.0\lib\netstandard2.0\Nito.Disposables.dll 48 | 49 | 50 | 51 | ..\packages\System.Buffers.4.4.0\lib\netstandard2.0\System.Buffers.dll 52 | 53 | 54 | ..\packages\System.Collections.Immutable.1.4.0\lib\netstandard2.0\System.Collections.Immutable.dll 55 | 56 | 57 | 58 | ..\packages\System.Memory.4.5.0\lib\netstandard2.0\System.Memory.dll 59 | 60 | 61 | 62 | ..\packages\System.Numerics.Vectors.4.4.0\lib\net46\System.Numerics.Vectors.dll 63 | 64 | 65 | ..\packages\System.Runtime.CompilerServices.Unsafe.4.5.0\lib\netstandard2.0\System.Runtime.CompilerServices.Unsafe.dll 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | {79e4ed3b-5594-466d-89f9-18d2f00a547e} 152 | BuildingGraph.Client.Core 153 | 154 | 155 | {6217d742-11dc-40d1-8125-d2b98414be03} 156 | BuildingGraph.Client.GraphQL 157 | 158 | 159 | {400e1964-b716-4ea4-b21e-15c1f2135888} 160 | BuildingGraph.Client.Neo4j 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. 170 | 171 | 172 | 173 | -------------------------------------------------------------------------------- /BuildingGraph.Integration.Revit/Geometry/Convert.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 | using BuildingGraph.Client.Model.Types; 9 | 10 | namespace BuildingGraph.Integration.Revit.Geometry 11 | { 12 | public static partial class Convert 13 | { 14 | public static IPoint3D ToBuildingGraph(this XYZ XYZ) 15 | { 16 | return new Point3D(XYZ.X, XYZ.Y, XYZ.Z); 17 | } 18 | 19 | } 20 | 21 | } 22 | -------------------------------------------------------------------------------- /BuildingGraph.Integration.Revit/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 | } -------------------------------------------------------------------------------- /BuildingGraph.Integration.Revit/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 | } -------------------------------------------------------------------------------- /BuildingGraph.Integration.Revit/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 | } -------------------------------------------------------------------------------- /BuildingGraph.Integration.Revit/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 | -------------------------------------------------------------------------------- /BuildingGraph.Integration.Revit/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 | } -------------------------------------------------------------------------------- /BuildingGraph.Integration.Revit/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 | -------------------------------------------------------------------------------- /BuildingGraph.Integration.Revit/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 | } -------------------------------------------------------------------------------- /BuildingGraph.Integration.Revit/Geometry/SolidGeometrySegment.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using HLApps.Revit.Utils; 5 | using Autodesk.Revit.DB; 6 | 7 | 8 | namespace HLApps.Revit.Geometry 9 | { 10 | public class SolidGeometrySegment : GeometrySegment 11 | { 12 | public SolidGeometrySegment(Solid geo, Element element, HLBoundingBoxXYZ bounds) 13 | { 14 | Geometry = geo; 15 | OriginatingElement = element.Id; 16 | OriginatingDocIdent = DocUtils.GetDocumentIdent(element.Document); 17 | if (element.Category != null) OriginatingElementCategory = element.Category.Id; 18 | 19 | Bounds = bounds; 20 | 21 | Removed = false; 22 | segId = Guid.NewGuid().ToString(); 23 | } 24 | 25 | public Solid Geometry { get; set; } 26 | 27 | Face[] _faces; 28 | public Face[] Faces 29 | { 30 | get 31 | { 32 | if (_faces == null) _faces = Geometry.Faces.OfType().ToArray(); 33 | return _faces; 34 | } 35 | } 36 | 37 | public override void Invalidate() 38 | { 39 | Geometry = null; 40 | Removed = true; 41 | } 42 | } 43 | 44 | } -------------------------------------------------------------------------------- /BuildingGraph.Integration.Revit/Graph/ConnectorPointGeometrySegment.cs: -------------------------------------------------------------------------------- 1 |  2 | using Autodesk.Revit.DB; 3 | using HLApps.Revit.Geometry; 4 | 5 | namespace BuildingGraph.Integration.Revit 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 | -------------------------------------------------------------------------------- /BuildingGraph.Integration.Revit/Graph/IMEPGraphWriter.cs: -------------------------------------------------------------------------------- 1 | using Autodesk.Revit.DB; 2 | using System.Threading.Tasks; 3 | 4 | namespace BuildingGraph.Integration.Revit 5 | { 6 | public interface IMEPGraphWriter 7 | { 8 | void Write(MEPRevitGraph mepGraph, Document rootDoc); 9 | } 10 | } -------------------------------------------------------------------------------- /BuildingGraph.Integration.Revit/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 BuildingGraph.Integration.Revit 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 | -------------------------------------------------------------------------------- /BuildingGraph.Integration.Revit/Graph/MEPGraphUtils.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System; 3 | using System.Linq; 4 | using Autodesk.Revit.DB; 5 | 6 | using BuildingGraph.Client; 7 | using BuildingGraph.Client.Model; 8 | using BuildingGraph.Client.Introspection; 9 | using BuildingGraph.Integration.Revit.Geometry; 10 | using HLApps.Revit.Parameters; 11 | 12 | namespace BuildingGraph.Integration.Revit 13 | { 14 | public static class MEPGraphUtils 15 | { 16 | public static object RevitToGraphValue(HLRevitElementData elmData) 17 | { 18 | var val = elmData.Value; 19 | if (val is ElementId) return (val as ElementId).IntegerValue; 20 | 21 | if (val is Element) return (val as Element).Name; 22 | 23 | return val; 24 | } 25 | 26 | public static Dictionary GetNodePropsWithElementProps(Node node, Element elm) 27 | { 28 | return GetNodePropsWithElementProps(node, elm, null, null, false); 29 | } 30 | 31 | /// 32 | /// Get a dictionary of paramters and values which match those required by the node type 33 | /// defined in the schema 34 | /// 35 | /// 36 | /// 37 | /// 38 | /// 39 | public static Dictionary GetNodePropsWithElementProps(Node node, Element elm, 40 | IBuildingGraphSchema schema, 41 | BuildingGraphMapping clientMapping, 42 | bool includeOnlyMappedFields) 43 | { 44 | var elmParms = node.GetAllProperties(); 45 | 46 | 47 | if (elm != null && elm.Location is LocationPoint) 48 | { 49 | var lpt = (elm.Location as LocationPoint); 50 | var insPt = lpt.Point; 51 | if (!elmParms.ContainsKey("Location")) elmParms.Add("Location", insPt.ToBuildingGraph()); 52 | //if (!elmParms.ContainsKey("LocationRotation")) elmParms.Add("LocationRotation", lpt.Rotation); 53 | } 54 | else if (elm != null && elm.Location is LocationCurve) 55 | { 56 | //just start and end points for now 57 | var asCurve = (elm.Location as LocationCurve).Curve; 58 | var insPt = asCurve.GetEndPoint(0); 59 | if (!elmParms.ContainsKey("Location")) elmParms.Add("Location", insPt.ToBuildingGraph()); 60 | 61 | var endPt = asCurve.GetEndPoint(1); 62 | if (!elmParms.ContainsKey("LocationEnd")) elmParms.Add("LocationEnd", endPt.ToBuildingGraph()); 63 | 64 | var length = asCurve.Length; 65 | if (!elmParms.ContainsKey("length")) elmParms.Add("Length", length); 66 | 67 | var slope = Math.Abs(endPt.Z - insPt.Z) / length; 68 | if (!elmParms.ContainsKey("slope")) elmParms.Add("slope", length); 69 | } 70 | 71 | IBuildingGraphType bqType = schema != null ? schema.GetBuildingGraphType(node.Label) : null; 72 | BuildingGraphMappedType clType = clientMapping != null ? clientMapping.Types.FirstOrDefault(ct => ct.Name == node.Label) : null; 73 | 74 | foreach (var param in elm.Parameters.OfType()) 75 | { 76 | var hp = new HLRevitParameter(param); 77 | var paramName = Utils.GetGraphQLCompatibleFieldName(param.Definition.Name); 78 | var val = RevitToGraphValue(hp); 79 | 80 | if (bqType != null && clientMapping != null) 81 | { 82 | //resolve mapped field name if present 83 | if (clType != null) 84 | { 85 | var mappedFielName = clType.ValueMap.FirstOrDefault(vm => vm.Value == paramName); 86 | if (mappedFielName.Value == paramName) paramName = mappedFielName.Key; 87 | } 88 | 89 | var paramField = bqType.Fields.FirstOrDefault(fb => fb.Name == paramName); 90 | if (includeOnlyMappedFields && paramField == null) continue; 91 | 92 | //attempt to convert units 93 | if (val is double) 94 | { 95 | var fieldUnit = paramField.Args.FirstOrDefault(arg => arg.Name == "unit"); 96 | if (fieldUnit == null) continue; 97 | 98 | //var fieldUnitType = schema.GetBuildingGraphType(fieldUnit.TypeName); 99 | 100 | var unitMapping = clientMapping.Types.FirstOrDefault(tp => tp.Name == fieldUnit.TypeName); 101 | 102 | var defaultValue = fieldUnit.DefaultValue != null ? fieldUnit.DefaultValue.ToString() : string.Empty; 103 | if (unitMapping != null && unitMapping.ValueMap.ContainsKey(fieldUnit.DefaultValue.ToString())) 104 | { 105 | var revitValue = unitMapping.ValueMap[defaultValue]; 106 | HLDisplayUnitTypeEnum revitUnitTypeEnum; 107 | if (Enum.TryParse(revitValue, out revitUnitTypeEnum)) 108 | { 109 | //var type = Type.GetType(unitMapping.NativeType);// "Namespace.MyClass, MyAssembly"); 110 | val = HLUnitUtils.FromInternalUnits((double)val, revitUnitTypeEnum); 111 | } 112 | } 113 | } 114 | } 115 | else 116 | { 117 | //brute force parse from string to primitive type 118 | if (val is string && val != null) 119 | { 120 | var valstr = val as string; 121 | valstr = valstr.Trim().ToLower(); 122 | 123 | if (valstr == "n/a" || valstr == "n\\a" || valstr == "uncontrolled" || valstr == "-") 124 | { 125 | val = null; 126 | } 127 | else if (valstr == "yes") 128 | { 129 | val = true; 130 | } 131 | else if (valstr == "no") 132 | { 133 | val = false; 134 | } 135 | else if (valstr.Contains(".") && double.TryParse(valstr, out double valDub)) 136 | { 137 | val = valDub; 138 | } 139 | else if (int.TryParse(valstr, out int valint)) 140 | { 141 | val = valint; 142 | } 143 | 144 | } 145 | 146 | } 147 | 148 | if (!elmParms.ContainsKey(paramName)) 149 | { 150 | elmParms.Add(paramName, val); 151 | } 152 | } 153 | 154 | return elmParms; 155 | } 156 | 157 | public static Dictionary GetEdgeProps(Element elm) 158 | { 159 | var eprops = new Dictionary(); 160 | if (elm != null) 161 | { 162 | eprops.Add("UniqueId", elm.UniqueId); 163 | eprops.Add("ModelId", elm.Id.IntegerValue); 164 | } 165 | 166 | return eprops; 167 | 168 | } 169 | } 170 | } 171 | -------------------------------------------------------------------------------- /BuildingGraph.Integration.Revit/Graph/MEPNodeEdge.cs: -------------------------------------------------------------------------------- 1 | //using Newtonsoft.Json.Serialization; 2 | using System.Collections.Generic; 3 | using BuildingGraph.Client.Model; 4 | 5 | namespace BuildingGraph.Integration.Revit 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 | -------------------------------------------------------------------------------- /BuildingGraph.Integration.Revit/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 BuildingGraph.Integration.Revit 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 | -------------------------------------------------------------------------------- /BuildingGraph.Integration.Revit/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 BuildingGraph.Integration.Revit 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 | -------------------------------------------------------------------------------- /BuildingGraph.Integration.Revit/Graph/MEPPathWriteCache.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using HLApps.Revit.Geometry.Octree; 3 | using HLApps.Revit.Geometry; 4 | using BuildingGraph.Integration.Revit.Parsers; 5 | 6 | namespace BuildingGraph.Integration.Revit 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 | -------------------------------------------------------------------------------- /BuildingGraph.Integration.Revit/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.Utils; 8 | using BuildingGraph.Integration.Revit.Parsers; 9 | 10 | namespace BuildingGraph.Integration.Revit 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 | -------------------------------------------------------------------------------- /BuildingGraph.Integration.Revit/Graph/Parsers/FaceIntersectRay.cs: -------------------------------------------------------------------------------- 1 | using Autodesk.Revit.DB; 2 | 3 | using HLApps.Revit.Geometry; 4 | 5 | namespace BuildingGraph.Integration.Revit.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 | -------------------------------------------------------------------------------- /BuildingGraph.Integration.Revit/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 BuildingGraph.Integration.Revit.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 | } -------------------------------------------------------------------------------- /BuildingGraph.Integration.Revit/Graph/Parsers/IRevitGraphParser.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using Autodesk.Revit.DB; 3 | 4 | namespace BuildingGraph.Integration.Revit.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 | -------------------------------------------------------------------------------- /BuildingGraph.Integration.Revit/Graph/Parsers/MEPGraphParserElectrical.cs: -------------------------------------------------------------------------------- 1 | using System.Linq; 2 | 3 | using Autodesk.Revit.DB; 4 | using Model = BuildingGraph.Client.Model; 5 | 6 | namespace BuildingGraph.Integration.Revit.Parsers 7 | { 8 | 9 | public class MEPGraphParserElectrical : MEPGraphParserConnectors 10 | { 11 | public override bool CanParse(Element elm) 12 | { 13 | 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 }; 14 | return elm.Category != null ? cats.Contains((BuiltInCategory)elm.Category.Id.IntegerValue) : false; 15 | } 16 | 17 | public override ElementFilter GetFilter() 18 | { 19 | 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 }; 20 | var emcf = new ElementMulticategoryFilter(cats); 21 | return emcf; 22 | } 23 | 24 | public override void ParseFrom(Element elm, MEPRevitGraphWriter writer) 25 | { 26 | 27 | //connect db panels to their circuits 28 | if (elm is FamilyInstance) 29 | { 30 | var fi = elm as FamilyInstance; 31 | var sysElm = fi.MEPModel; 32 | #if REVIT2022 33 | var systems = sysElm.GetElectricalSystems(); 34 | #else 35 | var systems = sysElm.ElectricalSystems; 36 | #endif 37 | 38 | if (sysElm != null && sysElm.HLGetElectricalSystems() != null) 39 | { 40 | var panleSystems = sysElm.HLGetElectricalSystems().Where(sy => sy.BaseEquipment != null && sy.BaseEquipment.Id == elm.Id); 41 | 42 | foreach (var sys in panleSystems) 43 | { 44 | writer.Graph.AddConnection(elm, sys, MEPPathConnectionType.Analytical, Model.MEPEdgeTypes.ELECTRICAL_FLOW_TO); 45 | 46 | try 47 | { 48 | var elmsINSys = sys.Elements.OfType(); 49 | 50 | foreach (var emms in elmsINSys) 51 | { 52 | writer.Graph.AddConnection(sys, emms, MEPPathConnectionType.Analytical, Model.MEPEdgeTypes.ELECTRICAL_FLOW_TO); 53 | 54 | ParseFrom(emms, writer); 55 | } 56 | } 57 | catch 58 | { 59 | //log exception 60 | } 61 | } 62 | } 63 | } 64 | 65 | base.ParseFrom(elm, writer); 66 | 67 | } 68 | 69 | } 70 | 71 | } 72 | -------------------------------------------------------------------------------- /BuildingGraph.Integration.Revit/Graph/Parsers/MEPGraphParserIoT.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | 5 | using Autodesk.Revit.DB; 6 | using Autodesk.Revit.DB.Mechanical; 7 | using HLApps.Revit.Utils; 8 | using HLApps.Revit.Geometry; 9 | using Model = BuildingGraph.Client.Model; 10 | 11 | namespace BuildingGraph.Integration.Revit.Parsers 12 | { 13 | public class MEPGraphParserIoT : MEPGraphParserConnectors 14 | { 15 | public override bool CanParse(Element elm) 16 | { 17 | var fi = elm as FamilyInstance; 18 | return fi != null && fi.Symbol != null && fi.Symbol.FamilyName != null && fi.Symbol.FamilyName.ToLower().StartsWith("hl_iot"); 19 | } 20 | 21 | 22 | public override ElementFilter GetFilter() 23 | { 24 | var dattFilter = new ElementCategoryFilter(BuiltInCategory.OST_DataDevices); 25 | return dattFilter; 26 | } 27 | 28 | public override void ParseFrom(ICollection elms, MEPRevitGraphWriter writer) 29 | { 30 | foreach (var elm in elms) 31 | { 32 | ParseFrom(elm, writer); 33 | } 34 | } 35 | 36 | 37 | public override void ParseFrom(Element elm, MEPRevitGraphWriter writer) 38 | { 39 | var fi = elm as FamilyInstance; 40 | if (fi == null) return; 41 | 42 | var elmHost = fi.Host; 43 | 44 | Transform tsx = Transform.Identity; 45 | if (elmHost is RevitLinkInstance) 46 | { 47 | RevitLinkInstance rl = elmHost as RevitLinkInstance; 48 | var ldoc = rl.GetLinkDocument(); 49 | var sRef = fi.HostFace.ConvertToStableRepresentation(elm.Document); 50 | //dcdb8503-82b6-4a11-a408-754c3e8e7289-0026baca:0:RVTLINK:3791865:0:INSTANCE:3769400:94:SURFACE 51 | string[] refTokens = sRef.Split(':'); 52 | var extIdst = refTokens[3]; //6ths index contains the elementID in host document! 53 | var extId = new ElementId(int.Parse(extIdst)); 54 | 55 | var lelmHost = ldoc.GetElement(extId); 56 | if (lelmHost != null) 57 | { 58 | writer.Graph.AddConnection(elm, lelmHost, MEPPathConnectionType.Analytical, Model.MEPEdgeTypes.SENSING); 59 | } 60 | 61 | tsx = rl.GetTotalTransform().Inverse; 62 | elmHost = lelmHost; 63 | } 64 | else if (elmHost != null && !(elmHost is ReferencePlane)) 65 | { 66 | writer.Graph.AddConnection(elm, elmHost, MEPPathConnectionType.Analytical, Model.MEPEdgeTypes.SENSING); 67 | } 68 | else if (fi.Space != null) 69 | { 70 | writer.Graph.AddConnection(elm, fi.Space, MEPPathConnectionType.Analytical, Model.MEPEdgeTypes.SENSING); 71 | } 72 | 73 | //find space, level, etc of host element. 74 | if (elmHost != null && !(elmHost is ReferencePlane)) 75 | { 76 | base.ScanSpacesFromElement(elmHost, writer.Graph, writer.Cache.ParsedElements, tsx, elm.Document); 77 | } 78 | } 79 | 80 | 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /BuildingGraph.Integration.Revit/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 | using Model = BuildingGraph.Client.Model; 9 | 10 | namespace BuildingGraph.Integration.Revit.Parsers 11 | { 12 | public class SpaceNetworkPathScanner : IMEPGraphElementScanner 13 | { 14 | BoundsOctree _geoTree; 15 | 16 | public void Initialise(ICollection geoSerchElements, BoundsOctree geo) 17 | { 18 | _geoTree = geo; 19 | 20 | 21 | } 22 | 23 | 24 | public void ScanFromDocument(Document doc, MEPRevitGraph graph, int maxDepth) 25 | { 26 | Dictionary> spaceToDoors = new Dictionary>(); 27 | 28 | scanFromDocument(graph, doc, Transform.Identity, doc); 29 | 30 | //get linked documents 31 | foreach (RevitLinkInstance linkedInstance in DocUtils.GetLinkInstances(doc)) 32 | { 33 | 34 | //RevitLinkType linkType = (RevitLinkType)doc.GetElement(linkedInstance.GetTypeId()) as RevitLinkType; 35 | 36 | //ExternalFileReference exfRef = linkType.GetExternalFileReference(); 37 | 38 | //if (exfRef.GetLinkedFileStatus() != LinkedFileStatus.Loaded) continue; 39 | 40 | 41 | var ldoc = linkedInstance.GetLinkDocument(); 42 | if (ldoc == null) continue; 43 | scanFromDocument(graph, ldoc, linkedInstance.GetTotalTransform().Inverse, doc); 44 | } 45 | 46 | } 47 | 48 | public void ScanFromElement(Element elm, MEPRevitGraph graph, int maxDepth) 49 | { 50 | //TODO: actually scan from the supplied element 51 | ScanFromDocument(elm.Document, graph, maxDepth); 52 | 53 | } 54 | 55 | void scanFromDocument(MEPRevitGraph graph, Document doc, Transform tr, Document spaceSourceDoc) 56 | { 57 | var doorCol = new FilteredElementCollector(doc); 58 | var doors = doorCol.OfCategory(BuiltInCategory.OST_Doors).WhereElementIsNotElementType().ToElements().OfType(); 59 | 60 | foreach (var door in doors) 61 | { 62 | if (door.Location == null) continue; 63 | 64 | var ho = door.FacingFlipped ? door.FacingOrientation.Negate() : door.FacingOrientation; 65 | //var bbox = door.get_BoundingBox(null); 66 | var midPoint = (door.Location as LocationPoint).Point + new XYZ(0, 0, 1); 67 | //if (bbox != null) 68 | //{ 69 | // midPoint = (bbox.Min + bbox.Max) / 2; 70 | //} 71 | 72 | //get point in front 73 | var hfOrt = ho.Normalize(); 74 | var frontPos = midPoint + hfOrt.Multiply(1.64042); //stub is 1.64042 feet (0.5 meters) 75 | var lpFrontPoint = tr.OfPoint(frontPos); 76 | var spFront = spaceSourceDoc.GetSpaceAtPoint(lpFrontPoint);//, phase); 77 | 78 | 79 | //get point behind 80 | var hbOrt = ho.Negate().Normalize(); 81 | var behindPos = midPoint + hbOrt.Multiply(1.64042); //stub is 1.64042 feet (0.5 meters) 82 | var lpBehindPoint = tr.OfPoint(behindPos); 83 | var spBehind = spaceSourceDoc.GetSpaceAtPoint(lpBehindPoint);//, phase); 84 | 85 | 86 | 87 | if (spFront != null) 88 | { 89 | var edges = graph.AddConnection(spFront, door, midPoint, MEPPathConnectionType.Phyiscal, Model.MEPEdgeTypes.FLOWS_TO); 90 | edges.ThisNode.OrginTransform = tr; 91 | } 92 | 93 | if (spBehind != null) 94 | { 95 | var edges = graph.AddConnection(door, spBehind, midPoint, MEPPathConnectionType.Phyiscal, Model.MEPEdgeTypes.FLOWS_TO); 96 | edges.ThisNode.OrginTransform = tr; 97 | } 98 | 99 | 100 | } 101 | } 102 | 103 | 104 | 105 | } 106 | 107 | } 108 | 109 | -------------------------------------------------------------------------------- /BuildingGraph.Integration.Revit/Graph/introspection/EnumUtils.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 | using BuildingGraph.Client.Introspection; 9 | using BuildingGraph.Integration.Revit; 10 | 11 | namespace BuildingGraph.Integration.Revit.Graph.introspection 12 | { 13 | class EnumUtils 14 | { 15 | 16 | public HLDisplayUnitTypeEnum ToRevitUnits(IBuildingGraphEnum bgEnum, string enumValue) 17 | { 18 | switch (enumValue) 19 | { 20 | case "m": 21 | return HLDisplayUnitTypeEnum.DUT_METERS; 22 | case "mm": 23 | return HLDisplayUnitTypeEnum.DUT_MILLIMETERS; 24 | case "A": 25 | return HLDisplayUnitTypeEnum.DUT_AMPERES; 26 | case "mA": 27 | return HLDisplayUnitTypeEnum.DUT_MILLIAMPERES; 28 | } 29 | 30 | throw new Exception("Unknown unit type " + enumValue); 31 | } 32 | 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /BuildingGraph.Integration.Revit/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 | -------------------------------------------------------------------------------- /BuildingGraph.Integration.Revit/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 | -------------------------------------------------------------------------------- /BuildingGraph.Integration.Revit/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 | -------------------------------------------------------------------------------- /BuildingGraph.Integration.Revit/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 | -------------------------------------------------------------------------------- /BuildingGraph.Integration.Revit/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 | [assembly: InternalsVisibleTo("BuildingGraph.Integration.Revit.Tests")] 38 | [assembly: InternalsVisibleTo("BuildingGraph.Integration.Revit.Explorables")] 39 | -------------------------------------------------------------------------------- /BuildingGraph.Integration.Revit/RevitGraphApp.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.ApplicationServices; 7 | using Autodesk.Revit.DB; 8 | 9 | 10 | 11 | namespace BuildingGraph.Integration.Revit 12 | { 13 | [Autodesk.Revit.Attributes.Regeneration(Autodesk.Revit.Attributes.RegenerationOption.Manual)] 14 | public class RevitGraphApp : IExternalDBApplication 15 | { 16 | public ExternalDBApplicationResult OnShutdown(ControlledApplication application) 17 | { 18 | return ExternalDBApplicationResult.Succeeded; 19 | } 20 | 21 | public ExternalDBApplicationResult OnStartup(ControlledApplication application) 22 | { 23 | return ExternalDBApplicationResult.Succeeded; 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /BuildingGraph.Integration.Revit/RevitGraphSyncService.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq; 3 | using System.Collections.Generic; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | using Autodesk.Revit.DB; 8 | using Nito.AsyncEx; 9 | using BuildingGraph.Client; 10 | using HLApps.Revit.Parameters; 11 | 12 | namespace BuildingGraph.Integration.Revit 13 | { 14 | 15 | public class RevitGraphSyncService 16 | { 17 | 18 | 19 | public void Sync(Document doc) 20 | { 21 | 22 | var client = new BuildingGraphClient(@"https://hlbuildinggraph.azure-api.net/dev-external/graphql?subscription-key=e24f1d99266045f4b7ff2656b05d7ddb"); 23 | 24 | var query = @"query($identity:String) { 25 | ParameterChange (filter:{IsClosed:false ModelElement_in:{Model_in:{Identity:$identity}}}) 26 | { 27 | ParameterName 28 | ModelElement{ 29 | UniqueId 30 | } 31 | AbstractElement{ 32 | Id 33 | } 34 | NewValue 35 | OldValue 36 | } 37 | }"; 38 | 39 | Dictionary vars = new Dictionary(); 40 | 41 | var docIdent = HLApps.Revit.Utils.DocUtils.GetDocumentIdent(doc); 42 | vars.Add("identity", "8764c510-57b7-44c3-bddf-266d86c26380-0000c160:C:\\Users\\reynoldsw\\Desktop\\Ventilation Pressure Drop Model\\Ventilation Pressure Drop Model.rvt"); 43 | 44 | var result = client.ExecuteQuery(query, vars); 45 | 46 | 47 | foreach (var parameterChange in result.ParameterChange) 48 | { 49 | if (parameterChange.NewValue != null) 50 | { 51 | 52 | var qlperamName = parameterChange.ParameterName.Value; 53 | var newValue = parameterChange.NewValue.Value; 54 | var elmId = parameterChange.ModelElement.UniqueId.Value; 55 | 56 | 57 | Element elm = doc.GetElement(elmId); 58 | if (elm == null) continue; 59 | 60 | 61 | foreach (var param in elm.Parameters.OfType()) 62 | { 63 | if (param.IsReadOnly) continue; 64 | 65 | var hp = new HLRevitParameter(param); 66 | var paramName = Utils.GetGraphQLCompatibleFieldName(param.Definition.Name); 67 | 68 | if (qlperamName == paramName) 69 | { 70 | hp.Value = newValue; 71 | } 72 | } 73 | 74 | } 75 | } 76 | 77 | 78 | } 79 | 80 | 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /BuildingGraph.Integration.Revit/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 | using BuildingGraph.Client.Neo4j; 8 | 9 | 10 | namespace BuildingGraph.Integration.Revit 11 | { 12 | public class RevitToGraphPublisher 13 | { 14 | Document _rdoc; 15 | MEPGraphWriter wre; 16 | public RevitToGraphPublisher(Document doc) 17 | { 18 | _rdoc = doc; 19 | } 20 | 21 | public void Publish(RevitToGraphPublisherSettings settings, Neo4jClient client) 22 | { 23 | var meGraph = new MEPRevitGraph(); 24 | MEPRevitGraphWriter mps = new MEPRevitGraphWriter(meGraph); 25 | 26 | if (settings.IncludeElectrical) mps.Parsers.Add(new Parsers.MEPGraphParserElectrical()); 27 | if (settings.IncludeMechanical) mps.Parsers.Add(new Parsers.MEPGraphParserConnectors()); 28 | if (settings.IncludeBoundaries) mps.Parsers.Add(new Parsers.MEPGraphParserSpaces()); 29 | //if (settings.IncludeBoundaries) mps.Parsers.Add(new Parsers.ClashDetection()); 30 | mps.Parsers.Add(new Parsers.MEPGraphParserIoT()); 31 | 32 | if (mps.Parsers.Count == 0) return; 33 | 34 | var mecFEc = new FilteredElementCollector(_rdoc); 35 | var mecFilter = mps.GetFilterForAllParsers; 36 | var mecElements = mecFEc.WherePasses(mecFilter).WhereElementIsNotElementType().ToElements(); 37 | 38 | var wfic = new FilteredElementCollector(_rdoc); 39 | var geoElementsFilter = new ElementMulticategoryFilter(new BuiltInCategory[] { BuiltInCategory.OST_Floors, BuiltInCategory.OST_Roofs, BuiltInCategory.OST_Windows, BuiltInCategory.OST_Doors, BuiltInCategory.OST_MEPSpaces, BuiltInCategory.OST_Rooms }); 40 | var geoElements = wfic.WherePasses(geoElementsFilter).WhereElementIsNotElementType().ToElements(); 41 | 42 | 43 | using (Transaction tx = new Transaction(_rdoc, "Build graph")) 44 | { 45 | tx.Start("Build graph"); 46 | mps.Write(mecElements, geoElements, -1, settings.DeepGeoMatch, _rdoc); 47 | tx.Commit(); 48 | } 49 | 50 | wre = new MEPGraphWriter(client); 51 | 52 | wre.Write(meGraph, _rdoc); 53 | 54 | } 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /BuildingGraph.Integration.Revit/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 BuildingGraph.Integration.Revit 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 bool DeepGeoMatch { get; set; } 25 | 26 | public string DBName { get; set; } 27 | public string DBPassword { get; set; } 28 | public string DBUsername { get; set; } 29 | public string DBHost { get; set; } 30 | public int DBPort { get; set; } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /BuildingGraph.Integration.Revit/RevitToGraphQLMappings.json: -------------------------------------------------------------------------------- 1 | { 2 | "Types": { 3 | "LengthUnits": { 4 | "Kind": "ENUM", 5 | "NativeType": "Autodesk.Revit.DB.DisplayUnitType", 6 | "Mappings": { 7 | "ft": "DUT_DECIMAL_FEET", 8 | "in": "DUT_DECIMAL_INCHES", 9 | "m": "DUT_METERS", 10 | "mm": "DUT_MILLIMETERS", 11 | "cm": "DUT_CENTIMETERS" 12 | } 13 | 14 | }, 15 | "AreaUnits": { 16 | "Kind": "ENUM", 17 | "NativeType": "Autodesk.Revit.DB.DisplayUnitType", 18 | "Mappings": { 19 | "mm2": "DUT_SQUARE_METERS", 20 | "ft2": "DUT_SQUARE_FEET" 21 | } 22 | 23 | }, 24 | "VolumeUnits": { 25 | "Kind": "ENUM", 26 | "NativeType": "Autodesk.Revit.DB.DisplayUnitType", 27 | "Mappings": { 28 | "mm3": "DUT_CUBIC_METERS", 29 | "ft3": "DUT_CUBIC_FEET" 30 | } 31 | 32 | }, 33 | "CurrentUnits": { 34 | "Kind": "ENUM", 35 | "NativeType": "Autodesk.Revit.DB.DisplayUnitType", 36 | "Mappings": { 37 | "A": "DUT_AMPERES", 38 | "mA": "DUT_MILLIAMPERES", 39 | "kA": "DUT_KILOAMPERES" 40 | } 41 | 42 | }, 43 | "VoltageUnits": { 44 | "Kind": "ENUM", 45 | "NativeType": "Autodesk.Revit.DB.DisplayUnitType", 46 | "Mappings": { 47 | "V": "DUT_VOLTS", 48 | "mV": "DUT_MILLIVOLTS", 49 | "kV": "DUT_KILOVOLTS" 50 | } 51 | 52 | }, 53 | "PowerUnits": { 54 | "Kind": "ENUM", 55 | "NativeType": "Autodesk.Revit.DB.DisplayUnitType", 56 | "Mappings": { 57 | "W": "DUT_WATTS", 58 | "kW": "DUT_KILOWATTS" 59 | } 60 | 61 | }, 62 | "Space": { 63 | "Kind": "OBJECT", 64 | "NativeType": "Autodesk.Revit.DB.Space", 65 | "Create": "CreateSpace", 66 | "Delete": "DeleteSpace", 67 | "Update": "UpdateSpace", 68 | "Mappings": {} 69 | }, 70 | "FanCoilUnit": { 71 | "Kind": "OBJECT", 72 | "NativeType": "Autodesk.Revit.DB.MechanicalEquipment", 73 | "Classifications": [ 74 | { 75 | "Classification": "Pr_70_65_03_29" 76 | } 77 | ] 78 | } 79 | } 80 | } -------------------------------------------------------------------------------- /BuildingGraph.Integration.Revit/Streams/RevitStreamConsumer.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 | using BuildingGraph.Client.Kafka; 9 | 10 | namespace BuildingGraph.Integration.Revit.Streams 11 | { 12 | 13 | //moved to UI for now 14 | 15 | 16 | 17 | } 18 | -------------------------------------------------------------------------------- /BuildingGraph.Integration.Revit/Units/Convert/LabelUtilsConvert.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 BuildingGraph.Integration.Revit 10 | { 11 | public partial class HLLabelUtils 12 | { 13 | 14 | public static string GetLableFor(HLUnitType unitType) 15 | { 16 | 17 | #if REVIT2022 18 | return LabelUtils.GetLabelForSpec(unitType.AsForgeTypedId); 19 | #else 20 | return LabelUtils.GetLabelFor(unitType.AsEnum); 21 | #endif 22 | } 23 | 24 | public static string GetLableFor(HLUnitSymbolType unitType) 25 | { 26 | #if REVIT2022 27 | return LabelUtils.GetLabelForSymbol(unitType.AsForgeTypedId); 28 | #else 29 | return LabelUtils.GetLabelFor(unitType.AsEnum); 30 | #endif 31 | 32 | } 33 | 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /BuildingGraph.Integration.Revit/Units/Convert/NoForgeTypeFoundException.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace BuildingGraph.Integration.Revit 4 | { 5 | 6 | public class NoForgeTypeFoundException : Exception 7 | { 8 | public NoForgeTypeFoundException() 9 | { 10 | } 11 | 12 | public NoForgeTypeFoundException(string message) 13 | : base(message) 14 | { 15 | } 16 | 17 | public NoForgeTypeFoundException(string message, Exception inner) 18 | : base(message, inner) 19 | { 20 | } 21 | } 22 | 23 | } 24 | -------------------------------------------------------------------------------- /BuildingGraph.Integration.Revit/Units/Convert/StringToForgeTypeId.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 BuildingGraph.Integration.Revit 10 | { 11 | public partial class HLConvert 12 | { 13 | #if REVIT2022 14 | 15 | /// 16 | /// Spec is UnitType in Revit 2022 < 17 | /// 18 | /// 19 | /// 20 | public static ForgeTypeId SpecToForgeTypeId(string unitTypeName) 21 | { 22 | var specs = SpecUtils.GetAllSpecs(); 23 | 24 | var spec = specs.FirstOrDefault(s => s.TypeId == unitTypeName); 25 | 26 | return spec; 27 | } 28 | #endif 29 | 30 | 31 | 32 | 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /BuildingGraph.Integration.Revit/Units/Convert/UnitFormatUtilsConvert.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 BuildingGraph.Integration.Revit 10 | { 11 | public partial class HLUnitFormatUtils 12 | { 13 | 14 | public static bool TryParse(Units units, HLUnitType hlUnit, string stringToParse, out double value) 15 | { 16 | 17 | #if REVIT2022 18 | return UnitFormatUtils.TryParse(units, hlUnit.AsForgeTypedId, stringToParse, out value); 19 | #else 20 | return UnitFormatUtils.TryParse(units, hlUnit.AsEnum, stringToParse, out value); 21 | #endif 22 | 23 | } 24 | 25 | } 26 | 27 | } 28 | -------------------------------------------------------------------------------- /BuildingGraph.Integration.Revit/Units/Convert/UnitUtilsConvert.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 BuildingGraph.Integration.Revit 10 | { 11 | public partial class HLUnitUtils 12 | { 13 | 14 | public static double FromInternalUnits(double from, HLDisplayUnitTypeEnum to) 15 | { 16 | 17 | #if REVIT2022 18 | var forgeType = HLConvert.ToForgeTypeId(to); 19 | return UnitUtils.ConvertFromInternalUnits(from, forgeType); 20 | #else 21 | return UnitUtils.ConvertFromInternalUnits(from, (DisplayUnitType)(int)to); 22 | #endif 23 | 24 | } 25 | 26 | 27 | 28 | public static double FromInternalUnits(double from, HLDisplayUnitType displayUnit) 29 | { 30 | #if REVIT2022 31 | return UnitUtils.ConvertFromInternalUnits(from, displayUnit.AsForgeTypedId); 32 | #else 33 | return UnitUtils.ConvertFromInternalUnits(from, (DisplayUnitType)(int)displayUnit.AsEnum); 34 | #endif 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /BuildingGraph.Integration.Revit/Units/Mappings/HLDisplayUnitType.cs: -------------------------------------------------------------------------------- 1 |  2 | 3 | using Autodesk.Revit.DB; 4 | 5 | namespace BuildingGraph.Integration.Revit 6 | { 7 | /// 8 | /// Enumerated by UnitTypeId in Revit 2022, DisplayUnitType in earlier versions 9 | /// 10 | public class HLDisplayUnitType 11 | { 12 | 13 | #if REVIT2022 14 | public HLDisplayUnitType(ForgeTypeId forgeTypeId) 15 | { 16 | AsForgeTypedId = forgeTypeId; 17 | } 18 | 19 | public ForgeTypeId AsForgeTypedId { get; private set; } 20 | 21 | public static bool operator ==(HLDisplayUnitType lhs, HLDisplayUnitTypeEnum rhs) 22 | { 23 | var hlut = HLConvert.ToHLDisplayUnitType(rhs); 24 | return lhs == hlut; 25 | } 26 | 27 | public static bool operator !=(HLDisplayUnitType lhs, HLDisplayUnitTypeEnum rhs) 28 | { 29 | var hlut = HLConvert.ToHLDisplayUnitType(rhs); 30 | return lhs != hlut; 31 | } 32 | 33 | 34 | public static bool operator ==(HLDisplayUnitType lhs, HLDisplayUnitType rhs) 35 | { 36 | return lhs.AsForgeTypedId == rhs.AsForgeTypedId; 37 | } 38 | 39 | public static bool operator !=(HLDisplayUnitType lhs, HLDisplayUnitType rhs) 40 | { 41 | return lhs.AsForgeTypedId != rhs.AsForgeTypedId; 42 | } 43 | 44 | public override int GetHashCode() 45 | { 46 | return AsForgeTypedId == null ? base.GetHashCode() : AsForgeTypedId.GetHashCode(); 47 | } 48 | 49 | public override bool Equals(object other) 50 | { 51 | if (other is HLDisplayUnitType) 52 | { 53 | return (other as HLDisplayUnitType).AsForgeTypedId == AsForgeTypedId; 54 | } 55 | return false; 56 | } 57 | 58 | #else 59 | 60 | public HLDisplayUnitType(DisplayUnitType enumValue) 61 | { 62 | AsEnum = enumValue; 63 | } 64 | 65 | public DisplayUnitType AsEnum { get; private set; } 66 | 67 | 68 | public static bool operator ==(HLDisplayUnitType lhs, HLDisplayUnitTypeEnum rhs) 69 | { 70 | return lhs.AsEnum == (DisplayUnitType)(int)rhs; 71 | } 72 | 73 | public static bool operator !=(HLDisplayUnitType lhs, HLDisplayUnitTypeEnum rhs) 74 | { 75 | return lhs.AsEnum != (DisplayUnitType)(int)rhs; ; 76 | } 77 | 78 | 79 | public static bool operator ==(HLDisplayUnitType lhs, HLDisplayUnitType rhs) 80 | { 81 | return lhs.AsEnum == rhs.AsEnum; 82 | } 83 | 84 | public static bool operator !=(HLDisplayUnitType lhs, HLDisplayUnitType rhs) 85 | { 86 | return lhs.AsEnum != rhs.AsEnum; 87 | } 88 | 89 | public override int GetHashCode() 90 | { 91 | return AsEnum.GetHashCode(); 92 | } 93 | 94 | public override bool Equals(object other) 95 | { 96 | if (other is HLDisplayUnitType) 97 | { 98 | return (other as HLDisplayUnitType).AsEnum == AsEnum; 99 | } 100 | else if (other is HLDisplayUnitTypeEnum || other is DisplayUnitType) 101 | { 102 | 103 | return AsEnum == (DisplayUnitType)(int)other; 104 | } 105 | 106 | 107 | return false; 108 | } 109 | 110 | #endif 111 | 112 | } 113 | 114 | public static class HLDisplayUnitTypeExtentions 115 | { 116 | 117 | public static HLDisplayUnitType HLGetDisplayUnitType(this Parameter param) 118 | { 119 | 120 | #if REVIT2022 121 | return new HLDisplayUnitType(param.GetUnitTypeId()); 122 | #else 123 | return new HLDisplayUnitType(param.DisplayUnitType); 124 | #endif 125 | 126 | } 127 | 128 | public static HLDisplayUnitType HLGetDisplayUnitType(this FamilyParameter param) 129 | { 130 | 131 | #if REVIT2022 132 | return new HLDisplayUnitType(param.GetUnitTypeId()); 133 | #else 134 | return new HLDisplayUnitType(param.DisplayUnitType); 135 | #endif 136 | 137 | } 138 | 139 | 140 | public static HLDisplayUnitType HLGetDisplayUnits(this FormatOptions options) 141 | { 142 | 143 | #if REVIT2022 144 | return new HLDisplayUnitType(options.GetUnitTypeId()); 145 | #else 146 | return new HLDisplayUnitType(options.DisplayUnits); 147 | #endif 148 | 149 | } 150 | 151 | } 152 | 153 | 154 | } 155 | -------------------------------------------------------------------------------- /BuildingGraph.Integration.Revit/Units/Mappings/HLEnumForgeWrapper.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Autodesk.Revit.DB; 3 | 4 | 5 | namespace BuildingGraph.Integration.Revit 6 | { 7 | /* 8 | public class HLEnumForgeWrapper where hlenum : System.Enum where native : System.Enum 9 | { 10 | #if REVIT2022 11 | 12 | public HLUnitType(ForgeTypeId forgeTypeId) 13 | { 14 | AsForgeTypedId = forgeTypeId; 15 | } 16 | 17 | public ForgeTypeId AsForgeTypedId { get; private set; } 18 | 19 | 20 | public static bool operator ==(HLUnitType lhs, HLUnitTypeEnum rhs) 21 | { 22 | 23 | //Convert to ForgeType? 24 | return false; 25 | } 26 | 27 | public static bool operator !=(HLUnitType lhs, HLUnitTypeEnum rhs) 28 | { 29 | 30 | //Convert to ForgeType? 31 | return false; 32 | } 33 | 34 | public static bool operator ==(HLUnitType lhs, HLUnitType rhs) 35 | { 36 | return lhs.AsForgeTypedId == rhs.AsForgeTypedId; 37 | } 38 | 39 | public static bool operator !=(HLUnitType lhs, HLUnitType rhs) 40 | { 41 | return lhs.AsForgeTypedId != rhs.AsForgeTypedId; 42 | } 43 | 44 | public override int GetHashCode() 45 | { 46 | return AsForgeTypedId == null ? base.GetHashCode() : AsForgeTypedId.GetHashCode(); 47 | } 48 | 49 | public override bool Equals(object other) 50 | { 51 | if (other is HLUnitType) 52 | { 53 | return (other as HLUnitType).AsForgeTypedId == AsForgeTypedId; 54 | } 55 | return false; 56 | } 57 | 58 | HLUnitTypeEnum asEnum; 59 | 60 | #else 61 | public HLEnumForgeWrapper(native enumValue) 62 | { 63 | AsEnum = enumValue; 64 | } 65 | 66 | public native AsEnum { get; private set; } 67 | 68 | 69 | public static bool operator ==(HLEnumForgeWrapper lhs, hlenum rhs) 70 | { 71 | return Convert.ToInt32(lhs.AsEnum) == Convert.ToInt32(rhs); 72 | } 73 | 74 | public static bool operator !=(HLEnumForgeWrapper lhs, hlenum rhs) 75 | { 76 | return Convert.ToInt32(lhs.AsEnum) != Convert.ToInt32(rhs); 77 | } 78 | 79 | public static bool operator ==(HLEnumForgeWrapper lhs, HLEnumForgeWrapper rhs) 80 | { 81 | return Convert.ToInt32(lhs.AsEnum) == Convert.ToInt32(rhs.AsEnum); 82 | } 83 | 84 | public static bool operator !=(HLEnumForgeWrapper lhs, HLEnumForgeWrapper rhs) 85 | { 86 | return Convert.ToInt32(lhs.AsEnum) != Convert.ToInt32(rhs.AsEnum); 87 | } 88 | 89 | public override int GetHashCode() 90 | { 91 | return AsEnum.GetHashCode(); 92 | } 93 | 94 | public override bool Equals(object other) 95 | { 96 | if (other is HLEnumForgeWrapper) 97 | { 98 | return (other as HLEnumForgeWrapper).AsEnum.Equals(AsEnum); 99 | } 100 | else if (other is HLUnitSymbolTypeEnum || other is UnitSymbolType) 101 | { 102 | return Convert.ToInt32(AsEnum) == Convert.ToInt32((UnitSymbolType)other); 103 | } 104 | 105 | return false; 106 | } 107 | #endif 108 | 109 | } 110 | */ 111 | } 112 | -------------------------------------------------------------------------------- /BuildingGraph.Integration.Revit/Units/Mappings/HLMEPSystem.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 | using Autodesk.Revit.DB.Electrical; 9 | 10 | namespace BuildingGraph.Integration.Revit 11 | { 12 | public static class HLMEPSystemExtenstions 13 | { 14 | 15 | public static ICollection HLGetElectricalSystems(this MEPModel mepModel) 16 | { 17 | #if REVIT2022 18 | return mepModel.GetElectricalSystems(); 19 | #else 20 | return mepModel.ElectricalSystems != null ? mepModel.ElectricalSystems.OfType().ToList() : null; 21 | #endif 22 | 23 | } 24 | 25 | 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /BuildingGraph.Integration.Revit/Units/Mappings/HLParameterType.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 | using Autodesk.Revit.DB; 9 | 10 | namespace BuildingGraph.Integration.Revit 11 | { 12 | 13 | 14 | 15 | 16 | public class HLParameterType 17 | { 18 | 19 | private ParameterType AsParameterType; 20 | 21 | //HLParameterTypeEnum hlpt; 22 | 23 | 24 | //UnitType ut; 25 | //ForgeTypeID; 26 | } 27 | 28 | 29 | } 30 | -------------------------------------------------------------------------------- /BuildingGraph.Integration.Revit/Units/Mappings/HLUnitSymbolType.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Linq; 3 | using System.Text; 4 | using System.Threading.Tasks; 5 | using Autodesk.Revit.DB; 6 | 7 | 8 | namespace BuildingGraph.Integration.Revit 9 | { 10 | 11 | /// 12 | /// UnitSymbolType == SymbolTypeId 13 | /// 14 | public class HLUnitSymbolType 15 | { 16 | 17 | #if REVIT2022 18 | 19 | public HLUnitSymbolType(ForgeTypeId forgeTypeId) 20 | { 21 | AsForgeTypedId = forgeTypeId; 22 | } 23 | 24 | public ForgeTypeId AsForgeTypedId { get; private set; } 25 | 26 | 27 | public static bool operator ==(HLUnitSymbolType lhs, HLUnitSymbolTypeEnum rhs) 28 | { 29 | var hlut = HLConvert.ToHLSymbolUnitType(rhs); 30 | return lhs == hlut; 31 | } 32 | 33 | public static bool operator !=(HLUnitSymbolType lhs, HLUnitSymbolTypeEnum rhs) 34 | { 35 | var hlut = HLConvert.ToHLSymbolUnitType(rhs); 36 | return lhs != hlut; 37 | } 38 | 39 | public static bool operator ==(HLUnitSymbolType lhs, HLUnitSymbolType rhs) 40 | { 41 | return lhs.AsForgeTypedId == rhs.AsForgeTypedId; 42 | } 43 | 44 | public static bool operator !=(HLUnitSymbolType lhs, HLUnitSymbolType rhs) 45 | { 46 | return lhs.AsForgeTypedId != rhs.AsForgeTypedId; 47 | } 48 | 49 | public override int GetHashCode() 50 | { 51 | return AsForgeTypedId == null ? base.GetHashCode() : AsForgeTypedId.GetHashCode(); 52 | } 53 | 54 | public override bool Equals(object other) 55 | { 56 | if (other is HLUnitSymbolType) 57 | { 58 | return (other as HLUnitSymbolType).AsForgeTypedId == AsForgeTypedId; 59 | } 60 | return false; 61 | } 62 | 63 | HLUnitTypeEnum asEnum; 64 | 65 | #else 66 | public HLUnitSymbolType(UnitSymbolType enumValue) 67 | { 68 | AsEnum = enumValue; 69 | } 70 | 71 | public UnitSymbolType AsEnum { get; private set; } 72 | 73 | 74 | public static bool operator ==(HLUnitSymbolType lhs, HLUnitSymbolTypeEnum rhs) 75 | { 76 | 77 | return lhs.AsEnum == (UnitSymbolType)(int)rhs; 78 | } 79 | 80 | public static bool operator !=(HLUnitSymbolType lhs, HLUnitSymbolTypeEnum rhs) 81 | { 82 | return lhs.AsEnum != (UnitSymbolType)(int)rhs; ; 83 | } 84 | 85 | 86 | 87 | public static bool operator ==(HLUnitSymbolType lhs, HLUnitSymbolType rhs) 88 | { 89 | return lhs.AsEnum == rhs.AsEnum; 90 | } 91 | 92 | public static bool operator !=(HLUnitSymbolType lhs, HLUnitSymbolType rhs) 93 | { 94 | return lhs.AsEnum != rhs.AsEnum; 95 | } 96 | 97 | public override int GetHashCode() 98 | { 99 | return AsEnum.GetHashCode(); 100 | } 101 | 102 | public override bool Equals(object other) 103 | { 104 | if (other is HLUnitSymbolType) 105 | { 106 | return (other as HLUnitSymbolType).AsEnum == AsEnum; 107 | } 108 | else if (other is HLUnitSymbolTypeEnum || other is UnitSymbolType) 109 | { 110 | 111 | return AsEnum == (UnitSymbolType)(int)other; 112 | } 113 | 114 | return false; 115 | } 116 | #endif 117 | 118 | } 119 | 120 | public static class HLUnitSymbolTypeExtentions 121 | { 122 | 123 | public static HLUnitSymbolType HLGetUnitSymbol(this FormatOptions options) 124 | { 125 | 126 | #if REVIT2022 127 | return new HLUnitSymbolType(options.GetSymbolTypeId()); 128 | #else 129 | return new HLUnitSymbolType(options.UnitSymbol); 130 | #endif 131 | 132 | } 133 | 134 | } 135 | 136 | } 137 | -------------------------------------------------------------------------------- /BuildingGraph.Integration.Revit/Units/Mappings/HLUnitType.cs: -------------------------------------------------------------------------------- 1 |  2 | 3 | using Autodesk.Revit.DB; 4 | 5 | namespace BuildingGraph.Integration.Revit 6 | { 7 | //needs to be an object not enum 8 | //so any conversion is always handled in the extension methods only, so, 9 | //not this rv2022 > to hl enum > () > rv2020, but this rv2022 > () > rv2022 (no conversion) 10 | //conversion should only takes place where explicit enum values are checked in the upstream methods. 11 | 12 | /// 13 | /// Enumerated by SpecTypeId in Revit 2022, UnitType in earlier versions 14 | /// 15 | public class HLUnitType 16 | { 17 | #if REVIT2022 18 | 19 | public HLUnitType(ForgeTypeId forgeTypeId) 20 | { 21 | AsForgeTypedId = forgeTypeId; 22 | } 23 | 24 | public ForgeTypeId AsForgeTypedId { get; private set; } 25 | 26 | 27 | public static bool operator ==(HLUnitType lhs, HLUnitTypeEnum rhs) 28 | { 29 | var hlut = HLConvert.ToHLUnitType(rhs); 30 | return lhs == hlut; 31 | } 32 | 33 | public static bool operator !=(HLUnitType lhs, HLUnitTypeEnum rhs) 34 | { 35 | var hlut = HLConvert.ToHLUnitType(rhs); 36 | return lhs != hlut; 37 | } 38 | 39 | public static bool operator ==(HLUnitType lhs, HLUnitType rhs) 40 | { 41 | return lhs.AsForgeTypedId == rhs.AsForgeTypedId; 42 | } 43 | 44 | public static bool operator !=(HLUnitType lhs, HLUnitType rhs) 45 | { 46 | return lhs.AsForgeTypedId != rhs.AsForgeTypedId; 47 | } 48 | 49 | public override int GetHashCode() 50 | { 51 | return AsForgeTypedId == null ? base.GetHashCode() : AsForgeTypedId.GetHashCode(); 52 | } 53 | 54 | public override bool Equals(object other) 55 | { 56 | if (other is HLUnitType) 57 | { 58 | return (other as HLUnitType).AsForgeTypedId == AsForgeTypedId; 59 | } 60 | return false; 61 | } 62 | 63 | #else 64 | public HLUnitType(UnitType enumValue) 65 | { 66 | AsEnum = enumValue; 67 | } 68 | 69 | public UnitType AsEnum { get; private set; } 70 | 71 | 72 | public static bool operator ==(HLUnitType lhs, HLUnitTypeEnum rhs) 73 | { 74 | return lhs.AsEnum == (UnitType)(int)rhs; 75 | } 76 | 77 | public static bool operator !=(HLUnitType lhs, HLUnitTypeEnum rhs) 78 | { 79 | return lhs.AsEnum != (UnitType)(int)rhs; ; 80 | } 81 | 82 | 83 | 84 | public static bool operator ==(HLUnitType lhs, HLUnitType rhs) 85 | { 86 | return lhs.AsEnum == rhs.AsEnum; 87 | } 88 | 89 | public static bool operator !=(HLUnitType lhs, HLUnitType rhs) 90 | { 91 | return lhs.AsEnum != rhs.AsEnum; 92 | } 93 | 94 | public override int GetHashCode() 95 | { 96 | return AsEnum.GetHashCode(); 97 | } 98 | 99 | public override bool Equals(object other) 100 | { 101 | if (other is HLUnitType) 102 | { 103 | return (other as HLUnitType).AsEnum == AsEnum; 104 | } 105 | else if (other is HLUnitTypeEnum || other is UnitType) 106 | { 107 | 108 | return AsEnum == (UnitType)(int)other; 109 | } 110 | 111 | return false; 112 | } 113 | #endif 114 | } 115 | 116 | 117 | public static class HLUnitTypeExtensions 118 | { 119 | public static HLUnitType HLGetUnitType(this Definition def) 120 | { 121 | 122 | #if REVIT2022 123 | return new HLUnitType(def.GetGroupTypeId()); 124 | #else 125 | return new HLUnitType(def.UnitType); 126 | #endif 127 | } 128 | 129 | public static HLUnitType HLGetUnitType(this ScheduleField field) 130 | { 131 | 132 | #if REVIT2022 133 | return new HLUnitType(field.GetSpecTypeId()); 134 | 135 | #else 136 | return new HLUnitType(field.UnitType); 137 | #endif 138 | 139 | } 140 | 141 | public static FormatOptions HLGetFormatOptions(this Units options, HLUnitType unitType) 142 | { 143 | 144 | #if REVIT2022 145 | return options.GetFormatOptions(unitType.AsForgeTypedId); 146 | #else 147 | return options.GetFormatOptions(unitType.AsEnum); 148 | #endif 149 | } 150 | 151 | 152 | } 153 | 154 | 155 | } 156 | -------------------------------------------------------------------------------- /BuildingGraph.Integration.Revit/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 | public 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 | -------------------------------------------------------------------------------- /BuildingGraph.Integration.Revit/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 | -------------------------------------------------------------------------------- /BuildingGraph.Integration.Revit/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 | -------------------------------------------------------------------------------- /BuildingGraph.Integration.Revit/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 | public static class MEPModelExtensions 9 | { 10 | 11 | public static IEnumerable hlGetElectricalSystems(this MEPModel model) 12 | { 13 | 14 | #if REVIT2022 15 | return model.GetElectricalSystems().OfType(); 16 | #else 17 | return sysElm.ElectricalSystems.OfType(); 18 | #endif 19 | 20 | } 21 | 22 | 23 | } 24 | 25 | static class RevitElementExtensions 26 | { 27 | 28 | 29 | public static Parameter HLGetParameter(this Element elm, string name) 30 | { 31 | 32 | var foundPramams = elm.GetParameters(name); 33 | 34 | if (foundPramams.Count == 0) 35 | { 36 | foundPramams = elm.Parameters.OfType().Where(p => string.Equals(p.Definition.Name, name, StringComparison.CurrentCultureIgnoreCase)).ToList(); 37 | } 38 | 39 | 40 | var firstValidParam = foundPramams.FirstOrDefault(p => p.HasValue); 41 | 42 | return firstValidParam != null ? firstValidParam : foundPramams.FirstOrDefault(); 43 | 44 | } 45 | 46 | public static Parameter HLGetParameter(this Element elm, BuiltInParameter bip) 47 | { 48 | 49 | return elm.get_Parameter(bip); 50 | 51 | } 52 | 53 | 54 | public static Parameter HLGetParameter(this Element elm, Guid Id) 55 | { 56 | 57 | return elm.get_Parameter(Id); 58 | 59 | } 60 | 61 | 62 | public static Parameter HLGetParameter(this Element elm, ElementId parameterId) 63 | { 64 | if (parameterId.IntegerValue == -1) return null; 65 | 66 | Parameter param = null; 67 | if (parameterId.IntegerValue < -1) 68 | { 69 | param = elm.get_Parameter((BuiltInParameter)parameterId.IntegerValue); 70 | } 71 | else 72 | { 73 | param = elm.Parameters.OfType().FirstOrDefault(pr => GetParameterId(pr).IntegerValue == parameterId.IntegerValue); 74 | } 75 | 76 | return param; 77 | } 78 | 79 | public static ElementId GetParameterId(Parameter param) 80 | { 81 | return param.Id; 82 | } 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /BuildingGraph.Integration.Revit/app.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /BuildingGraph.Integration.Revit/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /BuildingGraph.Integration.RevitUI/BuildingGraph.Integration.RevitUI.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {F5FECC1A-9803-43EA-A217-E9D321A7C2D2} 8 | Library 9 | Properties 10 | BuildingGraph.Integration.Revit.UIaddin 11 | HLApps.Revit.Graph.UIAddin 12 | v4.6.2 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 | GraphAppWindow.xaml 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | {79e4ed3b-5594-466d-89f9-18d2f00a547e} 54 | BuildingGraph.Client.Core 55 | 56 | 57 | {6217d742-11dc-40d1-8125-d2b98414be03} 58 | BuildingGraph.Client.GraphQL 59 | 60 | 61 | {400e1964-b716-4ea4-b21e-15c1f2135888} 62 | BuildingGraph.Client.Neo4j 63 | 64 | 65 | {93280ff6-c2cc-4ece-8c26-d6794f7121d3} 66 | BuildingGraph.Integration.Revit 67 | 68 | 69 | 70 | 71 | MSBuild:Compile 72 | Designer 73 | 74 | 75 | 76 | 77 | 78 | -------------------------------------------------------------------------------- /BuildingGraph.Integration.RevitUI/BuildingGraph.addin: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Revit To Graph 5 | BuildingGraph\BuildingGraph.Integration.RevitUI.dll 6 | 5EE88C10-F682-4A48-8975-CB5652917F6B 7 | BuildingGraph.Integration.Revit.UIAddin.GraphApp 8 | HLEA 9 | Will Reynolds @ Hoare Lea 10 | 11 | -------------------------------------------------------------------------------- /BuildingGraph.Integration.RevitUI/GraphApp.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Linq; 3 | using System.Text; 4 | using System.Threading.Tasks; 5 | using Autodesk.Revit.UI; 6 | using Autodesk.Revit.DB; 7 | using BuildingGraph.Client.Kafka; 8 | using BuildingGraph.Client; 9 | using System.IO; 10 | using BuildingGraph.Integration.Revit.Streams; 11 | 12 | 13 | namespace BuildingGraph.Integration.Revit.UIAddin 14 | { 15 | 16 | [Autodesk.Revit.Attributes.Regeneration(Autodesk.Revit.Attributes.RegenerationOption.Manual)] 17 | public class GraphApp : IExternalApplication 18 | { 19 | public static GraphApp Instance; 20 | 21 | 22 | public GraphApp() 23 | { 24 | Instance = this; 25 | } 26 | 27 | public Result OnShutdown(UIControlledApplication application) 28 | { 29 | 30 | return Result.Succeeded; 31 | } 32 | 33 | public Result OnStartup(UIControlledApplication application) 34 | { 35 | 36 | var appPanel = application.CreateRibbonPanel(Tab.AddIns, "HLApps"); 37 | var showAppBtn = new PushButtonData("hleaPublishToGraph", "Publish to Graph", System.Reflection.Assembly.GetExecutingAssembly().Location, typeof(GraphAppShowCommand).FullName); 38 | showAppBtn.ToolTip = "Publish the current Revit model to a graph database"; 39 | appPanel.AddItem(showAppBtn); 40 | 41 | var syncBtn = new PushButtonData("hleaSyncWithGraph", "Pull Changes", System.Reflection.Assembly.GetExecutingAssembly().Location, typeof(RevitGraphSyncCommand).FullName); 42 | appPanel.AddItem(syncBtn); 43 | //TODO: persist settings with local storage 44 | SessionSettings = new RevitToGraphPublisherSettings(); 45 | 46 | RevitEventDispatcher.Init(); 47 | 48 | 49 | 50 | var streamConsumer = new RevitStreamConsumer(); 51 | var bc = new BuildingGraphClient(@"http://localhost:4002/graphql", null); 52 | var spacesEsh = new ElementStreamHandler(RevitEventDispatcher.Current, bc); 53 | streamConsumer.StreamHandlers.Add(spacesEsh); 54 | streamConsumer.Start(); 55 | 56 | return Result.Succeeded; 57 | } 58 | 59 | private void Kc_NewMessageArrived(StreamMessage message) 60 | { 61 | RevitEventDispatcher.Current.QueueAction((UIApplication app) => { 62 | 63 | 64 | 65 | 66 | }); 67 | } 68 | 69 | public System.Windows.Window GraphAppWindow { get; set; } 70 | public RevitToGraphPublisherSettings SessionSettings { get; private set; } 71 | 72 | 73 | 74 | 75 | } 76 | 77 | //public class QucikStreamHandler 78 | } -------------------------------------------------------------------------------- /BuildingGraph.Integration.RevitUI/GraphAppShowCommand.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Autodesk.Revit.DB; 3 | using Autodesk.Revit.UI; 4 | 5 | using BuildingGraph.Integration.Revit.UIAddin.ViewModel; 6 | 7 | 8 | namespace BuildingGraph.Integration.Revit.UIAddin 9 | { 10 | [Autodesk.Revit.Attributes.Transaction(Autodesk.Revit.Attributes.TransactionMode.Manual)] 11 | public class GraphAppShowCommand : IExternalCommand 12 | { 13 | public Result Execute(ExternalCommandData cmdData, ref string message, ElementSet elements) 14 | { 15 | Document rDoc = cmdData.Application.ActiveUIDocument.Document; 16 | var gdApp = GraphApp.Instance; 17 | var publisher = new RevitToGraphPublisher(rDoc); 18 | GraphAppViewModel gvm = new GraphAppViewModel(publisher, gdApp); 19 | gdApp.GraphAppWindow = new GraphAppWindow(gvm); 20 | gdApp.GraphAppWindow.ShowDialog(); 21 | 22 | return Result.Succeeded; 23 | } 24 | } 25 | } -------------------------------------------------------------------------------- /BuildingGraph.Integration.RevitUI/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 | -------------------------------------------------------------------------------- /BuildingGraph.Integration.RevitUI/RevitEventDispatcher.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Concurrent; 3 | using Autodesk.Revit.UI; 4 | 5 | namespace BuildingGraph.Integration.Revit.UIAddin 6 | { 7 | 8 | public interface IRevitEventDispathcer 9 | { 10 | 11 | 12 | } 13 | 14 | 15 | public class RevitEventDispatcher : Autodesk.Revit.UI.IExternalEventHandler 16 | { 17 | public static RevitEventDispatcher Current { get; private set; } 18 | 19 | private ConcurrentQueue> _revitProcessingQueue = new ConcurrentQueue>(); 20 | private ExternalEvent _extEvent; 21 | 22 | public static void Init() 23 | { 24 | if (Current != null) Current._extEvent.Dispose(); 25 | Current = new RevitEventDispatcher(); 26 | } 27 | 28 | public RevitEventDispatcher() 29 | { 30 | _extEvent = ExternalEvent.CreateJournalable(this); 31 | } 32 | 33 | public void Execute(UIApplication app) 34 | { 35 | if (Current != null) Current.DoQueuedActions(app); 36 | } 37 | 38 | public string GetName() 39 | { 40 | return "HL Revit action subscriber"; 41 | } 42 | 43 | 44 | public void QueueAction(Action tAct) 45 | { 46 | 47 | _revitProcessingQueue.Enqueue(tAct); 48 | _extEvent.Raise(); 49 | 50 | } 51 | 52 | private void DoQueuedActions(UIApplication app) 53 | { 54 | if (_revitProcessingQueue.Count > 0) 55 | { 56 | Action dAct; 57 | if (_revitProcessingQueue.TryDequeue(out dAct)) 58 | { 59 | try 60 | { 61 | dAct.Invoke(app); 62 | } 63 | catch (Exception ex) 64 | { 65 | 66 | } 67 | } 68 | 69 | lock (_revitProcessingQueue) 70 | { 71 | if (_revitProcessingQueue.Count > 0) 72 | { 73 | _extEvent.Raise(); 74 | } 75 | } 76 | } 77 | 78 | } 79 | } 80 | } -------------------------------------------------------------------------------- /BuildingGraph.Integration.RevitUI/RevitGraphSyncCommand.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Autodesk.Revit.DB; 3 | using Autodesk.Revit.UI; 4 | 5 | namespace BuildingGraph.Integration.Revit.UIAddin 6 | { 7 | 8 | [Autodesk.Revit.Attributes.Transaction(Autodesk.Revit.Attributes.TransactionMode.Manual)] 9 | class RevitGraphSyncCommand : IExternalCommand 10 | { 11 | public Result Execute(ExternalCommandData cmdData, ref string message, ElementSet elements) 12 | { 13 | 14 | Document rDoc = cmdData.Application.ActiveUIDocument.Document; 15 | 16 | using (Transaction tx = new Transaction(rDoc, "gSync")) 17 | { 18 | tx.Start("gSync"); 19 | 20 | var bc = new RevitGraphSyncService(); 21 | bc.Sync(rDoc); 22 | 23 | tx.Commit(); 24 | } 25 | 26 | 27 | return Result.Succeeded; 28 | 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /BuildingGraph.Integration.RevitUI/Streams/RevitStreamConsumer.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 | using BuildingGraph.Client.Kafka; 9 | 10 | namespace BuildingGraph.Integration.Revit.Streams 11 | { 12 | public class RevitStreamConsumer 13 | { 14 | 15 | Client.BuildingGraphClient _client; 16 | 17 | 18 | public ICollection StreamHandlers = new List(); 19 | 20 | public RevitStreamConsumer() 21 | { 22 | 23 | kafkaConsumer = new KafkaConsumer("localhost:9092"); 24 | 25 | kafkaConsumer.NewMessageArrived += KafkaConsumer_NewMessageArrived; 26 | 27 | _client = new Client.BuildingGraphClient(@"http://localhost:4002/graphql", null); 28 | 29 | } 30 | 31 | 32 | private void KafkaConsumer_NewMessageArrived(StreamMessage message) 33 | { 34 | 35 | foreach (var handler in StreamHandlers) 36 | { 37 | handler.processRemote(message); 38 | } 39 | } 40 | 41 | public KafkaConsumer kafkaConsumer { get; private set; } 42 | 43 | 44 | public void Start() 45 | { 46 | kafkaConsumer.StartAsync("lc-ng", new string[] { "ext-service-abstractElements" }); 47 | } 48 | 49 | //cache of DBIDs to Revit IDs 50 | 51 | public void RefreshCacheFromGraph(Document doc) 52 | { 53 | //pull all elements 54 | 55 | var schme = _client.GetSchema(); 56 | 57 | var docIdent = HLApps.Revit.Utils.DocUtils.GetDocumentIdent(doc); 58 | var docVars = new Dictionary(); 59 | docVars.Add("modelIdent", docIdent); 60 | var modelElementsQuery = @"query($modelIdent:String){ 61 | Model (Identity:$modelIdent){ 62 | Identity 63 | ModelElements { 64 | UniqueId 65 | AbstractElement { 66 | __typename 67 | Id 68 | Name 69 | } 70 | } 71 | } 72 | }"; 73 | 74 | var modelElementQResult = _client.ExecuteQuery(modelElementsQuery, docVars); 75 | 76 | 77 | 78 | } 79 | 80 | } 81 | 82 | 83 | 84 | } 85 | -------------------------------------------------------------------------------- /BuildingGraph.Integration.RevitUI/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 | 31 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 104 | 105 | 106 | 107 | 108 | 111 | 114 | 115 | 116 | 117 | 118 | -------------------------------------------------------------------------------- /BuildingGraph.Integration.RevitUI/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 | using BuildingGraph.Integration.Revit.UIAddin.ViewModel; 7 | 8 | namespace BuildingGraph.Integration.Revit.UIAddin 9 | { 10 | internal partial class GraphAppWindow : Window 11 | { 12 | GraphAppViewModel _gappVM; 13 | public GraphAppWindow(GraphAppViewModel gappVM) 14 | { 15 | InitializeComponent(); 16 | 17 | _gappVM = gappVM; 18 | this.DataContext = gappVM; 19 | 20 | pwBox.PasswordChanged += PwBox_PasswordChanged; 21 | } 22 | 23 | private void PwBox_PasswordChanged(object sender, RoutedEventArgs e) 24 | { 25 | _gappVM.Password = pwBox.Password; 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /BuildingGraph.Integration.RevitUI/UI/ViewModel/BaseViewModel.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.ComponentModel; 5 | 6 | namespace BuildingGraph.Integration.Revit.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 | -------------------------------------------------------------------------------- /BuildingGraph.Integration.RevitUI/UI/ViewModel/Command.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Windows.Input; 3 | 4 | namespace BuildingGraph.Integration.Revit.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 | -------------------------------------------------------------------------------- /BuildingGraph.Integration.RevitUI/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 | using BuildingGraph.Client.Neo4j; 7 | 8 | namespace BuildingGraph.Integration.Revit.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 | 25 | public string DBName 26 | { 27 | get 28 | { 29 | return _settings.DBName; 30 | } 31 | set 32 | { 33 | _settings.DBName = value; 34 | NotifyPropertyChanged("DBName"); 35 | } 36 | } 37 | 38 | 39 | public string Username 40 | { 41 | get 42 | { 43 | return _settings.DBUsername; 44 | } 45 | set 46 | { 47 | _settings.DBUsername = value; 48 | NotifyPropertyChanged("Username"); 49 | } 50 | } 51 | 52 | 53 | public string Password 54 | { 55 | get 56 | { 57 | return _settings.DBPassword; 58 | } 59 | set 60 | { 61 | _settings.DBPassword = value; 62 | NotifyPropertyChanged("Password"); 63 | } 64 | } 65 | 66 | public string Host 67 | { 68 | get 69 | { 70 | return _settings.DBHost; 71 | } 72 | set 73 | { 74 | _settings.DBHost = value; 75 | NotifyPropertyChanged("Host"); 76 | } 77 | } 78 | public int Port 79 | { 80 | get 81 | { 82 | return _settings.DBPort; 83 | } 84 | set 85 | { 86 | _settings.DBPort = value; 87 | NotifyPropertyChanged("Port"); 88 | } 89 | } 90 | 91 | public bool IncludeBoundaries 92 | { 93 | get 94 | { 95 | return _settings.IncludeBoundaries; 96 | } 97 | set 98 | { 99 | _settings.IncludeBoundaries = value; 100 | NotifyPropertyChanged("IncludeBoundaries"); 101 | NotifyPropertyChanged("CanPublish"); 102 | } 103 | } 104 | public bool IncludeMechanical 105 | { 106 | get 107 | { 108 | return _settings.IncludeMechanical; 109 | } 110 | set 111 | { 112 | _settings.IncludeMechanical = value; 113 | NotifyPropertyChanged("IncludeMechanical"); 114 | NotifyPropertyChanged("CanPublish"); 115 | } 116 | } 117 | public bool IncludeElectrical 118 | { 119 | get 120 | { 121 | return _settings.IncludeElectrical; 122 | } 123 | set 124 | { 125 | _settings.IncludeElectrical = value; 126 | NotifyPropertyChanged("IncludeElectrical"); 127 | NotifyPropertyChanged("CanPublish"); 128 | } 129 | } 130 | 131 | public bool DeepGeoMatch 132 | { 133 | get 134 | { 135 | return _settings.DeepGeoMatch; 136 | } 137 | set 138 | { 139 | _settings.DeepGeoMatch = value; 140 | NotifyPropertyChanged("DeepGeoMatch"); 141 | } 142 | } 143 | 144 | public bool CanPublish 145 | { 146 | get 147 | { 148 | return IncludeBoundaries || IncludeMechanical || IncludeElectrical; 149 | } 150 | } 151 | 152 | Command _publishToGraphCommand; 153 | public Command PublishToGraphCommand 154 | { 155 | get 156 | { 157 | return _publishToGraphCommand; 158 | } 159 | } 160 | 161 | Command _cancelCommand; 162 | public Command CancelCommand 163 | { 164 | get 165 | { 166 | return _cancelCommand; 167 | } 168 | } 169 | 170 | Neo4jClient client; 171 | void PublishToGraph() 172 | { 173 | client = new Neo4jClient(new Uri(string.Format("bolt://{0}:{1}", Host, Port)), Username, Password, DBName); 174 | _publisher.Publish(_settings, client); 175 | Autodesk.Revit.UI.TaskDialog.Show("Model Processed", "The model will continue to be uploaded in the background"); 176 | 177 | } 178 | 179 | void Close() 180 | { 181 | var appWindow = _app.GraphAppWindow; 182 | if (appWindow != null && appWindow.IsVisible) appWindow.Close(); 183 | } 184 | } 185 | } 186 | -------------------------------------------------------------------------------- /BuildingGraph.Integration.RevitUI/app.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 willhl 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. 22 | --------------------------------------------------------------------------------