chore: Remove legacy .NET based IFC importer (#1118)

* remove IFC source files

* re-generate slnx files
This commit is contained in:
Jedd Morgan
2025-10-01 12:06:43 +01:00
committed by GitHub
parent 2cdf036172
commit 2d0b1a3a24
75 changed files with 0 additions and 5080 deletions
@@ -1,31 +0,0 @@
using Speckle.Sdk.SQLite;
namespace Speckle.Importers.Ifc.Tester;
public sealed class DummySendCacheManager(Dictionary<string, string> objects) : ISqLiteJsonCacheManager
{
public void Dispose() { }
public IReadOnlyCollection<(string, string)> GetAllObjects() => throw new NotImplementedException();
public void DeleteObject(string id) => throw new NotImplementedException();
public string? GetObject(string id) => null;
public void SaveObject(string id, string json) => throw new NotImplementedException();
public bool HasObject(string objectId) => false;
#pragma warning disable CA1065
public string Path => throw new NotImplementedException();
#pragma warning restore CA1065
public void SaveObjects(IEnumerable<(string id, string json)> items)
{
foreach (var (id, json) in items)
{
objects[id] = json;
}
}
public void UpdateObject(string id, string json) => throw new NotImplementedException();
}
@@ -1,43 +0,0 @@
using System.Text;
using Speckle.Sdk.Serialisation.V2;
using Speckle.Sdk.Serialisation.V2.Send;
using Speckle.Sdk.Transports;
namespace Speckle.Importers.Ifc.Tester;
public class DummyServerObjectManager : IServerObjectManager
{
public IAsyncEnumerable<(string, string)> DownloadObjects(
IReadOnlyCollection<string> objectIds,
IProgress<ProgressArgs>? progress,
CancellationToken cancellationToken
) => throw new NotImplementedException();
public Task<string?> DownloadSingleObject(
string objectId,
IProgress<ProgressArgs>? progress,
CancellationToken cancellationToken
) => throw new NotImplementedException();
public Task<Dictionary<string, bool>> HasObjects(
IReadOnlyCollection<string> objectIds,
CancellationToken cancellationToken
) => Task.FromResult(objectIds.ToDictionary(id => id, id => false));
public Task UploadObjects(
IReadOnlyList<BaseItem> objects,
bool compressPayloads,
IProgress<ProgressArgs>? progress,
CancellationToken cancellationToken
)
{
long totalBytes = 0;
foreach (var item in objects)
{
totalBytes += Encoding.Default.GetByteCount(item.Json.Value);
}
progress?.Report(new(ProgressEvent.UploadBytes, totalBytes, totalBytes));
return Task.CompletedTask;
}
}
@@ -1,66 +0,0 @@
#pragma warning disable CA1506
using System.Diagnostics;
using Ara3D.Utils;
//using JetBrains.Profiler.SelfApi;
using Microsoft.Extensions.DependencyInjection;
using Speckle.Importers.Ifc;
using Speckle.Importers.Ifc.Ara3D.IfcParser;
using Speckle.Importers.Ifc.Converters;
using Speckle.Importers.Ifc.Tester;
using Speckle.Importers.Ifc.Types;
using Speckle.Sdk.Serialisation.V2;
using Speckle.Sdk.Serialisation.V2.Send;
using Speckle.Sdk.SQLite;
var serviceProvider = Import.GetServiceProvider();
//DotMemory.Init();
var filePath = new FilePath(
//"C:\\Users\\adam\\Git\\speckle-server\\packages\\fileimport-service\\ifc-dotnet\\ifcs\\20210221PRIMARK.ifc"
//"C:\\Users\\adam\\Git\\speckle-server\\packages\\fileimport-service\\ifc-dotnet\\ifcs\\231110ADT-FZK-Haus-2005-2006.ifc"
//"C:\\Users\\adam\\Downloads\\T03PV06IMPMI01C.ifc"
"C:\\Users\\adam\\Downloads\\20231128_HW_Bouwkosten.ifc"
);
var ifcFactory = serviceProvider.GetRequiredService<IIfcFactory>();
var stopwatch = Stopwatch.StartNew();
Console.WriteLine($"Opening with WebIFC: {filePath}");
var model = ifcFactory.Open(filePath);
var ms = stopwatch.ElapsedMilliseconds;
Console.WriteLine($"Opened with WebIFC: {ms} ms");
var graph = IfcGraph.Load(new FilePath(filePath));
var ms2 = stopwatch.ElapsedMilliseconds;
Console.WriteLine($"Loaded with StepParser: {ms2 - ms} ms");
var converter = serviceProvider.GetRequiredService<IGraphConverter>();
var b = converter.Convert(model, graph);
ms = ms2;
ms2 = stopwatch.ElapsedMilliseconds;
Console.WriteLine($"Converted to Speckle Bases: {ms2 - ms} ms");
var factory = serviceProvider.GetRequiredService<ISerializeProcessFactory>();
var cache = $"C:\\Users\\adam\\Git\\temp\\{Guid.NewGuid()}.db";
using var sqlite = SqLiteJsonCacheManager.FromFilePath(cache, 2);
await using var process2 = factory.CreateSerializeProcess(
sqlite,
new DummyServerObjectManager(),
new Progress(true),
default,
new SerializeProcessOptions(SkipServer: true)
);
Console.WriteLine($"Caching to Speckle: {cache}");
/*var config = new DotMemory.Config();
config.OpenDotMemory();
config.SaveToDir("C:\\Users\\adam\\dotTraceSnapshots");
DotMemory.Attach(config);
DotMemory.GetSnapshot("Before");*/
var (rootId, _) = await process2.Serialize(b).ConfigureAwait(false);
Console.WriteLine(rootId);
ms2 = stopwatch.ElapsedMilliseconds;
Console.WriteLine($"Converted to JSON: {ms2 - ms} ms");
//DotMemory.GetSnapshot("After");
//DotMemory.Detach();
#pragma warning restore CA1506
@@ -1,36 +0,0 @@
using Speckle.Sdk.Transports;
namespace Speckle.Importers.Ifc.Tester;
public class Progress(bool write) : IProgress<ProgressArgs>
{
private readonly TimeSpan _debounce = TimeSpan.FromMilliseconds(1000);
private DateTime _lastTime = DateTime.UtcNow;
private long _totalBytes;
public void Report(ProgressArgs value)
{
if (write)
{
if (value.ProgressEvent == ProgressEvent.DownloadBytes)
{
Interlocked.Add(ref _totalBytes, value.Count);
}
var now = DateTime.UtcNow;
if (now - _lastTime >= _debounce)
{
if (value.ProgressEvent == ProgressEvent.DownloadBytes)
{
Console.WriteLine(value.ProgressEvent + " t " + _totalBytes);
}
else
{
Console.WriteLine(value.ProgressEvent + " c " + value.Count + " t " + value.Total);
}
_lastTime = now;
}
}
}
}
@@ -1,13 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<Configurations>Debug;Release;Local</Configurations>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\Speckle.Importers.Ifc\Speckle.Importers.Ifc.csproj" />
</ItemGroup>
</Project>
@@ -1,316 +0,0 @@
{
"version": 2,
"dependencies": {
"net8.0": {
"Microsoft.NETFramework.ReferenceAssemblies": {
"type": "Direct",
"requested": "[1.0.3, )",
"resolved": "1.0.3",
"contentHash": "vUc9Npcs14QsyOD01tnv/m8sQUnGTGOw1BCmKcv77LBJY7OxhJ+zJF7UD/sCL3lYNFuqmQEVlkfS4Quif6FyYg==",
"dependencies": {
"Microsoft.NETFramework.ReferenceAssemblies.net461": "1.0.3"
}
},
"Microsoft.SourceLink.GitHub": {
"type": "Direct",
"requested": "[8.0.0, )",
"resolved": "8.0.0",
"contentHash": "G5q7OqtwIyGTkeIOAc3u2ZuV/kicQaec5EaRnc0pIeSnh9LUjj+PYQrJYBURvDt7twGl2PKA7nSN0kz1Zw5bnQ==",
"dependencies": {
"Microsoft.Build.Tasks.Git": "8.0.0",
"Microsoft.SourceLink.Common": "8.0.0"
}
},
"PolySharp": {
"type": "Direct",
"requested": "[1.14.1, )",
"resolved": "1.14.1",
"contentHash": "mOOmFYwad3MIOL14VCjj02LljyF1GNw1wP0YVlxtcPvqdxjGGMNdNJJxHptlry3MOd8b40Flm8RPOM8JOlN2sQ=="
},
"Speckle.InterfaceGenerator": {
"type": "Direct",
"requested": "[0.9.6, )",
"resolved": "0.9.6",
"contentHash": "HKH7tYrYYlCK1ct483hgxERAdVdMtl7gUKW9ijWXxA1UsYR4Z+TrRHYmzZ9qmpu1NnTycSrp005NYM78GDKV1w=="
},
"GraphQL.Client": {
"type": "Transitive",
"resolved": "6.0.0",
"contentHash": "8yPNBbuVBpTptivyAlak4GZvbwbUcjeQTL4vN1HKHRuOykZ4r7l5fcLS6vpyPyLn0x8FsL31xbOIKyxbmR9rbA==",
"dependencies": {
"GraphQL.Client.Abstractions": "6.0.0",
"GraphQL.Client.Abstractions.Websocket": "6.0.0",
"System.Reactive": "5.0.0"
}
},
"GraphQL.Client.Abstractions": {
"type": "Transitive",
"resolved": "6.0.0",
"contentHash": "h7uzWFORHZ+CCjwr/ThAyXMr0DPpzEANDa4Uo54wqCQ+j7qUKwqYTgOrb1W40sqbvNaZm9v/X7It31SUw0maHA==",
"dependencies": {
"GraphQL.Primitives": "6.0.0"
}
},
"GraphQL.Client.Abstractions.Websocket": {
"type": "Transitive",
"resolved": "6.0.0",
"contentHash": "Nr9bPf8gIOvLuXpqEpqr9z9jslYFJOvd0feHth3/kPqeR3uMbjF5pjiwh4jxyMcxHdr8Pb6QiXkV3hsSyt0v7A==",
"dependencies": {
"GraphQL.Client.Abstractions": "6.0.0"
}
},
"GraphQL.Primitives": {
"type": "Transitive",
"resolved": "6.0.0",
"contentHash": "yg72rrYDapfsIUrul7aF6wwNnTJBOFvuA9VdDTQpPa8AlAriHbufeXYLBcodKjfUdkCnaiggX1U/nEP08Zb5GA=="
},
"Microsoft.Build.Tasks.Git": {
"type": "Transitive",
"resolved": "8.0.0",
"contentHash": "bZKfSIKJRXLTuSzLudMFte/8CempWjVamNUR5eHJizsy+iuOuO/k2gnh7W0dHJmYY0tBf+gUErfluCv5mySAOQ=="
},
"Microsoft.Data.Sqlite": {
"type": "Transitive",
"resolved": "7.0.5",
"contentHash": "KGxbPeWsQMnmQy43DSBxAFtHz3l2JX8EWBSGUCvT3CuZ8KsuzbkqMIJMDOxWtG8eZSoCDI04aiVQjWuuV8HmSw==",
"dependencies": {
"Microsoft.Data.Sqlite.Core": "7.0.5",
"SQLitePCLRaw.bundle_e_sqlite3": "2.1.4"
}
},
"Microsoft.Data.Sqlite.Core": {
"type": "Transitive",
"resolved": "7.0.5",
"contentHash": "FTerRmQPqHrCrnoUzhBu+E+1DNGwyrAMLqHkAqOOOu5pGfyMOj8qQUBxI/gDtWtG11p49UxSfWmBzRNlwZqfUg==",
"dependencies": {
"SQLitePCLRaw.core": "2.1.4"
}
},
"Microsoft.Extensions.Configuration": {
"type": "Transitive",
"resolved": "2.2.0",
"contentHash": "nOP8R1mVb/6mZtm2qgAJXn/LFm/2kMjHDAg/QJLFG6CuWYJtaD3p1BwQhufBVvRzL9ceJ/xF0SQ0qsI2GkDQAA==",
"dependencies": {
"Microsoft.Extensions.Configuration.Abstractions": "2.2.0"
}
},
"Microsoft.Extensions.Configuration.Abstractions": {
"type": "Transitive",
"resolved": "2.2.0",
"contentHash": "65MrmXCziWaQFrI0UHkQbesrX5wTwf9XPjY5yFm/VkgJKFJ5gqvXRoXjIZcf2wLi5ZlwGz/oMYfyURVCWbM5iw==",
"dependencies": {
"Microsoft.Extensions.Primitives": "2.2.0"
}
},
"Microsoft.Extensions.Configuration.Binder": {
"type": "Transitive",
"resolved": "2.2.0",
"contentHash": "vJ9xvOZCnUAIHcGC3SU35r3HKmHTVIeHzo6u/qzlHAqD8m6xv92MLin4oJntTvkpKxVX3vI1GFFkIQtU3AdlsQ==",
"dependencies": {
"Microsoft.Extensions.Configuration": "2.2.0"
}
},
"Microsoft.Extensions.DependencyInjection.Abstractions": {
"type": "Transitive",
"resolved": "8.0.0",
"contentHash": "cjWrLkJXK0rs4zofsK4bSdg+jhDLTaxrkXu4gS6Y7MAlCvRyNNgwY/lJi5RDlQOnSZweHqoyvgvbdvQsRIW+hg=="
},
"Microsoft.Extensions.Options": {
"type": "Transitive",
"resolved": "2.2.0",
"contentHash": "UpZLNLBpIZ0GTebShui7xXYh6DmBHjWM8NxGxZbdQh/bPZ5e6YswqI+bru6BnEL5eWiOdodsXtEz3FROcgi/qg==",
"dependencies": {
"Microsoft.Extensions.DependencyInjection.Abstractions": "2.2.0",
"Microsoft.Extensions.Primitives": "2.2.0",
"System.ComponentModel.Annotations": "4.5.0"
}
},
"Microsoft.Extensions.Primitives": {
"type": "Transitive",
"resolved": "2.2.0",
"contentHash": "azyQtqbm4fSaDzZHD/J+V6oWMFaf2tWP4WEGIYePLCMw3+b2RQdj9ybgbQyjCshcitQKQ4lEDOZjmSlTTrHxUg==",
"dependencies": {
"System.Memory": "4.5.1",
"System.Runtime.CompilerServices.Unsafe": "4.5.1"
}
},
"Microsoft.NETFramework.ReferenceAssemblies.net461": {
"type": "Transitive",
"resolved": "1.0.3",
"contentHash": "AmOJZwCqnOCNp6PPcf9joyogScWLtwy0M1WkqfEQ0M9nYwyDD7EX9ZjscKS5iYnyvteX7kzSKFCKt9I9dXA6mA=="
},
"Microsoft.SourceLink.Common": {
"type": "Transitive",
"resolved": "8.0.0",
"contentHash": "dk9JPxTCIevS75HyEQ0E4OVAFhB2N+V9ShCXf8Q6FkUQZDkgLI12y679Nym1YqsiSysuQskT7Z+6nUf3yab6Vw=="
},
"Speckle.Newtonsoft.Json": {
"type": "Transitive",
"resolved": "13.0.2",
"contentHash": "g1BejUZwax5PRfL6xHgLEK23sqHWOgOj9hE7RvfRRlN00AGt8GnPYt8HedSK7UB3HiRW8zCA9Pn0iiYxCK24BA=="
},
"SQLitePCLRaw.bundle_e_sqlite3": {
"type": "Transitive",
"resolved": "2.1.4",
"contentHash": "EWI1olKDjFEBMJu0+3wuxwziIAdWDVMYLhuZ3Qs84rrz+DHwD00RzWPZCa+bLnHCf3oJwuFZIRsHT5p236QXww==",
"dependencies": {
"SQLitePCLRaw.lib.e_sqlite3": "2.1.4",
"SQLitePCLRaw.provider.e_sqlite3": "2.1.4"
}
},
"SQLitePCLRaw.core": {
"type": "Transitive",
"resolved": "2.1.4",
"contentHash": "inBjvSHo9UDKneGNzfUfDjK08JzlcIhn1+SP5Y3m6cgXpCxXKCJDy6Mka7LpgSV+UZmKSnC8rTwB0SQ0xKu5pA==",
"dependencies": {
"System.Memory": "4.5.3"
}
},
"SQLitePCLRaw.lib.e_sqlite3": {
"type": "Transitive",
"resolved": "2.1.4",
"contentHash": "2C9Q9eX7CPLveJA0rIhf9RXAvu+7nWZu1A2MdG6SD/NOu26TakGgL1nsbc0JAspGijFOo3HoN79xrx8a368fBg=="
},
"SQLitePCLRaw.provider.e_sqlite3": {
"type": "Transitive",
"resolved": "2.1.4",
"contentHash": "CSlb5dUp1FMIkez9Iv5EXzpeq7rHryVNqwJMWnpq87j9zWZexaEMdisDktMsnnrzKM6ahNrsTkjqNodTBPBxtQ==",
"dependencies": {
"SQLitePCLRaw.core": "2.1.4"
}
},
"System.ComponentModel.Annotations": {
"type": "Transitive",
"resolved": "4.5.0",
"contentHash": "UxYQ3FGUOtzJ7LfSdnYSFd7+oEv6M8NgUatatIN2HxNtDdlcvFAf+VIq4Of9cDMJEJC0aSRv/x898RYhB4Yppg=="
},
"System.Memory": {
"type": "Transitive",
"resolved": "4.5.5",
"contentHash": "XIWiDvKPXaTveaB7HVganDlOCRoj03l+jrwNvcge/t8vhGYKvqV+dMv6G4SAX2NoNmN0wZfVPTAlFwZcZvVOUw=="
},
"System.Reactive": {
"type": "Transitive",
"resolved": "5.0.0",
"contentHash": "erBZjkQHWL9jpasCE/0qKAryzVBJFxGHVBAvgRN1bzM0q2s1S4oYREEEL0Vb+1kA/6BKb5FjUZMp5VXmy+gzkQ=="
},
"System.Runtime.CompilerServices.Unsafe": {
"type": "Transitive",
"resolved": "4.5.1",
"contentHash": "Zh8t8oqolRaFa9vmOZfdQm/qKejdqz0J9kr7o2Fu0vPeoH3BL1EOXipKWwkWtLT1JPzjByrF19fGuFlNbmPpiw=="
},
"speckle.connectors.common": {
"type": "Project",
"dependencies": {
"Microsoft.Extensions.DependencyInjection": "[2.2.0, )",
"Speckle.Connectors.Logging": "[1.0.0, )",
"Speckle.Objects": "[3.5.4, )",
"Speckle.Sdk": "[3.5.4, )",
"Speckle.Sdk.Dependencies": "[3.5.4, )"
}
},
"speckle.connectors.logging": {
"type": "Project"
},
"speckle.importers.ifc": {
"type": "Project",
"dependencies": {
"Ara3D.Buffers": "[1.4.5, )",
"Ara3D.Logging": "[1.4.5, )",
"Ara3D.Utils": "[1.4.5, )",
"Microsoft.Extensions.DependencyInjection": "[8.0.0, )",
"Speckle.Connectors.Common": "[1.0.0, )",
"Speckle.Objects": "[3.5.4, )",
"Speckle.Sdk": "[3.5.4, )"
}
},
"Ara3D.Buffers": {
"type": "CentralTransitive",
"requested": "[1.4.5, )",
"resolved": "1.4.5",
"contentHash": "SKcQqgtXukyHTlTKFPCaUW4spSkue3XfBU/GmoA7KhH6H995v6TbJxtqjs0EfSgnXEkajL8U7X1NqktScRozXw==",
"dependencies": {
"System.Memory": "4.5.5"
}
},
"Ara3D.Logging": {
"type": "CentralTransitive",
"requested": "[1.4.5, )",
"resolved": "1.4.5",
"contentHash": "7HPCe5Dq21JoOBF1iclk9H37XFCoB2ZzCPqTMNgdg4PWFvuRsofNbiuMdiE/HKgMHCVhy1C5opB2KwDKcO7Axw==",
"dependencies": {
"Ara3D.Utils": "1.4.5"
}
},
"Ara3D.Utils": {
"type": "CentralTransitive",
"requested": "[1.4.5, )",
"resolved": "1.4.5",
"contentHash": "yba/E7PpbWP0+RDp+KbKw/vBXnXBSIheScdpVKuDnr8ytRg8pZ2Jd6nwKES+G0FcVEB9PeOVmEW7SGrFvAwRCg=="
},
"Microsoft.Extensions.DependencyInjection": {
"type": "CentralTransitive",
"requested": "[2.2.0, )",
"resolved": "8.0.0",
"contentHash": "V8S3bsm50ig6JSyrbcJJ8bW2b9QLGouz+G1miK3UTaOWmMtFwNNNzUf4AleyDWUmTrWMLNnFSLEQtxmxgNQnNQ==",
"dependencies": {
"Microsoft.Extensions.DependencyInjection.Abstractions": "8.0.0"
}
},
"Microsoft.Extensions.Logging": {
"type": "CentralTransitive",
"requested": "[2.2.0, )",
"resolved": "2.2.0",
"contentHash": "Nxqhadc9FCmFHzU+fz3oc8sFlE6IadViYg8dfUdGzJZ2JUxnCsRghBhhOWdM4B2zSZqEc+0BjliBh/oNdRZuig==",
"dependencies": {
"Microsoft.Extensions.Configuration.Binder": "2.2.0",
"Microsoft.Extensions.DependencyInjection.Abstractions": "2.2.0",
"Microsoft.Extensions.Logging.Abstractions": "2.2.0",
"Microsoft.Extensions.Options": "2.2.0"
}
},
"Microsoft.Extensions.Logging.Abstractions": {
"type": "CentralTransitive",
"requested": "[2.2.0, )",
"resolved": "2.2.0",
"contentHash": "B2WqEox8o+4KUOpL7rZPyh6qYjik8tHi2tN8Z9jZkHzED8ElYgZa/h6K+xliB435SqUcWT290Fr2aa8BtZjn8A=="
},
"Speckle.DoubleNumerics": {
"type": "CentralTransitive",
"requested": "[4.1.0, )",
"resolved": "4.1.0",
"contentHash": "20DtS+FsDRsOD9+AU3TwNFZ0qrKo5f6f7B5ZR9wStsIHHHC9k7DpjbCvuNtmnSjx54MD+TJC7wV2f5iyGVPj1A=="
},
"Speckle.Objects": {
"type": "CentralTransitive",
"requested": "[3.5.4, )",
"resolved": "3.5.4",
"contentHash": "o7ex4+yHJYI8pJbsjNqw+D8r8WjkBoB5aK/GQlGJd/0zydrPxN4SMKS4arpRBR3CUD6JhtQMatScXZOrslGXQg==",
"dependencies": {
"Speckle.Sdk": "3.5.4"
}
},
"Speckle.Sdk": {
"type": "CentralTransitive",
"requested": "[3.5.4, )",
"resolved": "3.5.4",
"contentHash": "o4bEJTz+OBI1koy9xqXSIq3UtUFCKtk6Btg82rdVM2aFMPT3ZoYVarG+ylPcUOHd684XpgGASxE6dIgXz2pvng==",
"dependencies": {
"GraphQL.Client": "6.0.0",
"Microsoft.Data.Sqlite": "7.0.5",
"Microsoft.Extensions.DependencyInjection.Abstractions": "2.2.0",
"Microsoft.Extensions.Logging": "2.2.0",
"Speckle.DoubleNumerics": "4.1.0",
"Speckle.Newtonsoft.Json": "13.0.2",
"Speckle.Sdk.Dependencies": "3.5.4"
}
},
"Speckle.Sdk.Dependencies": {
"type": "CentralTransitive",
"requested": "[3.5.4, )",
"resolved": "3.5.4",
"contentHash": "d0ZOHiK11Hq9r7YEkfTvVu33ygWtsrgysIWdCRAz6rdlcAgMCEkWVBoe3jDjxdmUy20TToaQlFKfMH4hTyzWXg=="
}
}
}
}
@@ -1,75 +0,0 @@
using Ara3D.Utils;
using Speckle.Sdk.Api;
using Speckle.Sdk.Credentials;
using Speckle.Sdk.Models.Extensions;
namespace Speckle.Importers.Ifc.Tester2;
/// <summary>
/// This is a test file for testing the IFC importer locally
/// Except for the logic in the preview service, this is pretty much exactly the same as what is running when
/// you upload an ifc file.
/// </summary>
/// <param name="clientFactory"></param>
/// <param name="importer"></param>
/// <param name="accountManager"></param>
public sealed class IfcTester(IClientFactory clientFactory, Importer importer, IAccountManager accountManager)
{
// Settings, Change these to suit!
// private readonly ICollection<FilePath> _filePath = [new(@"C:\Users\Jedd\Desktop\GRAPHISOFT_Archicad_Sample_Project-S-Office_v1.0_AC25.ifc")]
private readonly IEnumerable<string> _filePaths = Directory.EnumerateFiles(
@"C:\Users\Jedd\Desktop\big files",
"*.ifc"
);
private readonly Uri _serverUrl = new("https://app.speckle.systems");
private const string PROJECT_ID = "f3a42bdf24";
public async Task Run(CancellationToken cancellationToken = default)
{
var account = accountManager.GetAccounts(_serverUrl).First();
using var speckleClient = clientFactory.Create(account);
foreach (var path in _filePaths)
{
try
{
await ImportFile(speckleClient, path, cancellationToken);
}
#pragma warning disable CA1031
catch (Exception ex)
#pragma warning restore CA1031
{
Console.WriteLine(ex.ToFormattedString());
}
}
}
private async Task ImportFile(IClient speckleClient, FilePath filePath, CancellationToken cancellationToken)
{
string modelName = filePath.GetFileName();
var existing = await speckleClient.Project.GetWithModels(
PROJECT_ID,
1,
modelsFilter: new(search: modelName),
cancellationToken: cancellationToken
);
string? existingModel = existing.models.items.Count >= 1 ? existing.models.items.First().id : null;
// Convert IFC to Speckle Objects
ImporterArgs args =
new()
{
ServerUrl = _serverUrl,
FilePath = filePath.ToString(),
ProjectId = PROJECT_ID,
ModelId = existingModel,
ModelName = filePath.GetFileName(),
VersionMessage = "",
Token = speckleClient.Account.token
};
var version = await importer.ImportIfc(args, null, cancellationToken);
Console.WriteLine($"File was successfully sent {version.id}");
}
}
@@ -1,12 +0,0 @@
using Microsoft.Extensions.DependencyInjection;
using Speckle.Importers.Ifc;
using Speckle.Importers.Ifc.Tester2;
// This is all DI setup, Look in IfcTester.cs for the real goodies
var serviceCollection = new ServiceCollection();
serviceCollection.AddIFCImporter();
serviceCollection.AddSingleton<IfcTester>();
var serviceProvider = serviceCollection.BuildServiceProvider();
var tester = serviceProvider.GetRequiredService<IfcTester>();
await tester.Run();
@@ -1,11 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\Speckle.Importers.Ifc\Speckle.Importers.Ifc.csproj" />
</ItemGroup>
</Project>
@@ -1,316 +0,0 @@
{
"version": 2,
"dependencies": {
"net8.0": {
"Microsoft.NETFramework.ReferenceAssemblies": {
"type": "Direct",
"requested": "[1.0.3, )",
"resolved": "1.0.3",
"contentHash": "vUc9Npcs14QsyOD01tnv/m8sQUnGTGOw1BCmKcv77LBJY7OxhJ+zJF7UD/sCL3lYNFuqmQEVlkfS4Quif6FyYg==",
"dependencies": {
"Microsoft.NETFramework.ReferenceAssemblies.net461": "1.0.3"
}
},
"Microsoft.SourceLink.GitHub": {
"type": "Direct",
"requested": "[8.0.0, )",
"resolved": "8.0.0",
"contentHash": "G5q7OqtwIyGTkeIOAc3u2ZuV/kicQaec5EaRnc0pIeSnh9LUjj+PYQrJYBURvDt7twGl2PKA7nSN0kz1Zw5bnQ==",
"dependencies": {
"Microsoft.Build.Tasks.Git": "8.0.0",
"Microsoft.SourceLink.Common": "8.0.0"
}
},
"PolySharp": {
"type": "Direct",
"requested": "[1.14.1, )",
"resolved": "1.14.1",
"contentHash": "mOOmFYwad3MIOL14VCjj02LljyF1GNw1wP0YVlxtcPvqdxjGGMNdNJJxHptlry3MOd8b40Flm8RPOM8JOlN2sQ=="
},
"Speckle.InterfaceGenerator": {
"type": "Direct",
"requested": "[0.9.6, )",
"resolved": "0.9.6",
"contentHash": "HKH7tYrYYlCK1ct483hgxERAdVdMtl7gUKW9ijWXxA1UsYR4Z+TrRHYmzZ9qmpu1NnTycSrp005NYM78GDKV1w=="
},
"GraphQL.Client": {
"type": "Transitive",
"resolved": "6.0.0",
"contentHash": "8yPNBbuVBpTptivyAlak4GZvbwbUcjeQTL4vN1HKHRuOykZ4r7l5fcLS6vpyPyLn0x8FsL31xbOIKyxbmR9rbA==",
"dependencies": {
"GraphQL.Client.Abstractions": "6.0.0",
"GraphQL.Client.Abstractions.Websocket": "6.0.0",
"System.Reactive": "5.0.0"
}
},
"GraphQL.Client.Abstractions": {
"type": "Transitive",
"resolved": "6.0.0",
"contentHash": "h7uzWFORHZ+CCjwr/ThAyXMr0DPpzEANDa4Uo54wqCQ+j7qUKwqYTgOrb1W40sqbvNaZm9v/X7It31SUw0maHA==",
"dependencies": {
"GraphQL.Primitives": "6.0.0"
}
},
"GraphQL.Client.Abstractions.Websocket": {
"type": "Transitive",
"resolved": "6.0.0",
"contentHash": "Nr9bPf8gIOvLuXpqEpqr9z9jslYFJOvd0feHth3/kPqeR3uMbjF5pjiwh4jxyMcxHdr8Pb6QiXkV3hsSyt0v7A==",
"dependencies": {
"GraphQL.Client.Abstractions": "6.0.0"
}
},
"GraphQL.Primitives": {
"type": "Transitive",
"resolved": "6.0.0",
"contentHash": "yg72rrYDapfsIUrul7aF6wwNnTJBOFvuA9VdDTQpPa8AlAriHbufeXYLBcodKjfUdkCnaiggX1U/nEP08Zb5GA=="
},
"Microsoft.Build.Tasks.Git": {
"type": "Transitive",
"resolved": "8.0.0",
"contentHash": "bZKfSIKJRXLTuSzLudMFte/8CempWjVamNUR5eHJizsy+iuOuO/k2gnh7W0dHJmYY0tBf+gUErfluCv5mySAOQ=="
},
"Microsoft.Data.Sqlite": {
"type": "Transitive",
"resolved": "7.0.5",
"contentHash": "KGxbPeWsQMnmQy43DSBxAFtHz3l2JX8EWBSGUCvT3CuZ8KsuzbkqMIJMDOxWtG8eZSoCDI04aiVQjWuuV8HmSw==",
"dependencies": {
"Microsoft.Data.Sqlite.Core": "7.0.5",
"SQLitePCLRaw.bundle_e_sqlite3": "2.1.4"
}
},
"Microsoft.Data.Sqlite.Core": {
"type": "Transitive",
"resolved": "7.0.5",
"contentHash": "FTerRmQPqHrCrnoUzhBu+E+1DNGwyrAMLqHkAqOOOu5pGfyMOj8qQUBxI/gDtWtG11p49UxSfWmBzRNlwZqfUg==",
"dependencies": {
"SQLitePCLRaw.core": "2.1.4"
}
},
"Microsoft.Extensions.Configuration": {
"type": "Transitive",
"resolved": "2.2.0",
"contentHash": "nOP8R1mVb/6mZtm2qgAJXn/LFm/2kMjHDAg/QJLFG6CuWYJtaD3p1BwQhufBVvRzL9ceJ/xF0SQ0qsI2GkDQAA==",
"dependencies": {
"Microsoft.Extensions.Configuration.Abstractions": "2.2.0"
}
},
"Microsoft.Extensions.Configuration.Abstractions": {
"type": "Transitive",
"resolved": "2.2.0",
"contentHash": "65MrmXCziWaQFrI0UHkQbesrX5wTwf9XPjY5yFm/VkgJKFJ5gqvXRoXjIZcf2wLi5ZlwGz/oMYfyURVCWbM5iw==",
"dependencies": {
"Microsoft.Extensions.Primitives": "2.2.0"
}
},
"Microsoft.Extensions.Configuration.Binder": {
"type": "Transitive",
"resolved": "2.2.0",
"contentHash": "vJ9xvOZCnUAIHcGC3SU35r3HKmHTVIeHzo6u/qzlHAqD8m6xv92MLin4oJntTvkpKxVX3vI1GFFkIQtU3AdlsQ==",
"dependencies": {
"Microsoft.Extensions.Configuration": "2.2.0"
}
},
"Microsoft.Extensions.DependencyInjection.Abstractions": {
"type": "Transitive",
"resolved": "8.0.0",
"contentHash": "cjWrLkJXK0rs4zofsK4bSdg+jhDLTaxrkXu4gS6Y7MAlCvRyNNgwY/lJi5RDlQOnSZweHqoyvgvbdvQsRIW+hg=="
},
"Microsoft.Extensions.Options": {
"type": "Transitive",
"resolved": "2.2.0",
"contentHash": "UpZLNLBpIZ0GTebShui7xXYh6DmBHjWM8NxGxZbdQh/bPZ5e6YswqI+bru6BnEL5eWiOdodsXtEz3FROcgi/qg==",
"dependencies": {
"Microsoft.Extensions.DependencyInjection.Abstractions": "2.2.0",
"Microsoft.Extensions.Primitives": "2.2.0",
"System.ComponentModel.Annotations": "4.5.0"
}
},
"Microsoft.Extensions.Primitives": {
"type": "Transitive",
"resolved": "2.2.0",
"contentHash": "azyQtqbm4fSaDzZHD/J+V6oWMFaf2tWP4WEGIYePLCMw3+b2RQdj9ybgbQyjCshcitQKQ4lEDOZjmSlTTrHxUg==",
"dependencies": {
"System.Memory": "4.5.1",
"System.Runtime.CompilerServices.Unsafe": "4.5.1"
}
},
"Microsoft.NETFramework.ReferenceAssemblies.net461": {
"type": "Transitive",
"resolved": "1.0.3",
"contentHash": "AmOJZwCqnOCNp6PPcf9joyogScWLtwy0M1WkqfEQ0M9nYwyDD7EX9ZjscKS5iYnyvteX7kzSKFCKt9I9dXA6mA=="
},
"Microsoft.SourceLink.Common": {
"type": "Transitive",
"resolved": "8.0.0",
"contentHash": "dk9JPxTCIevS75HyEQ0E4OVAFhB2N+V9ShCXf8Q6FkUQZDkgLI12y679Nym1YqsiSysuQskT7Z+6nUf3yab6Vw=="
},
"Speckle.Newtonsoft.Json": {
"type": "Transitive",
"resolved": "13.0.2",
"contentHash": "g1BejUZwax5PRfL6xHgLEK23sqHWOgOj9hE7RvfRRlN00AGt8GnPYt8HedSK7UB3HiRW8zCA9Pn0iiYxCK24BA=="
},
"SQLitePCLRaw.bundle_e_sqlite3": {
"type": "Transitive",
"resolved": "2.1.4",
"contentHash": "EWI1olKDjFEBMJu0+3wuxwziIAdWDVMYLhuZ3Qs84rrz+DHwD00RzWPZCa+bLnHCf3oJwuFZIRsHT5p236QXww==",
"dependencies": {
"SQLitePCLRaw.lib.e_sqlite3": "2.1.4",
"SQLitePCLRaw.provider.e_sqlite3": "2.1.4"
}
},
"SQLitePCLRaw.core": {
"type": "Transitive",
"resolved": "2.1.4",
"contentHash": "inBjvSHo9UDKneGNzfUfDjK08JzlcIhn1+SP5Y3m6cgXpCxXKCJDy6Mka7LpgSV+UZmKSnC8rTwB0SQ0xKu5pA==",
"dependencies": {
"System.Memory": "4.5.3"
}
},
"SQLitePCLRaw.lib.e_sqlite3": {
"type": "Transitive",
"resolved": "2.1.4",
"contentHash": "2C9Q9eX7CPLveJA0rIhf9RXAvu+7nWZu1A2MdG6SD/NOu26TakGgL1nsbc0JAspGijFOo3HoN79xrx8a368fBg=="
},
"SQLitePCLRaw.provider.e_sqlite3": {
"type": "Transitive",
"resolved": "2.1.4",
"contentHash": "CSlb5dUp1FMIkez9Iv5EXzpeq7rHryVNqwJMWnpq87j9zWZexaEMdisDktMsnnrzKM6ahNrsTkjqNodTBPBxtQ==",
"dependencies": {
"SQLitePCLRaw.core": "2.1.4"
}
},
"System.ComponentModel.Annotations": {
"type": "Transitive",
"resolved": "4.5.0",
"contentHash": "UxYQ3FGUOtzJ7LfSdnYSFd7+oEv6M8NgUatatIN2HxNtDdlcvFAf+VIq4Of9cDMJEJC0aSRv/x898RYhB4Yppg=="
},
"System.Memory": {
"type": "Transitive",
"resolved": "4.5.5",
"contentHash": "XIWiDvKPXaTveaB7HVganDlOCRoj03l+jrwNvcge/t8vhGYKvqV+dMv6G4SAX2NoNmN0wZfVPTAlFwZcZvVOUw=="
},
"System.Reactive": {
"type": "Transitive",
"resolved": "5.0.0",
"contentHash": "erBZjkQHWL9jpasCE/0qKAryzVBJFxGHVBAvgRN1bzM0q2s1S4oYREEEL0Vb+1kA/6BKb5FjUZMp5VXmy+gzkQ=="
},
"System.Runtime.CompilerServices.Unsafe": {
"type": "Transitive",
"resolved": "4.5.1",
"contentHash": "Zh8t8oqolRaFa9vmOZfdQm/qKejdqz0J9kr7o2Fu0vPeoH3BL1EOXipKWwkWtLT1JPzjByrF19fGuFlNbmPpiw=="
},
"speckle.connectors.common": {
"type": "Project",
"dependencies": {
"Microsoft.Extensions.DependencyInjection": "[2.2.0, )",
"Speckle.Connectors.Logging": "[1.0.0, )",
"Speckle.Objects": "[3.5.4, )",
"Speckle.Sdk": "[3.5.4, )",
"Speckle.Sdk.Dependencies": "[3.5.4, )"
}
},
"speckle.connectors.logging": {
"type": "Project"
},
"speckle.importers.ifc": {
"type": "Project",
"dependencies": {
"Ara3D.Buffers": "[1.4.5, )",
"Ara3D.Logging": "[1.4.5, )",
"Ara3D.Utils": "[1.4.5, )",
"Microsoft.Extensions.DependencyInjection": "[8.0.0, )",
"Speckle.Connectors.Common": "[1.0.0, )",
"Speckle.Objects": "[3.5.4, )",
"Speckle.Sdk": "[3.5.4, )"
}
},
"Ara3D.Buffers": {
"type": "CentralTransitive",
"requested": "[1.4.5, )",
"resolved": "1.4.5",
"contentHash": "SKcQqgtXukyHTlTKFPCaUW4spSkue3XfBU/GmoA7KhH6H995v6TbJxtqjs0EfSgnXEkajL8U7X1NqktScRozXw==",
"dependencies": {
"System.Memory": "4.5.5"
}
},
"Ara3D.Logging": {
"type": "CentralTransitive",
"requested": "[1.4.5, )",
"resolved": "1.4.5",
"contentHash": "7HPCe5Dq21JoOBF1iclk9H37XFCoB2ZzCPqTMNgdg4PWFvuRsofNbiuMdiE/HKgMHCVhy1C5opB2KwDKcO7Axw==",
"dependencies": {
"Ara3D.Utils": "1.4.5"
}
},
"Ara3D.Utils": {
"type": "CentralTransitive",
"requested": "[1.4.5, )",
"resolved": "1.4.5",
"contentHash": "yba/E7PpbWP0+RDp+KbKw/vBXnXBSIheScdpVKuDnr8ytRg8pZ2Jd6nwKES+G0FcVEB9PeOVmEW7SGrFvAwRCg=="
},
"Microsoft.Extensions.DependencyInjection": {
"type": "CentralTransitive",
"requested": "[2.2.0, )",
"resolved": "8.0.0",
"contentHash": "V8S3bsm50ig6JSyrbcJJ8bW2b9QLGouz+G1miK3UTaOWmMtFwNNNzUf4AleyDWUmTrWMLNnFSLEQtxmxgNQnNQ==",
"dependencies": {
"Microsoft.Extensions.DependencyInjection.Abstractions": "8.0.0"
}
},
"Microsoft.Extensions.Logging": {
"type": "CentralTransitive",
"requested": "[2.2.0, )",
"resolved": "2.2.0",
"contentHash": "Nxqhadc9FCmFHzU+fz3oc8sFlE6IadViYg8dfUdGzJZ2JUxnCsRghBhhOWdM4B2zSZqEc+0BjliBh/oNdRZuig==",
"dependencies": {
"Microsoft.Extensions.Configuration.Binder": "2.2.0",
"Microsoft.Extensions.DependencyInjection.Abstractions": "2.2.0",
"Microsoft.Extensions.Logging.Abstractions": "2.2.0",
"Microsoft.Extensions.Options": "2.2.0"
}
},
"Microsoft.Extensions.Logging.Abstractions": {
"type": "CentralTransitive",
"requested": "[2.2.0, )",
"resolved": "2.2.0",
"contentHash": "B2WqEox8o+4KUOpL7rZPyh6qYjik8tHi2tN8Z9jZkHzED8ElYgZa/h6K+xliB435SqUcWT290Fr2aa8BtZjn8A=="
},
"Speckle.DoubleNumerics": {
"type": "CentralTransitive",
"requested": "[4.1.0, )",
"resolved": "4.1.0",
"contentHash": "20DtS+FsDRsOD9+AU3TwNFZ0qrKo5f6f7B5ZR9wStsIHHHC9k7DpjbCvuNtmnSjx54MD+TJC7wV2f5iyGVPj1A=="
},
"Speckle.Objects": {
"type": "CentralTransitive",
"requested": "[3.5.4, )",
"resolved": "3.5.4",
"contentHash": "o7ex4+yHJYI8pJbsjNqw+D8r8WjkBoB5aK/GQlGJd/0zydrPxN4SMKS4arpRBR3CUD6JhtQMatScXZOrslGXQg==",
"dependencies": {
"Speckle.Sdk": "3.5.4"
}
},
"Speckle.Sdk": {
"type": "CentralTransitive",
"requested": "[3.5.4, )",
"resolved": "3.5.4",
"contentHash": "o4bEJTz+OBI1koy9xqXSIq3UtUFCKtk6Btg82rdVM2aFMPT3ZoYVarG+ylPcUOHd684XpgGASxE6dIgXz2pvng==",
"dependencies": {
"GraphQL.Client": "6.0.0",
"Microsoft.Data.Sqlite": "7.0.5",
"Microsoft.Extensions.DependencyInjection.Abstractions": "2.2.0",
"Microsoft.Extensions.Logging": "2.2.0",
"Speckle.DoubleNumerics": "4.1.0",
"Speckle.Newtonsoft.Json": "13.0.2",
"Speckle.Sdk.Dependencies": "3.5.4"
}
},
"Speckle.Sdk.Dependencies": {
"type": "CentralTransitive",
"requested": "[3.5.4, )",
"resolved": "3.5.4",
"contentHash": "d0ZOHiK11Hq9r7YEkfTvVu33ygWtsrgysIWdCRAz6rdlcAgMCEkWVBoe3jDjxdmUy20TToaQlFKfMH4hTyzWXg=="
}
}
}
}
@@ -1,190 +0,0 @@
using System.Text;
using Ara3D.Buffers;
using Speckle.Importers.Ifc.Ara3D.StepParser;
namespace Speckle.Importers.Ifc.Ara3D.IfcParser;
public static class IfcExtensions
{
public static uint AsId(this StepValue value) => value is StepUnassigned ? 0u : ((StepId)value).Id;
public static string AsString(this StepValue value) =>
value is StepString ss
? ss.AsString()
: value is StepNumber sn
? sn.Value.ToString()
: value is StepId si
? si.Id.ToString()
: value is StepSymbol ssm
? ssm.Name.ToString()
: "";
public static double AsNumber(this StepValue value) => value is StepUnassigned ? 0 : ((StepNumber)value).Value;
public static List<StepValue> AsList(this StepValue value) =>
value is StepUnassigned ? new List<StepValue>() : ((StepList)value).Values;
public static List<uint> AsIdList(this StepValue value) =>
value is StepUnassigned ? new List<uint>() : value.AsList().Select(AsId).ToList();
// Uses Latin1 encoding (aka ISO-8859-1)
// Extended characters converted using an IFC specific system
public static string AsString(this ByteSpan span) => Encoding.Latin1.GetString(span.ToSpan()).IfcToUnicode();
// https://technical.buildingsmart.org/resources/ifcimplementationguidance/string-encoding/
public static string IfcToUnicode(this string input)
{
if (!input.Contains('\\'))
return input;
var output = new StringBuilder();
var i = 0;
var length = input.Length;
while (i < length)
{
if (input[i] != '\\')
{
// Regular character, append to output
output.Append(input[i++]);
continue;
}
i++; // Move past '\'
if (i >= length)
{
output.Append('\\');
break;
}
var escapeChar = input[i++];
if (escapeChar == 'S' && i < length && input[i] == '\\')
{
i++; // Move past '\'
if (i < length)
{
var c = input[i++];
var code = c + 128;
output.Append((char)code);
}
else
{
output.Append("\\S\\");
}
continue;
}
if (escapeChar == 'X')
{
if (i < length && input[i] == '\\')
{
// Handle \X\XX escape sequence (8-bit character code)
i++; // Move past '\'
if (i + 1 < length)
{
var hex = input.Substring(i, 2);
i += 2;
var code = Convert.ToInt32(hex, 16);
output.Append((char)code);
}
else
{
output.Append("\\X\\");
}
continue;
}
// Handle extended \Xn\...\X0\ escape sequence
// Skip 'n' until the next '\'
while (i < length && input[i] != '\\')
i++;
if (i < length)
i++; // Move past '\'
// Collect hex digits until '\X0\'
var hexDigits = new StringBuilder();
while (i + 3 <= length && input.Substring(i, 3) != "\\X0")
{
hexDigits.Append(input[i++]);
}
if (i + 3 <= length && input.Substring(i, 3) == "\\X0")
{
i += 3; // Move past '\X0'
if (i < length && input[i] == '\\')
i++; // Move past '\'
var hexStr = hexDigits.ToString();
// Process hex digits in chunks of 4 (representing Unicode code points)
for (var k = 0; k + 4 <= hexStr.Length; k += 4)
{
var codeHex = hexStr.Substring(k, 4);
var code = Convert.ToInt32(codeHex, 16);
output.Append(char.ConvertFromUtf32(code));
}
continue;
}
// Invalid format, append as is
output.Append("\\X");
continue;
}
// Unrecognized escape sequence, append as is
output.Append('\\').Append(escapeChar);
}
return output.ToString();
}
public static string AsString(this StepString ss) => ss.Value.AsString();
public static object? ToJsonObject(this StepValue sv)
{
switch (sv)
{
case StepEntity stepEntity:
{
var attr = stepEntity.Attributes;
if (attr.Values.Count == 0)
return stepEntity.ToString();
if (attr.Values.Count == 1)
return attr.Values[0].ToJsonObject();
return attr.Values.Select(ToJsonObject).ToList();
}
case StepId stepId:
return stepId.Id;
case StepList stepList:
return stepList.Values.Select(ToJsonObject).ToList();
case StepNumber stepNumber:
return stepNumber.AsNumber();
case StepRedeclared stepRedeclared:
return null;
case StepString stepString:
return stepString.AsString();
case StepSymbol stepSymbol:
var tmp = stepSymbol.Name.AsString();
if (tmp == "T")
return true;
if (tmp == "F")
return false;
return tmp;
case StepUnassigned stepUnassigned:
return null;
default:
throw new ArgumentOutOfRangeException(nameof(sv));
}
}
}
@@ -1,66 +0,0 @@
using Speckle.Importers.Ifc.Ara3D.IfcParser.Schema;
using Speckle.Importers.Ifc.Ara3D.StepParser;
namespace Speckle.Importers.Ifc.Ara3D.IfcParser;
/// <summary>
/// It represents an entity definition. It is usually a single line in a STEP file.
/// Many entity definitions are derived from IfcRoot (including relations).
/// IfcRoot has a GUID, OwnerId, optional Name, and optional Description
/// https://iaiweb.lbl.gov/Resources/IFC_Releases/R2x3_final/ifckernel/lexical/ifcroot.htm
/// </summary>
public class IfcEntity
{
public StepInstance LineData { get; }
public IfcGraph Graph { get; }
public uint Id => LineData.Id;
public string Type => LineData?.EntityType ?? "";
public IfcEntity(IfcGraph graph, StepInstance lineData)
{
Graph = graph;
LineData = lineData;
}
public override bool Equals(object? obj)
{
if (obj is IfcEntity other)
return Id == other.Id;
return false;
}
public override int GetHashCode() => (int)Id;
public override string ToString() => $"{Type}#{Id}";
public bool IsIfcRoot => Count >= 4 && this[0] is StepString && (this[1] is StepId) || (this[1] is StepUnassigned);
// Modern IFC files conform to this, but older ones have been observed to have different length IDs.
// Leaving as a comment for now.
//&& str.Value.Length == 22;
public string Guid => ((StepString)this[0]).Value.ToString();
public uint OwnerId => (this[1] as StepId)?.Id ?? 0;
public string? Name => (this[2] as StepString)?.AsString();
public string? Description => (this[3] as StepString)?.AsString();
public int Count => LineData.Count;
public StepValue this[int i] => LineData[i];
public IReadOnlyList<IfcRelation> GetOutgoingRelations() => Graph.GetRelationsFrom(Id);
public IEnumerable<IfcNode> GetAggregatedChildren() =>
GetOutgoingRelations().OfType<IfcRelationAggregate>().SelectMany(r => r.GetRelatedNodes());
public IEnumerable<IfcNode> GetSpatialChildren() =>
GetOutgoingRelations().OfType<IfcRelationSpatial>().SelectMany(r => r.GetRelatedNodes());
public IEnumerable<IfcNode> GetChildren() => GetAggregatedChildren().Concat(GetSpatialChildren()).Distinct();
public IReadOnlyList<IfcPropSet> GetPropSets() =>
Graph.PropertySetsByNode.TryGetValue(Id, out var list) ? list : Array.Empty<IfcPropSet>();
}
@@ -1,260 +0,0 @@
using System.Diagnostics;
using Ara3D.Logging;
using Ara3D.Utils;
using Speckle.Importers.Ifc.Ara3D.IfcParser.Schema;
using Speckle.Importers.Ifc.Ara3D.StepParser;
namespace Speckle.Importers.Ifc.Ara3D.IfcParser;
/// <summary>
/// This is a high-level representation of an IFC model as a graph of nodes and relations.
/// It also contains the properties, and property sets.
/// </summary>
public sealed class IfcGraph
{
public static IfcGraph Load(FilePath fp, ILogger? logger = null) =>
new IfcGraph(new StepDocument(fp, logger), logger);
public StepDocument Document { get; }
public Dictionary<uint, IfcNode> Nodes { get; } = new Dictionary<uint, IfcNode>();
public List<IfcRelation> Relations { get; } = new List<IfcRelation>();
public Dictionary<uint, List<IfcRelation>> RelationsByNode { get; } = new Dictionary<uint, List<IfcRelation>>();
public Dictionary<uint, List<IfcPropSet>> PropertySetsByNode { get; } = new Dictionary<uint, List<IfcPropSet>>();
public uint IfcProjectId { get; }
public IfcNode AddNode(IfcNode n) => Nodes[n.Id] = n;
public IfcRelation AddRelation(IfcRelation r)
{
Relations.Add(r);
var id = r.From.Id;
if (!RelationsByNode.ContainsKey(id))
RelationsByNode[id] = new();
RelationsByNode[id].Add(r);
return r;
}
public IfcGraph(StepDocument d, ILogger? logger = null)
{
Document = d;
uint ifcProjectId = 0;
logger?.Log("Computing entities");
foreach (var inst in Document.RawInstances)
{
if (!inst.IsValid())
continue;
// Property Values
if (inst.Type.Equals("IFCPROPERTYSINGLEVALUE"))
{
var e = d.GetInstanceWithData(inst);
AddNode(new IfcProp(this, e, e[2]));
}
else if (inst.Type.Equals("IFCPROPERTYENUMERATEDVALUE"))
{
var e = d.GetInstanceWithData(inst);
AddNode(new IfcProp(this, e, e[2]));
}
else if (inst.Type.Equals("IFCPROPERTYREFERENCEVALUE"))
{
var e = d.GetInstanceWithData(inst);
AddNode(new IfcProp(this, e, e[3]));
}
else if (inst.Type.Equals("IFCPROPERTYLISTVALUE"))
{
var e = d.GetInstanceWithData(inst);
AddNode(new IfcProp(this, e, e[2]));
}
else if (inst.Type.Equals("IFCCOMPLEXPROPERTY"))
{
var e = d.GetInstanceWithData(inst);
AddNode(new IfcProp(this, e, e[3]));
}
// Quantities which are a treated as a kind of prop
// https://iaiweb.lbl.gov/Resources/IFC_Releases/R2x3_final/ifcquantityresource/lexical/ifcphysicalquantity.htm
else if (inst.Type.Equals("IFCQUANTITYLENGTH"))
{
// https://iaiweb.lbl.gov/Resources/IFC_Releases/R2x3_final/ifcquantityresource/lexical/ifcquantitylength.htm
var e = d.GetInstanceWithData(inst);
AddNode(new IfcProp(this, e, e[3]));
}
else if (inst.Type.Equals("IFCQUANTITYAREA"))
{
// https://iaiweb.lbl.gov/Resources/IFC_Releases/R2x3_final/ifcquantityresource/lexical/ifcquantityarea.htm
var e = d.GetInstanceWithData(inst);
AddNode(new IfcProp(this, e, e[3]));
}
else if (inst.Type.Equals("IFCQUANTITYVOLUME"))
{
// https://iaiweb.lbl.gov/Resources/IFC_Releases/R2x3_final/ifcquantityresource/lexical/ifcquantityvolume.htm
var e = d.GetInstanceWithData(inst);
AddNode(new IfcProp(this, e, e[3]));
}
else if (inst.Type.Equals("IFCQUANTITYCOUNT"))
{
// https://iaiweb.lbl.gov/Resources/IFC_Releases/R2x3_final/ifcquantityresource/lexical/ifcquantitycount.htm
var e = d.GetInstanceWithData(inst);
AddNode(new IfcProp(this, e, e[3]));
}
else if (inst.Type.Equals("IFCQUANTITYWEIGHT"))
{
// https://iaiweb.lbl.gov/Resources/IFC_Releases/R2x3_final/ifcquantityresource/lexical/ifcquantityweight.htm
var e = d.GetInstanceWithData(inst);
AddNode(new IfcProp(this, e, e[3]));
}
else if (inst.Type.Equals("IFCQUANTITYTIME"))
{
// https://iaiweb.lbl.gov/Resources/IFC_Releases/R2x3_final/ifcquantityresource/lexical/ifcquantitytime.htm
var e = d.GetInstanceWithData(inst);
AddNode(new IfcProp(this, e, e[3]));
}
else if (inst.Type.Equals("IFCPHYSICALCOMPLEXQUANTITY"))
{
//https://iaiweb.lbl.gov/Resources/IFC_Releases/R2x3_final/ifcquantityresource/lexical/ifcphysicalcomplexquantity.htm
var e = d.GetInstanceWithData(inst);
AddNode(new IfcProp(this, e, e[2]));
}
// Property Set (or element quantity)
else if (inst.Type.Equals("IFCPROPERTYSET"))
{
var e = d.GetInstanceWithData(inst);
AddNode(new IfcPropSet(this, e, (StepList)e[4]));
}
else if (inst.Type.Equals("IFCELEMENTQUANTITY"))
{
var e = d.GetInstanceWithData(inst);
AddNode(new IfcPropSet(this, e, e[5] as StepList));
}
// Aggregate relation
else if (inst.Type.Equals("IFCRELAGGREGATES"))
{
var e = d.GetInstanceWithData(inst);
AddRelation(new IfcRelationAggregate(this, e, (StepId)e[4], (StepList)e[5]));
}
// Spatial relation
else if (inst.Type.Equals("IFCRELCONTAINEDINSPATIALSTRUCTURE"))
{
var e = d.GetInstanceWithData(inst);
AddRelation(new IfcRelationSpatial(this, e, (StepId)e[5], (StepList)e[4]));
}
// Property set relations
else if (inst.Type.Equals("IFCRELDEFINESBYPROPERTIES"))
{
var e = d.GetInstanceWithData(inst);
AddRelation(new IfcPropSetRelation(this, e, (StepId)e[5], (StepList)e[4]));
}
// Type relations
else if (inst.Type.Equals("IFCRELDEFINESBYTYPE"))
{
var e = d.GetInstanceWithData(inst);
AddRelation(new IfcRelationType(this, e, (StepId)e[5], (StepList)e[4]));
}
else if (inst.Type.Equals("IFCPROJECT"))
{
//Special case for IFC Projects, track them as a root node.
var e = d.GetInstanceWithData(inst);
ifcProjectId = inst.Id;
AddNode(new IfcProject(this, e));
}
else if (
inst.Type.Equals("IFCSITE")
|| inst.Type.Equals("IFCBUILDING")
|| inst.Type.Equals("IFCBUILDINGSTOREY")
|| inst.Type.Equals("IFCFACILITY")
|| inst.Type.Equals("IFCFACILITYPART")
|| inst.Type.Equals("IFCBRIDGE")
|| inst.Type.Equals("IFCROAD")
|| inst.Type.Equals("IFCRAILWAY")
|| inst.Type.Equals("IFCMARINEFACILITY")
)
{
var e = d.GetInstanceWithData(inst);
AddNode(new IfcSpatialStructureElement(this, e));
}
// Everything else
else
{
// Simple IFC node: without step entity data.
var e = d.GetInstanceWithData(inst);
AddNode(new IfcNode(this, e));
}
}
if (ifcProjectId <= 0)
throw new SpeckleIfcException("There was no IfcProject in the file");
IfcProjectId = ifcProjectId;
logger?.Log("Creating lookup of property sets");
foreach (var psr in Relations.OfType<IfcPropSetRelation>())
{
var ps = psr.PropSet;
foreach (var id in psr.GetRelatedIds())
{
if (!PropertySetsByNode.ContainsKey(id))
PropertySetsByNode[id] = [];
PropertySetsByNode[id].Add(ps);
}
}
logger?.Log("Completed creating model graph");
}
public IEnumerable<IfcNode> GetNodes() => Nodes.Values;
public IEnumerable<IfcNode> GetNodes(IEnumerable<uint> ids) => ids.Select(GetNode);
public IfcNode GetOrCreateNode(StepInstance lineData, int arg)
{
if (arg < 0 || arg >= lineData.AttributeValues.Count)
throw new SpeckleIfcException("Argument index out of range");
return GetOrCreateNode(lineData.AttributeValues[arg]);
}
public IfcNode GetOrCreateNode(StepValue o) =>
GetOrCreateNode(o is StepId id ? id.Id : throw new SpeckleIfcException($"Expected a StepId value, not {o}"));
public IfcNode GetOrCreateNode(uint id)
{
var r = Nodes.TryGetValue(id, out var node) ? node : AddNode(new IfcNode(this, Document.GetInstanceWithData(id)));
Debug.Assert(r.Id == id);
return r;
}
public List<IfcNode> GetOrCreateNodes(List<StepValue> list) => list.Select(GetOrCreateNode).ToList();
public List<IfcNode> GetOrCreateNodes(StepInstance line, int arg)
{
if (arg < 0 || arg >= line.AttributeValues.Count)
throw new SpeckleIfcException("Argument out of range");
if (line.AttributeValues[arg] is not StepList agg)
throw new SpeckleIfcException("Expected a list");
return GetOrCreateNodes(agg.Values);
}
public IfcNode GetNode(StepId id) => GetNode(id.Id);
public IfcNode GetNode(uint id)
{
var r = Nodes[id];
Debug.Assert(r.Id == id);
return r;
}
public IfcNode GetIfcProject() => GetNode(IfcProjectId);
public IEnumerable<IfcPropSet> GetPropSets() => GetNodes().OfType<IfcPropSet>();
public IEnumerable<IfcProp> GetProps() => GetNodes().OfType<IfcProp>();
public IEnumerable<IfcRelationSpatial> GetSpatialRelations() => Relations.OfType<IfcRelationSpatial>();
public IEnumerable<IfcRelationAggregate> GetAggregateRelations() => Relations.OfType<IfcRelationAggregate>();
public IReadOnlyList<IfcRelation> GetRelationsFrom(uint id) =>
RelationsByNode.TryGetValue(id, out var list) ? list : Array.Empty<IfcRelation>();
}
@@ -1,22 +0,0 @@
using Speckle.Importers.Ifc.Ara3D.IfcParser.Schema;
using Speckle.Importers.Ifc.Ara3D.StepParser;
namespace Speckle.Importers.Ifc.Ara3D.IfcParser;
// https://standards.buildingsmart.org/IFC/RELEASE/IFC2x3/TC1/HTML/ifckernel/lexical/ifcreldefinesbyproperties.htm
public class IfcPropSetRelation : IfcRelation
{
public IfcPropSetRelation(IfcGraph graph, StepInstance lineData, StepId from, StepList to)
: base(graph, lineData, from, to) { }
public IfcPropSet PropSet
{
get
{
var node = Graph.GetNode(From);
if (node is not IfcPropSet r)
throw new SpeckleIfcException($"Expected a property set not {node} from id {From}");
return r;
}
}
}
@@ -1,26 +0,0 @@
using Speckle.Importers.Ifc.Ara3D.IfcParser.Schema;
using Speckle.Importers.Ifc.Ara3D.StepParser;
namespace Speckle.Importers.Ifc.Ara3D.IfcParser;
/// <summary>
/// Always express a 1-to-many relation
/// </summary>
public class IfcRelation : IfcEntity
{
public StepId From { get; }
public StepList To { get; }
public IfcRelation(IfcGraph graph, StepInstance lineData, StepId from, StepList to)
: base(graph, lineData)
{
if (!IsIfcRoot)
throw new SpeckleIfcException("Expected relation to be an IFC root entity");
From = from;
To = to;
}
public IEnumerable<uint> GetRelatedIds() => To.Values.Select(v => v.AsId());
public IEnumerable<IfcNode> GetRelatedNodes() => Graph.GetNodes(GetRelatedIds());
}
@@ -1,9 +0,0 @@
using Speckle.Importers.Ifc.Ara3D.StepParser;
namespace Speckle.Importers.Ifc.Ara3D.IfcParser;
public class IfcRelationAggregate : IfcRelation
{
public IfcRelationAggregate(IfcGraph graph, StepInstance lineData, StepId from, StepList to)
: base(graph, lineData, from, to) { }
}
@@ -1,9 +0,0 @@
using Speckle.Importers.Ifc.Ara3D.StepParser;
namespace Speckle.Importers.Ifc.Ara3D.IfcParser;
public class IfcRelationSpatial : IfcRelation
{
public IfcRelationSpatial(IfcGraph graph, StepInstance lineData, StepId from, StepList to)
: base(graph, lineData, from, to) { }
}
@@ -1,9 +0,0 @@
using Speckle.Importers.Ifc.Ara3D.StepParser;
namespace Speckle.Importers.Ifc.Ara3D.IfcParser;
public class IfcRelationType : IfcRelation
{
public IfcRelationType(IfcGraph graph, StepInstance lineData, StepId from, StepList to)
: base(graph, lineData, from, to) { }
}
@@ -1,9 +0,0 @@
using Speckle.Importers.Ifc.Ara3D.StepParser;
namespace Speckle.Importers.Ifc.Ara3D.IfcParser.Schema;
public class IfcNode : IfcEntity
{
public IfcNode(IfcGraph graph, StepInstance lineData)
: base(graph, lineData) { }
}
@@ -1,10 +0,0 @@
using Speckle.Importers.Ifc.Ara3D.StepParser;
namespace Speckle.Importers.Ifc.Ara3D.IfcParser.Schema;
public sealed class IfcProject(IfcGraph graph, StepInstance lineData) : IfcNode(graph, lineData)
{
public string? ObjectType => (LineData[4] as StepString)?.AsString();
public string? LongName => (LineData[5] as StepString)?.AsString();
public string? Phase => (LineData[6] as StepString)?.AsString();
}
@@ -1,21 +0,0 @@
using Speckle.Importers.Ifc.Ara3D.StepParser;
namespace Speckle.Importers.Ifc.Ara3D.IfcParser.Schema;
public class IfcProp : IfcNode
{
public readonly StepValue Value;
public new string Name => this[0].AsString();
public new string Description => this[1].AsString();
public IfcProp(IfcGraph graph, StepInstance lineData, StepValue value)
: base(graph, lineData)
{
if (lineData.Count < 2)
throw new SpeckleIfcException("Expected at least two values in the line data");
if (lineData[0] is not StepString)
throw new SpeckleIfcException("Expected the first value to be a string (Name)");
Value = value;
}
}
@@ -1,45 +0,0 @@
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using Speckle.Importers.Ifc.Ara3D.StepParser;
using Speckle.Sdk.Common;
namespace Speckle.Importers.Ifc.Ara3D.IfcParser.Schema;
// This merges two separate entity types: IfcPropertySet and IfcElementQuantity.
// Both of which are derived from IfcPropertySetDefinition.
// This is something that can be referred to by a PropertySetRelation
// An IfcElementQuantity has an additional "method of measurement" property.
// https://standards.buildingsmart.org/IFC/RELEASE/IFC2x3/TC1/HTML/ifckernel/lexical/ifcpropertyset.htm
// https://standards.buildingsmart.org/IFC/RELEASE/IFC2x3/TC1/HTML/ifcproductextension/lexical/ifcelementquantity.htm
public class IfcPropSet : IfcNode
{
public readonly StepList? PropertyIdList;
public IfcPropSet(IfcGraph graph, StepInstance lineData, StepList? propertyIdList)
: base(graph, lineData)
{
Debug.Assert(IsIfcRoot);
Debug.Assert(lineData.AttributeValues.Count is 5 or 6);
Debug.Assert(Type is "IFCPROPERTYSET" or "IFCELEMENTQUANTITY");
PropertyIdList = propertyIdList;
}
public IEnumerable<IfcProp> GetProperties()
{
for (var i = 0; i < NumProperties; ++i)
{
var id = PropertyId(i);
var node = Graph.GetNode(id);
if (node is not IfcProp prop)
throw new SpeckleIfcException($"Expected a property not {node} from id {id}");
yield return prop;
}
}
public bool IsQuantity => LineData.AttributeValues.Count == 6;
public string? MethodOfMeasurement => IsQuantity ? this[4]?.AsString() : null;
public int NumProperties => PropertyIdList?.Values.Count ?? 0;
[MemberNotNull(nameof(PropertyIdList))]
public uint PropertyId(int i) => PropertyIdList.NotNull().Values[i].AsId();
}
@@ -1,15 +0,0 @@
using Speckle.Importers.Ifc.Ara3D.StepParser;
namespace Speckle.Importers.Ifc.Ara3D.IfcParser.Schema;
/// <summary>
/// Types like IfcSite, IfcBuilding, IfcBuildingStorey
/// </summary>
/// <param name="graph"></param>
/// <param name="lineData"></param>
public class IfcSpatialStructureElement(IfcGraph graph, StepInstance lineData) : IfcNode(graph, lineData)
{
public string? ObjectType => (LineData[4] as StepString)?.AsString();
public string? LongName => (LineData[7] as StepString)?.AsString();
public string? CompositionType => (LineData[8] as StepString)?.AsString();
}
@@ -1,31 +0,0 @@
using System.Diagnostics;
using Ara3D.Buffers;
namespace Speckle.Importers.Ifc.Ara3D.StepParser;
public static class AlignedMemoryReader
{
public static unsafe AlignedMemory ReadAllBytes(string path, int bufferSize = 1024 * 1024)
{
using var fs = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read, bufferSize, false);
var fileLength = fs.Length;
if (fileLength > int.MaxValue)
throw new IOException("File too big: > 2GB");
var count = (int)fileLength;
var r = new AlignedMemory(count);
var pBytes = r.BytePtr;
while (count > 0)
{
var span = new Span<byte>(pBytes, count);
var n = fs.Read(span);
if (n == 0)
break;
pBytes += n;
count -= n;
}
Debug.Assert(count == 0);
return r;
}
}
@@ -1,13 +0,0 @@
using System.Runtime.CompilerServices;
using Ara3D.Buffers;
namespace Speckle.Importers.Ifc.Ara3D.StepParser;
public static class ByteSpanExtensions
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static double ToDouble(this ByteSpan self) => double.Parse(self.ToSpan());
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static int ToInt(this ByteSpan self) => int.Parse(self.ToSpan());
}
@@ -1,102 +0,0 @@
using System.Runtime.Intrinsics;
using Ara3D.Buffers;
using Ara3D.Logging;
using Ara3D.Utils;
namespace Speckle.Importers.Ifc.Ara3D.StepParser;
public sealed unsafe class StepDocument : IDisposable
{
public readonly FilePath FilePath;
public readonly byte* DataStart;
public readonly byte* DataEnd;
public readonly AlignedMemory Data;
/// <summary>
/// This is a list of raw step instance information.
/// Each one has only a type and an ID.
/// </summary>
public readonly StepRawInstance[] RawInstances;
/// <summary>
/// The number of raw instance
/// </summary>
public readonly int NumRawInstances;
/// <summary>
/// This gives us a fast way to look up a StepInstance by their ID
/// </summary>
public readonly Dictionary<uint, int> InstanceIdToIndex = new();
/// <summary>
/// This tells us the byte offset of the start of each line in the file
/// </summary>
public readonly List<int> LineOffsets;
public StepDocument(FilePath filePath, ILogger? logger = null)
{
FilePath = filePath;
logger ??= Logger.Null;
logger.Log($"Loading {filePath.GetFileSizeAsString()} of data from {filePath.GetFileName()}");
Data = AlignedMemoryReader.ReadAllBytes(filePath);
DataStart = Data.BytePtr;
DataEnd = DataStart + Data.NumBytes;
logger.Log($"Computing the start of each line");
// NOTE: this estimates that the average line length is at least 32 characters.
// This minimize the number of allocations that happen
var cap = Data.NumBytes / 32;
LineOffsets = new List<int>(cap);
// We are going to report the beginning of the lines, while the "ComputeLines" function
// will compute the ends of lines.
var currentLine = 1;
for (var i = 0; i < Data.NumVectors; i++)
{
StepLineParser.ComputeOffsets(((Vector256<byte>*)Data.BytePtr)[i], ref currentLine, LineOffsets);
}
logger.Log($"Found {LineOffsets.Count} lines");
logger.Log($"Creating instance records");
RawInstances = new StepRawInstance[LineOffsets.Count];
for (var i = 0; i < LineOffsets.Count - 1; i++)
{
var lineStart = LineOffsets[i];
var lineEnd = LineOffsets[i + 1];
var inst = StepLineParser.ParseLine(DataStart + lineStart, DataStart + lineEnd);
if (inst.IsValid())
{
InstanceIdToIndex.Add(inst.Id, NumRawInstances);
RawInstances[NumRawInstances++] = inst;
}
}
logger.Log($"Completed creation of STEP document from {filePath.GetFileName()}");
}
public void Dispose() => Data.Dispose();
public StepInstance GetInstanceWithData(uint id) => GetInstanceWithDataFromIndex(InstanceIdToIndex[id]);
public StepInstance GetInstanceWithDataFromIndex(int index) => GetInstanceWithData(RawInstances[index]);
public StepInstance GetInstanceWithData(StepRawInstance inst)
{
var attr = inst.GetAttributes(DataEnd);
var se = new StepEntity(inst.Type, attr);
return new StepInstance(inst.Id, se);
}
public static StepDocument Create(FilePath fp) => new(fp);
public IEnumerable<StepRawInstance> GetRawInstances(string typeCode) =>
RawInstances.Where(inst => inst.Type.Equals(typeCode));
public IEnumerable<StepInstance> GetInstances() => RawInstances.Select(GetInstanceWithData);
public IEnumerable<StepInstance> GetInstances(string typeCode) =>
GetRawInstances(typeCode).Select(GetInstanceWithData);
}
@@ -1,90 +0,0 @@
namespace Speckle.Importers.Ifc.Ara3D.StepParser;
public static unsafe class StepFactory
{
public static StepList GetAttributes(this StepRawInstance inst, byte* lineEnd)
{
if (!inst.IsValid())
return StepList.CreateDefault();
var ptr = inst.Type.End();
var token = StepTokenizer.ParseToken(ptr, lineEnd);
// TODO: there is a potential bug here when the line is split across multiple line
return CreateAggregate(ref token, lineEnd);
}
public static StepValue Create(ref StepToken token, byte* end)
{
switch (token.Type)
{
case StepTokenType.String:
return StepString.Create(token);
case StepTokenType.Symbol:
return StepSymbol.Create(token);
case StepTokenType.Id:
return StepId.Create(token);
case StepTokenType.Redeclared:
return StepRedeclared.Create(token);
case StepTokenType.Unassigned:
return StepUnassigned.Create(token);
case StepTokenType.Number:
return StepNumber.Create(token);
case StepTokenType.Ident:
var span = token.Span;
StepTokenizer.ParseNextToken(ref token, end);
var attr = CreateAggregate(ref token, end);
return new StepEntity(span, attr);
case StepTokenType.BeginGroup:
return CreateAggregate(ref token, end);
case StepTokenType.None:
case StepTokenType.Whitespace:
case StepTokenType.Comment:
case StepTokenType.Unknown:
case StepTokenType.LineBreak:
case StepTokenType.EndOfLine:
case StepTokenType.Definition:
case StepTokenType.Separator:
case StepTokenType.EndGroup:
default:
throw new SpeckleIfcException($"Cannot convert token type {token.Type} to a StepValue");
}
}
public static StepList CreateAggregate(ref StepToken token, byte* end)
{
var values = new List<StepValue>();
StepTokenizer.EatWSpace(ref token, end);
if (token.Type != StepTokenType.BeginGroup)
throw new SpeckleIfcException("Expected '('");
while (StepTokenizer.ParseNextToken(ref token, end))
{
switch (token.Type)
{
// Advance past comments, whitespace, and commas
case StepTokenType.Comment:
case StepTokenType.Whitespace:
case StepTokenType.LineBreak:
case StepTokenType.Separator:
case StepTokenType.None:
continue;
// Expected end of group
case StepTokenType.EndGroup:
return new StepList(values);
}
var curValue = Create(ref token, end);
values.Add(curValue);
}
throw new SpeckleIfcException("Unexpected end of input");
}
}
@@ -1,59 +0,0 @@
using Ara3D.Utils;
using Speckle.Sdk.Common;
namespace Speckle.Importers.Ifc.Ara3D.StepParser;
public class StepGraph
{
public StepDocument Document { get; }
public readonly Dictionary<uint, StepNode> Lookup = new();
public StepNode GetNode(uint id) => Lookup[id];
public IEnumerable<StepNode> Nodes => Lookup.Values;
public StepGraph(StepDocument doc)
{
Document = doc;
foreach (var e in doc.GetInstances())
{
var node = new StepNode(this, e);
Lookup.Add(node.Entity.Id, node);
}
foreach (var n in Nodes)
n.Init();
}
public static StepGraph Create(StepDocument doc) => new(doc);
public string ToValString(StepNode node, int depth) => ToValString(node.Entity.Entity, depth - 1);
public string ToValString(StepValue value, int depth)
{
if (value == null)
return "";
switch (value)
{
case StepList stepAggregate:
return $"({stepAggregate.Values.Select(v => ToValString(v, depth)).JoinStringsWithComma()})";
case StepEntity stepEntity:
return $"{stepEntity.EntityType}{ToValString(stepEntity.Attributes, depth)}";
case StepId stepId:
return depth <= 0 ? "#" : ToValString(GetNode(stepId.Id), depth - 1);
case StepNumber stepNumber:
case StepRedeclared stepRedeclared:
case StepString stepString:
case StepSymbol stepSymbol:
case StepUnassigned stepUnassigned:
default:
return value.ToString().NotNull();
}
}
}
@@ -1,25 +0,0 @@
namespace Speckle.Importers.Ifc.Ara3D.StepParser;
public class StepInstance
{
public readonly StepEntity Entity;
public readonly uint Id;
public List<StepValue> AttributeValues => Entity.Attributes.Values;
public string EntityType => Entity?.EntityType.ToString() ?? "";
public StepInstance(uint id, StepEntity entity)
{
Id = id;
Entity = entity;
}
public bool IsEntityType(string str) => EntityType == str;
public override string ToString() => $"#{Id}={Entity};";
public int Count => AttributeValues.Count;
public StepValue this[int i] => AttributeValues[i];
}
@@ -1,151 +0,0 @@
using System.Runtime.CompilerServices;
using System.Runtime.Intrinsics;
using System.Runtime.Intrinsics.X86;
using Ara3D.Buffers;
namespace Speckle.Importers.Ifc.Ara3D.StepParser;
public static class StepLineParser
{
public static readonly Vector256<byte> Comma = Vector256.Create((byte)',');
public static readonly Vector256<byte> NewLine = Vector256.Create((byte)'\n');
public static readonly Vector256<byte> StartGroup = Vector256.Create((byte)'(');
public static readonly Vector256<byte> EndGroup = Vector256.Create((byte)')');
public static readonly Vector256<byte> Definition = Vector256.Create((byte)'=');
public static readonly Vector256<byte> Quote = Vector256.Create((byte)'\'');
public static readonly Vector256<byte> Id = Vector256.Create((byte)'#');
public static readonly Vector256<byte> SemiColon = Vector256.Create((byte)';');
public static readonly Vector256<byte> Unassigned = Vector256.Create((byte)'*');
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void ComputeOffsets(in Vector256<byte> v, ref int index, List<int> offsets)
{
var r = Avx2.CompareEqual(v, NewLine);
var mask = (uint)Avx2.MoveMask(r);
if (mask == 0)
{
index += 32;
return;
}
// Fully unrolled handling of each bit
if ((mask & 0x00000001) != 0)
offsets.Add(index);
if ((mask & 0x00000002) != 0)
offsets.Add(index + 1);
if ((mask & 0x00000004) != 0)
offsets.Add(index + 2);
if ((mask & 0x00000008) != 0)
offsets.Add(index + 3);
if ((mask & 0x00000010) != 0)
offsets.Add(index + 4);
if ((mask & 0x00000020) != 0)
offsets.Add(index + 5);
if ((mask & 0x00000040) != 0)
offsets.Add(index + 6);
if ((mask & 0x00000080) != 0)
offsets.Add(index + 7);
if ((mask & 0x00000100) != 0)
offsets.Add(index + 8);
if ((mask & 0x00000200) != 0)
offsets.Add(index + 9);
if ((mask & 0x00000400) != 0)
offsets.Add(index + 10);
if ((mask & 0x00000800) != 0)
offsets.Add(index + 11);
if ((mask & 0x00001000) != 0)
offsets.Add(index + 12);
if ((mask & 0x00002000) != 0)
offsets.Add(index + 13);
if ((mask & 0x00004000) != 0)
offsets.Add(index + 14);
if ((mask & 0x00008000) != 0)
offsets.Add(index + 15);
if ((mask & 0x00010000) != 0)
offsets.Add(index + 16);
if ((mask & 0x00020000) != 0)
offsets.Add(index + 17);
if ((mask & 0x00040000) != 0)
offsets.Add(index + 18);
if ((mask & 0x00080000) != 0)
offsets.Add(index + 19);
if ((mask & 0x00100000) != 0)
offsets.Add(index + 20);
if ((mask & 0x00200000) != 0)
offsets.Add(index + 21);
if ((mask & 0x00400000) != 0)
offsets.Add(index + 22);
if ((mask & 0x00800000) != 0)
offsets.Add(index + 23);
if ((mask & 0x01000000) != 0)
offsets.Add(index + 24);
if ((mask & 0x02000000) != 0)
offsets.Add(index + 25);
if ((mask & 0x04000000) != 0)
offsets.Add(index + 26);
if ((mask & 0x08000000) != 0)
offsets.Add(index + 27);
if ((mask & 0x10000000) != 0)
offsets.Add(index + 28);
if ((mask & 0x20000000) != 0)
offsets.Add(index + 29);
if ((mask & 0x40000000) != 0)
offsets.Add(index + 30);
if ((mask & 0x80000000) != 0)
offsets.Add(index + 31);
// Update lineIndex to the next starting position
index += 32;
}
public static unsafe StepRawInstance ParseLine(byte* ptr, byte* end)
{
var start = ptr;
var cnt = end - ptr;
const int MIN_LINE_LENGTH = 5;
if (cnt < MIN_LINE_LENGTH)
return default;
// Parse the ID
if (*ptr++ != '#')
return default;
var id = 0u;
while (ptr < end)
{
if (*ptr < '0' || *ptr > '9')
break;
id = id * 10 + *ptr - '0';
ptr++;
}
var foundEquals = false;
while (ptr < end)
{
if (*ptr == '=')
foundEquals = true;
if (*ptr != (byte)' ' && *ptr != (byte)'=')
break;
ptr++;
}
if (!foundEquals)
return default;
// Parse the entity type name
var entityStart = ptr;
while (ptr < end)
{
if (!StepTokenizer.IsIdentLookup[*ptr])
break;
ptr++;
}
if (ptr == entityStart)
return default;
var entityType = new ByteSpan(entityStart, ptr);
return new(id, entityType, start);
}
}
@@ -1,52 +0,0 @@
using Ara3D.Utils;
namespace Speckle.Importers.Ifc.Ara3D.StepParser;
public class StepNode
{
public readonly StepGraph Graph;
public readonly StepInstance Entity;
public StepNode(StepGraph g, StepInstance e)
{
Graph = g;
Entity = e;
}
public List<StepNode> Nodes { get; } = new();
private void AddNodes(StepValue value)
{
if (value is StepId id)
{
var n = Graph.GetNode(id.Id);
Nodes.Add(n);
}
else if (value is StepList agg)
{
foreach (var v in agg.Values)
AddNodes(v);
}
}
public void Init()
{
foreach (var a in Entity.AttributeValues)
AddNodes(a);
}
public override string ToString() => Entity.ToString();
public string ToGraph(HashSet<StepNode>? prev = null)
{
prev ??= new HashSet<StepNode>();
if (prev.Contains(this))
return "_";
var nodeStr = Nodes.Select(n => n.ToGraph(prev)).JoinStringsWithComma();
return $"{EntityType}({nodeStr})";
}
public string EntityType => Entity.EntityType;
public string QuickHash() => $"{EntityType}:{Nodes.Count}";
}
@@ -1,20 +0,0 @@
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using Ara3D.Buffers;
namespace Speckle.Importers.Ifc.Ara3D.StepParser;
/// <summary>
/// Contains information about where an instance is within a file.
/// </summary>
[StructLayout(LayoutKind.Sequential, Pack = 1)]
[method: MethodImpl(MethodImplOptions.AggressiveInlining)]
public readonly unsafe struct StepRawInstance(uint id, ByteSpan type, byte* ptr)
{
public readonly uint Id = id;
public readonly ByteSpan Type = type;
public readonly byte* Ptr = ptr;
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public bool IsValid() => Id > 0;
}
@@ -1,17 +0,0 @@
using System.Diagnostics;
using Ara3D.Buffers;
namespace Speckle.Importers.Ifc.Ara3D.StepParser;
public readonly struct StepToken
{
public readonly ByteSpan Span;
public readonly StepTokenType Type;
public StepToken(ByteSpan span, StepTokenType type)
{
Span = span;
Debug.Assert(span.Length > 0);
Type = type;
}
}
@@ -1,22 +0,0 @@
namespace Speckle.Importers.Ifc.Ara3D.StepParser;
public enum StepTokenType : byte
{
None,
Ident,
String,
Whitespace,
Number,
Symbol,
Id,
Separator,
Unassigned,
Redeclared,
Comment,
Unknown,
BeginGroup,
EndGroup,
LineBreak,
EndOfLine,
Definition,
}
@@ -1,306 +0,0 @@
using System.Diagnostics;
using System.Runtime.CompilerServices;
using Ara3D.Buffers;
namespace Speckle.Importers.Ifc.Ara3D.StepParser;
public static class StepTokenizer
{
public static readonly StepTokenType[] TokenLookup = CreateTokenLookup();
public static readonly bool[] IsNumberLookup = CreateNumberLookup();
public static readonly bool[] IsIdentLookup = CreateIdentLookup();
public static StepTokenType[] CreateTokenLookup()
{
var r = new StepTokenType[256];
for (var i = 0; i < 256; i++)
r[i] = GetTokenType((byte)i);
return r;
}
public static bool[] CreateNumberLookup()
{
var r = new bool[256];
for (var i = 0; i < 256; i++)
r[i] = IsNumberChar((byte)i);
return r;
}
public static bool[] CreateIdentLookup()
{
var r = new bool[256];
for (var i = 0; i < 256; i++)
r[i] = IsIdentOrDigitChar((byte)i);
return r;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static StepTokenType LookupToken(byte b) => TokenLookup[b];
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool IsNumberChar(byte b)
{
switch (b)
{
case (byte)'0':
case (byte)'1':
case (byte)'2':
case (byte)'3':
case (byte)'4':
case (byte)'5':
case (byte)'6':
case (byte)'7':
case (byte)'8':
case (byte)'9':
case (byte)'E':
case (byte)'e':
case (byte)'+':
case (byte)'-':
case (byte)'.':
return true;
}
return false;
}
public static StepTokenType GetTokenType(byte b)
{
switch (b)
{
case (byte)'0':
case (byte)'1':
case (byte)'2':
case (byte)'3':
case (byte)'4':
case (byte)'5':
case (byte)'6':
case (byte)'7':
case (byte)'8':
case (byte)'9':
case (byte)'+':
case (byte)'-':
return StepTokenType.Number;
case (byte)' ':
case (byte)'\t':
return StepTokenType.Whitespace;
case (byte)'\n':
case (byte)'\r':
return StepTokenType.LineBreak;
case (byte)'\'':
case (byte)'"':
return StepTokenType.String;
case (byte)'.':
return StepTokenType.Symbol;
case (byte)'#':
return StepTokenType.Id;
case (byte)';':
return StepTokenType.EndOfLine;
case (byte)'(':
return StepTokenType.BeginGroup;
case (byte)'=':
return StepTokenType.Definition;
case (byte)')':
return StepTokenType.EndGroup;
case (byte)',':
return StepTokenType.Separator;
case (byte)'$':
return StepTokenType.Unassigned;
case (byte)'*':
return StepTokenType.Redeclared;
case (byte)'/':
return StepTokenType.Comment;
case (byte)'a':
case (byte)'b':
case (byte)'c':
case (byte)'d':
case (byte)'e':
case (byte)'f':
case (byte)'g':
case (byte)'h':
case (byte)'i':
case (byte)'j':
case (byte)'k':
case (byte)'l':
case (byte)'m':
case (byte)'n':
case (byte)'o':
case (byte)'p':
case (byte)'q':
case (byte)'r':
case (byte)'s':
case (byte)'t':
case (byte)'u':
case (byte)'v':
case (byte)'w':
case (byte)'x':
case (byte)'y':
case (byte)'z':
case (byte)'A':
case (byte)'B':
case (byte)'C':
case (byte)'D':
case (byte)'E':
case (byte)'F':
case (byte)'G':
case (byte)'H':
case (byte)'I':
case (byte)'J':
case (byte)'K':
case (byte)'L':
case (byte)'M':
case (byte)'N':
case (byte)'O':
case (byte)'P':
case (byte)'Q':
case (byte)'R':
case (byte)'S':
case (byte)'T':
case (byte)'U':
case (byte)'V':
case (byte)'W':
case (byte)'X':
case (byte)'Y':
case (byte)'Z':
case (byte)'_':
return StepTokenType.Ident;
default:
return StepTokenType.Unknown;
}
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool IsWhiteSpace(byte b) => b == ' ' || b == '\t';
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool IsLineBreak(byte b) => b == '\n' || b == '\r';
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool IsIdent(byte b) => b >= 'A' && b <= 'Z' || b >= 'a' && b <= 'z' || b == '_';
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool IsDigit(byte b) => b >= '0' && b <= '9';
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool IsIdentOrDigitChar(byte b) => IsIdent(b) || IsDigit(b);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static unsafe byte* AdvancePast(byte* begin, byte* end, string s)
{
if (end - begin < s.Length)
return null;
foreach (var c in s)
if (*begin++ != (byte)c)
return null;
return begin;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static unsafe StepToken ParseToken(byte* begin, byte* end)
{
var cur = begin;
var tt = InternalParseToken(ref cur, end);
Debug.Assert(cur < end);
var span = new ByteSpan(begin, cur);
return new StepToken(span, tt);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static unsafe bool EatWSpace(ref StepToken cur, byte* end)
{
while (
cur.Type == StepTokenType.Comment || cur.Type == StepTokenType.Whitespace || cur.Type == StepTokenType.LineBreak
)
{
if (!ParseNextToken(ref cur, end))
return false;
}
return true;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static unsafe bool ParseNextToken(ref StepToken prev, byte* end)
{
var cur = prev.Span.End();
if (cur >= end)
return false;
prev = ParseToken(cur, end);
return true;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static unsafe StepTokenType InternalParseToken(ref byte* cur, byte* end)
{
var type = TokenLookup[*cur++];
switch (type)
{
case StepTokenType.Ident:
while (IsIdentLookup[*cur])
cur++;
break;
case StepTokenType.String:
// usually it is as single quote,
// but in rare cases it could be a double quote
var quoteChar = *(cur - 1);
while (cur < end)
{
if (*cur++ == quoteChar)
{
if (*cur != quoteChar)
break;
else
cur++;
}
}
break;
case StepTokenType.LineBreak:
while (IsLineBreak(*cur))
cur++;
break;
case StepTokenType.Number:
while (IsNumberLookup[*cur])
cur++;
break;
case StepTokenType.Symbol:
while (*cur++ != '.') { }
break;
case StepTokenType.Id:
while (IsNumberLookup[*cur])
cur++;
break;
case StepTokenType.Comment:
var prev = *cur++;
while (cur < end && (prev != '*' || *cur != '/'))
prev = *cur++;
cur++;
break;
}
return type;
}
}
@@ -1,154 +0,0 @@
using System.Diagnostics;
using Ara3D.Buffers;
using Ara3D.Utils;
namespace Speckle.Importers.Ifc.Ara3D.StepParser;
/// <summary>
/// The base class of the different type of value items that can be found in a STEP file.
/// * Entity
/// * List
/// * String
/// * Symbol
/// * Unassigned token
/// * Redeclared token
/// * Number
/// </summary>
public class StepValue;
public class StepEntity : StepValue
{
public readonly ByteSpan EntityType;
public readonly StepList Attributes;
public StepEntity(ByteSpan entityType, StepList attributes)
{
Debug.Assert(!entityType.IsNull());
EntityType = entityType;
Attributes = attributes;
}
public override string ToString() => $"{EntityType}{Attributes}";
}
public class StepList : StepValue
{
public readonly List<StepValue> Values;
public StepList(List<StepValue> values) => Values = values;
public override string ToString() => $"({Values.JoinStringsWithComma()})";
public static StepList CreateDefault() => new(new List<StepValue>());
}
public class StepString : StepValue
{
public readonly ByteSpan Value;
public static StepString Create(StepToken token)
{
var span = token.Span;
Debug.Assert(token.Type == StepTokenType.String);
Debug.Assert(span.Length >= 2);
Debug.Assert(span.First() == '\'' || span.First() == '"');
Debug.Assert(span.Last() == '\'' || span.Last() == '"');
return new StepString(span.Trim(1, 1));
}
public StepString(ByteSpan value) => Value = value;
public override string ToString() => $"'{Value}'";
}
public class StepSymbol : StepValue
{
public readonly ByteSpan Name;
public StepSymbol(ByteSpan name) => Name = name;
public override string ToString() => $".{Name}.";
public static StepSymbol Create(StepToken token)
{
Debug.Assert(token.Type == StepTokenType.Symbol);
var span = token.Span;
Debug.Assert(span.Length >= 2);
Debug.Assert(span.First() == '.');
Debug.Assert(span.Last() == '.');
return new StepSymbol(span.Trim(1, 1));
}
}
public class StepNumber : StepValue
{
public readonly ByteSpan Span;
public double Value => Span.ToDouble();
public StepNumber(ByteSpan span) => Span = span;
public override string ToString() => $"{Value}";
public static StepNumber Create(StepToken token)
{
Debug.Assert(token.Type == StepTokenType.Number);
var span = token.Span;
return new(span);
}
}
public class StepId : StepValue
{
public readonly uint Id;
public StepId(uint id) => Id = id;
public override string ToString() => $"#{Id}";
public static unsafe StepId Create(StepToken token)
{
Debug.Assert(token.Type == StepTokenType.Id);
var span = token.Span;
Debug.Assert(span.Length >= 2);
Debug.Assert(span.First() == '#');
var id = 0u;
for (var i = 1; i < span.Length; ++i)
{
Debug.Assert(span.Ptr[i] >= '0' && span.Ptr[i] <= '9');
id = id * 10 + span.Ptr[i] - '0';
}
return new StepId(id);
}
}
public class StepUnassigned : StepValue
{
public static readonly StepUnassigned Default = new();
public override string ToString() => "$";
public static StepUnassigned Create(StepToken token)
{
Debug.Assert(token.Type == StepTokenType.Unassigned);
var span = token.Span;
Debug.Assert(span.Length == 1);
Debug.Assert(span.First() == '$');
return Default;
}
}
public class StepRedeclared : StepValue
{
public static readonly StepRedeclared Default = new();
public override string ToString() => "*";
public static StepRedeclared Create(StepToken token)
{
Debug.Assert(token.Type == StepTokenType.Redeclared);
var span = token.Span;
Debug.Assert(span.Length == 1);
Debug.Assert(span.First() == '*');
return Default;
}
}
@@ -1,31 +0,0 @@
using Speckle.Importers.Ifc.Ara3D.IfcParser.Schema;
using Speckle.Importers.Ifc.Types;
using Speckle.InterfaceGenerator;
using Speckle.Objects.Data;
using Speckle.Sdk.Models;
namespace Speckle.Importers.Ifc.Converters;
[GenerateAutoInterface]
public sealed class DataObjectConverter(IGeometryConverter geometryConverter) : IDataObjectConverter
{
public DataObject Convert(IfcModel model, IfcNode node, INodeConverter childrenConverter)
{
// Even if there is no geometry, this will return an empty collection.
var geo = model.GetGeometry(node.Id);
List<Base> displayValue = geo != null ? geometryConverter.Convert(geo) : new();
return new DataObject()
{
applicationId = node.Guid, // Guid is null for property values, and other Ifc entities not derived from IfcRoot
properties = node.ConvertPropertySets(),
name = node.Name ?? node.Guid,
displayValue = displayValue,
["@elements"] = childrenConverter.ConvertChildren(model, node).ToList(),
["ifcType"] = node.Type,
["expressID"] = node.Id,
["ownerId"] = node.OwnerId,
["description"] = node.Description,
};
}
}
@@ -1,20 +0,0 @@
using Speckle.Importers.Ifc.Types;
using Speckle.InterfaceGenerator;
using Speckle.Sdk.Models;
namespace Speckle.Importers.Ifc.Converters;
[GenerateAutoInterface]
public sealed class GeometryConverter(IMeshConverter meshConverter) : IGeometryConverter
{
public List<Base> Convert(IfcGeometry geometry)
{
List<Base> ret = new();
foreach (var mesh in geometry.GetMeshes())
{
ret.Add(meshConverter.Convert(mesh));
}
return ret;
}
}
@@ -1,28 +0,0 @@
using Speckle.Importers.Ifc.Ara3D.IfcParser;
using Speckle.Importers.Ifc.Services;
using Speckle.Importers.Ifc.Types;
using Speckle.InterfaceGenerator;
using Speckle.Sdk.Models;
namespace Speckle.Importers.Ifc.Converters;
[GenerateAutoInterface]
public sealed class GraphConverter(INodeConverter nodeConverter, IRenderMaterialProxyManager proxyManager)
: IGraphConverter
{
public Base Convert(IfcModel model, IfcGraph graph)
{
try
{
Base rootCollection = nodeConverter.Convert(model, graph.GetIfcProject());
//Grabing materials from ProxyManager
rootCollection["renderMaterialProxies"] = proxyManager.RenderMaterialProxies.Values.ToList();
return rootCollection;
}
finally
{
proxyManager.Clear();
}
}
}
@@ -1,74 +0,0 @@
using System.Drawing;
using Speckle.Importers.Ifc.Services;
using Speckle.Importers.Ifc.Types;
using Speckle.InterfaceGenerator;
using Speckle.Objects.Geometry;
using Speckle.Objects.Other;
namespace Speckle.Importers.Ifc.Converters;
[GenerateAutoInterface]
public sealed class MeshConverter(IRenderMaterialProxyManager renderMaterialManager) : IMeshConverter
{
public Mesh Convert(IfcMesh mesh)
{
var m = mesh.Transform;
var vp = mesh.Vertices;
var ip = mesh.Indices;
var vertices = new List<double>(vp.Length * 3);
foreach (var vertex in vp)
{
var x = vertex.PX;
var y = vertex.PY;
var z = vertex.PZ;
vertices.Add(m[0] * x + m[4] * y + m[8] * z + m[12]);
vertices.Add(-(m[2] * x + m[6] * y + m[10] * z + m[14]));
vertices.Add(m[1] * x + m[5] * y + m[9] * z + m[13]);
}
var faces = new List<int>(ip.Length * 4);
for (var i = 0; i < ip.Length; i += 3)
{
var a = ip[i];
var b = ip[i + 1];
var c = ip[i + 2];
faces.Add(3);
faces.Add(a);
faces.Add(b);
faces.Add(c);
}
RenderMaterial renderMaterial = ConvertRenderMaterial(mesh);
Mesh converted =
new()
{
applicationId = Guid.NewGuid().ToString(),
vertices = vertices,
faces = faces,
units = "m",
};
renderMaterialManager.AddMeshMapping(renderMaterial, converted);
return converted;
}
private static RenderMaterial ConvertRenderMaterial(IfcMesh mesh)
{
var color = mesh.Color;
var diffuse = Color.FromArgb(1, To8BitValue(color.R), To8BitValue(color.G), To8BitValue(color.B));
var name = $"IFC_MATERIAL:{(color.A, color.R, color.G, color.B).GetHashCode()}";
return new RenderMaterial()
{
applicationId = name,
name = name,
diffuse = diffuse.ToArgb(),
opacity = color.A
};
static int To8BitValue(double value) => (int)(value * 255);
}
}
@@ -1,44 +0,0 @@
using Speckle.Importers.Ifc.Ara3D.IfcParser.Schema;
using Speckle.Importers.Ifc.Types;
using Speckle.InterfaceGenerator;
using Speckle.Sdk.Models;
namespace Speckle.Importers.Ifc.Converters;
/// <summary>
/// This is the main "recursive" converter for converting all IfcTypes to Speckle
/// </summary>
[GenerateAutoInterface]
public sealed class NodeConverter(
IDataObjectConverter dataObjectConverter,
IIfcSpatialStructureElementConverter spatialStructureConverter,
IProjectConverter projectConverter
) : INodeConverter
{
/// <summary>
/// Converts Ifc nodes that inherits IfcRoot class To Speckle)
/// </summary>
/// <param name="model"></param>
/// <param name="node"></param>
/// <returns></returns>
public Base Convert(IfcModel model, IfcNode node)
{
if (!node.IsIfcRoot)
throw new ArgumentException("Expected to be an IfcRoot", paramName: nameof(node));
return node switch
{
IfcProject project => projectConverter.Convert(model, project, this),
//Note: we're only expecting IfcSite, IfcBuilding, and IfcBuildingStory's here...
//but I cba to add full classes + inheritance, so IfcSpatialStructureElements is the closest common class
IfcSpatialStructureElement structure => spatialStructureConverter.Convert(model, structure, this),
IfcPropSet => throw new NotImplementedException("We didn't expect IfcPropSets here!"),
_ => dataObjectConverter.Convert(model, node, this)
};
}
public IEnumerable<Base> ConvertChildren(IfcModel model, IfcNode node)
{
return node.GetChildren().Where(x => x.IsIfcRoot).Select(x => Convert(model, x));
}
}
@@ -1,41 +0,0 @@
using Speckle.Importers.Ifc.Ara3D.IfcParser;
using Speckle.Importers.Ifc.Ara3D.IfcParser.Schema;
namespace Speckle.Importers.Ifc.Converters;
public static class NodeExtensions
{
public static Dictionary<string, object?> ConvertPropertySets(this IfcNode node)
{
var result = new Dictionary<string, object?>();
foreach (var p in node.GetPropSets())
{
var name = p.Name;
if (string.IsNullOrWhiteSpace(name))
name = $"#{p.Id}";
var dict = ToSpeckleDictionary(p);
if (dict.Count > 0) //Ignore any empty psets, since they can bloat the data size
result[name] = dict;
}
return result;
}
public static Dictionary<string, object?> ToSpeckleDictionary(this IfcPropSet ps)
{
var d = new Dictionary<string, object?>();
foreach (var p in ps.GetProperties())
{
var value = p.Value.ToJsonObject();
if (value is not null)
{
// Ignoring null values since they'd otherwise bloat the data size of speckle models.
// Semantically, "null valued" and "not there" are different, but very few users care about the distinction.
d[p.Name] = value;
}
}
return d;
}
}
@@ -1,28 +0,0 @@
using Speckle.Importers.Ifc.Ara3D.IfcParser.Schema;
using Speckle.Importers.Ifc.Types;
using Speckle.InterfaceGenerator;
using Speckle.Sdk.Models.Collections;
namespace Speckle.Importers.Ifc.Converters;
[GenerateAutoInterface]
public sealed class ProjectConverter : IProjectConverter
{
public Collection Convert(IfcModel model, IfcProject node, INodeConverter childrenConverter)
{
return new Collection
{
name = node.Name ?? node.Guid,
applicationId = node.Guid,
elements = childrenConverter.ConvertChildren(model, node).ToList(),
["expressID"] = node.Id,
["ownerId"] = node.OwnerId,
["ifcType"] = node.Type,
["description"] = node.Description,
["objectType"] = node.ObjectType,
["longName"] = node.LongName,
["phase"] = node.Phase,
["properties"] = node.ConvertPropertySets(),
};
}
}
@@ -1,52 +0,0 @@
using Speckle.Importers.Ifc.Ara3D.IfcParser.Schema;
using Speckle.Importers.Ifc.Types;
using Speckle.InterfaceGenerator;
using Speckle.Objects.Data;
using Speckle.Sdk.Models;
using Speckle.Sdk.Models.Collections;
namespace Speckle.Importers.Ifc.Converters;
[GenerateAutoInterface]
public sealed class IfcSpatialStructureElementConverter(IGeometryConverter geometryConverter)
: IIfcSpatialStructureElementConverter
{
public Collection Convert(IfcModel model, IfcSpatialStructureElement node, INodeConverter childrenConverter)
{
var directGeometry = ConvertAsDataObject(model, node);
var relationalChildren = childrenConverter.ConvertChildren(model, node);
var allChildren = relationalChildren.Prepend(directGeometry).ToList();
//We're preferring to keep IFC collections lightweight, and adding a DataObject with the properties
// 1. Spatial elements can can have direct geometry (mostly only common with IFC Site)
// 2. Keeps property access simpler
return new Collection
{
name = node.Name ?? node.LongName ?? node.Guid,
elements = allChildren,
["expressID"] = node.Id,
};
}
private DataObject ConvertAsDataObject(IfcModel model, IfcSpatialStructureElement node)
{
var geo = model.GetGeometry(node.Id);
List<Base> displayValue = geo != null ? geometryConverter.Convert(geo) : new();
return new DataObject
{
["expressID"] = node.Id,
["ownerId"] = node.OwnerId,
["ifcType"] = node.Type,
["description"] = node.Description,
["objectType"] = node.ObjectType,
["compositionType"] = node.CompositionType,
["longName"] = node.LongName,
name = node.Name ?? node.LongName ?? node.Guid,
applicationId = node.Guid,
properties = node.ConvertPropertySets(),
displayValue = displayValue,
};
}
}
@@ -1,56 +0,0 @@
using System.Reflection;
using Microsoft.Extensions.DependencyInjection;
using Speckle.Connectors.Common;
using Speckle.Objects.Geometry;
using Speckle.Sdk;
using Speckle.Sdk.Transports;
using Version = Speckle.Sdk.Api.GraphQL.Models.Version;
namespace Speckle.Importers.Ifc;
/// <summary>
/// Static DI Wrapper around <see cref="Importer"/>
/// </summary>
public static class Import
{
public static ServiceProvider GetServiceProvider()
{
var serviceCollection = new ServiceCollection();
serviceCollection.AddIFCImporter();
return serviceCollection.BuildServiceProvider();
}
public static void AddIFCImporter(this ServiceCollection serviceCollection)
{
serviceCollection.AddSpeckleSdk(
new("IFC", "ifc"),
HostAppVersion.v2024.ToString(),
"IFC-Importer",
typeof(Point).Assembly
);
serviceCollection.AddSpeckleWebIfc();
serviceCollection.AddSingleton<Importer>();
serviceCollection.AddMatchingInterfacesAsTransient(Assembly.GetExecutingAssembly());
}
public static async Task<Version> Ifc(
ImporterArgs args,
IProgress<ProgressArgs>? progress = null,
CancellationToken cancellationToken = default
)
{
var serviceProvider = GetServiceProvider();
return await Ifc(serviceProvider, args, progress, cancellationToken);
}
public static async Task<Version> Ifc(
ServiceProvider serviceProvider,
ImporterArgs args,
IProgress<ProgressArgs>? progress = null,
CancellationToken cancellationToken = default
)
{
var importer = serviceProvider.GetRequiredService<Importer>();
return await importer.ImportIfc(args, progress, cancellationToken);
}
}
@@ -1,107 +0,0 @@
using System.Diagnostics;
using Ara3D.Utils;
using Speckle.Importers.Ifc.Ara3D.IfcParser;
using Speckle.Importers.Ifc.Converters;
using Speckle.Importers.Ifc.Types;
using Speckle.Sdk.Api;
using Speckle.Sdk.Api.GraphQL.Inputs;
using Speckle.Sdk.Api.GraphQL.Models;
using Speckle.Sdk.Credentials;
using Speckle.Sdk.Serialisation.V2;
using Speckle.Sdk.Serialisation.V2.Send;
using Speckle.Sdk.Transports;
using Version = Speckle.Sdk.Api.GraphQL.Models.Version;
namespace Speckle.Importers.Ifc;
public sealed class ImporterArgs
{
public required Uri ServerUrl { get; init; }
public required string FilePath { get; init; }
public required string ProjectId { get; init; }
public required string? ModelId { get; init; }
public required string ModelName { get; init; }
public required string VersionMessage { get; init; }
public required string Token { get; init; }
}
public sealed class Importer(
IIfcFactory ifcFactory,
IClientFactory clientFactory,
IGraphConverter converter,
ISerializeProcessFactory serializeProcessFactory
)
{
public async Task<Version> ImportIfc(
ImporterArgs args,
IProgress<ProgressArgs>? progress,
CancellationToken cancellationToken
)
{
var filePath = new FilePath(args.FilePath);
var stopwatch = Stopwatch.StartNew();
Console.WriteLine($"Starting processing file : {filePath.GetFileName()}");
var ifcModel = ifcFactory.Open(filePath);
var ms = stopwatch.ElapsedMilliseconds;
Console.WriteLine($"Opened with WebIFC: {ms} ms");
var graph = IfcGraph.Load(filePath);
var ms2 = stopwatch.ElapsedMilliseconds;
Console.WriteLine($"Loaded with StepParser: {ms2 - ms} ms");
var b = converter.Convert(ifcModel, graph);
ms = ms2;
ms2 = stopwatch.ElapsedMilliseconds;
Console.WriteLine($"Converted to Speckle Bases: {ms2 - ms} ms");
var process = serializeProcessFactory.CreateSerializeProcess(
args.ServerUrl,
args.ProjectId,
args.Token,
progress,
cancellationToken,
new SerializeProcessOptions(true, true, false, progress is null)
);
var (rootId, _) = await process.Serialize(b).ConfigureAwait(false);
Account account =
new()
{
token = args.Token,
serverInfo = new ServerInfo { url = args.ServerUrl.ToString() },
};
ms = ms2;
ms2 = stopwatch.ElapsedMilliseconds;
Console.WriteLine($"Uploaded to Speckle: {ms2 - ms} ms. Root id: {rootId}");
// 8 - Create the version (commit)
using var apiClient = clientFactory.Create(account);
var modelId = args.ModelId;
if (string.IsNullOrEmpty(modelId))
{
// Project level import, currently we're expecting the parsers to create the branch
// Quite smelly imo...
var input = new CreateModelInput(args.ModelName, null, args.ProjectId);
var model = await apiClient.Model.Create(input, cancellationToken);
modelId = model.id;
}
var speckleVersion = await apiClient.Version.Create(
new CreateVersionInput(rootId, modelId, args.ProjectId, message: args.VersionMessage, sourceApplication: "IFC"),
cancellationToken
);
ms = ms2;
ms2 = stopwatch.ElapsedMilliseconds;
Console.WriteLine($"Committed to Speckle: {ms2 - ms} ms - {GetUrl(speckleVersion, modelId)}");
Console.WriteLine();
return speckleVersion;
}
private static string GetUrl(Version version, string modelId)
{
return version.previewUrl.ToString().Replace("preview", "projects").Replace("commits/", $"models/{modelId}@");
}
}
@@ -1,107 +0,0 @@
using System.Diagnostics.CodeAnalysis;
using System.Runtime.InteropServices;
namespace Speckle.Importers.Ifc.Native;
[SuppressMessage("Globalization", "CA2101:Specify marshaling for P/Invoke string arguments")]
[SuppressMessage("Security", "CA5393:Do not use unsafe DllImportSearchPath value")]
internal static class WebIfc
{
#if WINDOWS
private const string DllName = "Native/web-ifc.dll";
private const CharSet Set = CharSet.Ansi;
#else
private const string DllName = "libweb-ifc.so";
private const CharSet Set = CharSet.Auto;
#endif
private const DllImportSearchPath ImportSearchPath = DllImportSearchPath.AssemblyDirectory;
[DllImport(DllName)]
[DefaultDllImportSearchPaths(ImportSearchPath)]
public static extern IntPtr InitializeApi();
[DllImport(DllName)]
[DefaultDllImportSearchPaths(ImportSearchPath)]
public static extern void FinalizeApi(IntPtr api);
[DllImport(DllName, CharSet = Set)]
[DefaultDllImportSearchPaths(ImportSearchPath)]
public static extern IntPtr LoadModel(IntPtr api, string fileName);
[DllImport(DllName, CharSet = Set)]
[DefaultDllImportSearchPaths(ImportSearchPath)]
public static extern string GetVersion();
[DllImport(DllName)]
[DefaultDllImportSearchPaths(ImportSearchPath)]
public static extern IntPtr GetMesh(IntPtr geometry, int index);
[DllImport(DllName)]
[DefaultDllImportSearchPaths(ImportSearchPath)]
public static extern int GetNumMeshes(IntPtr geometry);
[DllImport(DllName)]
[DefaultDllImportSearchPaths(ImportSearchPath)]
public static extern uint GetGeometryType(IntPtr geometry);
[DllImport(DllName)]
[DefaultDllImportSearchPaths(ImportSearchPath)]
public static extern uint GetGeometryId(IntPtr geometry);
[DllImport(DllName)]
[DefaultDllImportSearchPaths(ImportSearchPath)]
public static extern uint GetLineId(IntPtr line);
[DllImport(DllName)]
[DefaultDllImportSearchPaths(ImportSearchPath)]
public static extern uint GetLineType(IntPtr line);
[DllImport(DllName)]
[DefaultDllImportSearchPaths(ImportSearchPath)]
public static extern string GetLineArguments(IntPtr line);
[DllImport(DllName)]
[DefaultDllImportSearchPaths(ImportSearchPath)]
public static extern int GetNumVertices(IntPtr mesh);
[DllImport(DllName)]
[DefaultDllImportSearchPaths(ImportSearchPath)]
public static extern IntPtr GetVertices(IntPtr mesh);
[DllImport(DllName)]
[DefaultDllImportSearchPaths(ImportSearchPath)]
public static extern IntPtr GetTransform(IntPtr mesh);
[DllImport(DllName)]
[DefaultDllImportSearchPaths(ImportSearchPath)]
public static extern int GetNumIndices(IntPtr mesh);
[DllImport(DllName)]
[DefaultDllImportSearchPaths(ImportSearchPath)]
public static extern IntPtr GetIndices(IntPtr mesh);
[DllImport(DllName)]
[DefaultDllImportSearchPaths(ImportSearchPath)]
public static extern IntPtr GetColor(IntPtr mesh);
[DllImport(DllName)]
[DefaultDllImportSearchPaths(ImportSearchPath)]
public static extern IntPtr GetGeometryFromId(IntPtr model, uint id);
[DllImport(DllName)]
[DefaultDllImportSearchPaths(ImportSearchPath)]
public static extern int GetNumGeometries(IntPtr model);
[DllImport(DllName)]
[DefaultDllImportSearchPaths(ImportSearchPath)]
public static extern IntPtr GetGeometryFromIndex(IntPtr model, int index);
[DllImport(DllName)]
[DefaultDllImportSearchPaths(ImportSearchPath)]
public static extern uint GetMaxId(IntPtr model);
[DllImport(DllName)]
[DefaultDllImportSearchPaths(ImportSearchPath)]
public static extern IntPtr GetLineFromModel(IntPtr model, uint id);
}
@@ -1,33 +0,0 @@
using System.Reflection;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;
using Speckle.Importers.Ifc.Services;
using Speckle.Importers.Ifc.Types;
using Speckle.Sdk;
namespace Speckle.Importers.Ifc;
public static class ServiceRegistration
{
public static void AddSpeckleWebIfc(this IServiceCollection services)
{
services.AddSingleton<IIfcFactory, IfcFactory>();
services.AddSingleton<IRenderMaterialProxyManager, RenderMaterialProxyManager>();
}
public static IServiceCollection AddMatchingInterfacesAsTransient(
this IServiceCollection serviceCollection,
Assembly assembly
)
{
foreach (var type in assembly.ExportedTypes.Where(t => t.IsNonAbstractClass()))
{
foreach (var matchingInterface in type.FindMatchingInterface())
{
serviceCollection.TryAddTransient(matchingInterface, type);
}
}
return serviceCollection;
}
}
@@ -1,29 +0,0 @@
using Speckle.InterfaceGenerator;
using Speckle.Objects.Geometry;
using Speckle.Objects.Other;
using Speckle.Sdk.Common;
namespace Speckle.Importers.Ifc.Services;
[GenerateAutoInterface]
public sealed class RenderMaterialProxyManager : IRenderMaterialProxyManager
{
public Dictionary<string, RenderMaterialProxy> RenderMaterialProxies { get; } = new();
public void Clear() => RenderMaterialProxies.Clear();
public void AddMeshMapping(RenderMaterial renderMaterial, Mesh mesh)
{
string materialId = renderMaterial.applicationId.NotNull();
string meshId = mesh.applicationId.NotNull();
if (RenderMaterialProxies.TryGetValue(materialId, out RenderMaterialProxy? proxy))
{
proxy.objects.Add(meshId);
}
else
{
RenderMaterialProxies.Add(materialId, new() { objects = [meshId], value = renderMaterial, });
}
}
}
@@ -1,54 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<Configurations>Debug;Release;Local</Configurations>
<DefineConstants Condition=" '$(OS)' == 'Windows_NT' ">WINDOWS</DefineConstants>
<DefineConstants Condition=" '$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::Linux)))' ">LINUX</DefineConstants>
</PropertyGroup>
<PropertyGroup Label="Nuget Package Properties">
<IsPackable>true</IsPackable>
<IncludeSymbols>true</IncludeSymbols>
</PropertyGroup>
<PropertyGroup Label="Ignored Compile Warnings">
<NoWarn>
IDE1006;IDE0130;IDE0011;CA1051;CA1720;CA1002;CA1054;CA1028;CA1721;CA1502;CA1065;NU5104;
$(NoWarn)
</NoWarn>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Ara3D.Buffers" />
<PackageReference Include="Ara3D.Logging" />
<PackageReference Include="Ara3D.Utils" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection" VersionOverride="8.0.0" />
</ItemGroup>
<ItemGroup Condition="'$(Configuration)' == 'Local'">
<ProjectReference Include="..\..\..\..\speckle-sharp-sdk\src\Speckle.Sdk\Speckle.Sdk.csproj" />
<ProjectReference Include="..\..\..\..\speckle-sharp-sdk\src\Speckle.Objects\Speckle.Objects.csproj" />
</ItemGroup>
<ItemGroup Condition="'$(Configuration)' != 'Local'">
<PackageReference Include="Speckle.Sdk" />
<PackageReference Include="Speckle.Objects" />
</ItemGroup>
<ItemGroup>
<None Include="Native\web-ifc.dll" Pack="true" PackagePath="runtimes\win-x64\native">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
<PackageCopyToOutput>true</PackageCopyToOutput>
</None>
<None Include="Native\libweb-ifc.so" Pack="true" PackagePath="runtimes\linux-x64\native">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
<PackageCopyToOutput>true</PackageCopyToOutput>
</None>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\..\Sdk\Speckle.Connectors.Common\Speckle.Connectors.Common.csproj" />
</ItemGroup>
</Project>
@@ -1,14 +0,0 @@
using Speckle.Sdk;
namespace Speckle.Importers.Ifc;
public class SpeckleIfcException : SpeckleException
{
public SpeckleIfcException() { }
public SpeckleIfcException(string? message)
: base(message) { }
public SpeckleIfcException(string? message, Exception? inner = null)
: base(message, inner) { }
}
@@ -1,12 +0,0 @@
using System.Runtime.InteropServices;
namespace Speckle.Importers.Ifc.Types;
[StructLayout(LayoutKind.Sequential, Pack = 1)]
public readonly struct IfcColor
{
public readonly double R,
G,
B,
A;
}
@@ -1,21 +0,0 @@
using Speckle.InterfaceGenerator;
namespace Speckle.Importers.Ifc.Types;
[GenerateAutoInterface]
public sealed class IfcFactory : IIfcFactory
{
//probably never disposing this
private static readonly IntPtr _ptr = Importers.Ifc.Native.WebIfc.InitializeApi();
public IfcModel Open(string fullPath)
{
if (!File.Exists(fullPath))
{
throw new ArgumentException($"File does not exist: {fullPath}");
}
return new(Importers.Ifc.Native.WebIfc.LoadModel(_ptr, fullPath));
}
public string Version => Importers.Ifc.Native.WebIfc.GetVersion();
}
@@ -1,18 +0,0 @@
namespace Speckle.Importers.Ifc.Types;
public sealed class IfcGeometry(IntPtr geometry)
{
public IfcMesh GetMesh(int i) => new(Importers.Ifc.Native.WebIfc.GetMesh(geometry, i));
public int MeshCount => Importers.Ifc.Native.WebIfc.GetNumMeshes(geometry);
public IfcSchemaType Type => (IfcSchemaType)Importers.Ifc.Native.WebIfc.GetGeometryType(geometry);
public IEnumerable<IfcMesh> GetMeshes()
{
for (int i = 0; i < MeshCount; ++i)
{
yield return GetMesh(i);
}
}
}
@@ -1,9 +0,0 @@
namespace Speckle.Importers.Ifc.Types;
public sealed class IfcLine(IntPtr line)
{
public uint Id => Importers.Ifc.Native.WebIfc.GetLineId(line);
public IfcSchemaType Type => (IfcSchemaType)Importers.Ifc.Native.WebIfc.GetLineType(line);
public string Arguments() => Importers.Ifc.Native.WebIfc.GetLineArguments(line);
}
@@ -1,40 +0,0 @@
using System.Runtime.InteropServices;
using Speckle.Importers.Ifc.Native;
namespace Speckle.Importers.Ifc.Types;
public sealed class IfcMesh(IntPtr mesh)
{
public int VerticesCount => WebIfc.GetNumVertices(mesh);
public unsafe ReadOnlySpan<IfcVertex> Vertices
{
get
{
IfcVertex* ptr = (IfcVertex*)WebIfc.GetVertices(mesh);
return new ReadOnlySpan<IfcVertex>(ptr, VerticesCount);
}
}
public unsafe ReadOnlySpan<double> Transform
{
get
{
double* ptr = (double*)WebIfc.GetTransform(mesh);
return new ReadOnlySpan<double>(ptr, 16);
}
}
public int IndicesCount => WebIfc.GetNumIndices(mesh);
public unsafe ReadOnlySpan<int> Indices
{
get
{
var ptr = (int*)WebIfc.GetIndices(mesh);
return new ReadOnlySpan<int>(ptr, IndicesCount);
}
}
public IfcColor Color => Marshal.PtrToStructure<IfcColor>(WebIfc.GetColor(mesh));
}
@@ -1,33 +0,0 @@
namespace Speckle.Importers.Ifc.Types;
public sealed class IfcModel(IntPtr model)
{
public int GetNumGeometries() => Importers.Ifc.Native.WebIfc.GetNumGeometries(model);
public IfcGeometry? GetGeometry(uint id)
{
var geometry = Importers.Ifc.Native.WebIfc.GetGeometryFromId(model, id);
return geometry == IntPtr.Zero ? null : new IfcGeometry(geometry);
}
public IEnumerable<IfcGeometry> GetGeometries()
{
var numGeometries = Importers.Ifc.Native.WebIfc.GetNumGeometries(model);
for (int i = 0; i < numGeometries; ++i)
{
var gPtr = Importers.Ifc.Native.WebIfc.GetGeometryFromIndex(model, i);
if (gPtr != IntPtr.Zero)
{
yield return new IfcGeometry(gPtr);
}
}
}
public uint GetMaxId() => Importers.Ifc.Native.WebIfc.GetMaxId(model);
public IfcLine? GetLine(uint id)
{
var line = Importers.Ifc.Native.WebIfc.GetLineFromModel(model, id);
return line == IntPtr.Zero ? null : new IfcLine(line);
}
}
File diff suppressed because it is too large Load Diff
@@ -1,14 +0,0 @@
using System.Runtime.InteropServices;
namespace Speckle.Importers.Ifc.Types;
[StructLayout(LayoutKind.Sequential, Pack = 1)]
public readonly struct IfcVertex
{
public readonly double PX,
PY,
PZ;
public readonly double NX,
NY,
NZ;
}
@@ -1,304 +0,0 @@
{
"version": 2,
"dependencies": {
"net8.0": {
"Ara3D.Buffers": {
"type": "Direct",
"requested": "[1.4.5, )",
"resolved": "1.4.5",
"contentHash": "SKcQqgtXukyHTlTKFPCaUW4spSkue3XfBU/GmoA7KhH6H995v6TbJxtqjs0EfSgnXEkajL8U7X1NqktScRozXw==",
"dependencies": {
"System.Memory": "4.5.5"
}
},
"Ara3D.Logging": {
"type": "Direct",
"requested": "[1.4.5, )",
"resolved": "1.4.5",
"contentHash": "7HPCe5Dq21JoOBF1iclk9H37XFCoB2ZzCPqTMNgdg4PWFvuRsofNbiuMdiE/HKgMHCVhy1C5opB2KwDKcO7Axw==",
"dependencies": {
"Ara3D.Utils": "1.4.5"
}
},
"Ara3D.Utils": {
"type": "Direct",
"requested": "[1.4.5, )",
"resolved": "1.4.5",
"contentHash": "yba/E7PpbWP0+RDp+KbKw/vBXnXBSIheScdpVKuDnr8ytRg8pZ2Jd6nwKES+G0FcVEB9PeOVmEW7SGrFvAwRCg=="
},
"Microsoft.Extensions.DependencyInjection": {
"type": "Direct",
"requested": "[8.0.0, )",
"resolved": "8.0.0",
"contentHash": "V8S3bsm50ig6JSyrbcJJ8bW2b9QLGouz+G1miK3UTaOWmMtFwNNNzUf4AleyDWUmTrWMLNnFSLEQtxmxgNQnNQ==",
"dependencies": {
"Microsoft.Extensions.DependencyInjection.Abstractions": "8.0.0"
}
},
"Microsoft.NETFramework.ReferenceAssemblies": {
"type": "Direct",
"requested": "[1.0.3, )",
"resolved": "1.0.3",
"contentHash": "vUc9Npcs14QsyOD01tnv/m8sQUnGTGOw1BCmKcv77LBJY7OxhJ+zJF7UD/sCL3lYNFuqmQEVlkfS4Quif6FyYg==",
"dependencies": {
"Microsoft.NETFramework.ReferenceAssemblies.net461": "1.0.3"
}
},
"Microsoft.SourceLink.GitHub": {
"type": "Direct",
"requested": "[8.0.0, )",
"resolved": "8.0.0",
"contentHash": "G5q7OqtwIyGTkeIOAc3u2ZuV/kicQaec5EaRnc0pIeSnh9LUjj+PYQrJYBURvDt7twGl2PKA7nSN0kz1Zw5bnQ==",
"dependencies": {
"Microsoft.Build.Tasks.Git": "8.0.0",
"Microsoft.SourceLink.Common": "8.0.0"
}
},
"PolySharp": {
"type": "Direct",
"requested": "[1.14.1, )",
"resolved": "1.14.1",
"contentHash": "mOOmFYwad3MIOL14VCjj02LljyF1GNw1wP0YVlxtcPvqdxjGGMNdNJJxHptlry3MOd8b40Flm8RPOM8JOlN2sQ=="
},
"Speckle.InterfaceGenerator": {
"type": "Direct",
"requested": "[0.9.6, )",
"resolved": "0.9.6",
"contentHash": "HKH7tYrYYlCK1ct483hgxERAdVdMtl7gUKW9ijWXxA1UsYR4Z+TrRHYmzZ9qmpu1NnTycSrp005NYM78GDKV1w=="
},
"Speckle.Objects": {
"type": "Direct",
"requested": "[3.5.4, )",
"resolved": "3.5.4",
"contentHash": "o7ex4+yHJYI8pJbsjNqw+D8r8WjkBoB5aK/GQlGJd/0zydrPxN4SMKS4arpRBR3CUD6JhtQMatScXZOrslGXQg==",
"dependencies": {
"Speckle.Sdk": "3.5.4"
}
},
"Speckle.Sdk": {
"type": "Direct",
"requested": "[3.5.4, )",
"resolved": "3.5.4",
"contentHash": "o4bEJTz+OBI1koy9xqXSIq3UtUFCKtk6Btg82rdVM2aFMPT3ZoYVarG+ylPcUOHd684XpgGASxE6dIgXz2pvng==",
"dependencies": {
"GraphQL.Client": "6.0.0",
"Microsoft.Data.Sqlite": "7.0.5",
"Microsoft.Extensions.DependencyInjection.Abstractions": "2.2.0",
"Microsoft.Extensions.Logging": "2.2.0",
"Speckle.DoubleNumerics": "4.1.0",
"Speckle.Newtonsoft.Json": "13.0.2",
"Speckle.Sdk.Dependencies": "3.5.4"
}
},
"GraphQL.Client": {
"type": "Transitive",
"resolved": "6.0.0",
"contentHash": "8yPNBbuVBpTptivyAlak4GZvbwbUcjeQTL4vN1HKHRuOykZ4r7l5fcLS6vpyPyLn0x8FsL31xbOIKyxbmR9rbA==",
"dependencies": {
"GraphQL.Client.Abstractions": "6.0.0",
"GraphQL.Client.Abstractions.Websocket": "6.0.0",
"System.Reactive": "5.0.0"
}
},
"GraphQL.Client.Abstractions": {
"type": "Transitive",
"resolved": "6.0.0",
"contentHash": "h7uzWFORHZ+CCjwr/ThAyXMr0DPpzEANDa4Uo54wqCQ+j7qUKwqYTgOrb1W40sqbvNaZm9v/X7It31SUw0maHA==",
"dependencies": {
"GraphQL.Primitives": "6.0.0"
}
},
"GraphQL.Client.Abstractions.Websocket": {
"type": "Transitive",
"resolved": "6.0.0",
"contentHash": "Nr9bPf8gIOvLuXpqEpqr9z9jslYFJOvd0feHth3/kPqeR3uMbjF5pjiwh4jxyMcxHdr8Pb6QiXkV3hsSyt0v7A==",
"dependencies": {
"GraphQL.Client.Abstractions": "6.0.0"
}
},
"GraphQL.Primitives": {
"type": "Transitive",
"resolved": "6.0.0",
"contentHash": "yg72rrYDapfsIUrul7aF6wwNnTJBOFvuA9VdDTQpPa8AlAriHbufeXYLBcodKjfUdkCnaiggX1U/nEP08Zb5GA=="
},
"Microsoft.Build.Tasks.Git": {
"type": "Transitive",
"resolved": "8.0.0",
"contentHash": "bZKfSIKJRXLTuSzLudMFte/8CempWjVamNUR5eHJizsy+iuOuO/k2gnh7W0dHJmYY0tBf+gUErfluCv5mySAOQ=="
},
"Microsoft.Data.Sqlite": {
"type": "Transitive",
"resolved": "7.0.5",
"contentHash": "KGxbPeWsQMnmQy43DSBxAFtHz3l2JX8EWBSGUCvT3CuZ8KsuzbkqMIJMDOxWtG8eZSoCDI04aiVQjWuuV8HmSw==",
"dependencies": {
"Microsoft.Data.Sqlite.Core": "7.0.5",
"SQLitePCLRaw.bundle_e_sqlite3": "2.1.4"
}
},
"Microsoft.Data.Sqlite.Core": {
"type": "Transitive",
"resolved": "7.0.5",
"contentHash": "FTerRmQPqHrCrnoUzhBu+E+1DNGwyrAMLqHkAqOOOu5pGfyMOj8qQUBxI/gDtWtG11p49UxSfWmBzRNlwZqfUg==",
"dependencies": {
"SQLitePCLRaw.core": "2.1.4"
}
},
"Microsoft.Extensions.Configuration": {
"type": "Transitive",
"resolved": "2.2.0",
"contentHash": "nOP8R1mVb/6mZtm2qgAJXn/LFm/2kMjHDAg/QJLFG6CuWYJtaD3p1BwQhufBVvRzL9ceJ/xF0SQ0qsI2GkDQAA==",
"dependencies": {
"Microsoft.Extensions.Configuration.Abstractions": "2.2.0"
}
},
"Microsoft.Extensions.Configuration.Abstractions": {
"type": "Transitive",
"resolved": "2.2.0",
"contentHash": "65MrmXCziWaQFrI0UHkQbesrX5wTwf9XPjY5yFm/VkgJKFJ5gqvXRoXjIZcf2wLi5ZlwGz/oMYfyURVCWbM5iw==",
"dependencies": {
"Microsoft.Extensions.Primitives": "2.2.0"
}
},
"Microsoft.Extensions.Configuration.Binder": {
"type": "Transitive",
"resolved": "2.2.0",
"contentHash": "vJ9xvOZCnUAIHcGC3SU35r3HKmHTVIeHzo6u/qzlHAqD8m6xv92MLin4oJntTvkpKxVX3vI1GFFkIQtU3AdlsQ==",
"dependencies": {
"Microsoft.Extensions.Configuration": "2.2.0"
}
},
"Microsoft.Extensions.DependencyInjection.Abstractions": {
"type": "Transitive",
"resolved": "8.0.0",
"contentHash": "cjWrLkJXK0rs4zofsK4bSdg+jhDLTaxrkXu4gS6Y7MAlCvRyNNgwY/lJi5RDlQOnSZweHqoyvgvbdvQsRIW+hg=="
},
"Microsoft.Extensions.Options": {
"type": "Transitive",
"resolved": "2.2.0",
"contentHash": "UpZLNLBpIZ0GTebShui7xXYh6DmBHjWM8NxGxZbdQh/bPZ5e6YswqI+bru6BnEL5eWiOdodsXtEz3FROcgi/qg==",
"dependencies": {
"Microsoft.Extensions.DependencyInjection.Abstractions": "2.2.0",
"Microsoft.Extensions.Primitives": "2.2.0",
"System.ComponentModel.Annotations": "4.5.0"
}
},
"Microsoft.Extensions.Primitives": {
"type": "Transitive",
"resolved": "2.2.0",
"contentHash": "azyQtqbm4fSaDzZHD/J+V6oWMFaf2tWP4WEGIYePLCMw3+b2RQdj9ybgbQyjCshcitQKQ4lEDOZjmSlTTrHxUg==",
"dependencies": {
"System.Memory": "4.5.1",
"System.Runtime.CompilerServices.Unsafe": "4.5.1"
}
},
"Microsoft.NETFramework.ReferenceAssemblies.net461": {
"type": "Transitive",
"resolved": "1.0.3",
"contentHash": "AmOJZwCqnOCNp6PPcf9joyogScWLtwy0M1WkqfEQ0M9nYwyDD7EX9ZjscKS5iYnyvteX7kzSKFCKt9I9dXA6mA=="
},
"Microsoft.SourceLink.Common": {
"type": "Transitive",
"resolved": "8.0.0",
"contentHash": "dk9JPxTCIevS75HyEQ0E4OVAFhB2N+V9ShCXf8Q6FkUQZDkgLI12y679Nym1YqsiSysuQskT7Z+6nUf3yab6Vw=="
},
"Speckle.Newtonsoft.Json": {
"type": "Transitive",
"resolved": "13.0.2",
"contentHash": "g1BejUZwax5PRfL6xHgLEK23sqHWOgOj9hE7RvfRRlN00AGt8GnPYt8HedSK7UB3HiRW8zCA9Pn0iiYxCK24BA=="
},
"SQLitePCLRaw.bundle_e_sqlite3": {
"type": "Transitive",
"resolved": "2.1.4",
"contentHash": "EWI1olKDjFEBMJu0+3wuxwziIAdWDVMYLhuZ3Qs84rrz+DHwD00RzWPZCa+bLnHCf3oJwuFZIRsHT5p236QXww==",
"dependencies": {
"SQLitePCLRaw.lib.e_sqlite3": "2.1.4",
"SQLitePCLRaw.provider.e_sqlite3": "2.1.4"
}
},
"SQLitePCLRaw.core": {
"type": "Transitive",
"resolved": "2.1.4",
"contentHash": "inBjvSHo9UDKneGNzfUfDjK08JzlcIhn1+SP5Y3m6cgXpCxXKCJDy6Mka7LpgSV+UZmKSnC8rTwB0SQ0xKu5pA==",
"dependencies": {
"System.Memory": "4.5.3"
}
},
"SQLitePCLRaw.lib.e_sqlite3": {
"type": "Transitive",
"resolved": "2.1.4",
"contentHash": "2C9Q9eX7CPLveJA0rIhf9RXAvu+7nWZu1A2MdG6SD/NOu26TakGgL1nsbc0JAspGijFOo3HoN79xrx8a368fBg=="
},
"SQLitePCLRaw.provider.e_sqlite3": {
"type": "Transitive",
"resolved": "2.1.4",
"contentHash": "CSlb5dUp1FMIkez9Iv5EXzpeq7rHryVNqwJMWnpq87j9zWZexaEMdisDktMsnnrzKM6ahNrsTkjqNodTBPBxtQ==",
"dependencies": {
"SQLitePCLRaw.core": "2.1.4"
}
},
"System.ComponentModel.Annotations": {
"type": "Transitive",
"resolved": "4.5.0",
"contentHash": "UxYQ3FGUOtzJ7LfSdnYSFd7+oEv6M8NgUatatIN2HxNtDdlcvFAf+VIq4Of9cDMJEJC0aSRv/x898RYhB4Yppg=="
},
"System.Memory": {
"type": "Transitive",
"resolved": "4.5.5",
"contentHash": "XIWiDvKPXaTveaB7HVganDlOCRoj03l+jrwNvcge/t8vhGYKvqV+dMv6G4SAX2NoNmN0wZfVPTAlFwZcZvVOUw=="
},
"System.Reactive": {
"type": "Transitive",
"resolved": "5.0.0",
"contentHash": "erBZjkQHWL9jpasCE/0qKAryzVBJFxGHVBAvgRN1bzM0q2s1S4oYREEEL0Vb+1kA/6BKb5FjUZMp5VXmy+gzkQ=="
},
"System.Runtime.CompilerServices.Unsafe": {
"type": "Transitive",
"resolved": "4.5.1",
"contentHash": "Zh8t8oqolRaFa9vmOZfdQm/qKejdqz0J9kr7o2Fu0vPeoH3BL1EOXipKWwkWtLT1JPzjByrF19fGuFlNbmPpiw=="
},
"speckle.connectors.common": {
"type": "Project",
"dependencies": {
"Microsoft.Extensions.DependencyInjection": "[2.2.0, )",
"Speckle.Connectors.Logging": "[1.0.0, )",
"Speckle.Objects": "[3.5.4, )",
"Speckle.Sdk": "[3.5.4, )",
"Speckle.Sdk.Dependencies": "[3.5.4, )"
}
},
"speckle.connectors.logging": {
"type": "Project"
},
"Microsoft.Extensions.Logging": {
"type": "CentralTransitive",
"requested": "[2.2.0, )",
"resolved": "2.2.0",
"contentHash": "Nxqhadc9FCmFHzU+fz3oc8sFlE6IadViYg8dfUdGzJZ2JUxnCsRghBhhOWdM4B2zSZqEc+0BjliBh/oNdRZuig==",
"dependencies": {
"Microsoft.Extensions.Configuration.Binder": "2.2.0",
"Microsoft.Extensions.DependencyInjection.Abstractions": "2.2.0",
"Microsoft.Extensions.Logging.Abstractions": "2.2.0",
"Microsoft.Extensions.Options": "2.2.0"
}
},
"Microsoft.Extensions.Logging.Abstractions": {
"type": "CentralTransitive",
"requested": "[2.2.0, )",
"resolved": "2.2.0",
"contentHash": "B2WqEox8o+4KUOpL7rZPyh6qYjik8tHi2tN8Z9jZkHzED8ElYgZa/h6K+xliB435SqUcWT290Fr2aa8BtZjn8A=="
},
"Speckle.DoubleNumerics": {
"type": "CentralTransitive",
"requested": "[4.1.0, )",
"resolved": "4.1.0",
"contentHash": "20DtS+FsDRsOD9+AU3TwNFZ0qrKo5f6f7B5ZR9wStsIHHHC9k7DpjbCvuNtmnSjx54MD+TJC7wV2f5iyGVPj1A=="
},
"Speckle.Sdk.Dependencies": {
"type": "CentralTransitive",
"requested": "[3.5.4, )",
"resolved": "3.5.4",
"contentHash": "d0ZOHiK11Hq9r7YEkfTvVu33ygWtsrgysIWdCRAz6rdlcAgMCEkWVBoe3jDjxdmUy20TToaQlFKfMH4hTyzWXg=="
}
}
}
}
-30
View File
@@ -273,14 +273,6 @@ Project("{D954291E-2A0B-460D-934E-DC6B0785DB48}") = "Speckle.Converters.TeklaSha
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Importers", "Importers", "{0B7587C3-F447-44C0-7126-E1085C8A32F4}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Ifc", "Ifc", "{88E31408-0177-4235-0BE8-6C9C8103E392}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Speckle.Importers.Ifc.Tester2", "Importers\Ifc\Speckle.Importers.Ifc.Tester2\Speckle.Importers.Ifc.Tester2.csproj", "{2209146E-0E51-36BC-A05C-0778B5EEBBA1}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Speckle.Importers.Ifc.Tester", "Importers\Ifc\Speckle.Importers.Ifc.Tester\Speckle.Importers.Ifc.Tester.csproj", "{9DC47E2F-957F-CECC-82C0-1BAD872F8E13}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Speckle.Importers.Ifc", "Importers\Ifc\Speckle.Importers.Ifc\Speckle.Importers.Ifc.csproj", "{9F11639F-3AB6-867F-7968-FFF8BFD8C410}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Rhino", "Rhino", "{8F2BAB74-BA0A-005A-0FF9-9498950E3ADC}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Speckle.Importers.JobProcessor", "Importers\Rhino\Speckle.Importers.JobProcessor\Speckle.Importers.JobProcessor.csproj", "{391676A9-0E05-9346-FDB9-4F5296F00509}"
@@ -702,24 +694,6 @@ Global
{8DCCAE7B-088A-159B-E40D-A7295A7670B8}.Local|Any CPU.Build.0 = Local|Any CPU
{8DCCAE7B-088A-159B-E40D-A7295A7670B8}.Release|Any CPU.ActiveCfg = Release|Any CPU
{8DCCAE7B-088A-159B-E40D-A7295A7670B8}.Release|Any CPU.Build.0 = Release|Any CPU
{2209146E-0E51-36BC-A05C-0778B5EEBBA1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{2209146E-0E51-36BC-A05C-0778B5EEBBA1}.Debug|Any CPU.Build.0 = Debug|Any CPU
{2209146E-0E51-36BC-A05C-0778B5EEBBA1}.Local|Any CPU.ActiveCfg = Local|Any CPU
{2209146E-0E51-36BC-A05C-0778B5EEBBA1}.Local|Any CPU.Build.0 = Local|Any CPU
{2209146E-0E51-36BC-A05C-0778B5EEBBA1}.Release|Any CPU.ActiveCfg = Release|Any CPU
{2209146E-0E51-36BC-A05C-0778B5EEBBA1}.Release|Any CPU.Build.0 = Release|Any CPU
{9DC47E2F-957F-CECC-82C0-1BAD872F8E13}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{9DC47E2F-957F-CECC-82C0-1BAD872F8E13}.Debug|Any CPU.Build.0 = Debug|Any CPU
{9DC47E2F-957F-CECC-82C0-1BAD872F8E13}.Local|Any CPU.ActiveCfg = Local|Any CPU
{9DC47E2F-957F-CECC-82C0-1BAD872F8E13}.Local|Any CPU.Build.0 = Local|Any CPU
{9DC47E2F-957F-CECC-82C0-1BAD872F8E13}.Release|Any CPU.ActiveCfg = Release|Any CPU
{9DC47E2F-957F-CECC-82C0-1BAD872F8E13}.Release|Any CPU.Build.0 = Release|Any CPU
{9F11639F-3AB6-867F-7968-FFF8BFD8C410}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{9F11639F-3AB6-867F-7968-FFF8BFD8C410}.Debug|Any CPU.Build.0 = Debug|Any CPU
{9F11639F-3AB6-867F-7968-FFF8BFD8C410}.Local|Any CPU.ActiveCfg = Local|Any CPU
{9F11639F-3AB6-867F-7968-FFF8BFD8C410}.Local|Any CPU.Build.0 = Local|Any CPU
{9F11639F-3AB6-867F-7968-FFF8BFD8C410}.Release|Any CPU.ActiveCfg = Release|Any CPU
{9F11639F-3AB6-867F-7968-FFF8BFD8C410}.Release|Any CPU.Build.0 = Release|Any CPU
{391676A9-0E05-9346-FDB9-4F5296F00509}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{391676A9-0E05-9346-FDB9-4F5296F00509}.Debug|Any CPU.Build.0 = Debug|Any CPU
{391676A9-0E05-9346-FDB9-4F5296F00509}.Local|Any CPU.ActiveCfg = Local|Any CPU
@@ -939,10 +913,6 @@ Global
{94F25D9A-B6F6-D28E-D0D2-505B0593377D} = {1B231246-B9B0-FA75-34F3-A3EDE5646801}
{AE2D5433-EF5A-C41F-57DA-7F068F42B44E} = {94F25D9A-B6F6-D28E-D0D2-505B0593377D}
{16595D42-4729-C996-36A3-A46843542782} = {94F25D9A-B6F6-D28E-D0D2-505B0593377D}
{88E31408-0177-4235-0BE8-6C9C8103E392} = {0B7587C3-F447-44C0-7126-E1085C8A32F4}
{2209146E-0E51-36BC-A05C-0778B5EEBBA1} = {88E31408-0177-4235-0BE8-6C9C8103E392}
{9DC47E2F-957F-CECC-82C0-1BAD872F8E13} = {88E31408-0177-4235-0BE8-6C9C8103E392}
{9F11639F-3AB6-867F-7968-FFF8BFD8C410} = {88E31408-0177-4235-0BE8-6C9C8103E392}
{8F2BAB74-BA0A-005A-0FF9-9498950E3ADC} = {0B7587C3-F447-44C0-7126-E1085C8A32F4}
{391676A9-0E05-9346-FDB9-4F5296F00509} = {8F2BAB74-BA0A-005A-0FF9-9498950E3ADC}
{A9B240B9-4F3D-DB41-CB33-BD2019BBCCF2} = {8F2BAB74-BA0A-005A-0FF9-9498950E3ADC}
-5
View File
@@ -179,11 +179,6 @@
<Project Path="Converters\Tekla\Speckle.Converters.TeklaShared\Speckle.Converters.TeklaShared.shproj" />
</Folder>
<Folder Name="/Importers/" />
<Folder Name="/Importers/Ifc/">
<Project Path="Importers\Ifc\Speckle.Importers.Ifc.Tester2\Speckle.Importers.Ifc.Tester2.csproj" />
<Project Path="Importers\Ifc\Speckle.Importers.Ifc.Tester\Speckle.Importers.Ifc.Tester.csproj" />
<Project Path="Importers\Ifc\Speckle.Importers.Ifc\Speckle.Importers.Ifc.csproj" />
</Folder>
<Folder Name="/Importers/Rhino/">
<Project Path="Importers\Rhino\Speckle.Importers.JobProcessor\Speckle.Importers.JobProcessor.csproj" Type="C#">
<Configuration Solution="Local|Any CPU" Project="Debug|Any CPU" />
-5
View File
@@ -61,11 +61,6 @@
<Project Path="Converters\Civil3d\Speckle.Converters.Civil3dShared\Speckle.Converters.Civil3dShared.shproj" />
</Folder>
<Folder Name="/Importers/" />
<Folder Name="/Importers/Ifc/">
<Project Path="Importers\Ifc\Speckle.Importers.Ifc.Tester2\Speckle.Importers.Ifc.Tester2.csproj" />
<Project Path="Importers\Ifc\Speckle.Importers.Ifc.Tester\Speckle.Importers.Ifc.Tester.csproj" />
<Project Path="Importers\Ifc\Speckle.Importers.Ifc\Speckle.Importers.Ifc.csproj" />
</Folder>
<Folder Name="/Importers/Rhino/">
<Project Path="Importers\Rhino\Speckle.Importers.JobProcessor\Speckle.Importers.JobProcessor.csproj" Type="C#">
<Configuration Solution="Local|Any CPU" Project="Debug|Any CPU" />
-5
View File
@@ -61,11 +61,6 @@
<Project Path="Converters\Civil3d\Speckle.Converters.Civil3dShared\Speckle.Converters.Civil3dShared.shproj" />
</Folder>
<Folder Name="/Importers/" />
<Folder Name="/Importers/Ifc/">
<Project Path="Importers\Ifc\Speckle.Importers.Ifc.Tester2\Speckle.Importers.Ifc.Tester2.csproj" />
<Project Path="Importers\Ifc\Speckle.Importers.Ifc.Tester\Speckle.Importers.Ifc.Tester.csproj" />
<Project Path="Importers\Ifc\Speckle.Importers.Ifc\Speckle.Importers.Ifc.csproj" />
</Folder>
<Folder Name="/Importers/Rhino/">
<Project Path="Importers\Rhino\Speckle.Importers.JobProcessor\Speckle.Importers.JobProcessor.csproj" Type="C#">
<Configuration Solution="Local|Any CPU" Project="Debug|Any CPU" />
-30
View File
@@ -256,16 +256,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Speckle.Connectors.Naviswor
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Speckle.Connectors.Navisworks2025", "Connectors\Navisworks\Speckle.Connectors.Navisworks2025\Speckle.Connectors.Navisworks2025.csproj", "{7791806E-7531-41D8-9C9D-4A1249D9F99C}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Speckle.Importers.Ifc", "Importers\Ifc\Speckle.Importers.Ifc\Speckle.Importers.Ifc.csproj", "{E6B7A640-F85C-41C9-8226-B5310A98822D}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Ifc", "Ifc", "{F93052A6-6937-443F-8F1F-4A967A8A2BEF}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Importers", "Importers", "{336F0341-5C39-40F7-9377-122FED4E4549}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Speckle.Importers.Ifc.Tester", "Importers\Ifc\Speckle.Importers.Ifc.Tester\Speckle.Importers.Ifc.Tester.csproj", "{FCD6CB79-6B41-4448-99E1-787408AD24B0}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Speckle.Importers.Ifc.Tester2", "Importers\Ifc\Speckle.Importers.Ifc.Tester2\Speckle.Importers.Ifc.Tester2.csproj", "{17FB6920-DF63-4D94-86A4-F1619D501C6D}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Speckle.Connectors.Common.Tests", "Sdk\Speckle.Connectors.Common.Tests\Speckle.Connectors.Common.Tests.csproj", "{F86DFA8A-E2E0-4EBE-9BAF-72AE2698EDC6}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Speckle.Common.MeshTriangulation", "Sdk\Speckle.Common.MeshTriangulation\Speckle.Common.MeshTriangulation.csproj", "{B740A025-1035-4A75-865B-7825857D610C}"
@@ -669,24 +661,6 @@ Global
{7791806E-7531-41D8-9C9D-4A1249D9F99C}.Local|Any CPU.Build.0 = Local|Any CPU
{7791806E-7531-41D8-9C9D-4A1249D9F99C}.Release|Any CPU.ActiveCfg = Release|Any CPU
{7791806E-7531-41D8-9C9D-4A1249D9F99C}.Release|Any CPU.Build.0 = Release|Any CPU
{E6B7A640-F85C-41C9-8226-B5310A98822D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{E6B7A640-F85C-41C9-8226-B5310A98822D}.Debug|Any CPU.Build.0 = Debug|Any CPU
{E6B7A640-F85C-41C9-8226-B5310A98822D}.Local|Any CPU.ActiveCfg = Local|Any CPU
{E6B7A640-F85C-41C9-8226-B5310A98822D}.Local|Any CPU.Build.0 = Local|Any CPU
{E6B7A640-F85C-41C9-8226-B5310A98822D}.Release|Any CPU.ActiveCfg = Release|Any CPU
{E6B7A640-F85C-41C9-8226-B5310A98822D}.Release|Any CPU.Build.0 = Release|Any CPU
{FCD6CB79-6B41-4448-99E1-787408AD24B0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{FCD6CB79-6B41-4448-99E1-787408AD24B0}.Debug|Any CPU.Build.0 = Debug|Any CPU
{FCD6CB79-6B41-4448-99E1-787408AD24B0}.Local|Any CPU.ActiveCfg = Local|Any CPU
{FCD6CB79-6B41-4448-99E1-787408AD24B0}.Local|Any CPU.Build.0 = Local|Any CPU
{FCD6CB79-6B41-4448-99E1-787408AD24B0}.Release|Any CPU.ActiveCfg = Release|Any CPU
{FCD6CB79-6B41-4448-99E1-787408AD24B0}.Release|Any CPU.Build.0 = Release|Any CPU
{17FB6920-DF63-4D94-86A4-F1619D501C6D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{17FB6920-DF63-4D94-86A4-F1619D501C6D}.Debug|Any CPU.Build.0 = Debug|Any CPU
{17FB6920-DF63-4D94-86A4-F1619D501C6D}.Local|Any CPU.ActiveCfg = Debug|Any CPU
{17FB6920-DF63-4D94-86A4-F1619D501C6D}.Local|Any CPU.Build.0 = Debug|Any CPU
{17FB6920-DF63-4D94-86A4-F1619D501C6D}.Release|Any CPU.ActiveCfg = Release|Any CPU
{17FB6920-DF63-4D94-86A4-F1619D501C6D}.Release|Any CPU.Build.0 = Release|Any CPU
{F86DFA8A-E2E0-4EBE-9BAF-72AE2698EDC6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{F86DFA8A-E2E0-4EBE-9BAF-72AE2698EDC6}.Debug|Any CPU.Build.0 = Debug|Any CPU
{F86DFA8A-E2E0-4EBE-9BAF-72AE2698EDC6}.Local|Any CPU.ActiveCfg = Local|Any CPU
@@ -908,10 +882,6 @@ Global
{04FC86A3-2E25-41A1-98C5-10898616CD78} = {19F15419-F493-4D53-83EA-F90869D97D6E}
{FD44E1F0-D20A-49B6-ADC9-482D911A74FB} = {91DCAFB0-283B-4B07-9F6F-7335DECEEB08}
{7791806E-7531-41D8-9C9D-4A1249D9F99C} = {A88CFA1F-B2D5-4DBE-8496-68D0AFA46F2D}
{E6B7A640-F85C-41C9-8226-B5310A98822D} = {F93052A6-6937-443F-8F1F-4A967A8A2BEF}
{F93052A6-6937-443F-8F1F-4A967A8A2BEF} = {336F0341-5C39-40F7-9377-122FED4E4549}
{FCD6CB79-6B41-4448-99E1-787408AD24B0} = {F93052A6-6937-443F-8F1F-4A967A8A2BEF}
{17FB6920-DF63-4D94-86A4-F1619D501C6D} = {F93052A6-6937-443F-8F1F-4A967A8A2BEF}
{F86DFA8A-E2E0-4EBE-9BAF-72AE2698EDC6} = {2E00592E-558D-492D-88F9-3ECEE4C0C7DA}
{B740A025-1035-4A75-865B-7825857D610C} = {2E00592E-558D-492D-88F9-3ECEE4C0C7DA}
{65230E97-8EBA-4594-8A17-2847C5E2B459} = {2E00592E-558D-492D-88F9-3ECEE4C0C7DA}
-5
View File
@@ -179,11 +179,6 @@
<Project Path="Converters\Tekla\Speckle.Converters.TeklaShared\Speckle.Converters.TeklaShared.shproj" />
</Folder>
<Folder Name="/Importers/" />
<Folder Name="/Importers/Ifc/">
<Project Path="Importers\Ifc\Speckle.Importers.Ifc.Tester2\Speckle.Importers.Ifc.Tester2.csproj" />
<Project Path="Importers\Ifc\Speckle.Importers.Ifc.Tester\Speckle.Importers.Ifc.Tester.csproj" />
<Project Path="Importers\Ifc\Speckle.Importers.Ifc\Speckle.Importers.Ifc.csproj" />
</Folder>
<Folder Name="/Importers/Rhino/">
<Project Path="Importers\Rhino\Speckle.Importers.JobProcessor\Speckle.Importers.JobProcessor.csproj" Type="Classic C#">
<Configuration Solution="Local|Any CPU" Project="Debug|Any CPU" />
-5
View File
@@ -37,11 +37,6 @@
<Project Path="Converters\CSi\Speckle.Converters.ETABSShared\Speckle.Converters.ETABSShared.shproj" />
</Folder>
<Folder Name="/Importers/" />
<Folder Name="/Importers/Ifc/">
<Project Path="Importers\Ifc\Speckle.Importers.Ifc.Tester2\Speckle.Importers.Ifc.Tester2.csproj" />
<Project Path="Importers\Ifc\Speckle.Importers.Ifc.Tester\Speckle.Importers.Ifc.Tester.csproj" />
<Project Path="Importers\Ifc\Speckle.Importers.Ifc\Speckle.Importers.Ifc.csproj" />
</Folder>
<Folder Name="/Importers/Rhino/">
<Project Path="Importers\Rhino\Speckle.Importers.JobProcessor\Speckle.Importers.JobProcessor.csproj" Type="C#">
<Configuration Solution="Local|Any CPU" Project="Debug|Any CPU" />
-5
View File
@@ -57,11 +57,6 @@
<Project Path="Converters\Navisworks\Speckle.Converters.NavisworksShared\Speckle.Converters.NavisworksShared.shproj" />
</Folder>
<Folder Name="/Importers/" />
<Folder Name="/Importers/Ifc/">
<Project Path="Importers\Ifc\Speckle.Importers.Ifc.Tester2\Speckle.Importers.Ifc.Tester2.csproj" />
<Project Path="Importers\Ifc\Speckle.Importers.Ifc.Tester\Speckle.Importers.Ifc.Tester.csproj" />
<Project Path="Importers\Ifc\Speckle.Importers.Ifc\Speckle.Importers.Ifc.csproj" />
</Folder>
<Folder Name="/Importers/Rhino/">
<Project Path="Importers\Rhino\Speckle.Importers.JobProcessor\Speckle.Importers.JobProcessor.csproj" Type="C#">
<Configuration Solution="Local|Any CPU" Project="Debug|Any CPU" />
-5
View File
@@ -52,11 +52,6 @@
<Project Path="Converters\Revit\Speckle.Converters.RevitShared\Speckle.Converters.RevitShared.shproj" />
</Folder>
<Folder Name="/Importers/" />
<Folder Name="/Importers/Ifc/">
<Project Path="Importers\Ifc\Speckle.Importers.Ifc.Tester2\Speckle.Importers.Ifc.Tester2.csproj" />
<Project Path="Importers\Ifc\Speckle.Importers.Ifc.Tester\Speckle.Importers.Ifc.Tester.csproj" />
<Project Path="Importers\Ifc\Speckle.Importers.Ifc\Speckle.Importers.Ifc.csproj" />
</Folder>
<Folder Name="/Importers/Rhino/">
<Project Path="Importers\Rhino\Speckle.Importers.JobProcessor\Speckle.Importers.JobProcessor.csproj" Type="C#">
<Configuration Solution="Local|Any CPU" Project="Debug|Any CPU" />
-5
View File
@@ -52,11 +52,6 @@
<Project Path="Converters\Revit\Speckle.Converters.RevitShared\Speckle.Converters.RevitShared.shproj" />
</Folder>
<Folder Name="/Importers/" />
<Folder Name="/Importers/Ifc/">
<Project Path="Importers\Ifc\Speckle.Importers.Ifc.Tester2\Speckle.Importers.Ifc.Tester2.csproj" />
<Project Path="Importers\Ifc\Speckle.Importers.Ifc.Tester\Speckle.Importers.Ifc.Tester.csproj" />
<Project Path="Importers\Ifc\Speckle.Importers.Ifc\Speckle.Importers.Ifc.csproj" />
</Folder>
<Folder Name="/Importers/Rhino/">
<Project Path="Importers\Rhino\Speckle.Importers.JobProcessor\Speckle.Importers.JobProcessor.csproj" Type="C#">
<Configuration Solution="Local|Any CPU" Project="Debug|Any CPU" />
-5
View File
@@ -41,11 +41,6 @@
<Project Path="Converters\Rhino\Speckle.Converters.RhinoShared\Speckle.Converters.RhinoShared.shproj" />
</Folder>
<Folder Name="/Importers/" />
<Folder Name="/Importers/Ifc/">
<Project Path="Importers\Ifc\Speckle.Importers.Ifc.Tester2\Speckle.Importers.Ifc.Tester2.csproj" />
<Project Path="Importers\Ifc\Speckle.Importers.Ifc.Tester\Speckle.Importers.Ifc.Tester.csproj" />
<Project Path="Importers\Ifc\Speckle.Importers.Ifc\Speckle.Importers.Ifc.csproj" />
</Folder>
<Folder Name="/Importers/Rhino/">
<Project Path="Importers\Rhino\Speckle.Importers.JobProcessor\Speckle.Importers.JobProcessor.csproj" Type="C#">
<Configuration Solution="Local|Any CPU" Project="Debug|Any CPU" />
-5
View File
@@ -41,11 +41,6 @@
<Project Path="Converters\Tekla\Speckle.Converters.TeklaShared\Speckle.Converters.TeklaShared.shproj" />
</Folder>
<Folder Name="/Importers/" />
<Folder Name="/Importers/Ifc/">
<Project Path="Importers\Ifc\Speckle.Importers.Ifc.Tester2\Speckle.Importers.Ifc.Tester2.csproj" />
<Project Path="Importers\Ifc\Speckle.Importers.Ifc.Tester\Speckle.Importers.Ifc.Tester.csproj" />
<Project Path="Importers\Ifc\Speckle.Importers.Ifc\Speckle.Importers.Ifc.csproj" />
</Folder>
<Folder Name="/Importers/Rhino/">
<Project Path="Importers\Rhino\Speckle.Importers.JobProcessor\Speckle.Importers.JobProcessor.csproj" Type="C#">
<Configuration Solution="Local|Any CPU" Project="Debug|Any CPU" />