Jedd's IFC improvements (#510)

* ifc safe

* reverted LibraryImport as it would need more testing

* IFC app ids
This commit is contained in:
Jedd Morgan
2025-02-17 16:35:26 +00:00
committed by GitHub
parent f882b0f5bd
commit 6f03aa8678
22 changed files with 553 additions and 47 deletions
@@ -0,0 +1,33 @@
using Ara3D.Utils;
using Microsoft.Extensions.DependencyInjection;
using Speckle.Importers.Ifc;
using Speckle.Importers.Ifc.Ara3D.IfcParser;
using Speckle.Importers.Ifc.Converters;
using Speckle.Importers.Ifc.Tester2;
using Speckle.Importers.Ifc.Types;
using Speckle.Objects.Geometry;
using Speckle.Sdk.Host;
using Speckle.Sdk.Models;
// Settings
var filePath = new FilePath(@"C:\Users\Jedd\Desktop\231110AC11-Institute-Var-2-IFC.ifc");
const string PROJECT_ID = "f3a42bdf24";
// Setup
TypeLoader.Initialize(typeof(Base).Assembly, typeof(Point).Assembly);
var serviceCollection = new ServiceCollection();
serviceCollection.AddIFCImporter();
serviceCollection.AddSingleton<Sender>();
var serviceProvider = serviceCollection.BuildServiceProvider();
// Convert IFC to Speckle Objects
var ifcFactory = serviceProvider.GetRequiredService<IIfcFactory>();
var model = ifcFactory.Open(filePath);
var graph = IfcGraph.Load(new FilePath(filePath));
var converter = serviceProvider.GetRequiredService<IGraphConverter>();
var b = converter.Convert(model, graph);
//Send Speckle Objects to server
var sender = serviceProvider.GetRequiredService<Sender>();
await sender.Send(b, PROJECT_ID);
@@ -0,0 +1,48 @@
using Speckle.Sdk.Api;
using Speckle.Sdk.Api.GraphQL.Inputs;
using Speckle.Sdk.Api.GraphQL.Models;
using Speckle.Sdk.Common;
using Speckle.Sdk.Credentials;
using Speckle.Sdk.Models;
using Version = Speckle.Sdk.Api.GraphQL.Models.Version;
namespace Speckle.Importers.Ifc.Tester2;
public class Sender(IClientFactory clientFactory, IAccountManager accountManager, IOperations operations)
{
public const string MODEL_NAME = "IFC Import";
public async Task<Version> Send(Base rootObject, string projectId, CancellationToken cancellationToken = default)
{
var account = accountManager.GetDefaultAccount().NotNull();
using var client = clientFactory.Create(account);
var res = await operations.Send2(
new(account.serverInfo.url),
projectId,
account.token,
rootObject,
null,
cancellationToken
);
var t = await GetOrCreateIfcModel(client, projectId);
CreateVersionInput input = new(res.RootId, t.id, projectId);
return await client.Version.Create(input, cancellationToken);
}
public async Task<Model> GetOrCreateIfcModel(Client client, string projectId)
{
ProjectModelsFilter filter = new(null, null, null, null, MODEL_NAME, null);
var existing = await client.Model.GetModels(projectId, 1, modelsFilter: filter);
if (existing.items.Count != 0)
{
return existing.items[0];
}
CreateModelInput input = new(MODEL_NAME, null, projectId);
return await client.Model.Create(input);
}
}
@@ -0,0 +1,11 @@
<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>
@@ -0,0 +1,308 @@
{
"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.CSharp": {
"type": "Transitive",
"resolved": "4.7.0",
"contentHash": "pTj+D3uJWyN3My70i2Hqo+OXixq3Os2D1nJ2x92FFo6sk8fYS1m1WLNTs0Dc1uPaViH0YvEEwvzddQ7y4rhXmA=="
},
"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": "2.2.0",
"contentHash": "f9hstgjVmr6rmrfGSpfsVOl2irKAgr1QjrSi3FgnS7kulxband50f2brRLwySAQTADPZeTdow0mpSMcoAdadCw=="
},
"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.importers.ifc": {
"type": "Project",
"dependencies": {
"Ara3D.Buffers": "[1.4.5, )",
"Ara3D.Logging": "[1.4.5, )",
"Ara3D.Utils": "[1.4.5, )",
"Microsoft.Extensions.DependencyInjection": "[2.2.0, )",
"Speckle.Objects": "[3.1.0-dev.255, )",
"Speckle.Sdk": "[3.1.0-dev.255, )"
}
},
"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": "2.2.0",
"contentHash": "MZtBIwfDFork5vfjpJdG5g8wuJFt7d/y3LOSVVtDK/76wlbtz6cjltfKHqLx2TKVqTj5/c41t77m1+h20zqtPA==",
"dependencies": {
"Microsoft.Extensions.DependencyInjection.Abstractions": "2.2.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.0.1",
"contentHash": "MzEQ1Im0zTja+tEsdRIk/WlPiKqb22NmTOJcR1ZKm/mz46pezyyID3/wRz6vJUELMpSLnG7LhsxBL+nxbr7V0w=="
},
"Speckle.Objects": {
"type": "CentralTransitive",
"requested": "[3.1.0-dev.255, )",
"resolved": "3.1.0-dev.255",
"contentHash": "0S9YVdu5nx7SYS0y5Gq1nwCbxfYB2UxsUUCskaGmzRAm+QzHGqCLYHgadz7Sw5mNAF3bOTLVrOYMzyLAWFWxJA==",
"dependencies": {
"Speckle.Sdk": "3.1.0-dev.255"
}
},
"Speckle.Sdk": {
"type": "CentralTransitive",
"requested": "[3.1.0-dev.255, )",
"resolved": "3.1.0-dev.255",
"contentHash": "TsFpIv8ipvOD/r0se1XmcNPo7t5dWVadwV32Z6vUqoW3s94VIE54/ZTHNkRCEYHFhfOyTcFfbLegiei+0D13bQ==",
"dependencies": {
"GraphQL.Client": "6.0.0",
"Microsoft.CSharp": "4.7.0",
"Microsoft.Data.Sqlite": "[7.0.5]",
"Microsoft.Extensions.DependencyInjection.Abstractions": "[2.2.0]",
"Microsoft.Extensions.Logging": "[2.2.0]",
"Speckle.DoubleNumerics": "4.0.1",
"Speckle.Newtonsoft.Json": "13.0.2",
"Speckle.Sdk.Dependencies": "3.1.0-dev.255"
}
},
"Speckle.Sdk.Dependencies": {
"type": "CentralTransitive",
"requested": "[3.1.0-dev.255, )",
"resolved": "3.1.0-dev.255",
"contentHash": "koFeWc/EB2XrMH2aKl2Hqwrqk/fAGYEVKgxFlFpnEAsbZf7Kk57gBQ3ViV5l6X9vqMHGWFc4dWUp24diq/XPtQ=="
}
}
}
}
@@ -1,20 +1,20 @@
using Speckle.Importers.Ifc.Types;
using Speckle.InterfaceGenerator;
using Speckle.Sdk.Models.Collections;
using Speckle.Sdk.Models;
namespace Speckle.Importers.Ifc.Converters;
[GenerateAutoInterface]
public class GeometryConverter(IMeshConverter meshConverter) : IGeometryConverter
{
public Collection Convert(IfcGeometry geometry)
public IList<Base> Convert(IfcGeometry geometry)
{
var c = new Collection();
List<Base> ret = new();
foreach (var mesh in geometry.GetMeshes())
{
c.elements.Add(meshConverter.Convert(mesh));
ret.Add(meshConverter.Convert(mesh));
}
return c;
return ret;
}
}
@@ -1,4 +1,5 @@
using Speckle.Importers.Ifc.Ara3D.IfcParser;
using Speckle.Importers.Ifc.Services;
using Speckle.Importers.Ifc.Types;
using Speckle.InterfaceGenerator;
using Speckle.Sdk.Models;
@@ -7,13 +8,18 @@ using Speckle.Sdk.Models.Collections;
namespace Speckle.Importers.Ifc.Converters;
[GenerateAutoInterface]
public class GraphConverter(INodeConverter nodeConverter) : IGraphConverter
public class GraphConverter(INodeConverter nodeConverter, IRenderMaterialProxyManager proxyManager) : IGraphConverter
{
public Base Convert(IfcModel model, IfcGraph graph)
{
var collection = new Collection();
var children = graph.GetSources().Select(x => nodeConverter.Convert(model, x)).ToList();
collection.elements = children;
//Grabing materials from ProxyManager
collection["renderMaterialProxies"] = proxyManager.RenderMaterialProxies.Values.ToList();
return collection;
}
}
@@ -1,31 +1,35 @@
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 class MeshConverter : IMeshConverter
public class MeshConverter(IRenderMaterialProxyManager renderMaterialManager) : IMeshConverter
{
public unsafe Mesh Convert(IfcMesh mesh)
public Mesh Convert(IfcMesh mesh)
{
var m = (double*)mesh.Transform;
var vp = mesh.GetVertices();
var ip = mesh.GetIndexes();
var m = mesh.Transform;
var vp = mesh.Vertices;
var ip = mesh.Indices;
var vertices = new List<double>(mesh.VertexCount * 3);
for (var i = 0; i < mesh.VertexCount; i++)
var vertices = new List<double>(vp.Length * 3);
foreach (var vertex in vp)
{
var x = vp[i].PX;
var y = vp[i].PY;
var z = vp[i].PZ;
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>(mesh.IndexCount * 4);
for (var i = 0; i < mesh.IndexCount; i += 3)
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];
@@ -36,14 +40,35 @@ public class MeshConverter : IMeshConverter
faces.Add(c);
}
var color = mesh.GetColor();
List<int> colors = [(int)(color->A * 255), (int)(color->R * 255), (int)(color->G * 255), (int)(color->B * 255),];
return new Mesh()
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()
{
colors = colors,
vertices = vertices,
faces = faces,
units = "m",
applicationId = name,
name = name,
diffuse = diffuse.ToArgb(),
opacity = color.A
};
static int To8BitValue(double value) => (int)(value * 255);
}
}
@@ -37,8 +37,8 @@ public class NodeConverter(IGeometryConverter geometryConverter) : INodeConverte
if (geo != null)
{
var c = geometryConverter.Convert(geo);
if (c.elements.Count > 0)
b["@displayValue"] = c.elements;
if (c.Count > 0)
b["@displayValue"] = c;
}
// Create the children
@@ -39,10 +39,15 @@ public static class Import
{
TypeLoader.Initialize(typeof(Base).Assembly, typeof(Point).Assembly);
var serviceCollection = new ServiceCollection();
serviceCollection.AddIFCImporter();
return serviceCollection.BuildServiceProvider();
}
public static void AddIFCImporter(this ServiceCollection serviceCollection)
{
serviceCollection.AddSpeckleSdk(HostApplications.Other, HostAppVersion.v2024, "IFC-Importer");
serviceCollection.AddSpeckleWebIfc();
serviceCollection.AddMatchingInterfacesAsTransient(Assembly.GetExecutingAssembly());
return serviceCollection.BuildServiceProvider();
}
public static async Task<string> Ifc(
@@ -4,12 +4,11 @@ using System.Runtime.InteropServices;
namespace Speckle.Importers.Ifc.Native;
[SuppressMessage("Globalization", "CA2101:Specify marshaling for P/Invoke string arguments")]
[SuppressMessage("Interoperability", "CA1401:P/Invokes should not be visible")]
[SuppressMessage("Security", "CA5393:Do not use unsafe DllImportSearchPath value")]
public static class WebIfc
internal static class WebIfc
{
#if WINDOWS
private const string DllName = "web-ifc.dll";
private const string DllName = "Native/web-ifc.dll";
private const CharSet Set = CharSet.Ansi;
#else
private const string DllName = "libweb-ifc.so";
@@ -1,6 +1,7 @@
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;
@@ -11,6 +12,7 @@ public static class ServiceRegistration
public static void AddSpeckleWebIfc(this IServiceCollection services)
{
services.AddSingleton<IIfcFactory, IfcFactory>();
services.AddSingleton<IRenderMaterialProxyManager, RenderMaterialProxyManager>();
}
public static IServiceCollection AddMatchingInterfacesAsTransient(
@@ -0,0 +1,27 @@
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 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, });
}
}
}
@@ -3,9 +3,9 @@ using System.Runtime.InteropServices;
namespace Speckle.Importers.Ifc.Types;
[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct IfcColor
public readonly struct IfcColor
{
public double R,
public readonly double R,
G,
B,
A;
@@ -3,7 +3,7 @@ using Speckle.InterfaceGenerator;
namespace Speckle.Importers.Ifc.Types;
[GenerateAutoInterface]
public class IfcFactory : IIfcFactory
public sealed class IfcFactory : IIfcFactory
{
//probably never disposing this
private static readonly IntPtr _ptr = Importers.Ifc.Native.WebIfc.InitializeApi();
@@ -1,6 +1,6 @@
namespace Speckle.Importers.Ifc.Types;
public class IfcGeometry(IntPtr geometry)
public sealed class IfcGeometry(IntPtr geometry)
{
public IfcMesh GetMesh(int i) => new(Importers.Ifc.Native.WebIfc.GetMesh(geometry, i));
@@ -1,6 +1,6 @@
namespace Speckle.Importers.Ifc.Types;
public class IfcLine(IntPtr line)
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);
@@ -1,15 +1,40 @@
using System.Runtime.InteropServices;
using Speckle.Importers.Ifc.Native;
namespace Speckle.Importers.Ifc.Types;
public class IfcMesh(IntPtr mesh)
public sealed class IfcMesh(IntPtr mesh)
{
public int VertexCount => Importers.Ifc.Native.WebIfc.GetNumVertices(mesh);
public int VerticesCount => WebIfc.GetNumVertices(mesh);
public unsafe IfcVertex* GetVertices() => (IfcVertex*)Importers.Ifc.Native.WebIfc.GetVertices(mesh);
public unsafe ReadOnlySpan<IfcVertex> Vertices
{
get
{
IfcVertex* ptr = (IfcVertex*)WebIfc.GetVertices(mesh);
return new ReadOnlySpan<IfcVertex>(ptr, VerticesCount);
}
}
public IntPtr Transform => Importers.Ifc.Native.WebIfc.GetTransform(mesh);
public int IndexCount => Importers.Ifc.Native.WebIfc.GetNumIndices(mesh);
public unsafe ReadOnlySpan<double> Transform
{
get
{
double* ptr = (double*)WebIfc.GetTransform(mesh);
return new ReadOnlySpan<double>(ptr, 16);
}
}
public unsafe int* GetIndexes() => (int*)Importers.Ifc.Native.WebIfc.GetIndices(mesh);
public int IndicesCount => WebIfc.GetNumIndices(mesh);
public unsafe IfcColor* GetColor() => (IfcColor*)Importers.Ifc.Native.WebIfc.GetColor(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,6 +1,6 @@
namespace Speckle.Importers.Ifc.Types;
public class IfcModel(IntPtr model)
public sealed class IfcModel(IntPtr model)
{
public int GetNumGeometries() => Importers.Ifc.Native.WebIfc.GetNumGeometries(model);
@@ -3,12 +3,12 @@ using System.Runtime.InteropServices;
namespace Speckle.Importers.Ifc.Types;
[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct IfcVertex
public readonly struct IfcVertex
{
public double PX,
public readonly double PX,
PY,
PZ;
public double NX,
public readonly double NX,
NY,
NZ;
}
+8
View File
@@ -269,6 +269,7 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Speckle.Importers.Ifc", "Im
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Speckle.Importers.Ifc.Tester", "Importers\Ifc\Speckle.Importers.Ifc.Tester\Speckle.Importers.Ifc.Tester.csproj", "{B3B126CA-A419-48D1-B117-6DEE1DE1AFAD}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Speckle.Importers.Ifc.Tester2", "Importers\Ifc\Speckle.Importers.Ifc.Tester2\Speckle.Importers.Ifc.Tester2.csproj", "{867DC1A5-A886-4F49-8665-793EB9832F9E}"
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Speckle.Connectors.Common.Tests", "Sdk\Speckle.Connectors.Common.Tests\Speckle.Connectors.Common.Tests.csproj", "{C19C3EDF-D95D-4D22-9949-D99F91447AE7}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Speckle.Common.MeshTriangulation", "Sdk\Speckle.Common.MeshTriangulation\Speckle.Common.MeshTriangulation.csproj", "{20BB9687-2C92-44E9-9E2F-9D2F45641354}"
@@ -694,6 +695,12 @@ Global
{B3B126CA-A419-48D1-B117-6DEE1DE1AFAD}.Local|Any CPU.Build.0 = Local|Any CPU
{B3B126CA-A419-48D1-B117-6DEE1DE1AFAD}.Release|Any CPU.ActiveCfg = Release|Any CPU
{B3B126CA-A419-48D1-B117-6DEE1DE1AFAD}.Release|Any CPU.Build.0 = Release|Any CPU
{867DC1A5-A886-4F49-8665-793EB9832F9E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{867DC1A5-A886-4F49-8665-793EB9832F9E}.Debug|Any CPU.Build.0 = Debug|Any CPU
{867DC1A5-A886-4F49-8665-793EB9832F9E}.Local|Any CPU.ActiveCfg = Debug|Any CPU
{867DC1A5-A886-4F49-8665-793EB9832F9E}.Local|Any CPU.Build.0 = Debug|Any CPU
{867DC1A5-A886-4F49-8665-793EB9832F9E}.Release|Any CPU.ActiveCfg = Release|Any CPU
{867DC1A5-A886-4F49-8665-793EB9832F9E}.Release|Any CPU.Build.0 = Release|Any CPU
{C19C3EDF-D95D-4D22-9949-D99F91447AE7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{C19C3EDF-D95D-4D22-9949-D99F91447AE7}.Debug|Any CPU.Build.0 = Debug|Any CPU
{C19C3EDF-D95D-4D22-9949-D99F91447AE7}.Local|Any CPU.ActiveCfg = Local|Any CPU
@@ -829,6 +836,7 @@ Global
{0EF6C4D6-AC76-408F-8D32-2F9DA8006077} = {24750B06-C90D-43B1-B2E4-088D531D6748}
{9FD99F9B-8D50-4C7A-B3A6-22E28AB5F26B} = {0EF6C4D6-AC76-408F-8D32-2F9DA8006077}
{B3B126CA-A419-48D1-B117-6DEE1DE1AFAD} = {0EF6C4D6-AC76-408F-8D32-2F9DA8006077}
{867DC1A5-A886-4F49-8665-793EB9832F9E} = {0EF6C4D6-AC76-408F-8D32-2F9DA8006077}
{C19C3EDF-D95D-4D22-9949-D99F91447AE7} = {2E00592E-558D-492D-88F9-3ECEE4C0C7DA}
{20BB9687-2C92-44E9-9E2F-9D2F45641354} = {2E00592E-558D-492D-88F9-3ECEE4C0C7DA}
EndGlobalSection
+8
View File
@@ -277,6 +277,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Importers", "Importers", "{
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}"
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}"
@@ -684,6 +685,12 @@ Global
{FCD6CB79-6B41-4448-99E1-787408AD24B0}.Local|Any CPU.Build.0 = Debug|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 = Debug|Any CPU
@@ -819,6 +826,7 @@ Global
{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}
EndGlobalSection
+1
View File
@@ -1,4 +1,5 @@
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=DUI/@EntryIndexedValue">DUI</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=IFC/@EntryIndexedValue">IFC</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=UI/@EntryIndexedValue">UI</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=URI/@EntryIndexedValue">URI</s:String></wpf:ResourceDictionary>