Lens/FreeCAD Integration

Accepted enhancement proposal, collaboration features, the use of AI

Since the last post, there are various updates on the Lens/FreeCAD integration project: The accepted Variant Parts enhancement proposal, a generic framework for collaboration, and within NLnet, there is a discussion on how to handle the use of AI-generated code.

Enhancement proposal Variant Parts accepted

The most relevant links are:

After an initial discussion on the enhancement proposal, I have made some changes and moved the proposal to version 1.1. After that, there were no serious concerns raised and there was a final request to express concerns. This led to one more question if this proposal would also help with dependencies in FreeCAD's spreadsheet. I'm not too familiar with the spreadsheet implementation but it turned out that the work in PR #25603: Fine-grained recomputes that I presented in the last post did resolve dependency issues in Spreadsheet out-of-the-box. This gives me even more confidence in the fine-grained recompute work.

After answering this final question, there were no more concerns and we moved the proposal to Accepted! Thanks to everyone that contributed to the discussion! Fine-grained recomputes has already been done in the context of the NLnet Lens/FreeCAD integration, now we can move on to implementing the second phase of variant parts as well (which is not part of this project).

A generic collaboration framework

The most relevant links for this work are:

To support collaboration in Lens, it is necessary that FreeCAD itself has support for that as well. To start a discussion on this topic, I created Issue #25681 that highlights the fact that FreeCAD misses collaboration issues.

I knew that FreeCAD has support for annotations, but that this support is limited, so I created Issue #25682 to record what FreeCAD already has for annotating 3D geometry. A related collaboration feature is being able to have conversations with other users on the model. I created Issue #25685 to discuss this feature.

In this post, I was made aware of a Google Summer of Code project from 2019 on the BIM Collaboration Format (BCF) that has been documented on FreeCAD's wiki. This project created an BCF addon for FreeCAD that implements the BCF standard. I was unaware of this work but it was very useful for the discussion on conversations and annotations. To test the work, I updated the BCF plugin to FreeCAD 1.0. Unfortunately, the plugin seems to be unmaintained. The BCF standard describes to a large extent what I would like for Lens (I discuss it in this comment) but unfortunately, the support for collaboration features is within the BCF plugin only and as such, the logic can't be reused properly for other collaboration packages.

So, I'm looking for a generic framework for collaboration features that FreeCAD itself supports. The generic framework should be such that the Ondsel Lens Addon can make use of it, but also other initiatives for PDM-like features, and hopefully, the BCF plugin itself could also make use of the generic framework. For example, the BCF plugin does not make use of annotations in FreeCAD and with the generic collaboration framework, that would become accessible as well.

I had a discussion with two interested FreeCAD community members on how adding conversations (topics in BCF terminology) to the FreeCAD file would affect versioning of those files. This was a very interesting discussion on whether conversations/topics should be part of the FreeCAD file, just on the server, or in a separate file (what BCF does). The summary of the discussion starts in this comment and I conclude that with some support from Lens or a PDM, we can store annotations, topics/conversations in FreeCAD files and make use of links to make sure the version of the original model doesn't change (see this comment).

This also led to the question to what extent Lens is a PDM itself. I summarized this discussion in Issue #48: Extent to which Lens is a PDM.

In the mean-time I created an initial PR for a generic collaboration framework. For this work, it improves annotations in FreeCAD making it able to associate annotations with the model in such a way that if the model is transformed, the annotation automatically moves with it. The annotation represents a topic (a conversation) and it opens a task panel where the list of comments should be.

I presented this work at the Developer Meeting on 20 December and the suggestion that I got is to create an enhancement proposal for it. In fact, the suggestion was to create two enhancement proposals for it, one for the generic collaboration framework and one for how to integrate C++/Python package in FreeCAD preventing name space problems. I agree that this should be done but I didn't plan for this within this project, so I will have to try to find some time for that.

The use of AI

Within NLnet, there is a discussion on the use of AI in the open source projects they support. On Wednesday 17 December, there was a video meeting to discuss this topic. It was a very interesting discussion in which I also contributed a bit and shared the recent developments within the FreeCAD project.

The starting point is NLnet's Generative AI policy. I agree in a large part with that policy but I share the concerns of the majority of the participants that the requirements for logging the use of AI is excessive and probably also not necessary and/or helpful. NLnet agreed that this is the most likely point for revision and they were interested in our feedback. We agreed that the NLnet grantees would discuss their use of generative AI. Hence, this post.

Before I continue the discussion, first perhaps a personal opinion. Personally, I don't use any proprietary software. I'm still trying to figure out myself whether software that is trained on large data sets can be considered open source at all. This is similar to a phenomenon that I encountered in my academic career where some experiments can only be run with enormous resources, for example requiring the use of gigantic supercomputers, making it impossible for others to reproduce the results. Of this kind of research, you can question to what extent it is science. This paper discusses how to be open about the cost to reproduce (principle 8) in the context for cloud performance experiments, but I think the point is much broader than that.

Similarly, if it is impossible to gather the data or train on the data yourself to build your own program making use of an AI model, can you still call the resulting software open source? I don't think so. So, on that basis, I should reject using this software personally.

Another important reason to reject it, is that it requires so many resources to train and also query the models that it hurts the environment. The outcomes of large language models appear to be very useful, but 1) the effectiveness is actively questioned and 2) it is unclear if the perceived usefulness weighs up to the environmental costs.

Professionally, I feel I have to be a bit more lenient regarding these tools. For example, I now sometimes need to use Windows and Mac OS for testing FreeCAD on these platforms. FreeCAD makes use of GitHub, whereas I would prefer Codeberg that is built on Forgejo, so professionally I'm more lenient than I am personally.

This is also true for using AI agents. So, for professional use, I make use of AI tools such as ChatGPT and Copilot. I find them very useful and I have the impression that they increase my productivity, but I'm definitely aware of various studies such as this one that show decreased productivity in software development.

Before discussing my use of AI, I would like to share the discussion within the FreeCAD community where maintainers came-across PRs that seemed to be vibe-coded. Yorik van Havre wrote a very principled PR with changed contribution guidelines that evoked discussion. This topic was then discussed in this developer meeting (summarized here) and these changes to the contribution guidelines seem to be well supported.

My personal opinion is that AI is just a tool, like a more intelligent code-completer that can answer questions. I always make sure that the code that I submit is fully my own work, even though I may have had input from AI tools. My goal is to create minimal changes to the existing code anyway and each output of an AI tool is heavily redacted, unless it happens to be exactly what I want, which is very rare but happens for small code pieces. So, I'm quite sure that from the outside it is impossible to recognize that I had AI assistance on the code that I submitted.

One of the most useful features for me personally is the integration of GitHub Copilot into my editor Emacs where the AI agent very rapidly understands the boilerplate that I need to generate.

For example, if I don't understand something, I typically add logging with FC_MSG() statements such as:

std::optional<Base::Vector3d> Topic::getGeometryPosition() const
{
    FC_MSG("getGeometryPosition()");
    App::DocumentObject* obj = Geometry.getValue();
    if (!obj) {
        FC_MSG("  No geometry assigned");
        return std::nullopt;
    }
    ...

    return placement.getPosition();
    FC_MSG("end getGeometryPosition()");
}

Then the AI agent understands that I want to log the start and end of the function in this way and that I want to indent other statements with two spaces.

I think it may be useful to go over PR #26306 to explain how I used AI tools there. It consists of 3 commits and I think it is most helpful to go over these commits separately.

The PR improves annotation labels in the 3D view of FreeCAD and I wanted to make sure that I could double-click those labels in the 3D view. I consulted the AI agent extensively on how to do that best, but none of the answers that I got were helpful. After quite some experimentation assisted by the AI agent, I finally concluded myself that it is very difficult to detect double clicks on these kinds of labels, because these labels support dragging and as soon as such a label receives one click, it enters dragging mode.

The first commit adds a generic utility to detect double clicks. This is based on logic that I found in FreeCAD's Sketcher mode here. I created a small class that can be added to other classes for detection of double clicks for a specific circumstance. The design of the class and the decision to place it in src/Gui/Utilitities.h is fully my own.

In the end, there was lots of consulting with the AI that I basically used as a glorified search engine to go through Coin's (FreeCAD's renderer) API. Since most of it was useless, I decided I should really read the books that are recommended in their introduction, "The Inventor Mentor" and "The Inventor Toolmaker".

If my code is merged, I should create an issue on the Sketcher to try to make use of the generic code that I created.

The code in the second commit makes use of my generic code to detect double clicks when a dragging action starts. The design is purely my own and I remember that the AI integrated in my editor suggested something for this line, I believe dragger->setActive(false) which made sense to me, was something I needed, but turned out to be wrong. I remember that I cloned the source code of Coin to browse through the code to find the alternative that I used in the end. The comment on that line looks like something an AI could generate, but it is mine because to me it is not fully clear that such a statement actually cancels the dragger. To me, a boolean field (in Coin terms) seems more like something with which you can check whether the dragger is active, not that you can make it inactive.

So, for this commit, the input from AI was helpful because it gave me more trust in the fact that you could actually cancel the dragger action here, but the actual statement was found by myself from reading the Coin source code.

The third commit adds a whole new Collaboration module to FreeCAD. Adding a new module brings lots of boilerplate code such as CMakeLists.txt files. Since the module contains both C++ and Python code, I borrowed heavily from the Assembly workbench for which this is the case as well. For this module, however, I used a different setup where the C++ code resides in a Collaboration package, whereas the pure Python code resides in a collaboration package (with a lowercase "c"). Typically Python code in FreeCAD has no name space which can easily lead to conflicts in naming. For example, if there are two FreeCAD modules that use the file Utils.py or even an external workbench, there is already a problem.

So, this setup of a FreeCAD module is my own design. The design of the Collaboration module itself has been described in this comment and following and the outcome is to a great extent exactly what I described, except for placing labels in the top right corner which didn't work well.

The most challenging part of this work was this function that determines the position of an annotation label (a topic) in relation to a sub element from geometry, for example a face or an edge. To get this right, I consulted the AI extensively but I realized this is actually a very challenging problem because of all kinds of edge cases. I came to the conclusion myself that there was already code that handles all these edge cases perfectly (the Attacher logic) and I found a way to make use of that code. This code represents that solution and is much better than various implementation that I had before. The use of AI did not lead to this final solution but it helped me to have a conversation about these kinds of problems in general and provided context.

One other case for which I consulted the AI agent extensively is dealing with FreeCAD's property enumerations. FreeCAD's property enumerations are designed in a way that make it challenging to use C++ enumerations. The easiest way is to use strings, but this is not a good solution because these strings are not identifiers, so if there is a typo in a string, or you want to change the name of an enum value, you have to do a string replacement and have no type checking.

I consulted the AI on how to improve this line where I want "Absolute" to be something like PlacementType::Absolute. The AI gave very good solutions for this but the solutions were quite convoluted. I asked for simpler solutions but they had drawbacks as well.

In the end, I left it like I did initially and I want to bring this up in FreeCAD's Code Quality Working Group of which I'm a member. Property enumerations are problematic in other ways in FreeCAD as well, so we may find a solution for both of these problems in one go.

All in all, I come to the conclusion that I use AI mostly for consulting and getting ideas. Given this last contribution and write-up, I realize how little of the AI's suggestions actually end up in the code. I'm very confident that the code that I contribute overall can count as solely my own.

I also wonder how beneficial AI agents are to me. I think that I spent quite some time "conversing" with AI agents, but in the end, it may be much better to spend that time reading books such as on Open Inventor.

Lens Addon and FreeCAD fine-grained recomputes

Since the last post I have been working on the Lens addon and fine-grained recomputes in FreeCAD. In the Lens addon, I have added support for switching instances and for profiles. The fine-grained recomputes work is phase 1 of the implementation of what I proposed in enhancement proposal FEP-0010: Variant Parts.

Lens Addon enhancements

The Lens addon now supports not only switching instances, but also profiles which enable you to seamlessly switch between different Lens servers. The most important Pull Requests (PRs) are:

This led to a new release of the Lens addon version 2025.11.21.01 which is now available through the FreeCAD Addon Manager!

To make this happen, quite some issues needed to be solved, some of which included the Ondsel Lens server as well. They mainly involved setting up the server for a development environment to test the profiles.

There is also an issue on the server that I can't easily solve myself and affects the Lens addon:

The addon itself has seen some improvements as well, mostly related to managing versions for the addon (package.xml) and adding pre-commit and CI support for linting and remaining REUSE compliant:

Finally, I've updated the FreeCAD forum and there is a First Robotics Competition team working in FreeCAD that set up an Ondsel Server as well:

Fine-grained recomputes

For the work on fine-grained recomputes I submitted a PR. Important links:

The discussion on enhancement proposal FEP-0010: Variant Parts is ongoing. I brought it up again at FreeCAD developer meeting on Saturday 15 November. I introduced the changes that I made as a result of the discussion, mostly introducing a separation of concerns between "true" input properties and exposing properties.

Input properties allow you to refer to parent document objects from child document objects without needing complicated constructs such as hidden references that are not user-friendly. Exposed properties allow users to express the design intent which properties are meant to parameterize a part.

Support for fine-grained recomputes and input properties has been implemented in PR #25603: Fine-grained recomputes. It maintains a graph of dependencies between properties by means of inlists and outlists of dependency edges, edges that describe an edge in the dependency graph between properties. This PR tries to add this functionality with minimum changes to the original code, adding a runtime switch to recompute with the old coarse-grained dependency checking and with the new fine-grained dependency checking. The PR also adds various tests, some of which should work for both coarse-grained recompute, some only for fine-grained recomputed, and some only for coarse-grained recomputes. I hope this PR can help improve the discussion on the topic.

Enhancement Proposal Variant Parts

On this page, I will describe the progress I make on the NLnet Lens/FreeCAD integration project. In this post on the enhancement proposal for variant parts. Important links:

One of the first tasks is creating an enhancement proposal for Variant Parts. An enhancement proposal is a formal process to introduce large new changes to FreeCAD. Since the discussion may take a while, I focused on this part first.

Variant Parts are not only useful for parametric modeling, they are also useful for the Lens platform. The variant parts give users what I call an "Application Geometry Interface" in the form of properties that users can change to parameterize a part. This Application Geometry Interface serves two purposes: It makes it possible to create a variant by changing one of these properties. It also make it possible for the Lens platform to provide users these properties on the website to parameterize the parts.

With the Variant Parts enhancement proposal, the FreeCAD community can be involved before the code has been written for a change as large as this one. Since this proposal has already been preceded by the Research Variant Parts project (outcomes here), I have been able to move this proposal from the "Draft" staged to "Proposed" stage. We will now have a period of discussions before which this proposal will hopefully move to the "Accepted" stage.