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
484 stars 171 forks source link

[Question] Generating a sub-model starting from IFC + EntityLabel / GlobalId #240

Open westake opened 5 years ago

westake commented 5 years ago

Dear team, I am struggling to generate a sub-IFC model and I would highly appreciate your support.

My objective is to provide as input an IFC model and a GlobalId (or EntityLabel) of a floor, space, building, etc and to generate the IFC/wexbim sub-model considering the model hierarchy.

For instance if I provide the EntityLabel of floor 4, the output should be a new wexbim file containing the complete floor 4 of the building. If I provide the EntityLabel of the IfcBuilding (104 in the picture below), the sub-model should be exactly the same as the one in the original file.

What I did so far:

  1. I created the hierarchical structure based on @martin1cerny 's answer posted here

structure

  1. Depending on the input EntityLabel / GlobalId, I create the list of elements that must be included in the sub-model

  2. Based on the EntityLabel list, retrieve all IfcProducts from the initial model (model.InstanceHandles)

  3. Created a new model (the sub-model) by InsertCopy the list of IfcProducts into a new model and generate the wexbim:

code

  1. Preview the model on XbimWebUI

Some of my concerns:

I really appreciate any input!

martin1cerny commented 5 years ago

As your code is complaining about the log4net configuration missing I assume you are not using the latest xBIM libraries. Can you confirm that this is still a problem with the latest release? I have fixed a few issues lately.

westake commented 5 years ago

Thanks Martin, I'm using now the latest release and indeed lots of issues were solved, thank you! I will do further testing and let you know if I encounter any additional problems (for the moment looks like only the IFCWALLSTANDARDCASE are not transferred, but I will further check).

There is only one potential issue - regarding the IfcStore.InsertCopy(IEnumerable, Boolean, Boolean, XbimInstanceHandleMap) - it does not work with keepLabels = true as it always complain there is already an item with the same key added but I tested even with one element...

Thank you for your support!

martin1cerny commented 5 years ago

This will be caused by the IfcOwnerHistory initialization. Make sure the target model is completely empty or entity labels will clash.

westake commented 5 years ago

The model (subModel) should be empty as I am creating a new one as you can see in the code snippet above.

All my attempts failed. I tried to pass XbimEditorCredentials to IfcStore.Create and initialize the project as in this example but I am always getting the mentioned exception.

Do you have any hint for me? Thank you @martin1cerny !

andyward commented 5 years ago

IfcStore got refactored pretty heavily recently. It's possible I broke something as part of #227 - will take a look

andyward commented 5 years ago

OK, I can't reproduce this using IfcStore. It would be best if you could provide a test or, working example of it failing, including the definition of requiredProducts and a sample model.

westake commented 5 years ago

Hi Andy, I sent you an email containing a failing example including the ifc model. Thanks for support!

westake commented 5 years ago

Hello team!

I played a bit more with IfcStore.InsertCopy and besides the problem described above I discovered another potential issue (not sure what's the root cause right now). I tried to create a new model and copy the list of IIfcProduct from the initial model to the second model and create a wexbim afterwards based on the resulted model.

subModel.InsertCopy(model.Instances.OfType<IIfcProduct>(), true, false, map);

In parallel I also wrote the first model directly as a wexbim and compared the 2 models. I observed the following:

First model: screen shot 2019-01-31 at 3 36 21 pm

Second model (created with IfcStore.InsertCopy): screen shot 2019-01-31 at 3 31 37 pm

First model:

screen shot 2019-01-31 at 1 18 58 pm

Second model: screen shot 2019-01-31 at 3 39 10 pm

Here the original ifc files I used: IFC Models.zip

Moreover, sometimes the wexbim can become huge (Ifc model - 57 MB => wexbim 208 MB) and sometimes is significantly smaller than the ifc file. (e.g of ifc file that generates huge wexbim file: Quickstart.ifc.zip)

Do you have any clue what could be the root cause of this problem or what should I try?

I mention that I have the latest master Essentials and Geometry nuggets, installed from here: https://www.myget.org/F/xbim-master/api/v3/index.json

Thank you in advance for your support! Alexandru

martin1cerny commented 5 years ago

Hi Alexandru,

I'll try to get to this this week at some point.

Martin

westake commented 5 years ago

Hi @martin1cerny , do you have any update on this? Thanks and have a nice day! Alex

westake commented 5 years ago

Hi @martin1cerny, In the meantime, I discovered a faster way to generate filtered wexbim - using the SaveAsWexbim from IfcStoreGeometryExtensions and providing the optional param products here:

public static void SaveAsWexBim(this IModel model, BinaryWriter binaryStream, IEnumerable<IIfcProduct> products = null, IVector3D translation = null)

and avoiding the creation of a new in-memory model and using the time consuming IfcStore.InsertCopy. Unfortunately the overlapping layers (I think that's the reason for the visual artifacts) issue I reported above is still there... Do you have any suggestion how to avoid that?

Thanks, Alexandru

westake commented 5 years ago

Hello team,

Is there any update on the overlapping textures issue I mentioned above? Are there any known workarounds for this?

Thank you! Alex

westake commented 5 years ago

Hi @martin1cerny,

Do you have any update on overlapping textures issue I reported above?

Thank you in advance for your support! Alex

martin1cerny commented 5 years ago

Hi @Bissy29 ,

I just tried again and I can't see any problem using the latest code and this test:

const string original = @"IFC Schependomlaan.ifc";
using (var model = new IO.Memory.MemoryModel(ef2x3))
{
    var errs = model.LoadStep21(original);
    Assert.AreEqual(0, errs);
    using (model.BeginEntityCaching())
    using (model.BeginInverseCaching())
    {
        var products = model.Instances.OfType<IfcProduct>();
        using (var iModel = new IO.Memory.MemoryModel(ef2x3))
        {
            var map = new XbimInstanceHandleMap(model, iModel);
            using (var txn = iModel.BeginTransaction("Insert copy"))
            {
                var w = new Stopwatch();
                w.Start();
                iModel.InsertCopy(products, true, false, map);
                txn.Commit();
                w.Stop();

                var copies = Path.ChangeExtension(original, ".copy.ifc");
                using (var f = File.Create(copies))
                {
                    iModel.SaveAsIfc(f);
                    f.Close();
                }
            }

            // use all caching we can for this
            using (iModel.BeginEntityCaching())
            using (iModel.BeginInverseCaching())
            {
                // number of products should be the same
                var origProdCount = model.Instances.CountOf<IfcProduct>();
                var prodCount = iModel.Instances.CountOf<IfcProduct>();
                Assert.AreEqual(origProdCount, prodCount);

                // number of geometry representations should be the same
                var origRepCount = model.Instances.CountOf<IfcProductRepresentation>();
                var repCount = model.Instances.CountOf<IfcProductRepresentation>();
                Assert.AreEqual(origRepCount, repCount);

                // number of geometry representations should be the same
                var origRepItemCount = model.Instances.CountOf<IfcRepresentationItem>();
                var repItemCount = model.Instances.CountOf<IfcRepresentationItem>();
                Assert.AreEqual(origRepItemCount, repItemCount);

                // number of representation items in every product should be the same
                foreach (var product in model.Instances.OfType<IfcProduct>())
                {
                    var iProduct = map[new XbimInstanceHandle(product)].GetEntity() as IfcProduct;

                    var count = product.Representation?.Representations.SelectMany(r => r.Items).Count();
                    var iCount = iProduct.Representation?.Representations.SelectMany(r => r.Items).Count();

                    Assert.AreEqual(count, iCount);
                }
            }
        }
    }
}

The results seem to be visually identical with no visible artefacts:

image

image

If the problem still persists in your solution, can you provide a complete repeatable package? Code + IFC model (if other than already provided) + your resulting wexBIM file.

idars commented 4 years ago

Hello,

I've experienced these visual artefacts too, and they seem to occur if you save a model made with Create+InsertCopy directly as wexBIM as opposed to loading an already modified model from an IFC file.

string original = @"IFC Schependomlaan.ifc";
using (var model = IfcStore.Open(original))
{
    var products = model.Instances.OfType<IfcProduct>();

    using (var iModel = IfcStore.Create(model.SchemaVersion, Xbim.IO.XbimStoreType.InMemoryModel))
    {
        using (var txn = iModel.BeginTransaction())
        {
            var map = new XbimInstanceHandleMap(model, iModel);
            iModel.InsertCopy(products, true, true, map);
            txn.Commit();
        }

        var context = new Xbim3DModelContext(iModel);
        context.CreateContext();

        var copies = Path.ChangeExtension(original, "wexBIM");
        using (var f = File.Create(copies))
        {
            using (var writer = new BinaryWriter(f))
            {
                iModel.SaveAsWexBim(writer);
                writer.Close();
            }
            f.Close();
        }
    }
}

FlickeringWexbim.zip

This can also happen with other models. Saving a temporary IFC file of the model and then opening and exporting said file to wexBIM fixes this.

Hope this can lead you somewhere.