Compare commits

32 Commits

Author SHA1 Message Date
Jedd Morgan 24cc8fabbb Update README.md
.NET Build and Publish / build (push) Has been cancelled
2025-04-04 13:17:20 +01:00
Adam Hathcock 6809de16cb Merge pull request #5 from specklesystems/add-send-memory-fix
Update SDK and version to have send memory fix
2024-12-13 11:17:54 +00:00
Adam Hathcock 851b2cede1 Update SDK and version to have send memory fix 2024-12-13 11:16:24 +00:00
Adam Hathcock 793dcf8cf3 Merge pull request #4 from specklesystems/alan/misc-importer-fixes
Detachment and SDK updates for importer fixes
2024-12-11 09:20:12 +00:00
Adam Hathcock 391f49363f fix tester? 2024-12-11 08:25:59 +00:00
Adam Hathcock 60f70db08b reuse linux speckle and update version 2024-12-10 11:47:28 +00:00
Adam Hathcock 2db980e234 update SDK and format 2024-12-10 11:45:22 +00:00
Adam Hathcock 61f7f3fb79 more work to support latest SDK 2024-12-10 09:42:07 +00:00
Adam Hathcock ded649130a Fix up testing 2024-12-09 10:07:51 +00:00
Alan Rynne ca5b1dbb92 fix: CXPLA-137 NodeConverter detaches elements and displayValue 2024-12-05 17:37:34 +01:00
Alan Rynne 6a40a1ed99 fix: CXPLA-140 Mesh now uses correct face index 2024-12-05 17:37:16 +01:00
Alan Rynne b18cf0fa2c fix: CXPLA-136 Graph converter detached elements 2024-12-05 17:36:50 +01:00
Adam Hathcock 4c5ef03043 Merge pull request #3 from specklesystems/fix-restore
Fix restore
2024-11-28 10:20:59 +00:00
Adam Hathcock 409456f10a Merge branch 'main' into fix-restore 2024-11-28 10:20:03 +00:00
Adam Hathcock 003ce1e9da fix PR builds 2024-11-28 10:18:50 +00:00
Adam Hathcock 14cc98c7f5 tester needs different hash 2024-11-28 10:16:50 +00:00
Adam Hathcock 8890342dcf Revert "fix restore?"
This reverts commit 431841c520.
2024-11-28 10:16:06 +00:00
Adam Hathcock 431841c520 fix restore? 2024-11-28 10:14:23 +00:00
Adam Hathcock 8a978e8ea2 Merge pull request #2 from specklesystems/ignore-whitespace-fixes
Update from Ara3D that fixes whitespace and double quote issues
2024-11-28 10:13:02 +00:00
Adam Hathcock 60487ed801 bump version 2024-11-28 10:11:37 +00:00
Adam Hathcock 111da644d2 add PR build 2024-11-28 10:04:58 +00:00
Adam Hathcock 36bbf556fc update IFC doc parser to better handle whitespace and double quotes in IFC 2024-11-28 10:01:28 +00:00
Adam Hathcock 6a807c8e00 add tester files 2024-11-28 09:59:46 +00:00
Adam Hathcock 33a1e304d7 revert package lock 2024-11-26 10:47:13 +00:00
Adam Hathcock ae5e952483 update SDK 2024-11-26 10:39:04 +00:00
Adam Hathcock 38265d69d3 return the commit id 2024-11-21 12:05:38 +00:00
adamhathcock 13a7ea5aee try new version 2024-11-20 09:46:00 +00:00
adamhathcock 24a407be69 doesn't like the bash file 2024-11-20 09:33:35 +00:00
adamhathcock f5c80f7734 add pack for importer 2024-11-20 09:32:27 +00:00
Adam Hathcock 729f13d4e0 use main branch 2024-11-20 08:36:56 +00:00
Adam Hathcock 5cfa160d93 add github actions 2024-11-20 08:35:10 +00:00
Adam Hathcock 80eeadb411 Merge pull request #1 from specklesystems/use-ara3d
use ara3d stuff
2024-11-20 08:32:35 +00:00
36 changed files with 821 additions and 262 deletions
+13
View File
@@ -0,0 +1,13 @@
# To get started with Dependabot version updates, you'll need to specify which
# package ecosystems to update and where the package manifests are located.
# Please see the documentation for all configuration options:
# https://docs.github.com/code-security/dependabot/dependabot-version-updates/configuration-options-for-the-dependabot.yml-file
version: 2
updates:
- package-ecosystem: "npm" # See documentation for possible values
directory: "/" # Location of package manifests
schedule:
interval: "daily"
allow:
- dependency-type: "all"
+30
View File
@@ -0,0 +1,30 @@
name: .NET Build and Publish
on:
push:
branches: ["main"]
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Setup .NET
uses: actions/setup-dotnet@v4
with:
dotnet-version: 8.x.x
- uses: actions/cache@v4
with:
path: ~/.nuget/packages
key: ${{ runner.os }}-nuget-${{ hashFiles('**/packages.lock.json') }}
- name: 🔫 Build and Pack
run: dotnet run --project src/build/build.csproj -- pack
- name: Push to nuget.org
run: dotnet nuget push output/*.nupkg --source "https://api.nuget.org/v3/index.json" --api-key ${{secrets.CONNECTORS_NUGET_TOKEN }} --skip-duplicate
+26
View File
@@ -0,0 +1,26 @@
name: .NET Build
on:
pull_request:
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Setup .NET
uses: actions/setup-dotnet@v4
with:
dotnet-version: 8.x.x
- uses: actions/cache@v4
with:
path: ~/.nuget/packages
key: ${{ runner.os }}-nuget-${{ hashFiles('**/packages.lock.json') }}
- name: 🔫 Build
run: dotnet run --project src/build/build.csproj -- build
+2 -1
View File
@@ -2,4 +2,5 @@
.idea/
bin/
obj/
publish/
publish/
output/
+2
View File
@@ -1 +1,3 @@
# speckle-ifc-import
The code in this repo has been migrated to https://github.com/specklesystems/speckle-sharp-connectors/tree/dev/Importers/Ifc/Speckle.Importers.Ifc
+4 -4
View File
@@ -7,12 +7,12 @@
<PackageVersion Include="Glob" Version="1.1.9" />
<PackageVersion Include="Microsoft.Extensions.DependencyInjection" Version="8.0.1" />
<PackageVersion Include="SimpleExec" Version="12.0.0" />
<PackageVersion Include="Speckle.Objects" Version="3.1.0-dev.186" />
<PackageVersion Include="Speckle.Sdk" Version="3.1.0-dev.186" />
<PackageVersion Include="Speckle.Sdk.Dependencies" Version="3.1.0-dev.186" />
<PackageVersion Include="Speckle.Objects" Version="3.1.0-dev.216" />
<PackageVersion Include="Speckle.Sdk" Version="3.1.0-dev.216" />
<PackageVersion Include="Speckle.Sdk.Dependencies" Version="3.1.0-dev.216" />
<PackageVersion Include="Speckle.WebIfc" Version="0.0.64-speckle1" />
<PackageVersion Include="System.CommandLine" Version="2.0.0-beta4.22272.1" />
<GlobalPackageReference Include="Microsoft.SourceLink.GitHub" Version="8.0.0" />
<GlobalPackageReference Include="Speckle.InterfaceGenerator" Version="0.9.6" />
</ItemGroup>
</Project>
</Project>
@@ -0,0 +1,24 @@
using Speckle.Sdk.SQLite;
namespace Speckle.Importer.Tester;
public class DummySendCacheManager(Dictionary<string, string> objects) : ISqLiteJsonCacheManager
{
public IEnumerable<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;
public void SaveObjects(IEnumerable<(string id, string json)> items)
{
foreach (var (id, json) in items)
{
objects[id] = json;
}
}
}
@@ -0,0 +1,43 @@
using System.Text;
using Speckle.Sdk.Serialisation.V2;
using Speckle.Sdk.Serialisation.V2.Send;
using Speckle.Sdk.Transports;
namespace Speckle.Importer.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
) => throw new NotImplementedException();
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;
}
}
+50
View File
@@ -0,0 +1,50 @@
using System.Diagnostics;
using Ara3D.IfcParser;
using Ara3D.Utils;
using Microsoft.Extensions.DependencyInjection;
using Speckle.Importer.Tester;
using Speckle.Sdk.Serialisation.V2.Send;
using Speckle.WebIfc.Importer;
using Speckle.WebIfc.Importer.Converters;
using Speckle.WebIfc.Importer.Ifc;
var serviceProvider = Import.GetServiceProvider();
var filePath = new FilePath(
"C:\\Users\\adam\\Git\\speckle-server\\packages\\fileimport-service\\ifc-dotnet\\ifcs\\20210221PRIMARK.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 objects = new Dictionary<string, string>();
var process2 = new SerializeProcess(
new Progress(true),
new DummySendCacheManager(objects),
new DummyServerObjectManager(),
new BaseChildFinder(new BasePropertyGatherer()),
new ObjectSerializerFactory(new BasePropertyGatherer()),
new SerializeProcessOptions(true, true, true, true)
);
Console.ReadLine();
var (rootId, _) = await process2.Serialize(b, default).ConfigureAwait(false);
Console.WriteLine(rootId);
ms2 = stopwatch.ElapsedMilliseconds;
Console.WriteLine($"Converted to JSON: {ms2 - ms} ms");
Console.ReadLine();
+36
View File
@@ -0,0 +1,36 @@
using Speckle.Sdk.Transports;
namespace Speckle.Importer.Tester;
public class Progress(bool write) : IProgress<ProgressArgs>
{
private readonly TimeSpan DEBOUNCE = TimeSpan.FromSeconds(1);
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;
}
}
}
}
@@ -0,0 +1,14 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\Speckle.WebIfc.Importer\Speckle.WebIfc.Importer.csproj" />
</ItemGroup>
</Project>
@@ -0,0 +1,299 @@
{
"version": 2,
"dependencies": {
"net8.0": {
"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"
}
},
"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": "8.0.2",
"contentHash": "3iE7UF7MQkCv1cxzCahz+Y/guQbTqieyxyaWKhrRO91itI9cOKO76OHeQDahqG4MmW5umr3CcCvGmK92lWNlbg=="
},
"Microsoft.Extensions.Logging": {
"type": "Transitive",
"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": "Transitive",
"resolved": "2.2.0",
"contentHash": "B2WqEox8o+4KUOpL7rZPyh6qYjik8tHi2tN8Z9jZkHzED8ElYgZa/h6K+xliB435SqUcWT290Fr2aa8BtZjn8A=="
},
"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.SourceLink.Common": {
"type": "Transitive",
"resolved": "8.0.0",
"contentHash": "dk9JPxTCIevS75HyEQ0E4OVAFhB2N+V9ShCXf8Q6FkUQZDkgLI12y679Nym1YqsiSysuQskT7Z+6nUf3yab6Vw=="
},
"Speckle.DoubleNumerics": {
"type": "Transitive",
"resolved": "4.0.1",
"contentHash": "MzEQ1Im0zTja+tEsdRIk/WlPiKqb22NmTOJcR1ZKm/mz46pezyyID3/wRz6vJUELMpSLnG7LhsxBL+nxbr7V0w=="
},
"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.webifc.importer": {
"type": "Project",
"dependencies": {
"Ara3D.Buffers": "[1.4.5, )",
"Ara3D.Logging": "[1.4.5, )",
"Ara3D.Utils": "[1.4.5, )",
"Microsoft.Extensions.DependencyInjection": "[8.0.1, )",
"Speckle.Objects": "[3.1.0-dev.216, )",
"Speckle.Sdk": "[3.1.0-dev.216, )",
"Speckle.WebIfc": "[0.0.64-speckle1, )",
"System.CommandLine": "[2.0.0-beta4.22272.1, )"
}
},
"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": "[8.0.1, )",
"resolved": "8.0.1",
"contentHash": "BmANAnR5Xd4Oqw7yQ75xOAYODybZQRzdeNucg7kS5wWKd2PNnMdYtJ2Vciy0QLylRmv42DGl5+AFL9izA6F1Rw==",
"dependencies": {
"Microsoft.Extensions.DependencyInjection.Abstractions": "8.0.2"
}
},
"Speckle.Objects": {
"type": "CentralTransitive",
"requested": "[3.1.0-dev.216, )",
"resolved": "3.1.0-dev.216",
"contentHash": "oHyjQ0VFFcRNjgohlNQxtg1xxI6pNfpTNHZtkfVkQftb9ijbZ4MgG8nnW3vsBO/smRtBxynncrO9d3j40Iyqiw==",
"dependencies": {
"Speckle.Sdk": "3.1.0-dev.216"
}
},
"Speckle.Sdk": {
"type": "CentralTransitive",
"requested": "[3.1.0-dev.216, )",
"resolved": "3.1.0-dev.216",
"contentHash": "tnsNOzooSIBhQk3BX3xudrRLL3A+n8ojfG81dJpKA8bSDOszdwPR2nWBJVA24KpZ6J3666jfRsi6NvAaxNFRcQ==",
"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.216"
}
},
"Speckle.Sdk.Dependencies": {
"type": "CentralTransitive",
"requested": "[3.1.0-dev.216, )",
"resolved": "3.1.0-dev.216",
"contentHash": "v3EBevnZqcPres3xWn0mcnCCKhSLlqwTyfqUOTQSWHCCBBos8t0aBIQ21EBEkDaklaS7auj+Rk7vWByvgcrUbQ=="
},
"Speckle.WebIfc": {
"type": "CentralTransitive",
"requested": "[0.0.64-speckle1, )",
"resolved": "0.0.64-speckle1",
"contentHash": "dJQ4mPgiNAVjdyZNvejmnv0UTqNHw/7BCEbYUumKklLyzXtVAARGXRsDDbNNwJv3Y/L/6kVgwUehU9BbpAKURA=="
},
"System.CommandLine": {
"type": "CentralTransitive",
"requested": "[2.0.0-beta4.22272.1, )",
"resolved": "2.0.0-beta4.22272.1",
"contentHash": "1uqED/q2H0kKoLJ4+hI2iPSBSEdTuhfCYADeJrAqERmiGQ2NNacYKRNEQ+gFbU4glgVyK8rxI+ZOe1onEtr/Pg=="
}
}
}
}
+8
View File
@@ -8,10 +8,14 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "config", "config", "{5E9269
Directory.Build.props = Directory.Build.props
Directory.Packages.props = Directory.Packages.props
global.json = global.json
..\.github\workflows\main.yml = ..\.github\workflows\main.yml
..\.github\workflows\pr.yml = ..\.github\workflows\pr.yml
EndProjectSection
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "build", "build\build.csproj", "{8E89E5BD-4EE3-4993-9D42-14F668F2A0D6}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Speckle.Importer.Tester", "Speckle.Importer.Tester\Speckle.Importer.Tester.csproj", "{A0464E50-D451-4D19-B76B-DFDF53161F5B}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -26,5 +30,9 @@ Global
{8E89E5BD-4EE3-4993-9D42-14F668F2A0D6}.Debug|Any CPU.Build.0 = Debug|Any CPU
{8E89E5BD-4EE3-4993-9D42-14F668F2A0D6}.Release|Any CPU.ActiveCfg = Release|Any CPU
{8E89E5BD-4EE3-4993-9D42-14F668F2A0D6}.Release|Any CPU.Build.0 = Release|Any CPU
{A0464E50-D451-4D19-B76B-DFDF53161F5B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{A0464E50-D451-4D19-B76B-DFDF53161F5B}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A0464E50-D451-4D19-B76B-DFDF53161F5B}.Release|Any CPU.ActiveCfg = Release|Any CPU
{A0464E50-D451-4D19-B76B-DFDF53161F5B}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
EndGlobal
@@ -1,12 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\Ara3D.StepParser\Ara3D.StepParser.csproj" />
</ItemGroup>
</Project>
@@ -151,7 +151,7 @@ public static class Extensions
public static string AsString(this StepString ss) => ss.Value.AsString();
public static object? ToJsonObject(this StepValue sv)
public static object ToJsonObject(this StepValue sv)
{
switch (sv)
{
@@ -12,7 +12,7 @@ public class IfcEntity
{
public StepInstance LineData { get; }
public IfcGraph Graph { get; }
public uint Id => LineData.Id;
public uint Id => (uint)LineData.Id;
public string Type => LineData?.EntityType ?? "";
public IfcEntity(IfcGraph graph, StepInstance lineData)
@@ -21,13 +21,10 @@ public class IfcEntity
LineData = lineData;
}
public override bool Equals(object? obj)
public override bool Equals(object obj)
{
if (obj is IfcEntity other)
{
return Id == other.Id;
}
return false;
}
@@ -36,19 +33,23 @@ public class IfcEntity
public override string ToString() => $"{Type}#{Id}";
public bool IsIfcRoot =>
Count >= 4 && this[0] is StepString str && this[1] is StepId && str.Value.Length == 22;
Count >= 4 && this[0] is StepString str && (this[1] is StepId) || (this[1] is StepUnassigned);
public string? Guid => IsIfcRoot ? (this[0] as StepString)?.Value.ToString() : null;
// 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 => IsIfcRoot ? (this[0] as StepString)?.Value.ToString() : null;
public uint OwnerId => IsIfcRoot ? (this[1] as StepId)?.Id ?? 0 : 0;
public string? Name => IsIfcRoot ? (this[2] as StepString)?.AsString() : null;
public string Name => IsIfcRoot ? (this[2] as StepString)?.AsString() : null;
public string? Description => IsIfcRoot ? (this[3] as StepString)?.AsString() : null;
public string Description => IsIfcRoot ? (this[3] as StepString)?.AsString() : null;
public int Count => LineData.Count;
public StepValue? this[int i] => LineData[i];
public StepValue this[int i] => LineData[i];
public IReadOnlyList<IfcRelation> GetOutgoingRelations() => Graph.GetRelationsFrom(Id);
@@ -1,4 +1,4 @@
using System.Diagnostics;
using System.Diagnostics;
using Ara3D.Logging;
using Ara3D.StepParser;
using Ara3D.Utils;
@@ -164,7 +164,7 @@ public class IfcGraph
logger?.Log("Retrieving the roots of all of the spatial relationship");
RootIds = GetSpatialRelations()
.Where(r => r.From != null)
.Select(r => r.From.Id)
.Select(r => (uint)r.From.Id)
.Distinct()
.ToList();
@@ -195,7 +195,7 @@ public class IfcGraph
public IfcNode GetOrCreateNode(StepValue o) =>
GetOrCreateNode(
o is StepId id ? id.Id : throw new Exception($"Expected a StepId value, not {o}")
o is StepId id ? (uint)id.Id : throw new Exception($"Expected a StepId value, not {o}")
);
public IfcNode GetOrCreateNode(uint id)
@@ -214,7 +214,7 @@ public class IfcGraph
{
if (arg < 0 || arg >= line.AttributeValues.Count)
throw new Exception("Argument out of range");
if (line.AttributeValues[arg] is not StepList agg)
if (!(line.AttributeValues[arg] is StepList agg))
throw new Exception("Expected a list");
return GetOrCreateNodes(agg.Values);
}
@@ -4,24 +4,18 @@ namespace Ara3D.IfcParser;
public class IfcProp : IfcNode
{
public readonly StepValue? Value;
public readonly StepValue Value;
public new string? Name => this[0]?.AsString();
public new string? Description => this[1]?.AsString();
public new string Name => this[0].AsString();
public new string Description => this[1].AsString();
public IfcProp(IfcGraph graph, StepInstance lineData, StepValue? value)
public IfcProp(IfcGraph graph, StepInstance lineData, StepValue value)
: base(graph, lineData)
{
if (lineData.Count < 2)
{
throw new System.Exception("Expected at least two values in the line data");
}
if (lineData[0] is not StepString)
{
if (!(lineData[0] is StepString))
throw new System.Exception("Expected the first value to be a string (Name)");
}
Value = value;
}
}
@@ -1,14 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Ara3D.Buffers" Version="1.4.5" />
<PackageReference Include="Ara3D.Logging" Version="1.4.5" />
<PackageReference Include="Ara3D.Utils" Version="1.4.5" />
</ItemGroup>
</Project>
@@ -5,17 +5,23 @@ using Ara3D.Utils;
namespace Ara3D.StepParser;
public sealed unsafe class StepDocument : IDisposable
public 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 List<StepRawInstance> RawInstances = new();
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
@@ -27,19 +33,20 @@ public sealed unsafe class StepDocument : IDisposable
/// </summary>
public readonly List<int> LineOffsets;
public StepDocument(FilePath filePath, ILogger? logger = null)
public StepDocument(FilePath filePath, ILogger logger = null)
{
FilePath = filePath;
logger ??= Logger.Null;
logger = 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 more than 16 characters.
// This is a reasonable estimate. Only very degenerate files would not meet that.
var cap = Data.NumBytes / 16;
// 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
@@ -47,7 +54,7 @@ public sealed unsafe class StepDocument : IDisposable
var currentLine = 1;
for (var i = 0; i < Data.NumVectors; i++)
{
StepLineParser.ComputeLines(
StepLineParser.ComputeOffsets(
((Vector256<byte>*)Data.BytePtr)[i],
ref currentLine,
LineOffsets
@@ -57,49 +64,45 @@ public sealed unsafe class StepDocument : IDisposable
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, i, RawInstances.Count, lineStart, lineEnd);
var inst = StepLineParser.ParseLine(DataStart + lineStart, DataStart + lineEnd);
if (inst.IsValid())
{
RawInstances.Add(inst);
InstanceIdToIndex.Add(inst.Id, i);
InstanceIdToIndex.Add(inst.Id, NumRawInstances);
RawInstances[NumRawInstances++] = inst;
}
}
logger.Log($"Completed creation of STEP document from {filePath.GetFileName()}");
}
public void Dispose() => Data.Dispose();
public StepRawInstance GetRawInstance(uint id) => RawInstances[InstanceIdToIndex[id]];
public StepInstance GetInstanceWithData(uint id) =>
GetInstanceWithDataFromIndex(InstanceIdToIndex[id]);
public StepInstance GetInstanceWithData(uint id) => GetInstanceWithData(GetRawInstance(id));
public int GetLineEnd(int lineIndex)
{
if (lineIndex + 1 == LineOffsets.Count)
{
return Data.NumBytes;
}
return LineOffsets[lineIndex + 1];
}
public StepInstance GetInstanceWithDataFromIndex(int index) =>
GetInstanceWithData(RawInstances[index]);
public StepInstance GetInstanceWithData(StepRawInstance inst)
{
var lineEnd = GetLineEnd(inst.LineIndex);
var attr = inst.GetAttributes(DataStart + lineEnd);
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) =>
RawInstances.Where(ri => ri.Type.Equals(typeCode)).Select(GetInstanceWithData);
GetRawInstances(typeCode).Select(GetInstanceWithData);
}
@@ -1,5 +1,3 @@
using System.Diagnostics;
namespace Ara3D.StepParser;
public static unsafe class StepFactory
@@ -7,7 +5,7 @@ public static unsafe class StepFactory
public static StepList GetAttributes(this StepRawInstance inst, byte* lineEnd)
{
if (!inst.IsValid())
return StepList.Default;
return default;
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
@@ -62,7 +60,9 @@ public static unsafe class StepFactory
public static StepList CreateAggregate(ref StepToken token, byte* end)
{
var values = new List<StepValue>();
Debug.Assert(token.Type == StepTokenType.BeginGroup);
StepTokenizer.EatWSpace(ref token, end);
if (token.Type != StepTokenType.BeginGroup)
throw new Exception("Expected '('");
while (StepTokenizer.ParseNextToken(ref token, end))
{
@@ -71,6 +71,7 @@ public static unsafe class StepFactory
// Advance past comments, whitespace, and commas
case StepTokenType.Comment:
case StepTokenType.Whitespace:
case StepTokenType.LineBreak:
case StepTokenType.Separator:
case StepTokenType.None:
continue;
@@ -28,10 +28,9 @@ public class StepGraph
public static StepGraph Create(StepDocument doc) => new(doc);
public string? ToValString(StepNode node, int depth) =>
ToValString(node.Entity.Entity, depth - 1);
public string ToValString(StepNode node, int depth) => ToValString(node.Entity.Entity, depth - 1);
public string? ToValString(StepValue? value, int depth)
public string ToValString(StepValue value, int depth)
{
if (value == null)
return "";
@@ -7,7 +7,7 @@ public class StepInstance
public List<StepValue> AttributeValues => Entity.Attributes.Values;
public string EntityType => Entity.EntityType.ToString() ?? "";
public string EntityType => Entity?.EntityType.ToString() ?? "";
public StepInstance(uint id, StepEntity entity)
{
@@ -21,9 +21,5 @@ public class StepInstance
public int Count => AttributeValues.Count;
public StepValue this[int i]
#pragma warning disable CA1065
=>
i < Count ? AttributeValues[i] : throw new IndexOutOfRangeException();
#pragma warning restore CA1065
public StepValue this[int i] => i < Count ? AttributeValues[i] : null;
}
@@ -18,139 +18,134 @@ public class StepLineParser
public static readonly Vector256<byte> Unassigned = Vector256.Create((byte)'*');
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void ComputeLines(in Vector256<byte> v, ref int lineIndex, List<int> lineIndices)
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)
{
lineIndex += 32;
index += 32;
return;
}
// Fully unrolled handling of each bit
if ((mask & 0x00000001) != 0)
lineIndices.Add(lineIndex);
offsets.Add(index);
if ((mask & 0x00000002) != 0)
lineIndices.Add(lineIndex + 1);
offsets.Add(index + 1);
if ((mask & 0x00000004) != 0)
lineIndices.Add(lineIndex + 2);
offsets.Add(index + 2);
if ((mask & 0x00000008) != 0)
lineIndices.Add(lineIndex + 3);
offsets.Add(index + 3);
if ((mask & 0x00000010) != 0)
lineIndices.Add(lineIndex + 4);
offsets.Add(index + 4);
if ((mask & 0x00000020) != 0)
lineIndices.Add(lineIndex + 5);
offsets.Add(index + 5);
if ((mask & 0x00000040) != 0)
lineIndices.Add(lineIndex + 6);
offsets.Add(index + 6);
if ((mask & 0x00000080) != 0)
lineIndices.Add(lineIndex + 7);
offsets.Add(index + 7);
if ((mask & 0x00000100) != 0)
lineIndices.Add(lineIndex + 8);
offsets.Add(index + 8);
if ((mask & 0x00000200) != 0)
lineIndices.Add(lineIndex + 9);
offsets.Add(index + 9);
if ((mask & 0x00000400) != 0)
lineIndices.Add(lineIndex + 10);
offsets.Add(index + 10);
if ((mask & 0x00000800) != 0)
lineIndices.Add(lineIndex + 11);
offsets.Add(index + 11);
if ((mask & 0x00001000) != 0)
lineIndices.Add(lineIndex + 12);
offsets.Add(index + 12);
if ((mask & 0x00002000) != 0)
lineIndices.Add(lineIndex + 13);
offsets.Add(index + 13);
if ((mask & 0x00004000) != 0)
lineIndices.Add(lineIndex + 14);
offsets.Add(index + 14);
if ((mask & 0x00008000) != 0)
lineIndices.Add(lineIndex + 15);
offsets.Add(index + 15);
if ((mask & 0x00010000) != 0)
lineIndices.Add(lineIndex + 16);
offsets.Add(index + 16);
if ((mask & 0x00020000) != 0)
lineIndices.Add(lineIndex + 17);
offsets.Add(index + 17);
if ((mask & 0x00040000) != 0)
lineIndices.Add(lineIndex + 18);
offsets.Add(index + 18);
if ((mask & 0x00080000) != 0)
lineIndices.Add(lineIndex + 19);
offsets.Add(index + 19);
if ((mask & 0x00100000) != 0)
lineIndices.Add(lineIndex + 20);
offsets.Add(index + 20);
if ((mask & 0x00200000) != 0)
lineIndices.Add(lineIndex + 21);
offsets.Add(index + 21);
if ((mask & 0x00400000) != 0)
lineIndices.Add(lineIndex + 22);
offsets.Add(index + 22);
if ((mask & 0x00800000) != 0)
lineIndices.Add(lineIndex + 23);
offsets.Add(index + 23);
if ((mask & 0x01000000) != 0)
lineIndices.Add(lineIndex + 24);
offsets.Add(index + 24);
if ((mask & 0x02000000) != 0)
lineIndices.Add(lineIndex + 25);
offsets.Add(index + 25);
if ((mask & 0x04000000) != 0)
lineIndices.Add(lineIndex + 26);
offsets.Add(index + 26);
if ((mask & 0x08000000) != 0)
lineIndices.Add(lineIndex + 27);
offsets.Add(index + 27);
if ((mask & 0x10000000) != 0)
lineIndices.Add(lineIndex + 28);
offsets.Add(index + 28);
if ((mask & 0x20000000) != 0)
lineIndices.Add(lineIndex + 29);
offsets.Add(index + 29);
if ((mask & 0x40000000) != 0)
lineIndices.Add(lineIndex + 30);
offsets.Add(index + 30);
if ((mask & 0x80000000) != 0)
lineIndices.Add(lineIndex + 31);
offsets.Add(index + 31);
// Update lineIndex to the next starting position
lineIndex += 32;
index += 32;
}
public static unsafe StepRawInstance ParseLine(
byte* ptr,
int lineIndex,
int index,
int i,
int end
)
public static unsafe StepRawInstance ParseLine(byte* ptr, byte* end)
{
var cnt = end - i;
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[i++] != '#')
if (*ptr++ != '#')
return default;
var id = 0u;
while (i < end)
while (ptr < end)
{
if (ptr[i] < '0' || ptr[i] > '9')
if (*ptr < '0' || *ptr > '9')
break;
id = id * 10 + ptr[i] - '0';
i++;
id = id * 10 + *ptr - '0';
ptr++;
}
var foundEquals = false;
while (i < end)
while (ptr < end)
{
if (ptr[i] == '=')
if (*ptr == '=')
foundEquals = true;
if (ptr[i] != (byte)' ' && ptr[i] != (byte)'=')
if (*ptr != (byte)' ' && *ptr != (byte)'=')
break;
i++;
ptr++;
}
if (!foundEquals)
return default;
// Parse the entity type name
var entityStart = i;
while (i < end)
var entityStart = ptr;
while (ptr < end)
{
if (!StepTokenizer.IsIdentLookup[ptr[i]])
if (!StepTokenizer.IsIdentLookup[*ptr])
break;
i++;
ptr++;
}
if (i == entityStart)
if (ptr == entityStart)
return default;
var entityType = new ByteSpan(ptr + entityStart, ptr + i);
return new(id, entityType, lineIndex, index);
var entityType = new ByteSpan(entityStart, ptr);
return new(id, entityType, start);
}
}
@@ -37,7 +37,7 @@ public class StepNode
public override string ToString() => Entity.ToString();
public string ToGraph(HashSet<StepNode>? prev = null)
public string ToGraph(HashSet<StepNode> prev = null)
{
prev ??= new HashSet<StepNode>();
if (prev.Contains(this))
@@ -9,15 +9,12 @@ namespace Ara3D.StepParser;
/// </summary>
[StructLayout(LayoutKind.Sequential, Pack = 1)]
[method: MethodImpl(MethodImplOptions.AggressiveInlining)]
public readonly struct StepRawInstance(uint id, ByteSpan type, int lineIndex, int index)
public readonly unsafe struct StepRawInstance(uint id, ByteSpan type, byte* ptr)
{
public readonly uint Id = id;
public readonly ByteSpan Type = type;
public readonly int LineIndex = lineIndex;
public readonly int Index = index;
public readonly byte* Ptr = ptr;
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public bool IsValid() => Id > 0;
public override string ToString() => $"{Id} = {Type}";
}
@@ -92,6 +92,7 @@ public static class StepTokenizer
return StepTokenType.LineBreak;
case (byte)'\'':
case (byte)'"':
return StepTokenType.String;
case (byte)'.':
@@ -220,6 +221,21 @@ public static class StepTokenizer
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)
{
@@ -243,11 +259,14 @@ public static class StepTokenizer
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++ == '\'')
if (*cur++ == quoteChar)
{
if (*cur != '\'')
if (*cur != quoteChar)
break;
else
cur++;
@@ -51,8 +51,8 @@ public class StepString : StepValue
var span = token.Span;
Debug.Assert(token.Type == StepTokenType.String);
Debug.Assert(span.Length >= 2);
Debug.Assert(span.First() == '\'');
Debug.Assert(span.Last() == '\'');
Debug.Assert(span.First() == '\'' || span.First() == '"');
Debug.Assert(span.Last() == '\'' || span.Last() == '"');
return new StepString(span.Trim(1, 1));
}
@@ -1,6 +1,7 @@
using Ara3D.IfcParser;
using Speckle.InterfaceGenerator;
using Speckle.Sdk.Models;
using Speckle.Sdk.Models.Collections;
using Speckle.WebIfc.Importer.Ifc;
namespace Speckle.WebIfc.Importer.Converters;
@@ -10,9 +11,9 @@ public class GraphConverter(INodeConverter nodeConverter) : IGraphConverter
{
public Base Convert(IfcModel model, IfcGraph graph)
{
var b = new Base();
var collection = new Collection();
var children = graph.GetSources().Select(x => nodeConverter.Convert(model, x)).ToList();
b["elements"] = children;
return b;
collection.elements = children;
return collection;
}
}
@@ -30,7 +30,7 @@ public class MeshConverter : IMeshConverter
var a = ip[i];
var b = ip[i + 1];
var c = ip[i + 2];
faces.Add(0);
faces.Add(3);
faces.Add(a);
faces.Add(b);
faces.Add(c);
@@ -38,12 +38,12 @@ public class NodeConverter(IGeometryConverter geometryConverter) : INodeConverte
{
var c = geometryConverter.Convert(geo);
if (c.elements.Count > 0)
b["displayValue"] = c.elements;
b["@displayValue"] = c.elements;
}
// Create the children
var children = node.GetChildren().Select(x => Convert(model, x)).ToList();
b["elements"] = children;
b["@elements"] = children;
// Add the properties
foreach (var p in node.GetPropSets())
+47 -21
View File
@@ -8,7 +8,6 @@ using Speckle.Sdk;
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.Host;
using Speckle.Sdk.Models;
@@ -19,13 +18,30 @@ using Speckle.WebIfc.Importer.Converters;
using Speckle.WebIfc.Importer.Ifc;
namespace Speckle.WebIfc.Importer;
public static class Import
{
public static async Task Ifc(string url, string filePath, string streamId,
string modelId, string commitMessage, string token, IProgress<ProgressArgs>? progress = null)
public static async Task<string> Ifc(
string url,
string filePath,
string streamId,
string modelId,
string commitMessage,
string token,
IProgress<ProgressArgs>? progress = null
)
{
var serviceProvider = GetServiceProvider();
await Ifc(serviceProvider, url, filePath, streamId, modelId, commitMessage, token, progress);
return await Ifc(
serviceProvider,
url,
filePath,
streamId,
modelId,
commitMessage,
token,
progress
);
}
public static ServiceProvider GetServiceProvider()
@@ -38,14 +54,20 @@ public static class Import
return serviceCollection.BuildServiceProvider();
}
public static async Task Ifc(IServiceProvider serviceProvider, string url, string filePath, string streamId,
string modelId, string commitMessage, string token, IProgress<ProgressArgs>? progress = null)
public static async Task<string> Ifc(
IServiceProvider serviceProvider,
string url,
string filePath,
string streamId,
string modelId,
string commitMessage,
string token,
IProgress<ProgressArgs>? progress = null
)
{
var ifcFactory = serviceProvider.GetRequiredService<IIfcFactory>();
var clientFactory = serviceProvider.GetRequiredService<IClientFactory>();
var baseUri = new Uri(url);
Console.WriteLine(ifcFactory.Version);
var stopwatch = Stopwatch.StartNew();
var model = ifcFactory.Open(filePath);
@@ -63,27 +85,31 @@ public static class Import
Console.WriteLine($"Converted to Speckle Bases: {ms2 - ms} ms");
var serializeProcessFactory = serviceProvider.GetRequiredService<ISerializeProcessFactory>();
var process = serializeProcessFactory.CreateSerializeProcess(baseUri, streamId, token, progress);
var (rootId, _) = await process.Serialize(b, default, new SerializeProcessOptions(true, true, false))
.ConfigureAwait(false);
Account account = new() { token = token, serverInfo = new ServerInfo { url = baseUri.ToString(), } };
var process = serializeProcessFactory.CreateSerializeProcess(
baseUri,
streamId,
token,
progress,
new SerializeProcessOptions(true, true, false, true)
);
var (rootId, _) = await process.Serialize(b, default).ConfigureAwait(false);
Account account = new()
{
token = token,
serverInfo = new ServerInfo { url = baseUri.ToString() },
};
ms = ms2;
ms2 = stopwatch.ElapsedMilliseconds;
Console.WriteLine($"Uploaded to Speckle: {ms2 - ms} ms");
// 8 - Create the version (commit)
using var apiClient = clientFactory.Create(account);
_ = await apiClient
.Version.Create(
new CreateVersionInput(
rootId,
modelId,
streamId,
message: commitMessage
)
);
var commitId = await apiClient.Version.Create(
new CreateVersionInput(rootId, modelId, streamId, message: commitMessage)
);
ms = ms2;
ms2 = stopwatch.ElapsedMilliseconds;
Console.WriteLine($"Committed to Speckle: {ms2 - ms} ms");
return commitId;
}
}
@@ -1,9 +1,15 @@
<Project Sdk="Microsoft.NET.Sdk">
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup>
<PropertyGroup Label="Nuget Package Properties">
<IsPackable>true</IsPackable>
<IncludeSymbols>true</IncludeSymbols>
<version>0.0.7</version>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Ara3D.Buffers" />
<PackageReference Include="Ara3D.Logging" />
+13 -13
View File
@@ -53,18 +53,18 @@
},
"Speckle.Objects": {
"type": "Direct",
"requested": "[3.1.0-dev.186, )",
"resolved": "3.1.0-dev.186",
"contentHash": "NuKYQLfG32v+NsjlAamECyBfLAD19LWjuWHnH/ZqCDVxebXsCDh19Y//W/8rQPKuM7ojbO1nSjxZiRwhITQP8A==",
"requested": "[3.1.0-dev.216, )",
"resolved": "3.1.0-dev.216",
"contentHash": "oHyjQ0VFFcRNjgohlNQxtg1xxI6pNfpTNHZtkfVkQftb9ijbZ4MgG8nnW3vsBO/smRtBxynncrO9d3j40Iyqiw==",
"dependencies": {
"Speckle.Sdk": "3.1.0-dev.186"
"Speckle.Sdk": "3.1.0-dev.216"
}
},
"Speckle.Sdk": {
"type": "Direct",
"requested": "[3.1.0-dev.186, )",
"resolved": "3.1.0-dev.186",
"contentHash": "9+s6TiJ59hw5G7hPHE7WmF6D/3zoXCCgJFaYEsfXxQi2SBEkCthuJq7MfkSoukvEM0N/OwEoSuCwS+G5vbE3/Q==",
"requested": "[3.1.0-dev.216, )",
"resolved": "3.1.0-dev.216",
"contentHash": "tnsNOzooSIBhQk3BX3xudrRLL3A+n8ojfG81dJpKA8bSDOszdwPR2nWBJVA24KpZ6J3666jfRsi6NvAaxNFRcQ==",
"dependencies": {
"GraphQL.Client": "6.0.0",
"Microsoft.CSharp": "4.7.0",
@@ -73,14 +73,14 @@
"Microsoft.Extensions.Logging": "2.2.0",
"Speckle.DoubleNumerics": "4.0.1",
"Speckle.Newtonsoft.Json": "13.0.2",
"Speckle.Sdk.Dependencies": "3.1.0-dev.186"
"Speckle.Sdk.Dependencies": "3.1.0-dev.216"
}
},
"Speckle.WebIfc": {
"type": "Direct",
"requested": "[0.0.64-speckle1, )",
"resolved": "0.0.64-speckle1",
"contentHash": "oJgPu/LCypQLelDrtV6+dk0Qm+3VSEYWXCjeXHs2/ekOZEKwpFKhcKVOd1uMjtVLh+n3CZ/6tMgO1nZq9FpwMw=="
"resolved": "0.0.64-speckle1",
"contentHash": "dJQ4mPgiNAVjdyZNvejmnv0UTqNHw/7BCEbYUumKklLyzXtVAARGXRsDDbNNwJv3Y/L/6kVgwUehU9BbpAKURA=="
},
"System.CommandLine": {
"type": "Direct",
@@ -277,9 +277,9 @@
},
"Speckle.Sdk.Dependencies": {
"type": "CentralTransitive",
"requested": "[3.1.0-dev.186, )",
"resolved": "3.1.0-dev.186",
"contentHash": "fGD7PtPYuyNe7hPOuEFvEi4qy5gpLZHqeNjQ8ZhRF6nodUjJTUDNHq/VQiJ4GW5u7d+mnnwCBx+9GwlRSJW3Cg=="
"requested": "[3.1.0-dev.216, )",
"resolved": "3.1.0-dev.216",
"contentHash": "v3EBevnZqcPres3xWn0mcnCCKhSLlqwTyfqUOTQSWHCCBBos8t0aBIQ21EBEkDaklaS7auj+Rk7vWByvgcrUbQ=="
}
}
}
+7 -6
View File
@@ -35,10 +35,7 @@ Target(
() => RunAsync("dotnet", "csharpier --check .", BASE_PATH)
);
Target(
RESTORE,
() => RunAsync("dotnet", $"restore {SOLUTION} --locked-mode", BASE_PATH)
);
Target(RESTORE, () => RunAsync("dotnet", $"restore {SOLUTION} --locked-mode", BASE_PATH));
Target(
BUILD,
@@ -55,13 +52,17 @@ Target(
DependsOn(BUILD),
async () =>
{
await RunAsync("dotnet", $"publish {SOLUTION} -c Release --no-restore --no-build -o publish/", BASE_PATH)
await RunAsync(
"dotnet",
$"publish {SOLUTION} -c Release --no-restore --no-build -o publish/",
BASE_PATH
)
.ConfigureAwait(false);
}
);
static Task RunPack() =>
RunAsync("dotnet", $"pack {SOLUTION} -c Release -o output --no-build", BASE_PATH);
RunAsync("dotnet", $"pack {SOLUTION} -c Release -o output/ --no-restore --no-build", BASE_PATH);
Target(PACK, DependsOn(BUILD), RunPack);
+50 -50
View File
@@ -1,51 +1,51 @@
{
"version": 2,
"dependencies": {
"net8.0": {
"Bullseye": {
"type": "Direct",
"requested": "[5.0.0, )",
"resolved": "5.0.0",
"contentHash": "bqyt+m17ym+5aN45C5oZRAjuLDt8jKiCm/ys1XfymIXSkrTFwvI/QsbY3ucPSHDz7SF7uON7B57kXFv5H2k1ew=="
},
"Glob": {
"type": "Direct",
"requested": "[1.1.9, )",
"resolved": "1.1.9",
"contentHash": "AfK5+ECWYTP7G3AAdnU8IfVj+QpGjrh9GC2mpdcJzCvtQ4pnerAGwHsxJ9D4/RnhDUz2DSzd951O/lQjQby2Sw=="
},
"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"
}
},
"SimpleExec": {
"type": "Direct",
"requested": "[12.0.0, )",
"resolved": "12.0.0",
"contentHash": "ptxlWtxC8vM6Y6e3h9ZTxBBkOWnWrm/Sa1HT+2i1xcXY3Hx2hmKDZP5RShPf8Xr9D+ivlrXNy57ktzyH8kyt+Q=="
},
"Speckle.InterfaceGenerator": {
"type": "Direct",
"requested": "[0.9.6, )",
"resolved": "0.9.6",
"contentHash": "HKH7tYrYYlCK1ct483hgxERAdVdMtl7gUKW9ijWXxA1UsYR4Z+TrRHYmzZ9qmpu1NnTycSrp005NYM78GDKV1w=="
},
"Microsoft.Build.Tasks.Git": {
"type": "Transitive",
"resolved": "8.0.0",
"contentHash": "bZKfSIKJRXLTuSzLudMFte/8CempWjVamNUR5eHJizsy+iuOuO/k2gnh7W0dHJmYY0tBf+gUErfluCv5mySAOQ=="
},
"Microsoft.SourceLink.Common": {
"type": "Transitive",
"resolved": "8.0.0",
"contentHash": "dk9JPxTCIevS75HyEQ0E4OVAFhB2N+V9ShCXf8Q6FkUQZDkgLI12y679Nym1YqsiSysuQskT7Z+6nUf3yab6Vw=="
}
}
}
{
"version": 2,
"dependencies": {
"net8.0": {
"Bullseye": {
"type": "Direct",
"requested": "[5.0.0, )",
"resolved": "5.0.0",
"contentHash": "bqyt+m17ym+5aN45C5oZRAjuLDt8jKiCm/ys1XfymIXSkrTFwvI/QsbY3ucPSHDz7SF7uON7B57kXFv5H2k1ew=="
},
"Glob": {
"type": "Direct",
"requested": "[1.1.9, )",
"resolved": "1.1.9",
"contentHash": "AfK5+ECWYTP7G3AAdnU8IfVj+QpGjrh9GC2mpdcJzCvtQ4pnerAGwHsxJ9D4/RnhDUz2DSzd951O/lQjQby2Sw=="
},
"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"
}
},
"SimpleExec": {
"type": "Direct",
"requested": "[12.0.0, )",
"resolved": "12.0.0",
"contentHash": "ptxlWtxC8vM6Y6e3h9ZTxBBkOWnWrm/Sa1HT+2i1xcXY3Hx2hmKDZP5RShPf8Xr9D+ivlrXNy57ktzyH8kyt+Q=="
},
"Speckle.InterfaceGenerator": {
"type": "Direct",
"requested": "[0.9.6, )",
"resolved": "0.9.6",
"contentHash": "HKH7tYrYYlCK1ct483hgxERAdVdMtl7gUKW9ijWXxA1UsYR4Z+TrRHYmzZ9qmpu1NnTycSrp005NYM78GDKV1w=="
},
"Microsoft.Build.Tasks.Git": {
"type": "Transitive",
"resolved": "8.0.0",
"contentHash": "bZKfSIKJRXLTuSzLudMFte/8CempWjVamNUR5eHJizsy+iuOuO/k2gnh7W0dHJmYY0tBf+gUErfluCv5mySAOQ=="
},
"Microsoft.SourceLink.Common": {
"type": "Transitive",
"resolved": "8.0.0",
"contentHash": "dk9JPxTCIevS75HyEQ0E4OVAFhB2N+V9ShCXf8Q6FkUQZDkgLI12y679Nym1YqsiSysuQskT7Z+6nUf3yab6Vw=="
}
}
}
}