CadInput is a PROTOTYPE QGIS Python plugin that allows to numerically constrain the cursor to achieve efficient and precise digitizing, as possible in CAD packages, with any QGIS tool.
A demo of an older version is available here : https://vimeo.com/85052231
It currently relies on too many hacks and may therefore be unstable. DO NOT USE THIS IN PRODUCTION !!!
Validating an editfield with Return will lock the value. Setting a value to an empty string will unlock the value.
You can enter basic math operations in the editfields.
Shortcuts are accessible if the MapCanvas or the CadInputWidget have focus :
Please report bugs and ideas on the issue tracker : https://github.com/olivierdalang/CadInput/issues
Or send me some feedback at : olivier.dalang@gmail.com
Please submit your ideas on the tracker : https://github.com/olivierdalang/CadInput/issues
The plugin relies on several hacks to work, since (afaik) the current QGIS API : - does not allow to hook into MapCanvas mouse events - does not allow numerical input for tools in scene coordinates - does not allow to restrict background snapping on Vertexes or Segments only - does not allow free drawing on the mapcanvas
To be able to capture the mouseEvents of the MapCanvas, the plugin installs an eventFilter on it.
Capturing and editing the mouseEvents is fine for graphical feedback, but does not allow for precise input (since mouseEvents are in pixels, and not in map units). To workaround this limitation, the plugin creates a memory layer, in which a point is created each time a precise coordinate input is needed, to which the native tools will snap. Unfortunately, to snap to this layer only without possible interference from other regular layers snapping, the plugin must iterate through all layers and remove (temporarily) their snapping.
To be able to freely draw on the MapCanvas, the plugin adds a QWidget as child of the mapCanvas. A drawback is that there is a "double cursor", the native QGIS cursor, and a CadInput-specific cursor, inducing a little bit of confusion.
In current version, QgsMapCanvas emits xyCoordinates(const QgsPoint &p) on mouseMoveEvent. The same could be done for mousePressEvent and mouseReleaseEvent (maybe with better names?). I'm not sure this would be usable for the plugin though, since it needs to be able to modify those events too.
For instance by adding
void QgsMapTool::scenePressEvent( QMouseEvent *e, QgsPoint *p ) // and the same for move and release events
Or by adding an optional scenePos *pos=0
parameter to the existing void QgsMapTool::canvasPressEvent( QMouseEvent *e )
This could anyways be very useful for different uses (automation ?).
The problem is, it seems the snapping/coordinate translation is implemented by each Tool subclass... So it will be some work which would require anyway a more general MapTools refactoring !
Add a QgsMapCanvasSnapper's snapToSpecificLayer method (exactly the same as snapToActiveLayer except it's not the active layer)
int snapToSpecificLayers( const QPoint& p, QList<QgsSnappingResult>& results, QgsVectorLayer layer, QgsSnapper::SnappingType snap_to, double snappingTol = -1, const QList<QgsPoint>& excludePoints = QList<QgsPoint>() );
Modify QgsMapCanvasSnapper's snapToBackgroundLayers method to work like snapToCurrentLayer.
int snapToBackgroundLayers( const QPoint& p, QList<QgsSnappingResult>& results, const QList<QgsPoint>& excludePoints = QList<QgsPoint>() );
would become
int snapToBackgroundLayers( const QPoint& p, QList<QgsSnappingResult>& results, QgsSnapper::SnappingType snap_to, double snappingTol = -1, const QList<QgsPoint>& excludePoints = QList<QgsPoint>() );
Alternatively, QgsSnappingResult could have a field informing wheter it was a vertex or a segment snap.
Some tools work in click-click mode (add feature...), but some other in click-drag mode (move vertex, ...). That second method is less common in CAD softwares, since it is less practical. Those click-drag tools work currently with the plugin, but the user must keep the mouse pressed, which is a bit annoying. Allowing click-move-click mode for those tool as well would be an improvement.
See http://hub.qgis.org/issues/7058