PlanX CAD Toolset

AutoCAD-style drafting workbench inside QGIS • v1.27.0 • 39 tools

1. Overview

PlanX CAD Toolset delivers an AutoCAD-style drafting workbench within QGIS, providing 39 tools across six categories: drawing, editing, construction, transform, measurement, and urban planning. Every tool is accessible through an AutoCAD-style command line with muscle-memory aliases (L, TR, F, CO, etc.), empty-Enter repeat-last convention, Up/Down history recall, and a searchable command palette. The plugin has zero external dependencies and supports QGIS 3.28 through 4.x on both PyQt5 and PyQt6.

2. Geometric Foundations

2.1 Computational Geometry in CAD

The plugin's editing tools implement classic computational geometry algorithms as formalised by de Berg et al. (2008). The fillet operation solves the tangent-circle problem: given two line segments meeting at an intersection point, find the two tangent points and the arc centre such that the arc radius equals a user-specified value and the arc is tangent to both lines. The chamfer operation generalises this with unequal cutback distances. The offset operation uses the straight-skeleton approximation implemented by QGIS's offsetCurve() with round join style. The trim and extend operations solve line-segment intersection and ray-casting problems, respectively.

2.2 Affine Transformations

Transform tools (Move, Copy, Rotate, Scale, Mirror, Align) apply affine transformations through homogeneous coordinates. A 2D affine transformation is expressed in matrix form as:

\(\begin{pmatrix} x' \\ y' \end{pmatrix} = \begin{pmatrix} m_{11} & m_{12} \\ m_{21} & m_{22} \end{pmatrix} \begin{pmatrix} x \\ y \end{pmatrix} + \begin{pmatrix} d_x \\ d_y \end{pmatrix}\)

The Mirror tool constructs a reflection matrix from the axis direction: \(m_{11} = 2u_x^2 - 1\), \(m_{12} = m_{21} = 2u_x u_y\), \(m_{22} = 2u_y^2 - 1\). The Align tool composes translation, rotation, and optional scaling into a single QTransform matrix using two source-to-destination point pairs. All transforms preserve Z and M values and handle multipart geometries correctly.

2.3 CRS-Aware Coordinate Operations

Farin (2002) notes that distance-based operations in CAD systems are meaningless in angular coordinate systems. The plugin addresses this through a local metric work CRS: every distance-bearing operation (precision input, offset, fillet, chamfer, buffer, hatch) transforms geometries to a local UTM or Azimuthal Equidistant (for polar regions) projection before computing in metres, then transforms results back. This ensures that a 5-metre offset applied in EPSG:4326 produces a geometrically correct 5-metre offset on the ground.

3. Drawing Tools (6)

6 Tools with Precision Input

All drawing tools support native QGIS snapping, Backspace undo, Enter finish, and Escape cancel.

4. Editing Tools (20)

4.1 Core Modification Tools

Offset, Fillet, Chamfer, Break, Lengthen

Offset O: Enter distance, click side for preview. Uses QgsGeometry.offsetCurve() with round join style in local metric CRS. Computes both left and right offsets, picks nearest to click point.

Buffer B: Dialog for distance, join style (Round/Bevel/Miter), segment count. Pick any readable feature. Output to managed planx_buffer layer.

Hatch H: Pick polygon. Dialog for pattern (parallel/cross/diagonal), spacing, angle, colour. Algorithm creates parallel lines spanning the polygon bounding box diagonal at the specified angle, clips each against the polygon via line.intersection(polygon). Works in local UTM. Max 20,000 candidate lines.

Construction XL/RAY/SEG: Three modes. Infinite mode extends through both points by 10x canvas diagonal. Ray extends from first through second. Segment is bounded. Writes to planx_construction layer with dashed cyan style.

Divide DIV: Dialog for segment count (2–10,000) and method. Split mode uses QgsGeometry.interpolate() at regular intervals along cumulative distance. Points mode creates points on planx_divisions layer.

Multi-Offset MO: Comma-separated distances; left/right/both/pick-side modes. Batched undo for all offsets.

5. Fillet and Chamfer Geometry

Tangent Arc and Straight Corner Resolution

Both operations follow a common two-step pattern: (1) find intersection of two picked lines, (2) compute cutback points and connection geometry.

Fillet algorithm (create_fillet_and_trims()):

  1. Find the intersection point of the two input lines via line_intersection() (determinant-based 2D line intersection).
  2. Determine unit vectors from the intersection toward the "keep" end of each line.
  3. Compute included angle: \(\theta = \arccos(\mathbf{v}_1 \cdot \mathbf{v}_2)\), clamped to \([-1, 1]\).
  4. Tangent distance: \(d_t = r / \tan(\theta/2)\).
  5. Tangent points: \(\mathbf{tp}_i = \mathbf{p}_{\mathrm{inter}} + d_t \cdot \mathbf{v}_i\).
  6. Arc centre along bisector: \(d_c = r / \sin(\theta/2)\), \(\mathbf{c} = \mathbf{p}_{\mathrm{inter}} + d_c \cdot \frac{\mathbf{v}_1 + \mathbf{v}_2}{\|\mathbf{v}_1 + \mathbf{v}_2\|}\).
  7. Construct 20-segment arc through the shortest angular sweep (not forced CCW).
  8. Snap first and last arc points exactly to tangent points for topology safety.

Chamfer algorithm (create_chamfer_and_trims()): Similar to fillet but produces a straight line. Cut back along each direction vector by user-specified distances \(d_1\) and \(d_2\). Validates that cutback does not exceed the available leg length. If "equal" checkbox is active, \(d_1 = d_2\). Rejects cutbacks longer than the retained leg.

Both operations work on a single edit command spanning both layers. Live preview shows the arc/line on hover before the final click. Trim operations trim each line to its tangent/cutback point via trim_line_to_point().

6. Trim, Extend, Break, and Lengthen

Line-Endpoint Operations

Trim TR: Pick cutting boundary, then target line region to remove. Splits target at intersection points via splitGeometry(). Keeps all parts except the one nearest the click point. For multi-part layers, adds extra parts as new features with copied attributes. Fallback: subtracts narrow buffer around cutting boundary.

Extend EX: Pick boundary, then line to extend. Projects a ray from the terminal segment direction, extends by the bounding box diagonal length, intersects with boundary geometry. Picks nearest forward intersection point. Appends to line preserving all existing vertices.

Break BR: Pick line, click two break points or Enter after one for break-at-point. Uses line_substring() which walks cumulative segment distances preserving interior vertices. Single-point mode splits at point; two-point mode creates a gap (first part + remainder).

Lengthen LEN: Three modes. Delta: target = current + value (negative shortens). Percent: target = current × value / 100. Total: target = value. Shortening uses line_substring() from the appropriate end. Extending moves the terminal vertex along the terminal segment direction by the extra distance. Pick the line near the end to modify.

7. Multi-Feature Operations

Join, Align, Stretch, Explode, Vertex Edit

Join J: Multiple picks (left-click to add, right-click to finish). Dialog tolerance. Iteratively welds paths by checking all four endpoint-pair cases with tolerance distance. Result replaces first feature; deletes originals.

Align AL: Pick feature, source1→dest1, source2→dest2. Enter after first pair = translate only. Optional scaling by pair length ratio. Transform: translate(-src1) + rotate + translate(+dst1) composed into a single QTransform. Two-pair mode derives rotation from source and destination vectors; scale factor = |dest_vector| / |source_vector|.

Stretch S: Crossing window defines vertices to move by (dx, dy). Iterates all vertices; moves those inside QgsRectangle. Operates across all editable layers simultaneously. Polygon rings stay closed. Returns None if no vertex falls in window.

Explode X: Parts mode splits multipart via asGeometryCollection(). Segments mode splits lines/polygon boundaries into individual two-point segments. Optional source removal. Writes to planx_explode layer for cross-type explosions.

Vertex Edit VE: Renders all vertices as orange QgsVertexMarker box handles. Drag to move (via moveVertex()), right-click to delete (via deleteVertex()), click on line to insert (via insertVertex()). Multipart-safe with part/vertex index tracking. Refuses operations leaving fewer than 2 (line) or 4 (polygon ring) vertices.

8. Transform Tools (6)

Affine Transformations with Precision

Move M / Copy CO: Base point + target point. Translation via QgsGeometry.translate(dx, dy). Copy duplicates geometry + attributes as new feature. Both support precision input (relative, polar, direct distance).

Rotate RO: Centre + reference direction + target angle. Hold Ctrl for 90-degree snap (round(angle/90) × 90). Accepts direct angle entry. Uses QgsGeometry.rotate() in local metric CRS.

Scale SC: Centre + reference distance + target distance. Factor = target / reference. Matrix: QTransform(factor, 0, 0, factor, cx(1-factor), cy(1-factor)).

Mirror MI: Two-point axis. Reflection matrix from normalised axis direction (ux, uy): \(m_{11} = 2u_x^2 - 1\), \(m_{12} = m_{21} = 2u_x u_y\), \(m_{22} = 2u_y^2 - 1\), translation = (start - m*start). Adds mirrored copy; never modifies original.

Array AR: Dialog for rectangular (rows, cols, dx, dy) or polar (count, sweep angle) parameters. Rectangular: nested-loop translation. Polar: equal-angle rotation around centre. Max 10,000 copies. Live preview via unaryUnion().

All transforms are multipart, curve, and Z/M-safe via QTransform-based affine operations.

9. Urban Planning Tools (3)

Road Platform Generator ROAD

Dialog: road type (Vehicular/Pedestrian/Bicycle/Collector/Arterial), direction, lane count (1–8), lane width (2–10 m), median width (0–20 m), sidewalks (0–10 m each side). Live total width readout. Sketch centreline on canvas. RoadGenerator.generate() offsets centreline in local CRS for each lane, median, and sidewalk edge. Writes to planx_road_platform MultiLineString layer with 11 attribute fields (road_id, road_type, component, side, lane_no, lane_width, median_width, sidewalk_left, sidewalk_right, direction, visible). Supports one-way and two-way generation.

Block Chamfer BLOCK

One-click corner resolution. Straight mode: finds two nearest intersecting line features near click point, trims both by distance along each line from the intersection, adds straight connection. Curved mode: uses same fillet geometry as the Fillet tool. Remnant cleanup: deletes lines shorter than the cleanup threshold within tolerance of the corner centre. Supports sequential corners (click→result→click→result...).

10. Junction Solver

Geometric Intersection Resolution (JUNCTION)

The junction solver (urban/junction_geometry.py) is a pure-geometry module operating on curb half-edges. Its algorithm proceeds through five phases:

  1. Half-edge extraction: Click the junction centre. Creates a circular buffer at the specified impact radius (3–100 m). Intersects with road platform features. Extracts outward curb rays (CurbHalfEdge objects) with cut points, outward direction vectors, and road/component metadata.
  2. Approach clustering (cluster_approaches()): Groups half-edges by road ID, sorts by angle, clusters edges within an angular tolerance (default 12°). Merges wrap-around clusters near 0/360°. Discards clusters with fewer than 2 edges. Each cluster becomes an Approach with left_curb() and right_curb() (signed lateral offset via cross product).
  3. Sector pairing: For each approach in counter-clockwise order, the active corner sector spans between the current approach's left curb and the next approach's right curb. Sectors with sweep angle ≥ π (straight-through or reflex) are skipped—these are not local corners.
  4. Corner solving: Uses the support_line_intersection() method (2D cross-product intersection of directed support lines). Chamfer mode: extends from intersection by distance along each ray, connects with straight line. Fillet mode: uses the tangent-circle algorithm from the Fillet tool, adapted for directed rays. Validates each solution against distance constraints.
  5. Application: Trims road platform components at tangent/cutback points. Creates connection geometry (arc or line) from the first road's attributes. Optionally creates round or teardrop traffic islands on planx_junction_islands layer. All within a single rollback-safe edit command.

11. Precision Point Input

Four Input Formats, Metre-Accurate in All CRS

The precision input system (core/precision_input.py) supports four coordinate formats, all resolved through a local UTM work CRS for metre-accuracy:

Type a number, minus sign, or @ directly on the canvas, or focus the command line with Ctrl+Shift+S. Supported by Line, Polyline, Rectangle, Circle, Polygon, Arc, Move, Copy, Rotate, and Scale.

12. Command Line

AutoCAD-Style Command Interface

The dock includes a command line (CommandLineEdit) with: muscle-memory aliases (65 entries: L = Line, TR = Trim, CO = Copy, F = Fillet, CHA = Chamfer, XL = Construction Infinite, DIM = Dimension, etc.), full autocomplete by alias, tool key, and fuzzy name match (QCompleter with PopupCompletion), 50-entry history ring with consecutive duplicate skipping, empty-Enter to repeat the last tool or finish an in-progress sketch, and session persistence for recent tools and pinned favourites. Ctrl+Shift+Space repeats the last tool instantly. Ctrl+Shift+S focuses the command line. Ctrl+Shift+Q opens the Command Palette dialog with fuzzy search across all 39 tools.

13. Managed Layer System

Eight Output Layers, Auto-Created on First Use

The plugin uses managed memory layers for output tools rather than writing to the user's active layer:

LayerGeometryCreated By
planx_bufferPolygonBuffer tool
planx_constructionLineStringConstruction Line tools
planx_dimensionsLineStringDimension tool
planx_hatchLineStringHatch tool
planx_divisionsPointDivide tool (points mode)
planx_explodeLineStringExplode tool (cross-type)
planx_road_platformMultiLineStringRoad Generator, Junction
planx_junction_islandsPolygonJunction (islands)

Layers are reused across sessions: get_or_create_layer() searches existing project layers by name, validates WKB type, CRS, and field schema. If no compatible layer exists, creates a new in-memory layer. The road platform layer supports bilingual (English/Turkish) schemas with road_field_name() translation for legacy compatibility.

14. CRS Safety

Local Metric Work CRS for Distance-Bearing Operations

The function local_metric_crs(point, source_crs) creates a local work CRS where distances are true metres:

  1. Transform the work point to WGS84 geographic coordinates.
  2. For normal latitudes (−80° to 84°): compute UTM zone as \(\lfloor(\lambda + 180)/6\rfloor + 1\), EPSG = 32600 + zone (north) or 32700 + zone (south).
  3. For polar regions: use Azimuthal Equidistant projection (AEQD) centred on the work point, which preserves distances and angles from the centre.

This CRS is used by: precision input resolution, rotate/mirror operations, circle/polygon/rectangle geometry building in geographic projects, offset/fillet/chamfer/hatch, road generator, junction solver, and block chamfer. Each operation gets its own CRS based on its specific work location, so even operations far apart in the project receive the appropriate zone.

15. Edit Session Safety

Transactional Geometry Operations

Every geometry-modifying operation uses beginEditCommand()/endEditCommand() for transactional safety with full rollback on failure. Multi-layer operations (Fillet, Chamfer, Junction) open edit commands on all involved layers simultaneously and only commit if all succeed. The Junction solver keeps its edit command open across trim operations, corner connection adds, and median cap creation. Tools that write to managed layers check layer.isEditable() before starting their own session; if the layer is already being edited by the user, they use the existing session without auto-committing. Drawing tools auto-start editing if the target layer is not already editable.

For single-part layers, operations that would produce disconnected MultiLineString results (Trim, Divide) replace the original feature with the first part and add remaining parts as new features with copied attributes incremented through the self-pick exclusion buffer.

16. Workflow Guide

  1. Open the PlanX CAD dock from the toolbar icon. The dock shows collapsible tool groups, a command line, recent tools, and quick-action buttons.
  2. Ensure the target layer is editable. The dock's layer state indicator shows the active layer name and edit status.
  3. Choose a tool by clicking its icon, typing its alias in the command line, or using a keyboard shortcut.
  4. For drawing tools: keep snapping enabled. Use precision input for exact placement. Backspace to undo last vertex, Enter to finish, Escape to cancel.
  5. For editing tools: pick reference geometry first, then the target. Tools like Trim, Extend, Fillet, and Chamfer exclude self-pick.
  6. Use Ctrl+Shift+Space to repeat the last tool. Pin frequently used tools for one-click access.
  7. Use the Docs button for in-context help, Keys for the shortcut reference, and Diag / Stats for diagnostics.
  8. Hatch and Buffer output to their respective managed layers; cut/copy them to your working layer as needed.

17. Technical Notes

18. Literature

  1. Farin, G. (2002). Curves and Surfaces for CAGD: A Practical Guide (5th ed.). Morgan Kaufmann. DOI: 10.1016/B978-1-55860-737-8.X5000-5
  2. de Berg, M., Cheong, O., van Kreveld, M., & Overmars, M. (2008). Computational Geometry: Algorithms and Applications (3rd ed.). Springer. DOI: 10.1007/978-3-540-77974-2
  3. Douglas, D. H. & Peucker, T. K. (1973). Algorithms for the reduction of the number of points required to represent a digitized line or its caricature. Cartographica, 10(2), 112–122. DOI: 10.3138/FM57-6770-U75U-7727
  4. Goldman, R. (2003). Pyramid Algorithms: A Dynamic Programming Approach to Curves and Surfaces for Geometric Modeling. Morgan Kaufmann. DOI: 10.1016/B978-1-55860-354-7.X5000-3
  5. O'Rourke, J. (1998). Computational Geometry in C (2nd ed.). Cambridge University Press. DOI: 10.1017/CBO9780511804120
  6. Glassner, A. S. (Ed.). (1990). Graphics Gems. Academic Press. DOI: 10.1016/C2009-0-22266-2
  7. Snyder, J. P. (1987). Map Projections—A Working Manual (USGS Professional Paper 1395). U.S. Government Printing Office. DOI: 10.3133/pp1395
  8. Eminoğlu, Y. (2025). PlanX CAD Toolset: An AutoCAD-style drafting workbench for QGIS. Zenodo. DOI: 10.5281/zenodo.20753127