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
469 stars 170 forks source link

Altering IfcProjects worldcoordinatesystem yields differing results. #355

Open Payani-T opened 3 years ago

Payani-T commented 3 years ago

I'm trying to create a small piece of software that moves IFC files between a local and world coordinate system. We work in projects were we get tons of models weekly and there's always one or two exported in the wrong system, being able to move these would be of great help.

I've used the code below to some success, but the issue I'm having is when opening the altered IFC its location depends on what file reader is in use. We are using Navisworks Manage, and when its using the normal reader the file doesn't move, if we select the Revit one it does but it takes forever to open. Linking the file in to Revit is usually successful. (going to try Solibri on Monday)

is moving all the individual objects in relation to the ifcproject or ifcsites location the only way to assure the altered position is always shown?

//Open Model using (var model = IfcStore.Open(OpenLocation.Text, editor)) { var project = model.Instances.OfType().FirstOrDefault();

            using (var txn = model.BeginTransaction())
            {

                //Create new placement based on previous model placement and currently selected profile.
                IfcAxis2Placement3D currentwcs = (IfcAxis2Placement3D)project.ModelContext.WorldCoordinateSystem;

                var newPlacement = model.Instances.New<IfcAxis2Placement3D>();
                newPlacement.Location = model.Instances.New<IfcCartesianPoint>(p => p.SetXYZ(currentwcs.Location.X + currentprofile.X,
                                                                                             currentwcs.Location.Y + currentprofile.Y,
                                                                                             currentwcs.Location.Z + currentprofile.Z));

                project.ModelContext.WorldCoordinateSystem = newPlacement;

                txn.Commit();
            }

            string saveloc = System.IO.Path.GetDirectoryName(OpenLocation.Text) + @"\UNVERIFIED_MOVED_"
                                                                    + System.IO.Path.GetFileName(OpenLocation.Text);

            model.SaveAs(saveloc);
        }
bekraft commented 3 years ago

Hi, I do the alignment in a similar way. Actually, I don‘t know where the ‚ModelContext‘s WCS is from, but I assume your are fetching the root placement from the model‘s placement tree. I retrieve it using the first product descendant of the project root (if there‘s a single otherwise it gets tricky). If you directly pass in coordinate values, you‘ll silently assume a model length measurement unit. If these unit factors differ from model to model you will get scaling effects on the importer side. So make sure all models deal with the same scale of length. Concerning Revit: We perceived a lot of problems with IFCs having „large“ offsets. Somehow the shift between global internal origin and the building components lead to accuracy problems inside the geometry kernel (usually Revit complains about unconnected faces...). It also has problems with full placements in terms of rotated and translated placements. It doesn‘t apply the rotation part. Navisworks has similar problems. In general, it’s best practice for Revit to reference IFC models only, not to import. For Solibri everything works fine.

Payani-T commented 3 years ago

Hi,

Thanks for your reply. Neither do i to be perfectly honest, its been a bit of trying this and that to see what works. Now that ive had a moment to test things it seems that it is only the revit importer that "sees" the changes to the location, when opening the files in solibri or bimvision they end up on the same spot as they started on. So the move only shows up in revit or when using the revit importer in navisworks. Ill give what you said a try when i get some time over. Was considering trying to move the ifc site rather than the wcs aswell, something has to work :) thanks for the tip, was actually working on some kind of value conversion as we tend to get files in mm and m.

I havent actually encountered the unconnected faces issue yet, but we do get alot of "jumping" when we turn on our survey base point and project basepoint(if i remember correctly the differece is around 165 113 x 6 332 268 meters) or when we have any file or item far away. It goes away thoug when turning them off or if your using a crop so the issue is managable.
Agreed, we got a strict only linking policy, it will be even stricter when im done with our bim manual!

Payani-T commented 3 years ago

Hi, I do the alignment in a similar way. Actually, I don‘t know where the ‚ModelContext‘s WCS is from, but I assume your are fetching the root placement from the model‘s placement tree. I retrieve it using the first product descendant of the project root (if there‘s a single otherwise it gets tricky).

would you mind sharing how you do it? i cant seem to get it working. Had a go at moving the site but the problem reversed it self. I can now see the moved objects when using the normal Navisworks import. however, when opening the file in revit it has not moved from its original position.

might just stick to the first bit of code i posted and do the move with the transform tool within Navis if its needed.

bekraft commented 3 years ago

My solution (under heavy dev: https://github.com/bekraft/BitubTRex/tree/dev) is a little more complex since it wraps it into a transform worker class. It's implemented as a 2-by-2-point affine transformation. Means, a delta transformation is computed from a source point and a direction X-vector to a target point and a target direction vector. Afterwards the inverse delta is put onto the current root placement. The basic math happens here: IfcReferenceAxis.TransformAxisTo and is applied here IfcPlacementTransformRequest.ChangePlacement.

There a test case which wraps the complete workflow IfcPlacementTransformRequestTests.OffsetShiftAndRotateTest1