xBimTeam / XbimEssentials

A .NET library to work with data in the IFC format. This is the core component of the Xbim Toolkit
https://xbimteam.github.io/
Other
477 stars 171 forks source link

Model instances filter from interfaces #541

Closed RolandoTonin closed 7 months ago

RolandoTonin commented 7 months ago

I want to filter elements in a model by user interfaces choices (check names from a listview in a WPF App). I has written a method like this:

public IEnumerable<object> GetElementsToCheck(object model, string iifcInterface)
{
    if (model is IfcStore ifcModel)
    {
        switch (iifcInterface)
        {
            case "IIfcBuildingElement":
                return ifcModel.Instances.OfType<IIfcBuildingElement>();
            case "IIfcBuildingElementProxy":
                return ifcModel.Instances.OfType<IIfcBuildingElementProxy>();
            case "IIfcElement":
                return ifcModel.Instances.OfType<IIfcElement>();
            case "IIfcPile":
                return ifcModel.Instances.OfType<IIfcPile>();
            case "IIfcBeam":
                return ifcModel.Instances.OfType<IIfcBeam>();
            case "IIfcColumn":
                return ifcModel.Instances.OfType<IIfcColumn>();
            case "IIfcPipeSegment":
                return ifcModel.Instances.OfType<IIfcPipeSegment>();
            case "IIfcPipeSegmentType":
                return ifcModel.Instances.OfType<IIfcPipeSegmentType>();
            case "IIfcProject":
                return ifcModel.Instances.OfType<IIfcProject>();

            default:
                throw new NotImplementedException($"choices not implemented for:  {iifcClass})");
        }
    } 

this method must be updated every time i insert a new IFC interfaces. Is it possible to convert a interfaces name like above to an .interfaces type and pass it to a methods like OfType?

thanks a lot Rolando

andyward commented 7 months ago

There's an overload of OfType that takes a string. So you can do

  return ifcModel.Instances.OfType("IfcBeam", true); // returns an IEnumerable<IPersistEntity>

Note this is the typename not interface name, so drop the leading 'I'

RolandoTonin commented 7 months ago

Thanks Andy,

I have checked and it seems to work fine. I had tried with the same method but passing interface not class and with interfaces name not working. I have a further question. If I need to use an array of class name strings (multiselect) instead a singol string class name, how can I do to avoid duplicate element in result IEnumerable? thanks a lot Rolando

andyward commented 7 months ago

Something like this:

using Xbim.Common;
using Xbim.Ifc;

IModel model = IfcStore.Open("SampleHouse4.ifc");

var types = new List<string>() { "IfcWall", "IfcWallStandardCase", "IfcDoor" };

IEnumerable<IPersistEntity> entities = GetEntities(model, types);

foreach (var entity in entities)
{
    Console.WriteLine(entity);
}

static IEnumerable<IPersistEntity> GetEntities(IModel model, List<string> types)
{
    var entities = Enumerable.Empty<IPersistEntity>();

    foreach (var type in types)
    {
        entities = entities.Union(model.Instances.OfType(type, true));
    }
    return entities;
}

Union will deduplicate the items. If you'd used Concat instead you would end up with duplicate IFCWallStandardCases since OfType("IfcWall") includes all subclasses by default

RolandoTonin commented 7 months ago

thamks a lot Andy. It Works fine.

RolandoTonin commented 5 months ago

Hy Andy,

I have another question.

Is it possible to get IFCPRESENTATIOLAYER value from an element instance like an IFCBuildingElementProxy?

I have tried to explore c# properties of an IIfcBuildingElementProxy in a debug window in Visual Studio but I Have not found it.

I have also tried a different way such as this:

var layers = model.Instances.Where(a => a != null);

but when I want to explore in debug windows layers properties I haven't found elements directly associated

Thanks a lot

Rolando

Da: Andy Ward @.> Inviato: lunedì 4 dicembre 2023 16:25 A: xBimTeam/XbimEssentials @.> Cc: RolandoTonin @.>; Author @.> Oggetto: Re: [xBimTeam/XbimEssentials] Model instances filter from interfaces (Issue #541)

Something like this:

using Xbim.Common;

using Xbim.Ifc;

IModel model = IfcStore.Open("SampleHouse4.ifc");

var types = new List() { "IfcWall", "IfcWallStandardCase", "IfcDoor" };

IEnumerable entities = GetEntities(model, types);

foreach (var entity in entities)

{

Console.WriteLine(entity);

}

static IEnumerable GetEntities(IModel model, List types)

{

var entities = Enumerable.Empty<IPersistEntity>();

foreach (var type in types)

{

    entities = entities.Union(model.Instances.OfType(type, true));

}

return entities;

}

Union will deduplicate the items. If you'd used Concat instead you would end up with duplicate IFCWallStandardCases since OfType("IfcWall") includes all subclasses by default

- Reply to this email directly, view it on GitHubhttps://github.com/xBimTeam/XbimEssentials/issues/541#issuecomment-1838876666, or unsubscribehttps://github.com/notifications/unsubscribe-auth/ACKQZ3N2HLRMORF55KPSINTYHXTLTAVCNFSM6AAAAABAFRDYH6VHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMYTQMZYHA3TMNRWGY. You are receiving this because you authored the thread.Message ID: @.**@.>>

andyward commented 5 months ago

Rolando,

Assuming you mean IfcPresentationLayerAssignment you'd just need to traverse the relationships as shown by the diagram in https://standards.buildingsmart.org/IFC/DEV/IFC4_2/FINAL/HTML/link/ifcpresentationlayerassignment.htm

e.g. IfcProduct => Representation => Representations=> LayerAssignments

Using XbimXplorer is a good way to see these relations:

image

RolandoTonin commented 5 months ago

Thanks Andy,

I'll explain. I need to retrieve the name of the IIfcPresentationLayerAssignment for each IIfcBuildingElementProxy and if its name matches a search filter then I can do certain operations on it. I have tried with below code but x is always null....

foreach (IIfcBuildingElementProxy element in model.Instances.OfType()) {

foreach(IIfcRepresentation itm in element.Representation.Representations)
{
    var x = itm.LayerAssignments.FirstOrDefault();
    if(x != null && x is IIfcPresentationLayerAssignment layer)
    {
        //......
    }
}

}

Thanks a lot Rolando

Da: Andy Ward @.> Inviato: giovedì 29 febbraio 2024 18:07 A: xBimTeam/XbimEssentials @.> Cc: RolandoTonin @.>; Author @.> Oggetto: Re: [xBimTeam/XbimEssentials] Model instances filter from interfaces (Issue #541)

Rolando,

Assuming you mean IfcPresentationLayerAssignment you'd just need to traverse the relationships as shown by the diagram in https://standards.buildingsmart.org/IFC/DEV/IFC4_2/FINAL/HTML/link/ifcpresentationlayerassignment.htm

e.g. IfcProduct => Representation => Representations=> LayerAssignments

Using XbimXplorer is a good way to see these relations:

image.png (view on web)https://github.com/xBimTeam/XbimEssentials/assets/923699/a0a572e5-c022-4d57-946e-b8c65f7fc088

- Reply to this email directly, view it on GitHubhttps://github.com/xBimTeam/XbimEssentials/issues/541#issuecomment-1971583387, or unsubscribehttps://github.com/notifications/unsubscribe-auth/ACKQZ3JNCUVF274JVSDXUELYV5P23AVCNFSM6AAAAABAFRDYH6VHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMYTSNZRGU4DGMZYG4. You are receiving this because you authored the thread.Message ID: @.**@.>>

andyward commented 5 months ago

I guess there may be no LayerAssignments in the model. Check in XbimXplorer (or just inspect the IFC)

Another option is you may have the wrong schema namespaces. What are your using statements on this code?

RolandoTonin commented 5 months ago

Thanks Andy,

effectively if I open IFC 2x3 in XBIM Xplorer it seems that aren't LayerAssignment:

@.***

But if I open the same IFCModel in Navisworks 2023 and select the same IFCBuildingElementProxy I have:

@.***

Where IfcPresentationLayer has a value.

In Ifc File I Have found:

2019053=IFCPRESENTATIONLAYERASSIGNMENT('PR_35_31_05_05',$,(#76477,#181120,#257154,#288724,#579634,#1477332,#1482451,#1517873,#1532625,#1604962,#1622538,#1640219,#1690031,#1793388,#1806057,#1826357,#1834616),'98');

And for the first element of the list:

76477=IFCFACETEDBREP(#76478);

76478=IFCCLOSEDSHELL((#72764,#72768,#72772,#72776,#72780,..........

Also, I have just tried in my code to inspect IfcBuildingElementProxy using instance (using Ifc.......2x3) instead interfaces, like this method:

using Xbim.Ifc2x3.PresentationOrganizationResource; using Xbim.Ifc2x3.ProductExtension; using Xbim.Ifc2x3.RepresentationResource; ....

private string GetIIfcPresentationLayerAssignmentName2X3(IIfcBuildingElementProxy element) { if(element is IfcBuildingElementProxy bep) { foreach (IfcRepresentation itm in bep.Representation.Representations) { var x = itm.LayerAssignments.FirstOrDefault(); if (x != null && x is IfcPresentationLayerAssignment layer) { return layer.Name; } } } return string.Empty; }

Thanks a lot Andy for your answers Rolando Tonin

Da: Andy Ward @.> Inviato: venerdì 1 marzo 2024 12:04 A: xBimTeam/XbimEssentials @.> Cc: RolandoTonin @.>; Author @.> Oggetto: Re: [xBimTeam/XbimEssentials] Model instances filter from interfaces (Issue #541)

I guess there may be no LayerAssignments in the model. Check in XbimXplorer (or just inspect the IFC)

Another option is you may have the wrong schema namespaces. What are your using statements on this code?

- Reply to this email directly, view it on GitHubhttps://github.com/xBimTeam/XbimEssentials/issues/541#issuecomment-1972983446, or unsubscribehttps://github.com/notifications/unsubscribe-auth/ACKQZ3KRQNJBWPFDO66WUYLYWBOBFAVCNFSM6AAAAABAFRDYH6VHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMYTSNZSHE4DGNBUGY. You are receiving this because you authored the thread.Message ID: @.**@.>>

andyward commented 5 months ago

So that's down to the tool that exported/authored the IFC originally & not something you can solve in xbim...