Sunday, 27 January 2013

Drawing Module: A Sneak Peak!

Having some time off this weekend, I have spent a bit of time further working on the experimental Drawing Module: I won't post the details of how I've got to where I am but I thought I would provide to you lucky guys a sneak peak at what I have currently achieved:


The left is the Drawing Module using QGraphicsView elements and the test model is on the right, although I am trying to work out why the projection isn't correct - maybe it's first angle projection? Also the edges that don't match up are arc of ellipses that aren't correct but that should be trivial to fix.

The point is I have manage to correctly project edges and rebuild nearly all the edge references from the original model, I found that on some occasions because a curve is broken up, the references can be lost but these are nearly always in 3D views, which would be difficult to dimension. It also supports edge selection and moving this projected view around the canvas despite there being no template.

The next step will be to tidy up the code and implement full interactivity and integration with FreeCAD's App::Property system, so that it can take advantage of the undo/redo framework.

 One of the frustrating things is not having anti-aliasing support in the opensource ATI drivers.

Wednesday, 23 January 2013

The Drawing Module: Part 2

As previously discussed the Drawing Module does it's job and produces the drawing our users require, but has its limitations. Now having some a little spare time every now and then in the evening, it seemed a nice little job in the mean time to experiment to see if we could improve this. How I envisage the Drawing Module to work is similar to what I've experienced in the past but relatively similar to its current behaviour.

Planned Workflow:

This is just an idea of the workflow I had in mind for using the Drawing Module.
  1. Create Part/Assembly
  2. Opens Drawing workbench
  3. Creates Page Feature
  4. Select template document and page properties (inherit data from FreeCAD document)
  5. Select Part and create view (2D or 3D Projection, Section)
  6. Add dimensions (attempt to import any sketcher dimensions - will require name framework)
  7. Manipulate view features directly (move, 
  8. Orthographic Projections can be created by dragging a projection in direction.
  9. Provide a Measure tool for edges
  10. Add Annotations to drawing
  11. Provide a BOM or List of Parts

A note on page templates:

Currently the template would be kept as SVG so that this can be edited. I still don't know if these could be generalised so that it can be exported to another format but I don't think it would make much sense. However ideally it should be very easy to manipulate any 'placeholders' . This is not an immediate issue but I would speculate that the template placeholders would have a special edit mode to prevent any accidental changes by the user.


Below are the first jobs that need achieving for experimenting with a few ideas.

First Job: Low level shape storage

By unifying and abstracting the resultant shapes that are projected by Brep_HLR there is no restriction how these can be later represented. This means if the projected shape is a circle, we store the center point coordinates and its radius. This is extended to points, ellipses, b-spline form.



These can later be converted very easily into any other format whether .SVG, .DXF, Html Canvas or perhaps even Librecad may produce their own representation - who knows? 

It also allows us to represent this graphically in any way we want. Every time our part feature changes, this geometry is recalculated and can be then used in the user interface as needed.

Second Job: Building References

Looking more deeper into the projection code. Their algorithm seems to work by projecting all the edges and faces onto a projection plane, quite similar to an OpenGL projector. Then the algorithm sorts through all the edges and compares these with each project face to check if they are hidden.




Each edge and face is mapped from the original TopoDS_Shape and an index is built. By extracting these we can build up better integration so the drawing can have more interaction. I.e. we can extract edge lengths or update the projection without losing our annotations.


Third Job: Graphically Interface for Drawing

This could be done in SVG or using any other method. I prefer the use of QGraphicsView simply because it provides a framework for building up interactivity at a lower level which I don't think can be achieved in a web interface and should hopefully improve performance too. It would have been interesting to have used QML or QtQuick, but there are no objects available for drawing arbitrary shapes till Qt 5 and is more appropriate for dynamic interfaces. 

Conclusion:

Obviously there is more stuff that definitely needs considering, but this is at the moment an experiment to see what is feasible. In summary, what I am attempted is building a lower level data structure for storing geometry and reference data that can be exported and manipulated easily in any format. Then integrating this into QGraphicsView. 

Overtime I will report on my progress for what I have currently achieved in my spare time.


Friday, 18 January 2013

The Drawing Module

Over Christmas I have been away at home and in the mean time been quite busy with several projects for University and following graduation next Summer. Time has been quite short, so I haven't had the greatest chance to really work on much and that includes the CAM module. Instead, for the hour or two I have most evenings, I have been looking at several areas and thought it would be interesting to take on the Drawing Module. This module is quite isolated therefore much easier to develop without having to consult people.

Drawing Module:

The Drawing module is used for 'documentation' of FreeCAD part models. There is a great misconception that it should be the equivalent of AutoCAD or its free equivalent LibreCAD, which only recently have I had chance to use for documenting an architecture based project. There has been many discussions on this area on the forums in particular: however I didn't feel the module was intended for the production of technical drawings similar to other commercial offerings.

What I was taught as Engineer is that the production of technical drawings is to provide a reference detailed copy transferred to paper or electronic equivalent. This document should be readable by someone else and should allow this person to fully recreate the component inside CAD or manufacturing this. LibreCAD does offer the ability to document work becomes very cumbersome and leads to unproductive workflow. Let me illustrate, the user must have to export the model projection (degrading model information) and then manually drawing the Dimension lines each time.

What do I mean degrading information?

For example, when the Assembly feature comes this will support higher level information including the relationships of each part and most importantly a BOM - bill of materials. We also lose references between geometric entities such as edges. This means if we update the drawing, these changes are not necessarily propagated through and create extra work for us. With the development of Topological Naming, this should immediately take advantage of this.

The Current Drawing Module:



The Current Drawing module projects a part into a selected view and then gathers all the shapes and exports this directly into a the correct schema (.svg, .dxf) this works fine, as demonstrated currently, however is restrictive. Currently the drawing editor use QGraphicsView with QSvg which displays the SVG Result from the projection algorithm but doesn't allow any direct editing other than manipulating the SVG.

 There is currently the idea of moving to QWebview and rendering using the webkit browser, but I don't think this is appropriate even though it would improve the opportunity to interact. Using SVG for manipulating the drawing seems a bad idea and a more lower level data structure seems more appropriate.


Hopefully later I will explain what I am proposing....

Sunday, 25 November 2012

Further Progress on CAM Module API

It's been over a month since the last post. We are making good progress on the CAM Module. Andrew Robinson has being putting his great coding skills to creating a very powerful API for creating Tool Path Plugins - considerably better than what I had already achieved. It's great to reflect on the different perspective on approaching a given problem. Our greatest difficulty is probably the time zone difference, when he is awake, I am a sleep. It's made communication interesting at times, especially the late nights.

With major rewriting of the API and being quite busy on my own project recently, I haven't been involved as much other than discussion.

New Github branch:

To collaborate better and remove old code, following a manual merge we had to also create a new Git-hub branch titled cam-py to push our work to.

Taking a step back to take big steps ahead!

From working together, it was clearly obvious that using Boost::Python was not the most elegant of solutions and having no experience with python it was not the most elegant method of approaching the loading and registering plugins.

Over the course of the past month, Andrew has been developing the python plugin loading and re factoring some of the factory methods lower down, so that Python plugins can be searched and loaded at run time. This essentially means you can rewrite and edit your scripts whilst FreeCAD is running. Potentially we could explore the idea of having a script window. What would be interesting in the long term is having an online plugin repository that allows individual developers / users to tweak the scripts and share these with everyone online.

Dynamic Loading of Library Plugins:

Most applications allow library plugins or extensions to be dynamically loaded at run time. Having compiled library plugins creates an interface to allow proprietary plugins to work with the FreeCAD cam module. It could be argued that we should promote openness but it gives freedom and flexibility for commercial developers to offer their solution using FreeCAD. 

Also we have decided that for the Cam Module, all c++ TPGs will be loaded dynamically like this. Since each plugin is loaded on demand, memory consumption should be reduced and loading times when switching to this work bench should be improved.

Building up GUI interface:

Andrew did some work on the GUI using a separate dock interface - which currently scans and loads python plugins into the application. Below is a screenshot demonstrating that Cam Module loading two python based plugins. 

The design of our API aims to have no discrete distinction when loading and using c++ and python TPG plugins inside the CAM Module. 

Next steps:

Work will continue on getting the API working and building the plugin infrastructure into the FreeCAD document structure so that we can allow geometry to be extracted and used by the plugins in their algorithms. Also how data is stored permanently needs to be implemented too.






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

Friday, 19 October 2012

2000 Reads and Quick Guide to connecting Boost Signals

Well to say I only started this blog in summer, I'm pretty impressed to reach 2000 reads. Atleast someone must find my writing useful. Further work continues on refining the structure of the CAM module. Things are going reasonably well and each piece of the jigsaw is coming together.

I also stumbled on a little GEM on the forums after I was having problems creating the Document Objects that have children, for example like this hierarchy below...



If we delete ToolPaths using the GUI, ideally we want the children (TPGFeature) to be delete accordingly. Inheriting from a App::DocumentObject we do not get such a luxury.

Solution - Using Boost::Signals:

We need to set up an signal/slot mechanism using the Boost Libraries to observe when a document object is deleted.These are pretty simple to use and remove the need for having to use QT and it's signal/slot mechanism that requires inheriting from QObject and run through the MOC preprocessor. This is fine in context of the GUI interface, but isn't necessary in the rest of the application.

Boost signals are pretty straightforward to use:

In the class header file we need to include these. Essentially the typedef is just a typing shortcut to make the syntax less cumbersome to write.
#include <boost/signals.hpp>
typedef boost::signals::connection Connection;
In the class declaration we need a Connection member delObjConnection and this slot function that will be called when a signal is intercepted. In our case, when the signalDeletedObject is made within our slot function onDelete we need to have a App::DocumentObject as parameter. This slot function has to be public.
public:
    ///SLOTS
    void onDelete(const App::DocumentObject &docObj);
protected:
    ///Connections
    Connection delObjConnection;
In the class definition, we now need to set up our connection and also implement our slot. The function onSettingDocument overrides the implementation in App::DocumentObject. This is called just after the CamFeature object has been constructed and has a document assigned to it. (This was only recently added in the GIT master)

CamFeature::~CamFeature()
{
    delObjConnection.disconnect();
}

void CamFeature::onSettingDocument()
{
    //Create a signal to observe slot if this item is deleted
    delObjConnection = getDocument()->signalDeletedObject.connect(boost::bind(&Cam::CamFeature::onDelete, this, _1));
}

That's pretty much it. Now we can delete child objects in the onDelete slot we have made!

Wednesday, 17 October 2012

Cam Module - Work over the Weekend

Git Repo:

I have created a GIT Repo on github that the other guys are going to push back their changes to, so look here if you're interested in seeing our progress.

Weekend Work:

I spent the last weekend laying the ground work structure for the FreeCAD Cam Module - inadvertently helped by my student house mates being away, making it calm around here. Essentially the hardest or laborious task was creating the source structure. There are several classes which require both the declaration and definition just to work. This leads to a file tree in the module like so:


And there's more GUI stuff too!

This was created based on the design document we created over last week outlining a proposal for how all this stuff could fit together.



The Dependency Graph:

FreeCAD has a fairly intelligent system of managing updates through the document. Each document object can be referenced by a series of links which behave as dependency. When a Document Object changes or it's property. When this happens the property or Document Object is 'touched' and this indicates it should be recompute the hierarchy tree.



Any dependencies that reference this object will automatically be requested to recompute and update themselves. This is what drives parametric design but being transparent to the developer.

The first attempt at fitting these classes together wasn't entirely successful and in its process also made the discovery of some good fixes in the base FreeCAD application. The end result for the dependency chart (below) for the structure seemed logical but introduced several difficulties.


Logically the structure makes sense in terms of the object hierarchy. However, for the program it doesn't. When the StockGeometry, or CamPartList features update, the tool paths will not automatically update. It took me two hours to figure that one out and it didn't look pretty. Boo hoo.

I had two beers and a night off to think about this on Sunday. It became apparent that the CamFeature was simply a top level container that would provide a general interface for accessing and managing the other features - it didn't control the actual CAM process.

Instead I created an object hierarchy like so. Essentially GCodeFeature is the result from the combined results of the TPG. However we get the all the glorious updating mechanism with this.


The ToolPaths manages the Input and controls the process of updating the TPGFeatures eventually more intelligently.

The TPGFeatures are quite dumb. They behave like blackboxes and are given an input, do their thing and spit back a result. The nice thing is thing about this it will allow new TPG's to be more quickly developed since the developers don't have to set up the document feature, but only have to provide the input and in return can get the GCode back.

Sunday, 14 October 2012

CAM Module

FreeCAD CAM Module.  Take 2:

After a fair bit of discussion through the Google Docs, Blog Entries, Forum Posts and ofcourse some IRC chatting Ideas we have pushed again and started the CAM 2 Module. Perhaps it's incorrect to say CAM2 but we are definitely putting the new source files in a new folder since we are essentially starting from scratch. We have even been blessed with a new subheading on the FreeCAD forums.

Objectives for this Module:

Essentially we aim to integrate the whole CAM workflow into FreeCAD.  The tool algorithms are developed  already in many libraries and are already useful but there is no practical integration within FreeCAD.


Secondary Objective : To cut out Sliptonic's spider!

The rough workings of CAM from a newbie:

The module will take your 3D Part within FreeCAD as the primary input. We provide a set process this with tooling algorithms which generates machine instructions (tool paths) known as GCODE. These are post-processed manually by the user and can be visualised within FreeCAD to check for any problems. We are basing a lot of the design on the work already achieved by HeeksCNC.

CAM in this Module will be a subtractive process -we remove material from a piece of Stock - such as sheet of steel by a series of operations. Each operation will be generated by a TPG - a Tool Path Generator. These are plugins which can be written in c++, python perhaps other languages and use their own algorithms to generate paths for the CAM Machine to remove material. These TPGs aim to be flexible, so we can call a  process to proprietary application allow this to do the hard work and then import it back into FreeCAD, but this process being entirely transparent. 

How I fit into this:

The strangest experience with this side project is that I have very little practical knowledge and experience working with CAM so I am very reliant on the wisdom of our CAM experts who have set up their requirements and how the perceive it working within FreeCAD. This is what makes it interesting in respect but also a difficult task. It is good practice working in an environment like this because I still yet to find a job that involves team work at such level haha.

My role in this project is to try and build up the basic FreeCAD infrastructure and then this will allow the other developers such as awallin, arobinson, dfalck to work on this independently, integrating the tools in.

Additionally work to build an awesome GUI interface into this ofcourse!

Saturday, 6 October 2012

Back to University. Back to FreeCAD. Updates

After my intermission of going on holiday in Europe (if you could call it that) , I am now back at University and have some free time to work on FreeCAD.

Coding Improvements to the Render Module:

The past few days I've tidied up the Render Module and improve the QML code to improve the quality of the UI presentation. In addition I have now implemented the saving and restoration of material properties, so this means for example you can save the 'colour' within the Matte material.

During mid-September inside the Render Module, I tidied up some QT and Coin3D GUI dependencies that existed in the core application functionality. These were trivial changes and other small coding improvements were made to the Render Module.

Building on Windows:

To give the Render Module a greater spectrum of Testers, we would like to get the Render Module compile on Windows. Work was done to implement class definitions that were missing.

There was a brief discussion on building using QT 4.5/ QT 4.6, which the current Windows Libpack includes. Unfortunately this doesn't include QML or/ QtDeclarative Modules, therefore it isn't possible to build the render module on Windows yet. In practice this means that the Render Module will not be available till the 0.14 release, when we can guarantee that most Linux distributions will include this. However, this will give another 6 months of testing to ensure that this module contains more features and improve the quality through testing.

GIT Housekeeping:

Having been working solely on the Render Module over the past three months, in my own ignorance, I have refrained from keeping an updated revision of the FreeCAD source. I've now forked and cloned from the FreeCAD source mirror on github and have set up a new repository and merged the Render Module into a new branch:

This somewhat both complicates and simplifies keeping upto date with the FreeCAD repository and there is always the added difficulty of learning something new!

CAM Module:

I am looking into helping start an initiative to implement CAM functionality into FreeCAD with guidance from Daniel Falck and Brad Collette. Currently trying to work out how this system will work and draw up a structure for this. I will report back on this in short time.