Compare commits

...

4 Commits

Author SHA1 Message Date
Jedd Morgan b485a4ff6f Don't build everything when zero changes (#715)
.NET Build and Publish / build-windows (push) Has been cancelled
.NET Build and Publish / build-linux (push) Has been cancelled
.NET Build and Publish / deploy-installers (push) Has been cancelled
2025-03-26 15:21:12 +00:00
Jedd Morgan 5697afc292 fix(ifc): Fixed regression with IFC Site geometry not being converted (#712)
* IFC spatial elements now attach geometry as separate data object

* removed unnecessary attribute

* Updated tester for faster testing
2025-03-26 14:57:50 +00:00
Adam Hathcock 4ec45d3cd5 Merge pull request #709 from specklesystems/dev
.NET Build and Publish / build-windows (push) Has been cancelled
.NET Build and Publish / build-linux (push) Has been cancelled
.NET Build and Publish / deploy-installers (push) Has been cancelled
Bump sdk to 3.1.7 (#708)
2025-03-25 12:14:05 +00:00
Jedd Morgan ac1345bbaf Merge pull request #703 from specklesystems/dev
Update dev into main
2025-03-25 11:54:03 +00:00
7 changed files with 62 additions and 38 deletions
+1 -4
View File
@@ -66,10 +66,7 @@ public static class Affected
Console.WriteLine("Affected project group being built: " + group.HostAppSlug);
}
if (groups.Count > 0)
{
return groups.ToArray();
}
return groups.ToArray();
}
Console.WriteLine("Using all project groups: " + string.Join(',', Consts.ProjectGroups));
@@ -15,18 +15,32 @@ namespace Speckle.Importers.Ifc.Tester2;
public sealed class IfcTester(IClientFactory clientFactory, Importer importer, IAccountManager accountManager)
{
// Settings, Change these to suit!
private readonly FilePath _filePath =
//new(@"C:\Users\Jedd\Desktop\GRAPHISOFT_Archicad_Sample_Project-S-Office_v1.0_AC25.ifc");
new(@"C:\Users\Jedd\Desktop\EST-BRE-AF-3D-BT1-30-SD-00001-A-P.ifc");
// 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\", "*.ifc");
private readonly Uri _serverUrl = new("https://app.speckle.systems");
private const string PROJECT_ID = "f3a42bdf24";
public async Task Run()
public async Task Run(CancellationToken cancellationToken = default)
{
var account = accountManager.GetAccounts(_serverUrl).First();
using var speckleClient = clientFactory.Create(account);
string modelName = _filePath.GetFileName();
var existing = await speckleClient.Project.GetWithModels(PROJECT_ID, 1, modelsFilter: new(search: modelName));
foreach (var path in _filePaths)
{
await ImportFile(speckleClient, path, cancellationToken);
}
}
private async Task ImportFile(Client 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
@@ -35,14 +49,14 @@ public sealed class IfcTester(IClientFactory clientFactory, Importer importer, I
new()
{
ServerUrl = _serverUrl,
FilePath = _filePath.ToString(),
FilePath = filePath.ToString(),
ProjectId = PROJECT_ID,
ModelId = existingModel,
ModelName = _filePath.GetFileName(),
ModelName = filePath.GetFileName(),
VersionMessage = "",
Token = account.token
Token = speckleClient.Account.token
};
var version = await importer.ImportIfc(args, null, default);
var version = await importer.ImportIfc(args, null, cancellationToken);
Console.WriteLine($"File was successfully sent {version.id}");
}
}
@@ -1,5 +1,4 @@
using System.Diagnostics.CodeAnalysis;
using Speckle.Importers.Ifc.Ara3D.IfcParser.Schema;
using Speckle.Importers.Ifc.Ara3D.IfcParser.Schema;
using Speckle.Importers.Ifc.Ara3D.StepParser;
namespace Speckle.Importers.Ifc.Ara3D.IfcParser;
@@ -34,20 +33,19 @@ public class IfcEntity
public override string ToString() => $"{Type}#{Id}";
[MemberNotNullWhen(true, nameof(Guid))]
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 => IsIfcRoot ? ((StepString)this[0]).Value.ToString() : null;
public string Guid => ((StepString)this[0]).Value.ToString();
public uint OwnerId => IsIfcRoot ? (this[1] as StepId)?.Id ?? 0 : 0;
public uint OwnerId => (this[1] as StepId)?.Id ?? 0;
public string? Name => IsIfcRoot ? (this[2] as StepString)?.AsString() : null;
public string? Name => (this[2] as StepString)?.AsString();
public string? Description => IsIfcRoot ? (this[3] as StepString)?.AsString() : null;
public string? Description => (this[3] as StepString)?.AsString();
public int Count => LineData.Count;
@@ -11,9 +11,6 @@ public sealed class DataObjectConverter(IGeometryConverter geometryConverter) :
{
public DataObject Convert(IfcModel model, IfcNode node, INodeConverter childrenConverter)
{
if (!node.IsIfcRoot)
throw new ArgumentException("Expected to be an IfcRoot", paramName: nameof(node));
// 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();
@@ -24,7 +21,7 @@ public sealed class DataObjectConverter(IGeometryConverter geometryConverter) :
properties = node.ConvertPropertySets(),
name = node.Name ?? node.Guid,
displayValue = displayValue,
["@elements"] = childrenConverter.ConvertChildren(model, node),
["@elements"] = childrenConverter.ConvertChildren(model, node).ToList(),
["ifcType"] = node.Type,
["expressID"] = node.Id,
["ownerId"] = node.OwnerId,
@@ -37,8 +37,8 @@ public sealed class NodeConverter(
};
}
public List<Base> ConvertChildren(IfcModel model, IfcNode node)
public IEnumerable<Base> ConvertChildren(IfcModel model, IfcNode node)
{
return node.GetChildren().Where(x => x.IsIfcRoot).Select(x => Convert(model, x)).ToList();
return node.GetChildren().Where(x => x.IsIfcRoot).Select(x => Convert(model, x));
}
}
@@ -10,14 +10,11 @@ public sealed class ProjectConverter : IProjectConverter
{
public Collection Convert(IfcModel model, IfcProject node, INodeConverter childrenConverter)
{
if (!node.IsIfcRoot) //I'd really rather have a class for this (IfcRoot : IfcNode)
throw new ArgumentException("Expected to be an IfcRoot", paramName: nameof(node));
return new Collection
{
name = node.Name ?? node.Guid,
applicationId = node.Guid,
elements = childrenConverter.ConvertChildren(model, node),
elements = childrenConverter.ConvertChildren(model, node).ToList(),
["expressID"] = node.Id,
["ownerId"] = node.OwnerId,
["ifcType"] = node.Type,
@@ -1,23 +1,41 @@
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 : IIfcSpatialStructureElementConverter
public sealed class IfcSpatialStructureElementConverter(IGeometryConverter geometryConverter)
: IIfcSpatialStructureElementConverter
{
public Collection Convert(IfcModel model, IfcSpatialStructureElement node, INodeConverter childrenConverter)
{
if (!node.IsIfcRoot) //I'd really rather have a class for this (IfcRoot : IfcNode)
throw new ArgumentException("Expected to be an IfcRoot", paramName: nameof(node));
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.Guid,
applicationId = node.Guid,
elements = childrenConverter.ConvertChildren(model, node),
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,
@@ -25,7 +43,10 @@ public sealed class IfcSpatialStructureElementConverter : IIfcSpatialStructureEl
["objectType"] = node.ObjectType,
["compositionType"] = node.CompositionType,
["longName"] = node.LongName,
["properties"] = node.ConvertPropertySets(),
name = node.Name ?? node.LongName ?? node.Guid,
applicationId = node.Guid,
properties = node.ConvertPropertySets(),
displayValue = displayValue,
};
}
}