Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

IFC with RepresentationInstances #1066

Open
wants to merge 17 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions Elements.Serialization.IFC/src/IFCElementExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,13 @@ internal static List<IfcProduct> ToIfcProducts(this Element e,
geoElement = (GeometricElement)e;
id = geoElement.Id;
trans = geoElement.Transform;

// Origin of Elements.Door is in the center. Origin of IFCDoor is in the corner.
if (e is Door door)
{
var correctedOrigin = door.Transform.Origin - 0.5 * door.DoorWidth * door.Transform.XAxis;
trans = new Transform(correctedOrigin, door.Transform.XAxis, door.Transform.YAxis, door.Transform.ZAxis);
}
}

if (updateElementRepresentation)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,35 +13,32 @@ internal class FromIfcBeamConverter : IFromIfcProductConverter
{
public GeometricElement ConvertToElement(IfcProduct ifcProduct, RepresentationData repData, List<string> constructionErrors)
{
if (!(ifcProduct is IfcBeam ifcBeam))
if (ifcProduct is not IfcBeam ifcBeam)
{
return null;
}

var elementTransform = repData.Transform;

if (repData.Extrude == null)
{
constructionErrors.Add($"#{ifcProduct.StepId}: Conversion of IfcBeam without extrude or mapped item representation to Beam is not supported.");
return null;
}

var representation = new Representation(repData.SolidOperations);

var centerLine = new Line(Vector3.Origin, repData.Extrude.Direction, repData.Extrude.Height);
var transformedLine = centerLine.TransformedLine(repData.ExtrudeTransform);
var transformedLine = repData.Extrude.LocalTransform == null ? centerLine : centerLine.TransformedLine(repData.Extrude.LocalTransform);

var result = new Beam(transformedLine,
repData.Extrude.Profile,
0,
0,
0,
elementTransform,
repData.Material,
representation,
false,
IfcGuid.FromIfcGUID(ifcBeam.GlobalId),
ifcBeam.Name);

transform: repData.Transform,
isElementDefinition: false,
id: IfcGuid.FromIfcGUID(ifcBeam.GlobalId),
name: ifcBeam.Name ?? "")
{
RepresentationInstances = repData.RepresentationInstances
};
return result;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,32 +13,33 @@ internal class FromIfcColumnConverter : IFromIfcProductConverter
{
public GeometricElement ConvertToElement(IfcProduct ifcProduct, RepresentationData repData, List<string> constructionErrors)
{
if (!(ifcProduct is IfcColumn ifcColumn))
if (ifcProduct is not IfcColumn ifcColumn)
{
return null;
}

var elementTransform = repData.Transform;

if (repData.Extrude == null)
{
constructionErrors.Add($"#{ifcProduct.StepId}: Conversion of IfcColumn without extrude or mapped item representation to Column is not supported.");
return null;
}

var result = new Column(repData.ExtrudeTransform.Origin,
var originTransform = repData.Extrude.LocalTransform ?? new Transform();

var result = new Column(originTransform.Origin,
repData.Extrude.Height,
null,
repData.Extrude.Profile,
0,
0,
0,
elementTransform,
repData.Material,
new Representation(repData.SolidOperations),
false,
IfcGuid.FromIfcGUID(ifcColumn.GlobalId),
ifcColumn.Name);
transform: repData.Transform,
isElementDefinition: false,
id: IfcGuid.FromIfcGUID(ifcColumn.GlobalId),
name: ifcColumn.Name ?? "")
{
RepresentationInstances = repData.RepresentationInstances
};
return result;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ internal class FromIfcDoorConverter : IFromIfcProductConverter
{
public GeometricElement ConvertToElement(IfcProduct ifcProduct, RepresentationData repData, List<string> constructionErrors)
{
if (!(ifcProduct is IfcDoor ifcDoor))
if (ifcProduct is not IfcDoor ifcDoor)
{
return null;
}
Expand Down Expand Up @@ -44,13 +44,14 @@ public GeometricElement ConvertToElement(IfcProduct ifcProduct, RepresentationDa
doorThickness,
openingSide,
openingType,
repData.Transform,
repData.Material,
new Representation(repData.SolidOperations),
false,
IfcGuid.FromIfcGUID(ifcDoor.GlobalId),
ifcDoor.Name
);
transform: repData.Transform,
isElementDefinition: false,
id: IfcGuid.FromIfcGUID(ifcDoor.GlobalId),
name: ifcDoor.Name ?? ""
)
{
RepresentationInstances = repData.RepresentationInstances
};

return result;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,46 +22,34 @@ public GeometricElement ConvertToElement(IfcProduct ifcProduct, RepresentationDa
return null;
}

if (repData.SolidOperations.Count == 0)
if (repData.RepresentationInstances.Count == 0)
{
constructionErrors.Add($"#{ifcProduct.StepId}: {ifcProduct.GetType().Name} did not have any solid operations in it's representation.");
constructionErrors.Add($"#{ifcProduct.StepId}: {ifcProduct.GetType().Name} did not have any representation items that could be converted to RepresentationInstance.");
return null;
}

var geom = new GeometricElement(repData.Transform,
repData.Material ?? BuiltInMaterials.Default,
new Representation(repData.SolidOperations),
false,
IfcGuid.FromIfcGUID(ifcProduct.GlobalId),
ifcProduct.Name);
var geom = new GeometricElement(transform: repData.Transform,
isElementDefinition: false,
id: IfcGuid.FromIfcGUID(ifcProduct.GlobalId),
name: ifcProduct.Name ?? "")
{
RepresentationInstances = repData.RepresentationInstances
};

// geom.Representation.SkipCSGUnion = true;
return geom;
}

public bool CanConvert(IfcProduct ifcProduct)
{
if (ifcProduct is IfcBuildingElement)
{
return true;
}

if (ifcProduct is IfcFurnishingElement)
{
return true;
}

if (ifcProduct is IfcSpace)
{
return true;
}

if (ifcProduct is IfcSite)
return ifcProduct switch
{
return true;
}

return false;
IfcBuildingElement => true,
IfcFurnishingElement => true,
IfcSpace => true,
IfcSite => true,
_ => false
};
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ internal class FromIfcFloorConverter : IFromIfcProductConverter
{
public GeometricElement ConvertToElement(IfcProduct ifcProduct, RepresentationData repData, List<string> constructionErrors)
{
if (!(ifcProduct is IfcSlab slab))
if (ifcProduct is not IfcSlab slab)
{
return null;
}
Expand All @@ -24,13 +24,16 @@ public GeometricElement ConvertToElement(IfcProduct ifcProduct, RepresentationDa
return null;
}

var floor = new Floor(repData.Extrude.Profile,
var localTransform = repData.Extrude.LocalTransform ?? new Transform();
var floor = new Floor(repData.Extrude.Profile.Transformed(localTransform),
repData.Extrude.Height,
repData.Transform,
repData.Material,
new Representation(repData.SolidOperations),
false,
IfcGuid.FromIfcGUID(slab.GlobalId));
transform: repData.Transform,
isElementDefinition: false,
id: IfcGuid.FromIfcGUID(slab.GlobalId),
name: slab.Name ?? "")
{
RepresentationInstances = repData.RepresentationInstances
};

return floor;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,42 +11,42 @@ namespace Elements.Serialization.IFC.IFCToHypar.Converters
{
internal class FromIfcSpaceConverter : IFromIfcProductConverter
{
private static readonly Material DEFAULT_MATERIAL = new Material("space", new Color(1.0f, 0.0f, 1.0f, 0.5f), 0.0f, 0.0f);

public GeometricElement ConvertToElement(IfcProduct product, RepresentationData repData, List<string> constructionErrors)
{
if (!(product is IfcSpace ifcSpace))
if (product is not IfcSpace ifcSpace)
{
return null;
}

var elementMaterial = repData.Material ?? DEFAULT_MATERIAL;

var extrude = repData.Extrude;

if (extrude != null)
{

var result = new Space(extrude.Profile,
extrude.Height,
elementMaterial,
repData.Transform,
new Representation(repData.SolidOperations),
false,
Guid.NewGuid(),
ifcSpace.Name);
transform: repData.Transform,
isElementDefinition: false,
id: Guid.NewGuid(),
name: ifcSpace.Name ?? "");

return result;
}

var solid = repData.SolidOperations.FirstOrDefault()?.Solid;
var solidOperations = repData.GetSolidOperations();
var solid = solidOperations.FirstOrDefault()?.Solid;

if (solid == null)
{
constructionErrors.Add($"#{product.StepId}: Conversion of IfcSpace without solid or mapped item representation to Space is not supported.");
return null;
}

return new Space(solid, repData.Transform, elementMaterial, false, Guid.NewGuid(), ifcSpace.Name);
var space = new Space(solid, transform: repData.Transform, isElementDefinition: false, id: Guid.NewGuid(), name: ifcSpace.Name)
{
RepresentationInstances = repData.RepresentationInstances
};

return space;
}

public bool CanConvert(IfcProduct ifcProduct)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ internal class FromIfcWallConverter : IFromIfcProductConverter

public GeometricElement ConvertToElement(IfcProduct ifcProduct, RepresentationData repData, List<string> constructionErrors)
{
if (!(ifcProduct is IfcWall wall))
if (ifcProduct is not IfcWall wall)
{
return null;
}
Expand All @@ -27,12 +27,13 @@ public GeometricElement ConvertToElement(IfcProduct ifcProduct, RepresentationDa

var result = new Wall(repData.Extrude.Profile,
repData.Extrude.Height,
repData.Material,
repData.Transform,
new Representation(repData.SolidOperations),
false,
IfcGuid.FromIfcGUID(wall.GlobalId),
wall.Name);
transform: repData.Transform,
isElementDefinition: false,
id: IfcGuid.FromIfcGUID(wall.GlobalId),
name: wall.Name ?? "")
{
RepresentationInstances = repData.RepresentationInstances
};
return result;
}

Expand Down
41 changes: 3 additions & 38 deletions Elements.Serialization.IFC/src/IFCToHypar/FromIfcModelProvider.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@ internal class FromIfcModelProvider
private readonly List<IfcRelationship> _ifcRelationships;

private readonly Dictionary<Element, IfcProduct> _elementToIfcProduct;
private readonly Dictionary<Guid, GeometricElement> _elementDefinitions;
private readonly List<string> _constructionErrors;

private readonly MaterialExtractor _materialExtractor;
Expand Down Expand Up @@ -70,7 +69,6 @@ public FromIfcModelProvider(string path,
_materialExtractor = new MaterialExtractor(styledItems);

_elementToIfcProduct = new Dictionary<Element, IfcProduct>();
_elementDefinitions = new Dictionary<Guid, GeometricElement>();

_representationDataExtractor = representationExtractor ?? GetDefaultRepresentationDataExtractor(_materialExtractor);
_fromIfcToElementsConverter = fromIfcConverter ?? GetDefaultFromIfcConverter();
Expand Down Expand Up @@ -136,39 +134,6 @@ private Element ConvertIfcProductToElement(IfcProduct product)
return null;
}

// If the product has IfcMappedItem representation, it will be used
// to create an ElementInstance. If the definition isn't exist in
// _elementDefinitions, it will be extracted from IfcMappedItem
// and added to _elementDefinitions.
if (repData.MappingInfo != null)
{
// TODO: Handle IfcMappedItem
// - Idea: Make Representations an Element, so that they can be shared.
// - Idea: Make PropertySet an Element. PropertySets can store type properties.
if (!_elementDefinitions.TryGetValue(repData.MappingInfo.MappingId, out var definition))
{
definition = _fromIfcToElementsConverter.ConvertToElement(product, repData, _constructionErrors);

if (definition == null)
{
//Debug.Assert(false, "Cannot convert definition to GeometricElement.");
return null;
}

definition.IsElementDefinition = true;
_elementDefinitions.Add(repData.MappingInfo.MappingId, definition);
//definition.SkipCSGUnion = true;
}

// The cartesian transform needs to be applied
// before the element transformation because it
// may contain scale and rotation.
var instanceTransform = new Transform(repData.MappingInfo.MappingTransform);
instanceTransform.Concatenate(repData.Transform);
var instance = definition.CreateInstance(instanceTransform, product.Name ?? "");
return instance;
}

// If the product doesn't have an IfcMappedItem representation, it will be converted to
// a GeometricElement.
var element = _fromIfcToElementsConverter.ConvertToElement(product, repData, _constructionErrors);
Expand Down Expand Up @@ -224,10 +189,10 @@ private static IFromIfcProductConverter GetDefaultFromIfcConverter()
/// </summary>
private static IfcRepresentationDataExtractor GetDefaultRepresentationDataExtractor(MaterialExtractor materialExtractor)
{
IfcRepresentationDataExtractor extractor = new IfcRepresentationDataExtractor(materialExtractor);
IfcRepresentationDataExtractor extractor = new IfcRepresentationDataExtractor();

extractor.AddRepresentationParser(new IfcFacetedBrepParser());
extractor.AddRepresentationParser(new IfcExtrudedAreaSolidParser());
extractor.AddRepresentationParser(new IfcFacetedBrepParser(materialExtractor));
extractor.AddRepresentationParser(new IfcExtrudedAreaSolidParser(materialExtractor));
extractor.AddRepresentationParser(new IfcMappedItemParser(extractor));
extractor.AddRepresentationParser(new IfcBooleanClippingResultParser(extractor));

Expand Down
Loading
Loading