Geometry of linked files

Geometry of linked files

BenoitE&A
Collaborator Collaborator
6,091 Views
11 Replies
Message 1 of 12

Geometry of linked files

BenoitE&A
Collaborator
Collaborator

Hey all,

I have a problem with linked files in a host Revit document. 

Basically, I create a new document, link my clients document to mine and then do my stuff in my document only, not touching the original documents. Then I send my work to the clients and they just have to link it to their own documents.

Since I work on Rooms and they are hosted by Views and that Views are hosted by Levels, I need to re-create all the levels of the linked document in my own document.

This creates a transformation between my linked documents and my host document. 

For example, my lowest level is -19.25 in my host document and 516.70 in my linked document.

But when I try to use GetTransform it returns my identity : 

 

IList<Element> links = new FilteredElementCollector(uidoc.Document)
.OfCategory(BuiltInCategory.OST_RvtLinks)
.OfClass(typeof(RevitLinkInstance))
.ToElements();

foreach (Element instanceDoc in links)
{
collector = new FilteredElementCollector((instanceDoc as RevitLinkInstance).GetLinkDocument())
.OfClass(typeof(Level));
Transform t = (instanceDoc as RevitLinkInstance).GetTransform();
monMessage += "\r\n X " + t.BasisX
+ "\r\n Y " + t.BasisY
+ "\r\n Z " + t.BasisZ
+ "\r\n origine " + t.Origin
+ "\r\n échelle " + t.Scale;

 

Any idea where I am wrong ?

Thanks

Benoit


Benoit FAVRE
CEO of etudes & automates
www.etudesetautomates.com/
0 Likes
Accepted solutions (2)
6,092 Views
11 Replies
Replies (11)
Message 2 of 12

JimJia
Alumni
Alumni

Dear Benoit,

 

Please have a try using following codes:

IList<Element> linkInstances = new FilteredElementCollector(doc).OfClass(typeof(RevitLinkInstance)).ToElements();

            if (linkInstances.Count > 0)
            {
                foreach (Element link in linkInstances)
                {
                    RevitLinkInstance linkInst = (link as RevitLinkInstance);


                    Transform linkTrf = linkInst.GetTotalTransform();
                }
            }

The linkTrf transform is the one you want.


Jim Jia
Autodesk Forge Evangelist
https://forge.autodesk.com
Developer Technical Services
Autodesk Developer Network
Email: [email protected]
0 Likes
Message 3 of 12

BenoitE&A
Collaborator
Collaborator

Hey Jim,

Thanks for your fast reply, it does not change a thing. I correctly get the RevitLinkInstance but not the transforms (which are the identity transform).

 

Full code below.

Benoit

 

IList<Element> links = new FilteredElementCollector(uidoc.Document)
.OfClass(typeof(RevitLinkInstance))
.ToElements();

monMessage += "\r\n Document Hote " + uidoc.Document.PathName;

 

FilteredElementCollector collector = new FilteredElementCollector(uidoc.Document)
.OfClass(typeof(Level));
foreach (Element niveau in collector)
{
monMessage += "\r\n un niveau créé " + niveau.Name + " elevation " + (niveau as Level).Elevation;
}

 

foreach (Element instanceDoc in links)
{
monMessage += "\r\n Document suivant " + (instanceDoc as RevitLinkInstance).GetLinkDocument().PathName;
collector = new FilteredElementCollector((instanceDoc as RevitLinkInstance).GetLinkDocument())
.OfClass(typeof(Level));
foreach(Element niveau in collector)
{
monMessage += "\r\n un niveau créé " + niveau.Name + " elevation " + (niveau as Level).Elevation;
}
Transform t = (instanceDoc as RevitLinkInstance).GetTransform();
monMessage += "\r\n X " + t.BasisX
+ "\r\n Y " + t.BasisY
+ "\r\n Z " + t.BasisZ
+ "\r\n origine " + t.Origin
+ "\r\n échelle " + t.Scale;
}


Benoit FAVRE
CEO of etudes & automates
www.etudesetautomates.com/
0 Likes
Message 4 of 12

RPTHOMAS108
Mentor
Mentor

Works with either TotalTransform or Transform, think TotalTransform is for transformed instances within links rather than links themselves but to be honest I've never needed to use it.

 

If the instance is orientated to the space it lies within then identity would be expected regardless of level offset.

 

In the below you need to add 4.9 to the 9.8 value to get the actual level of the linked levels. If you are creating levels in your model based on a linked model then you really need to acquire co-ordinates if you want your level values to match in elevation. You need to tell your model where the elevation base should be to have the created levels in your model reflect the true value (according to the relative link position and its elevation base offset).

 

 

Capture1003.PNG

 

Capture1003a.PNG

Blue levels = linked model selected

 

If I want the black levels to be representative of the blue then I need to acquire co-ordinates which will change black level 1 to -1.5m (-4.921 ft). Alternatively if I publish co-ordinates then blue level 1 will change to 1.5m etc. The transform will tell me where the levels are in my model but the created level will have nonsense values until I acquire coordinates from the link (assuming link has correct levels and you want to acquire rather than publish). 

 

0 Likes
Message 5 of 12

BenoitE&A
Collaborator
Collaborator

Hi Richard,

Thanks for your detailed reply (as usual).

Yes indeed I create new levels in my host model in order to have the right view range for my views (I have large models with multiple floor elevations for the same level).

I thought the total transform would precisely give me this information : the offset between the basis in my host model and the basis in the linked models. If not, I don't understand what it is used for. So if it does not work I can indeed compute the offset between the values in the 2 basis by hand and put it back into the model, it is easy but a bit unsatisfactory, right ?

Benoit


Benoit FAVRE
CEO of etudes & automates
www.etudesetautomates.com/
0 Likes
Message 6 of 12

RPTHOMAS108
Mentor
Mentor

If you linked in the other model at 0,0,0 and it is parallel to the model co-ordinate system then there is no obvious reason for the .GetTransform functions but this isn't often the case for two models created by separate teams from separate templates.

 

The GetTotalTransform function is also used in nested family instances i.e. what is the placement base point (origin) and orientation (basis) of a nested family and how does this relate to the model space the host family is located in.

 

In relation to the .IsIdentity property it is probably badly named because the transform works based on a 3x4 matrix so how can it be identity? I think we understand it to mean that it is equivalent to a 3x3 matrix with origin set to zero and basis x,y,z pointing to their respective global axis i.e. no change from original and transformed geometry. When you use .OfPoint origin is considered when you use .OfVector origin is ignored. A transformation without origin has no translation.

 

0 Likes
Message 7 of 12

BenoitE&A
Collaborator
Collaborator

Hey,

Thanks Richard for your help.

Still my question remains: my model's basis and my linked model's basis are clearly translated one to the other, and the TotalTransform function returns the identity transformation. So how do I get my transformation without doing it "by hand" ?

Benoit


Benoit FAVRE
CEO of etudes & automates
www.etudesetautomates.com/
0 Likes
Message 8 of 12

RPTHOMAS108
Mentor
Mentor
Accepted solution

According to the internal co-ordinate system your models share the same origin and alignment.

 

Please clarify:

  1. if you are inserting by origin to origin or shared coordinates?
  2. How are you coming to the conclusion there is a translation between your models (from Revit level values or reading internal co-ordinates)?
  3. When you state two different level values for bottom level are different are they set to Shared or Project? If both set to project then do the differences in level still not relate to the physical gap between them?
  4. Note that you cannot set a level to be measured from the relative location but you can set an elevation marker to this, as below. In the below example -0.366 is actually 0 in terms of internal co-ordinates. In the lookup and on the level class this is noted as ProjectElevation but that is confusing terminology since it isn't relative to project base point (which can be moved just as the survey point can).

Capture1403.PNG

Message 9 of 12

BenoitE&A
Collaborator
Collaborator
Accepted solution

Hi Richard,

Sorry for the delay I had some urgent stuff.

So I guess I have the answer to my original question, easier than I thought.

Here are the answers to the questions you asked :

1/ I use Origin to Origin, the only way to get my 2 models at their right position (without having to modify the position after loading).

2/ I come to the conclusion that there is a coordinate modification between my 2 models because I check my levels elevation both in my host model and in my linked models. And I have created all the levels of my host model myself, so I know by construction that they are the same as the levels of the linked model.

3/ I don't understand the question. The thing is, I created the bottom level in the Host model so I know it is the same as the bottom level of my linked models. So having 2 different elevations for the same level means that the basis in which the coordinates are evaluated is not the same in host and linked model.

4/ ok. It drives me to the solution I have found : using ProjectElevation instead of Elevation. And this looks ok, I still need to confirm this.

Thank you for your time.

Benoit

 


Benoit FAVRE
CEO of etudes & automates
www.etudesetautomates.com/
0 Likes
Message 10 of 12

jeremytammik
Autodesk
Autodesk

Dear Benoit and Richard,

 

Can you share a snippet of code illustrating how all the elevations from the different levels from the linked documents can be listed in one single coherent list?

 

Thank you!

 

Cheers,

 

Jeremy

 



Jeremy Tammik
Developer Technical Services
Autodesk Developer Network, ADN Open
The Building Coder

0 Likes
Message 11 of 12

BenoitE&A
Collaborator
Collaborator

Hi Jeremy,

I don't know if it is the best way but here is what we created:

- First find all documents and linkedDocuments of the HostDocument. Since a document can be linked in another, we use recursion and store the list of RevitLinkInstances in a class variable. I wrote this quick so maybe there are some mistakes.

        internal List<RevitLinkInstance> _listRLI;
        internal static void FindAllDocuments(Document currentDoc)
        {
            FilteredElementCollector links = new FilteredElementCollector(currentDoc)
                .OfClass(typeof(RevitLinkInstance));
            foreach(Element e in links)
            {
                RevitLinkInstance rli = e as RevitLinkInstance;
                if (rli == null)
                    continue;
                if (_listRLI.Contains(rli))
                    continue;
                _listRLI.Add(rli);
                Document doc = rli.GetLinkDocument();
                FindAllDocuments(doc);
            }
        }

Then for each document (found from the RevitLinkInstance) you can collect all levels. And check if its elevation is close to the elevation of a level you already have in your list (by say 1 cm).


Benoit FAVRE
CEO of etudes & automates
www.etudesetautomates.com/
Message 12 of 12

jeremytammik
Autodesk
Autodesk

Dear Benoit,

 

Thank you very much for your helpful and complete answer!

 

All clear now, I hope.

 

Cheers,

 

Jeremy

 



Jeremy Tammik
Developer Technical Services
Autodesk Developer Network, ADN Open
The Building Coder

0 Likes