How to execute BooleanOperations on Revit-Solid by AutoCAD?

How to execute BooleanOperations on Revit-Solid by AutoCAD?

ankofl
Advocate Advocate
29,422 Views
20 Replies
Message 1 of 21

How to execute BooleanOperations on Revit-Solid by AutoCAD?

ankofl
Advocate
Advocate

We are all familiar with the problems with Boolean operations on solid objects. A lot of exceptions occur during the operations of union, intersection and subtraction. In one of the branches, it was proposed to export Revit-Solid to Cascad-Colid, perform painful and other operations in it, and upload back only the result of such calculations, or transfer Cascad-Solid back to Revit-Solid. 
SIX years after the beginning of this branch, the developers from Autodesk have not provided us with a working solution to this problem.
In my opinion, this is too complicated and time-consuming task to translate from Revit to Cascada, and it may be better to export Solid not to Cascad, but to AutoCAD, or rather use the loaded libraries to work with AutoCAD, but perform all operations in the Revit process. The already established export from DWG to RWT speaks in favor of this decision. Maybe it is possible to export Revit-Solid to AutoCAD-Solid and perform Boolean operations already there?

0 Likes
Accepted solutions (2)
29,423 Views
20 Replies
Replies (20)
Message 2 of 21

RPTHOMAS108
Mentor
Mentor

I've manually carried out boolean operations in AutoCad in the past (quite a while ago however) and I think you would likely get the same issues there unless they've updated what AutoCad uses since. People have noted that such operations are more stable in Dynamo since it uses a slightly different system so my focus would be more on that. It did occur to me that the reason could be the unit system. Since Revit uses ft and not a smaller unit such as inches or mm you have smaller number on the LHS of the decimal place and so the floating point errors also shift over. Or to put it another way the decimal part has errors that occur through operations that the integer part doesn't and by using ft you are relying on more decimal places for accuracy of the same real world sized object (around 3 more) than you would be for mm. 

 

All the units in Dynamo are converted to 'Dynamo Units' before such processing it seems. Would be interesting to test if you get more stability carrying out the operations after scaling the solids up SolidUtils.CreateTransformed (transform with uniform scale). You would likely have an issue if you then scale it back down (an edge too short) but it depends on the purpose of your operation i.e. calculating volume area vs needing to use in geometry. Perhaps I'm just clutching at straws since Dynamo uses it's own library also.

 

The other issue is that Revit doesn't appear to support all the forms of geometry that AutoCad does so you could end up after such operations in AutoCad having geometry that can't be brought back or is partial.

 

I think there is already a process in place for the connections which uses Advanced steel. When I looked at that previously it was working with dwgs in the background. Obviously you can Document.Export a dwg/sat use AutoCAD as a com server from the Revit process and Document.Import it back to access the geometry in Revit.

 

Message 3 of 21

ankofl
Advocate
Advocate

Dear RPTHOMAS108, the fact is that in AutoCAD it is impossible to pass a Solid object in the form of dots, triangles, or directly Solid itself. You can only create a Solid in AutoCAD itself using standard tools: extrusion, shift, etc. and then apply Boolean operations on them, such as addition, subtraction and intersection. If I am wrong, and any of the AutoCAD libraries makes it possible to upload Solid to it from Revit, or create Solid based on surfaces or triangles from Revit, I will be glad if you let me know. Otherwise, you will have to create many different methods to export different types of geometry to AutoCAD, which would then perform Boolean and other operations on them!
Thanks!

0 Likes
Message 4 of 21

RPTHOMAS108
Mentor
Mentor

Not sure about the AutoCAD API not used it for a while but you can open a dwg for sure and export a dwg from Revit also.

 

I think I would look for methods relating to SATs. e.g. Document.Import

 

Although generally I would probably leave AutoCAD out of the process.

AutoCAD 2022 Developer and ObjectARX Help | Boolean Method (ActiveX) | Autodesk

 

Most (if not all) of what you do via ActiveX/VBA can be accessed via COM, although VBA examples are VB6 but would be easy to convert to VB.Net and therefore C#. Then instead of using ThisDrawing/ThisApplication you would be creating a reference to such via COM. So I don't think it is imposable just wouldn't be the first direction I take with this.

 

I would try and look more closely at what Dynamo is doing since those components now come with Revit and AutoCAD doesn't. Even if they do have access to AutoCAD it doesn't mean they've installed it along with Revit.

 

Also as noted I've got a lot of 3d modelling experience as a user of AutoCad and like in Revit API Boolean operations either work or they don't (you need a good overlap of volume for certain operations to work). I think it comes down to if the faces become degenerate due to vertices merging (some libraries are better at cleaning up such things).

0 Likes
Message 5 of 21

ankofl
Advocate
Advocate

Thanks for the information.
To be honest, I don't quite understand how to transfer Boolean operations from Revit to Dynamo, and even more so how this will solve the problem, since they both rely on the same mechanisms.
In another branch, there was an idea about transferring Revit geometry to OpenCascade geometry, and performing further Boolean operations already in the OpenCascade system. It looks like I'll have to stop at this option

0 Likes
Message 6 of 21

RPTHOMAS108
Mentor
Mentor

I think Dynamo is using a different library it has the whole proto geometry thing with you having to convert between Dynamo geometry and Revit API geometry.

 

There are also more functions for manipulating geometry. The Revit API just exposes what Revit uses internally and those things often have their quirks.

 

Revit to ProtoSolid 

 

If we were able to pick out every single bit like this or just the bits we needed for a task then we could perhaps utilise the library in the API without Dynamo. Instead of this people focus their efforts in trying to load all the other dependencies of Dynamo just so they can do with the API what they do with Dynamo. They start with Dynamo 'oh this is so easy' they progress to the API then comes the repeated question 'how do I do this that I am doing in Dynamo with the API?' What can be said, nothing other than 'Dynamo is more end user orientated and if you want to solve the same problem as a developer you have to go back to first principles.' It is a frustration that Dynamo geometry operations are so easy in comparison.

 

C:\Program Files\Autodesk\Revit 2024\AddIns\DynamoForRevit\libg_229_0_0

C:\Program Files\Autodesk\Revit 2024\AddIns\DynamoForRevit\LibG.Interface.dll
C:\Program Files\Autodesk\Revit 2024\AddIns\DynamoForRevit\ProtoGeometry.dll

0 Likes
Message 7 of 21

ankofl
Advocate
Advocate

I sincerely hope that the correction of Boolean operations on solids in the Revit Api will happen in the near future, because at the moment the development of our own solution transferring Boolean operations from C# Revit to C++ OpenCascade looks excessively forced.Снимок экрана 2023-08-23 153911.jpg

0 Likes
Message 8 of 21

jeremy_tammik
Alumni
Alumni

Yup, valid concern, and sorry about the slow progress. I asked the development team for an update for you.

  

Jeremy Tammik Developer Advocacy and Support + The Building Coder + Autodesk Developer Network + ADN Open
Message 9 of 21

jeremy_tammik
Alumni
Alumni

They say: Unfortunately, we haven't had a chance to make progress on the front but are definitely aware of the issues. We have also had quite a few recent problem reports elsewhere related to failed Boolean operations.

  

By the way, a data set of issues with Booleans in the Revit API context might be nice to have.

  

Bringing the geometry into Dynamo and doing the operations there would be my recommendation, as it allows the user to see the intermediate steps when there is any kind of failure, which would make things easier to troubleshoot. They would want to learn the Dynamo intricacies, and of course running in the context of Dynamo means they aren't developing an add-in anymore but a Dynamo graph (in which they can call the Revit API).

  

Jeremy Tammik Developer Advocacy and Support + The Building Coder + Autodesk Developer Network + ADN Open
0 Likes
Message 10 of 21

ankofl
Advocate
Advocate
Accepted solution

Well, after a few days of development.. My decision to transfer Boolean operations from Revit C# to OpenCascade C++ is starting to bring results!
Of course, there are still problems with data transformation and backward compatibility (there is still a lot of work to be done on this), but in general, the solution has the right to life.
Here I want to address the question of how soon it will be possible to solve the problem with Boolean operations in Revit? If it's not a matter of two weeks, apparently I will have to perform further operations in geometry based on OpenCascade
Снимок экрана 2023-08-24 160728.jpg

Message 11 of 21

ankofl
Advocate
Advocate

Воз и ныне там...

0 Likes
Message 12 of 21

ankofl
Advocate
Advocate

Is this a response from ChatGPT to raise the reputation of the participant? If not, can you describe in more detail the conversion of Solid objects from Revit to AutoCAD and the result back?

0 Likes
Message 13 of 21

jeremy_tammik
Alumni
Alumni

My sentiments exactly. Where is the Unlike button?

 

By the way, congratulations on your success with OpenCascade! The  timeframe for progress on development of improvements to the built-in Boolean solid operations is probably a lot larger than two weeks, so your path is definitely worth pursuing if you need an immediate solution. I would love to share the technical details of your approach on the blog, if you are interested in that. Good luck and have fun!

    

Jeremy Tammik Developer Advocacy and Support + The Building Coder + Autodesk Developer Network + ADN Open
Message 14 of 21

ankofl
Advocate
Advocate
Accepted solution

Dear @jeremy_tammik 

Well
, it seems I'm finally close to a solution that suits me

UPD 08.09.2024:

Create .off file from revit-solid:

 

 

public static bool WriteOff(this Solid solid, out List<string> listString)
		{
			listString = ["OFF"];

			if(solid.CreateMesh(out var listVectors, out var listTri))
			{
				listString.Add($"{listVectors.Count} {listTri.Count} 0");
				listString.Add($"");

				foreach (var p in listVectors)
				{
					listString.Add(p.Write());
				}

				foreach (var v in listTri)
				{
					listString.Add($"3  {v.iA} {v.iB} {v.iC}");
				}

				return true;
			}
			return false;
		}

 

 

and this:

 

 

public static bool CreateMesh(this Solid solid, out List<XYZ> listVectors, out List<Tri> listTri)
		{
			double k = UnitUtils.ConvertFromInternalUnits(1, UnitTypeId.Meters);
			listVectors = [];
			listTri = [];

			bool allPlanar = true;

			int indV = 0;
			foreach (Face face in solid.Faces)
			{
				if (face is PlanarFace pFace)
				{
					Mesh mesh = pFace.Triangulate();
					for (int tN = 0; tN < mesh.NumTriangles; tN++)
					{
						var tri = mesh.get_Triangle(tN);

						var pT = new int[3];

						for (int vN = 0; vN < 3; vN++)
						{
							var p = tri.get_Vertex(vN) * k;

							if (p.Contain(listVectors, out XYZ pF, out int index))
							{
								pT[vN] = index;
							}
							else
							{
								pT[vN] = indV;
								listVectors.Add(p);
								indV++;
							}
						}

						listTri.Add(new(pT[2], pT[1], pT[0]));
					}
				}
				else
				{
					allPlanar = false;
				}
			}

			return allPlanar;
		}

 

 



Load .off file

 

 

#pragma once

bool load_from(const char* path, Mesh& output) {
    output.clear();
    std::ifstream input;
    input.open(path);
    if (!input) {
        return false;
    }
    else if (!(input >> output)) {
        return false;
    }

    input.close();
    return true;
}

 

 

Execute boolean

 

 

#pragma once

bool boolean_simple(Mesh m1, Mesh m2, b_t type, Mesh& out) {    
    out.clear();
    int code = 0;    
    if (!CGAL::is_triangle_mesh(m1)) {
        PMP::triangulate_faces(m1);
    }
    if (!CGAL::is_triangle_mesh(m2)) {
        PMP::triangulate_faces(m2);
    }
    if (type == b_t::join) {
        if (!PMP::corefine_and_compute_union(m1, m2, out)){
            std::cout << "fail_join ";
            return false;
        }
    }
    else if (type == b_t::inter) {
        if (!PMP::corefine_and_compute_intersection(m1, m2, out)){
            std::cout << "fail_inter ";
            return false;
        }
    }    
    else if (type == b_t::dif) {
        if (!PMP::corefine_and_compute_difference(m1, m2, out)) {
            std::cout << "fail_dif ";
            return false;
        }
    }  
    else {
        throw;
    }
    return true;
}

 

 


Save .off file:

 

 

#pragma once
#include <CGAL/Polygon_mesh_processing/IO/polygon_mesh_io.h>

bool save_to(const std::string path, Mesh input) {
    if (!CGAL::is_valid_polygon_mesh(input)) {
        return false;
    }
    try {
        if (CGAL::IO::write_polygon_mesh(path + ".off", input, CGAL::parameters::stream_precision(17))) {
            return true;
        }
        else {
            return false;
        }
    }
    catch (const std::exception& e) {
        std::cout << "save_to: exception!" << std::endl;
    }    
    return false;
}

 

 


Then you can upload the .off file back to revit, or do other manipulations with it. However, as far as I know, API Revit does not allow you to create a full-fledged Solid object, but only a triangular grid, i.e. you can upload the grid obtained through CGAL to Revit for viewing, but you will not be able to perform further operations on solid with it, but only view its geometry through DirectShape

Message 15 of 21

jeremy_tammik
Alumni
Alumni

Wow! Congratulations! That looks like a brilliant solution. Thank you for sharing it. Regarding your final sentences, I believe you can in fact generate solid shapes in your DirectShape object by using the BRepBuilder class; it allows direct construction of geometry objects including solids, closed and open shells, etc.:

  

  

Jeremy Tammik Developer Advocacy and Support + The Building Coder + Autodesk Developer Network + ADN Open
Message 16 of 21

jeremy_tammik
Alumni
Alumni

Thank you again for sharing this. I put it into context and shared it on the blog for wider recognition:

  

  

Do you have anything to correct or more to add since last? Thank you!

  

Jeremy Tammik Developer Advocacy and Support + The Building Coder + Autodesk Developer Network + ADN Open
Message 17 of 21

ankofl
Advocate
Advocate

Good afternoon!
Thank you so much for mentioning my answer in your blog! It's very nice! At the moment, my main task in my current job is to finish the program for creating an energy model of a building and calculating heat loss with its help (the required amount of energy and maintaining the internal temperature in rooms at a given temperature outside, taking into account the thermal resistance to heat transfer of building structures). At the current stage, I have implemented the intersection of 3D surfaces in 2D, and then converting the result back to 3D. The result can be seen in the screenshot below, it shows the intersection of indoor surfaces with outdoor space.
ankofl_0-1727090569374.png

What am I doing all this for? Since my last post, I have actually been busy implementing these intersections in 3D/2D from the beginning to the end of each working day.

I am very, very grateful to you for the BRepBuilder Class link to the article on creating a Solid object using BRepBuilder, and I can't wait to try to recreate a Solid object from .OFF file.
This will definitely be the first thing I'll do as soon as I have some free time.

Of
course, I will post the results of the work on creating a Solid object from an OFF file here as soon as they are ready.

Thank you @jeremy_tammik, for blogging and taking your time with us! Your help is very valuable to us!

 

Message 18 of 21

jeremy_tammik
Alumni
Alumni

Brilliant! Glad to hear you are making such good progress, and happy to be of help. I added you motivation and nice picture to the post as well...  🙂

   

Jeremy Tammik Developer Advocacy and Support + The Building Coder + Autodesk Developer Network + ADN Open
Message 19 of 21

ankofl
Advocate
Advocate

Thank you! )

One
of the users asked me a question in a personal message about using CGAL in Revit. I tried to send him a reply, but first I got a strange error about invalid tag (to be honest, I get it when I try to send every response, for example in this forum branch), but here, when I click the "Post" button again, the error disappears and the message is successfully sent.
ankofl_2-1727098974195.png

But when I try to click the "Post" button again to send a private message, a second error occurs, about exceeding the message limit at this point in time, although this was the first message I tried to send today.
ankofl_1-1727098861108.png

In any case, now I do not have the opportunity to reply to the user with a personal message, and given that this information, I think, will be useful to everyone who has read this topic up to this point, I will post the answer here.

To tell the truth, CGAL is distributed under the GPLv3 license, which is incompatible with REvit, which means we do not have the right to directly call, for example, through [DllImport] cpp-dll from RevitAPI. Of course, GeometryFactory has a commercial CGAL license that allows it to be done, but when I wrote them an appeal asking about the license price, I received the following response:

 

 

Hi Andrey,

I didn't reply earlier as I am on a business trip.

We in general do not reply to people asking for prices when it is a gmail,
yahoo, or yandex email address. We want to know who we deal with.
With the war in Ukraine we are even more interested who we license
and what will be done with it.  I hope on your understanding, and
please don't take it personal.

We sell the different CGAL components for a one-time license fee,
typically for several 10K Euro.  Their functionality must not directly be
re-exposed. What I mean we do not allow Unity-Boolean-operations
just being a wrapper around CGAL-Boolean-operations.

Best,

Andreas

Андрей Колесов
2 июля в 15:39
Good afternoon!

How much does a commercial license for your CGAL product cost?

-- 
Andreas Fabri, PhD
Chief Officer, GeometryFactory
Editor, The CGAL Project

phone: +33.492.954.912    skype: andreas.fabri

 

 

At that moment, I was interested in interacting with CGAL through Unity (a game engine, but in a legal and technical context it would be similar to using it in Revit). And even if you comply with their terms of use, ten thousand euros per year is probably not the amount you would like to spend on a commercial CGAL license.

Therefore, in this case, it remains only to use CGAL as a separate application running in a separate process, without transmitting and receiving any arguments and call results from it.

In this case, all communication should take place in standard ways through the computer's file system.

I.e. created .off the file, we launched the cpp-exe program in a separate process, waited for its execution during which it should independently record the output.off the file, and after closing the process, if the output file has been created, read it and recreate the geometry based on it again. If the file was not created, return false or something like that from the method.

I hope, it was able to help someone

0 Likes
Message 20 of 21

jeremy_tammik
Alumni
Alumni

Thank you for the clarification and clear and useful explanation of how you can deal with the licensing restrictions. I remember now that licensing limitations were a stumbling block for me too decades ago when exploring the usage of LEDA, now part of CGAL.

   

   

Jeremy Tammik Developer Advocacy and Support + The Building Coder + Autodesk Developer Network + ADN Open