Version: 0.1.0 | Author: Yusuf Eminoglu | License: GPL-3.0
ParcelFlux subdivides zoning blocks (imar adalar) into individual parcels with tunable geometric variation. It operates on polygon layers and produces a memory layer of parcel polygons with area and optional facade-tracking columns.
The engine processes each input block polygon independently through six stages:
1.8 * lot_width, the block is treated as single-row (one strip of
parcels). Otherwise it is double-row (two opposing strips on either side of
the centerline).lot_width, with optional variation
(width, fishbone, asymmetry, h-line shift).native:splitwithlines. Residual fragments below the area threshold are
merged into the neighbor with the longest shared edge, in up to 3 passes.max_area or
below 5 m² are excluded. Remaining parcels are written to a memory layer with
area and optional ID/facade columns.lot_widthDefault: 16.0 m | Range: 5.0 – 100.0 m
Target frontage width of each parcel. This is the primary control over parcel count. Smaller values produce more parcels per block; larger values produce fewer, wider parcels.
where L_centerline is the length of the line connecting the midpoints of the two shortest edges. In double-row mode, each side independently computes its parcel count.
min_areaDefault: 300.0 m² | Range: 0.0 – 999999.0 m²
Parcels smaller than this threshold are merged into the adjacent neighbour with the longest shared boundary. This operates alongside the merge-threshold rule. Set to 0 to disable hard-minimum enforcement.
max_areaDefault: 2000.0 m² | Range: 0.0 – 999999.0 m²
Parcels exceeding this area are filtered out of the output. Use a high value (e.g. 999999) to keep all parcels regardless of size.
merge_thresholdDefault: 35.0 % | Range: 0.0 – 100.0 %
Residual (sliver) merging threshold expressed as a percentage of the mean parcel area after the current pass. The threshold is recomputed after each merge pass:
Any parcel with area < T_pass is merged into its neighbor with the longest
shared edge. Three passes are attempted; the process stops early if no parcels are merged
in a pass. Higher values = more aggressive merging. 0 = only the min_area
rule applies.
uniform_cornersDefault: enabled (True)
Controls how leftover space along the centerline is distributed:
width_variationDefault: 0.0 % | Range: 0.0 – 25.0 %
Per-parcel random width variation. Each parcel in a row receives an independent random multiplier:
After randomization, all widths are re-normalized so their sum equals the available centerline length. At 0%, all parcels in a row are identical. At 15% with a 20 m target, parcels range from approximately 17 m to 23 m.
fishbone_offsetDefault: 0.0 % | Range: 0.0 – 15.0 %
Organic zigzag shift applied to division-line endpoints along the centerline direction. Creates a herringbone pattern that mimics traditional settlement morphologies.
At 0%, division lines are straight. At 5-10%, the herringbone effect becomes visually apparent. The two endpoints of each division line are offset independently, so lines can slant rather than remaining parallel.
row_width_asymmetryDefault: 0.0 % | Range: 0.0 – 25.0 %
Creates different parcel widths on the two rows on opposite sides of the centerline. This models real-world patterns where north-facing parcels may be wider (more desirable solar orientation) than south-facing ones.
This parameter is ignored in single-row mode (when the block's short edge < 1.8 * lot_width).
hline_offsetDefault: 0.0 % | Range: 0.0 – 25.0 %
Shifts the center division line away from the geometric midpoint of the block's short edges, producing asymmetric front/rear depths.
At 0%, the block is split exactly in half. At 10%, the h-line is randomly placed between 40%-60% along each short edge. One row gets deeper parcels, the other gets shallower ones. This is useful for differentiating front-garden and back-garden depths.
The decision rule is:
Rationale for 1.8: each parcel row needs at least lot_width depth.
A factor of 1.8 provides a 10% margin (two rows need ~2.0x, thresholding at 1.8 ensures
rows are not too shallow). A block with short edge = 30 m and lot_width = 16 m triggers
double-row mode because 30 ≥ 1.8 * 16 = 28.8.
After the split, sliver polygons (triangular fragments, narrow strips) inevitably form near block edges and division-line intersections. The 3-pass merging algorithm handles these:
max(threshold_pct * mean, min_area) is a candidate.intersection().length() on LineString
intersections).geometry.combine().This is a greedy algorithm — it processes candidates in feature-ID order and does not revisit already-merged parcels within a single pass. The 3-pass structure allows cascading merges: a merged parcel from pass 1 may itself be below threshold in pass 2 and get merged again.
| Column | Type | Description |
|---|---|---|
| Copied from input layer | ||
block_id * | String | Source feature ID of the parent block |
| Computed columns | ||
parcel_id * | Integer | Sequential parcel number (1..N) |
area_m2 | Double | Parcel area in square metres |
| Facade tracking columns * (placeholders) | ||
facade_front * | String | Front facade edge description (empty) |
facade_side * | String | Side facade edge description (empty) |
facade_back * | String | Back facade edge description (empty) |
facade_count * | Integer | Number of facade edges (0) |
is_corner * | Boolean | Corner-parcel flag (False) |
front_direction * | String | Cardinal direction hint (empty) |
* = optional; controlled by "Add ID columns" and "Add facade columns" checkboxes in the dock UI.
| Version | Status |
|---|---|
| QGIS 3.28 | Minimum supported |
| QGIS 3.34 LTR | Supported |
| QGIS 3.40 LTR | Supported |
| QGIS 4.x | Supported (tested with qgisMaximumVersion=4.99) |
The plugin uses only stable PyQGIS APIs and native Processing algorithms. The
QgsWkbTypes.GeometryType enum is resolved at import time with a try/except
fallback for QGIS 3.
ParcelFlux 0.1.0 — part of the PlanX Geospatial Tools suite.