Highlight 100,000 nodes(XYZ coordinates) at once in Revit

Highlight 100,000 nodes(XYZ coordinates) at once in Revit

Anonymous
Not applicable
1,660 Views
18 Replies
Message 1 of 19

Highlight 100,000 nodes(XYZ coordinates) at once in Revit

Anonymous
Not applicable

 used AVF style to highlight the nodes. Right now, it is taking about 3 seconds to create around 30,000 nodes. But, when I try to move around my model by changing the view angles in 3D view after highlighting by AVF markers, it is so so so laggy while moving around in 3D view. Revit just takes forever for that. 

 

In later part of the project, I'll be creating 100,000 or more nodes, and I can't go ahead with AVF markers. I also tried creating spheres using direct shapes. It takes about 20 seconds to create 30,000 spheres, however its a bit less lagging while moving around in 3D view in case of spheres. I did like spheres a bit more, but it takes too long to create them.

 

So, what would be a better way in my case to highlight the nodes, about 100,000 nodes at once and then moving around in 3D view?

0 Likes
Accepted solutions (2)
1,661 Views
18 Replies
Replies (18)
Message 2 of 19

Sean_Page
Collaborator
Collaborator

Could you place a family (spherical or other) at the locations? I have used a method like this for a space planning  add-in and it is usually pretty quick.

Sean Page, AIA, NCARB, LEED AP
Partner, Computational Designer, Architect
Message 3 of 19

jeremytammik
Autodesk
Autodesk

Don't use spheres in this number in any shape or form!

  

Even with a totally minimal tessellation, each sphere will require at least 4 x 4 x 2 = 32 triangles to display.

 

Probably MUCH more!

  

Use a tetrahedron instead, clocking in at four faces.

  

If nothing else, you have reduced your triangle count by a factor of eight (probably much more).

  



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

Message 4 of 19

Anonymous
Not applicable

Instead of sphere, I tried just by creating a single line using below code.

 

XYZ q = p + new XYZ(0,0,0.5);

Line line = Line.CreateBound(p, q);

ModelCurve curve = doc.IsFamilyDocument
? doc.FamilyCreate.NewModelCurve(line, sketchPlane)
: doc.Create.NewModelCurve(line, sketchPlane);

 

So, in this case I am creating only one curve each time, so it should take less time. Now, I can highlight around 60,000 lines in 30 seconds, an improvement in speed. But, still it's too slow.

 

Is there any other way, where I can highlight couple of thousands of XYZ coordinates in few seconds.

0 Likes
Message 5 of 19

Anonymous
Not applicable

Can you provide some example of like which type of Family I can use and how to place it at the location? I can try that and see how much feasible is it in my case. Thank you.

0 Likes
Message 6 of 19

Sean_Page
Collaborator
Collaborator

What does the bit of your code look.like where your creating these? Are you doing it one at a time within a single transaction or creating all the lines in a list then crating them? Seems like there may be something in that we could may see. Also, make sure your disposing of the geometry so your not loading up your RAM.

Sean Page, AIA, NCARB, LEED AP
Partner, Computational Designer, Architect
0 Likes
Message 7 of 19

Anonymous
Not applicable

I am not sure if it is the best way to do this. But, this is how I am doing it.

 

using (Transaction t = new Transaction(uidoc.Document, "Highlight Nodes"))
{

foreach (XYZ xyz in xyzList)
{

XYZ q = p + new XYZ(0,0,0.5);

Line line = Line.CreateBound(p, q);

ModelCurve curve = doc.IsFamilyDocument
? doc.FamilyCreate.NewModelCurve(line, sketchPlane)
: doc.Create.NewModelCurve(line, sketchPlane);}

}

 

 

0 Likes
Message 8 of 19

Sean_Page
Collaborator
Collaborator

Not sure it would accelerate it that much, but it would probably make sense to move your FamilyDoc check outside of the loop. That way it only has to do it once, and then you determine which Method to use.

 

Also, are you doing anything with the ModelCurve that is created? The code doesn't look like it, but yet you are Creating a variable and storing it, at least until the next one is made.

Sean Page, AIA, NCARB, LEED AP
Partner, Computational Designer, Architect
0 Likes
Message 9 of 19

jeremytammik
Autodesk
Autodesk

You model curves are all database elements. That is heavy weight. Can you possibly create non-database-resident in-memory objects instead and highlight those using AVF, the analysis visualisation framework?

 

https://thebuildingcoder.typepad.com/blog/avf/

 

And, another, totally separate suggestion: displaying 100000 objects sounds like a point cloud to me. Can't you create a point cloud for your points and use the point cloud functionality to visualise them? That is exactly what it is made for!

 



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

0 Likes
Message 10 of 19

Anonymous
Not applicable

Thank you for pointing out those details. I tried removing unnecessary things outside of transaction.

It did accelerate it by few seconds, but it didn't make any significant improvement in the loading time. 

Next step, I am looking into using PointCloud as suggested by jeremy. 

 

0 Likes
Message 11 of 19

Anonymous
Not applicable

I was using AVF framework, but it was still taking too long to load. And the performance of AVF while moving around in 3D view was a major drawback. 

 

I started looking into PointCloud. I found below example here, http://help.autodesk.com/view/RVT/2016/ENU/?guid=GUID-B80DBCF1-56A8-4864-A0CD-181466E0EDE8.

 

PointCloudType type = PointCloudType.Create(doc, "rcs", "c:\\32_cafeteria.rcs");
    return (PointCloudInstance.Create(doc, type.Id, Transform.Identity));

I am first trying to understand, how PointCloud works and how does it take the input of xyz coordinates.
And if we provide input by a file, then what should be the format of the file.
Can you provide an example or a link to a good documentation, where I can take a look.
Thank you.

0 Likes
Message 12 of 19

jeremytammik
Autodesk
Autodesk

So am I. I have been trying for years. Things changed since Revit 2016, and I have no up-to-date answer to that. I am asking the development team for you right now.

 



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

Message 13 of 19

Anonymous
Not applicable

So, we got it to work but in a bit hacky way because we couldn't figure out how to supply our coordinates to the PointCloud. So, we are still looking deep into PointClouds. But, the performance has been improved by a great deal. So, we will move ahead with Point Clouds in our project.

Thank you for helping out and replying so quickly.

0 Likes
Message 14 of 19

jeremytammik
Autodesk
Autodesk

Can you share the most important steps in getting it to work so far? What exactly did you achieve, and how? Thank you!

 



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

0 Likes
Message 15 of 19

Anonymous
Not applicable
Accepted solution

https://github.com/jeremytammik/RevitSdkSamples/tree/master/SDK/Samples/PointCloudEngine/CS.

 

Above link really helped us understand how PointCloudEngine works, and we were able to make our own custom Engine. 

 

Step-1: Create PointCloud engine (use the reference code provided in sdk)

 

Step-2: Initialize engine, and register it.

IPointCloudEngine engine = new BasicPointCloudEngine(PointCloudEngineType.Predefined);
PointCloudEngineRegistry.RegisterPointCloudEngine("test", engine, false);

 

Step-3: Provide input of points

In the sdk, there is a method called GeneratePoints in PointCloudCellStorage class, where points are being added to a buffer called m_pointsBuffer. 

Now, we can't call that method because it is being called automatically by PointCloudType.Create(). 

So, we created a list of the XYZ points, which we want to highlight and made it available throughout our package. And in GeneratePoints method, we iterate through that list and add points to a buffer called m_pointsBuffer. 

So, now when we use PointCLoudType.Create(), our engine will add our points to that buffer.

 

Step-4: Display the PointCloud.

PointCloudType type = PointCloudType.Create(m_doc, "test", "");
PointCloudInstance instance = PointCloudInstance.Create(m_doc, type.Id, Transform.Identity);

Whenever you want to display the PointCloud, use above code, and it'll highlight all the points provided to engine.

We also used doc.delete(instance.id), so that next time we show the modify our list and show new points.

 

For the speed, it can highlight around 100,000 points per second. 

Main problem with pointcloud is that the highlighted part is really small. So, you would want to create more points close to each other, so that the cluster can be easily visible.

 

0 Likes
Message 16 of 19

Anonymous
Not applicable
Accepted solution

https://github.com/jeremytammik/RevitSdkSamples/tree/master/SDK/Samples/PointCloudEngine/CS

Above link really helped us understand how PointCloud works, and we were able to create our own custom engine.

We are focusing on PredefinedPointCloud class, because we want to provide non-file-based input.

 

Step-1: Create your engine (use the code provided in the above link,)

 

Step-2: Initialize your engine, and register it.

IPointCloudEngine engine = new BasicPointCloudEngine(PointCloudEngineType.Predefined);
PointCloudEngineRegistry.RegisterPointCloudEngine("apipc", engine, false);

We do this only once, so we have put above code in start-up part of the addin.

 

Step-3: Provide input to the engine.

Whenever we want to provide the input of XYZ coordinates, we create a list of all the coordinates we want to highlight, and make that list available throughout our package.

Now, there is a method called GeneratePoints in PointCloudCellStorage, which adds all the individual points to a buffer called m_pointsBuffer.

We can't call that method directly, because it is being called automatically by Revit when we use PointCloudType.Create().

So, we changed the GeneratePoints in method our engine and made it iterate through our list of coordinates, and add those points to the buffer m_pointsBuffer.

 

Step-4: Display your points.

PointCloudType type = PointCloudType.Create(m_doc, "test", "");
PointCloudInstance instance = PointCloudInstance.Create(m_doc, type.Id, Transform.Identity);

So, here when we use PointCLoudType.Create(), it will eventually automatically call the method GeneratePoints and highlight our provided list of points.

We also used doc.delete(instance.id), so every time we create new instance, it'll delete the old PointCloudInstance.

 

For speed, it can highlight about 100,000 points per second. So, that's impressive.

A major drawback is that the highlighted part is very small, so you would want to create a group of points together, so the cluster can be easily visible.

 

I hope above explanation is understandable. 

Message 17 of 19

Anonymous
Not applicable

I have another question. So, you mentioned that the ModelCurves are heavy weight. 

I also want to draw lines in my project. Right now, with ModelCurves it takes more than a minute to draw few hundreds lines. 

For points, we used light-weight PointClouds to display them, which is really fast.

Similarly, is there any light weight way to draw lines in Revit?

0 Likes
Message 18 of 19

jeremytammik
Autodesk
Autodesk

Thank you for the explanation making use of the point cloud engine.

  

What version of Revit are you working with? 

  

I was under the impression that the point cloud engine functionality in Revit is deprecated. 

  

Happy to hear it still does the job well enough to satisfy your requirements.

    

Nope, I am not aware of any similar functionality for lines.

   

You can always add a bunch of points close together to approximate a line.

   



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

0 Likes
Message 19 of 19

Anonymous
Not applicable

We are using Revit 2019. It seems to be working fine. 

Right, I'll try putting bunch of points to make a line. 

0 Likes