Showing posts with label FreeCAD Module. Show all posts
Showing posts with label FreeCAD Module. Show all posts

Saturday, 27 October 2012

A busy-ish week. Further work on CAM Plugins

The week's been a busy one with Group Project work at University - having way too many meetings, that haven't resulted in a great outcome.


Work on the CAM Module (no pretty pictures):


This post is in reference to recent commit history in the CAM developer branch


Nevertheless there are has been a few more opportunities to work on the CAM module.  The Cam Objects have been tweaked so that the Tool Path Generators are automatically updated when there is change to the Part Geometry and the Stock Geometry material. This is useful for obvious reasons so that the whole Cam Feature will automatically update itself and along with this the resultant GCode rather than having to manually calculate all the features again.

The next step was attempted to integrate a Cam Library - libarea-clipper into the source tree and make the python bindings available for other python modules within FreeCAD. This was only really good practice learning how to play with CMake configuration files, that's all, but the end result is that our TPG's can now use this library if they are c++ or python!

Work also began on working on the TPGFactory methods for essentially loading all the TPG's if they are c++ based or Python based.

C++ was pretty straight forward going where we can interact with the TPG and TPGFeature very easily.

Python requires making an extension using boost::python. This has its set of many difficulties and still has alot of work to get done but in practice it does work.

One stumbling point was that for TPGPython our c++ python extension to be loaded into Python, we have to put this in a seperate dynamic library. Frustratingly this took some time to realise and required numerous changes to the CMakeLists.txt file - the build configuration script we use.

Another painful learning experience was figuring out why the virtual method run()  was not being called. This virtual method is defined inside python and are later called. The first thing I forgot was define the callback - see here and I had implemented the run method in TPGPython which created a conflict. Finally atleast we have an interesting message when we call the run method()

I've also implemented the file search function that looks for .tpg files within a directory and is recursive too.

There's still a lot more work to do, but things are coming together fairly nicely. My apologies if this post hasn't made  much sense.

Sunday, 21 October 2012

Help for creating C++ Modules in FreeCAD

Being slightly hungover from a crazy night out, I figured I might aswell try and doing something useful, so I am going to try and explain the structure for implementing a structure using c++ in FreeCAD.

It's useful to understand this to build a clear logical  structure rather than a mashup, which makes it more easy to document improving accessible for people to understand how the module fits together and get them developing! That's one of the reason's I'm not a big fan of using python solely in FreeCAD modules...

The App & GUI:

FreeCAD is essentially built around two core areas - the application code and the GUI which is essential for users to get something productive out of the program. 

Application:

The application provides the facility to perform operations, calculations, managethe document structure and its features. It's built around numerous libraries, the obvious one being OpenCascade which provides the modelling features. The application should be usable without a GUI so it behaves like a console application. 

FreeCAD comprehensivly uses python throughout to give greater power to users and ease development. It's very easy for the users to run commands in the python interpreter. Even still the application code can still execute python commands which are typically used for creating / editing features but quite essential for enabling the undo-redo system to work.

Any GUI related libraries cannot be used in the application module, however, we can still use some modules from QT as part of the application modules, such as:

  • QTCore
  • QTNetwork
  • QTXML

The Gui

The GUI is infact optional, and this can be ommited whilst compiling. This eventually give us greater flexibility in terms of the user interaction. For example we could in theory build a WebGL version of FreeCAD.

The GUI uses the Coin3D for managing the OpenGL Scenegraph based on the Open Inventor whilst we use Qt4 for providing the overall application user interface. These are linked together using SoQtViewer. 

Building a Structure:

I always recommend to look at the Sketcher Module which despite it's complexity is a classic example of how a c++ module should look.

It's best to seperate the module into two seperate folders atleast, the App and the GUI folder. This helps prevent cross contamination of GUI code into the application code. 

Below is simple diagram explaining how the structure fits together.



Each module will have it's own Features and potentially sub features too. Depending on the complexity of the feature, these features should only provide an interface (python) to another class which is intialised as a protected member and is callable. This keeps the document feature easier to work with and keeps the main functions are processes isolated together. Usually I create a seperate subfolder in the app directory to keep these classes together.

Each document feature declares a string to a specified viewprovider - defined in

const char* getViewProviderName() const 

This allows FreeCAD to load the viewprovider if there is a GUI interface. Each View Provider is assigned a pcObject which references the document feature that it is assigned to. other gui elements have to be implemented such as command.cpp, workbench and if needed the taskdialog and its taskboxes.

Document Objects / Features:

Each Module will have to define its own document feature, this is achieved by inheriting from App::DocumentObject.  There are many virtual class members that can be overriden. Each Feature has then several properties that can be used to store such as
  • Integers (App::PropertyInteger)
  • Floats (App::PropertyFloat)
  • Strings (App::PropertyString)
  • Lists
  • Links (App::PropertyLink)
  • SubLinks (App::PropertySubLink)  - a link to a feature and with a sub reference (e.g. a face, or edge on a part)
Including these makes life much simpler for the programmer; we don't have to worry about undo-redo mechanism and saving and restoring these into the document. We can also define our own properties but this introduces further complexities and should tried to be avoided.

We can link together other features using links and this introduces a dependency. When the sub feature is touched - its properties have changed, the parent feature will update itself accordingly. We can control this behaviour by re-implementing the following methods

  • void onBeforeChanged(const App::Property* /*prop*/)
  • void onAfterChanged(const App::Property* /*prop*/)
  • void onChanged(const App::Property* /*prop*/)
  • short mustExecute() const;
The main calculations or functions are perfomed in

App::DocumentObjectExecReturn *execute(void);

these are called when the recompute method is called either for the document feature or the whole document.

A document feature can also be implemented to take advantage of python. This requires defining an XML file and then implementing the generating functions in a myFeaturePyImp.cpp file. Generally an argument list is parsed and then if valid the correct c++ functions are called in the document feature. 

ViewProviders

ViewProviders provide the majority of the interface for a document feature. It manages the object's presentation and manipulation in the 3D view by allowing the developer to manipulate the Coin3D scenegraph. Also it defines how the feature is handled and presented in the Document Tree.

ViewProviders inherit from Gui/ViewProvider.h but can also inherit from other ViewProvider classes to obtain already defined behaviours. There aren't any members that need to be defined but it makes sense that you do.

GUI::Commands

These are basically commands that are registered in the GUI application that can be called by tool bar icons or the main menus. These can be programmed with a lot of logic during the prototyping phase, but it's not recommended that they are simple commands which will use the python interface.

 The things to remember:

  • Seperate your module into Application and GUI
  • Keep your Document Features as interfaces
  • Use App::Properties to save you time
  • Seperate processes and calculations into seperate classes
  • Keep Things Simple At First - get your module working and build up