{"name": "Align Features to Path", "package_name": "align_features_to_path", "version": "14.7.7", "experimental": false, "qgis_min": "3.16.0", "qgis_max": "4.99.0", "downloads": 110, "uploaded_by": "MustafaELghazaly", "upload_datetime": "2026-11-04T13:17:54.083259", "changelog": "v15.5.7: Path-end fix. The alignment area has flat ends again (engine\nlogic of v15.4.2): v15.5.3's Round-in-engine anchored every vertex in\nthe end half-disc onto the single end point, which produced a fan of\nlines and stair-shaped slivers around the path end. Results are now\nidentical to v15.4.2 for both Square and Round; Round only changes the\ndrawn corridor. Square is the default. All v15.5.x UI, speed and\ncurve-smoothing improvements are kept.\nv15.5.6: Smooth curves \u2014 no more small kinks. Curve (C) and Arc (Z)\nsegments are now sampled uniformly at 0.5\u00b0 per chord and committed\nwithout the old Douglas-Peucker thinning, which had kept only ~8\nvertices per radian and left 5\u20139\u00b0 corners on long curves. A\nhalf-circle now lands as ~360 vertices instead of ~35. Because the\naligned boundary is traced along these same path vertices, the\naligned edge is round too: measured max deflection 0.50\u00b0 on both\nthe drawn path and the aligned polygon (was up to 8.9\u00b0), with no\nreversal/spur. Preview and commit use the identical point list.\nNew suite tests/curve_smoothness.py (26/26).\nv15.5.5: Two workflow fixes. (1) No need to stand on a layer in the\nLayers panel: when the active item is not a line/polygon layer (or\nnothing is selected), the plugin keeps the last alignable layer used,\notherwise picks the topmost line/polygon layer in the project by\nitself. The target line still shows which layer will be aligned.\n(2) Align now consumes the path: the tolerance corridor, the amber\npath overlay and the start/end markers all disappear when the result\nis applied, and the path state is reset so nothing is left drawn on\nthe map. Undo still restores the previous geometries. New UI checks:\nno-active-layer alignment, path overlay/markers hidden after Align\n(71/71 UI checks).\nv15.5.4: Smooth corridors and instant Align. The two tolerance fills now\nmeet exactly on the drawn path \u2014 the old offset-ring mask could\nself-intersect on tight bends and GEOS then returned the whole\ncorridor for both sides, which is what produced the jagged \"sawtooth\"\nsplit in the screenshots. Each side is now built with\nsingleSidedBuffer() from the path extended over the round caps, so the\nsplit follows the path vertex-for-vertex, the cap stays filled, and\nleft+right cover the full buffer exactly (13/13 geometry checks).\nAlignment speed: the whole-layer QgsSpatialIndex build is gone (the\nprovider's own rectangle filter is used instead \u2014 10,000 parcels now\ntake 0.012 s to fetch), Align reuses the Preview result when nothing\nchanged (0.003 s), the engine's per-vertex projection and\nedge-crossing queries are cached, progress events are throttled to\n50 ms, and edits are applied as one beginEditCommand per layer. The\npreview corridor is hidden the moment Align starts and stays hidden\nafterwards. Engine results remain identical to v15.4.2 for Square in\nall 23 equivalence scenarios.\nv15.5.3: Round ends now do what they say \u2014 the half-disc around the\nstart and end of the path is genuinely part of the alignment area.\nPreviously the Round/Square choice only changed how the tolerance\ncorridor was drawn; the engine always used flat ends, so a parcel\ncorner poking into the rounded cap stayed put. Now Round matches the\npreview: vertices inside the half-disc are eligible and anchor on the\npath endpoint, so the piece inside the cap is pulled onto the path\n(and Square still leaves it untouched). Along the path \u2014 the whole\ninterior \u2014 behaviour is unchanged. Also fixed a latent\nnon-determinism: shared-vertex welding iterated features in memory\naddress order, which could pick a different canonical vertex between\nruns; it now uses the caller's stable feature order. Verified: Square\nresults are identical to v15.4.2 in all 23 equivalence scenarios, and\nthe interior is identical for both end styles. New round_ends.py test\n(29 checks).\nv15.5.2: Cleaner canvas and one-click targeting \u2014 the Target Layers\nselectors are gone; Preview and Align now run directly on the active\nQGIS layer (with a single-vector-layer fallback), and the panel shows\na read-only target line instead. The overlay palette was rebalanced to\nmuted tones: amber path, sage traced edges, warm-ivory previews, and a\nteal / slate-blue tolerance corridor. Duplicate side outlines and halos\nwere removed so the corridor is two soft fills plus one warm outline,\nand all preview bands are thinner. Side fills are stronger for\nlegibility while staying transparent. The alignment engine remains\nbyte-identical to v15.4.2.\nv15.5.1: Fixes and polish \u2014 the tolerance corridor now renders in the\ncorrect canvas z-order, so the cyan/left and violet/right buffer is\nactually visible above raster and vector layers (previously only the\nreadout and badge appeared). Fill opacity is slightly stronger for\nlegibility over satellite imagery. The alignment path is thinner\n(2 px core, 7 px dark halo) and the Trace / Edge Snap indicators use\ncompact dots instead of large glyphs. New gazelle-head plugin icon\n(icon.svg + 256 px icon.png), also used in the panel header. The\nalignment engine remains byte-identical to v15.4.2.\nv15.5.0: Professional digitising upgrade \u2014 UI and interaction only; the\nalignment engine file is byte-identical, so alignment results are\nunchanged. New charcoal panel with Line / Curve / Arc segmented\ncontrols, explicit Left / Right curve-side selection (F flips while\ndrawing) and persistent per-mode side memory, plus Trace and Edge Snap\nswitches that stay in sync with the T key. A high-contrast amber path\nwith a dark halo replaces the light-blue one; traced edges (lime),\nlive preview (sky blue), tangent arcs (pink / violet) and snapped\nvertices (orange with white halo) are now visually distinct. The\ntolerance preview is a two-tone corridor \u2014 cyan left, violet right \u2014\nwith dark/light double outlines, a distance + area readout and a\nfloating canvas badge; updates are debounced (45 ms) so dragging the\ndistance stays smooth. Trace projects the cursor with a continuity\nbias and a hard distance cutoff and caches the local edge graph, so it\nno longer hops to a neighbouring boundary or loses the edge mid-stroke.\nEdge Snap resolves vertex > true junction > nearest point along an edge.\nv15.4.2: Far fewer vertices. Committed curve arcs (C / Z) are thinned to\nthe few vertices the curve needs (was 48+ per arc), and after Fit to\nPath the redundant path-trace vertices and collinear densification\npoints are removed from the result (shared boundaries stay identical).\nOblique dividers are no longer bent onto the path. Parcel\ndividers that meet the road at 30-45 degrees (diagonal parcels) were\nclassified as edges running ALONG the path (old fixed 45 degree\ncut-off), so they were moved and ended in a diagonal stub instead of\nbeing extended / trimmed straight to the path. An edge is now a\ndivider when it is shared with another parcel and >= 30 degrees to\nthe path, or clearly more oblique than the neighbouring frontage edge.\nv15.4.1: The retry after an overlap / self-crossing no longer demotes\nEVERY divider of the offending parcels to the nearest-point anchor\n(which bent dividers far from the problem, up to ~50 m, and changed\nparcel areas by hundreds of m2). The first retries now demote only the\ndividers whose extended line touches the overlap / crossing; later\nretries fall back to the previous behaviour, so the result is never\nworse than before.\nv15.4.0: Dividers no longer bend when the divider ends in a short jog next\nto the path. The extension used only the LAST edge of the divider, so a\nshort, differently-angled end edge sent the extension the wrong way: the\nring crossed itself (bow-tie), the result was rejected and the dividers\nfell back to nearest-point anchoring, which bent them. Now a divider\nthat ends in a jog is retried along its own earlier, real direction\n(jog dropped, divider stays straight); only dividers that still fail\nuse the nearest-point anchor. Also: the verification ignores overlaps\nthat already exist in the input data.\nv15.3.1: Verification ignores overlaps that already exist in the input\ndata (only NEW or enlarged overlaps trigger the fallback / warning),\nas was already done for gaps.\nv15.3.0: Align Edge logic (like ArcGIS Pro). Only the boundary that runs\nALONG the path (within ~45 degrees of it) is moved. Dividers that\narrive across the path keep their own shape, including small jogs and\ncorners: only the end that meets the new boundary is extended or\ntrimmed along its own line, and a divider that runs through the path\nis cut at its first crossing. Classification is computed once for\nthe whole layer so neighbouring parcels always agree. The result is\nverified (overlaps AND gaps); if it fails, the previous classic\nbehaviour is used automatically.\nv15.2.0: Path ends. Geometry beyond the start/end of the path is never\nmoved, densified or used as an anchor, and the alignment area has\nflat ends regardless of the Round/Square setting (a round cap made\nthe edges arriving from outside get cut at the arc and bent).\nv15.1.0: Dividers no longer bend. Where a parcel boundary runs into the\ntolerance area it is now EXTENDED (or trimmed) along its own line\nuntil it meets the path, instead of being dragged sideways to the\nnearest path point. Vertices beyond the end of the path are left\nalone (no more fan of lines meeting at the path end). The result is\nverified: any divider that would cause an overlap falls back to the\nold nearest-point anchor automatically.\nv15.0.0: Topology fix. Verified in QGIS 4.2 on grid and Voronoi parcel\nlayers (0 invalid / 0 overlaps / 0 gaps at realistic tolerances;\nthe previous version produced hundreds). Root causes fixed:\n(1) edge densification and buffer-crossing points were computed\nin the direction each polygon happened to traverse an edge, so two\nneighbours got different vertices on their shared boundary - both\nare now direction independent; (2) Preserve Shape clamped vertices\nin an order-dependent way and joined them with chords - it now\nwalks the path in arc-length order; (3) new shared-vertex pass\n(vertex welding + T-junction insertion, like topological editing);\n(4) self-touching rings are split into valid MultiPolygons instead\nof being left invalid; (5) hairpin guard for paths that double\nback; (6) dialog: results were matched to layers by feature id,\nwhich wrote geometry to the wrong layer when two layers shared an\nid - now matched by object identity; (7) CRS round trip no longer\nperturbs unchanged vertices; (8) warnings are shown to the user.\nv14.7.3-local: Security fixes \u2014 replaced all bare 'except Exception:'\nclauses with specific exception types (TypeError, AttributeError,\nValueError, KeyError, RuntimeError, ZeroDivisionError) per Bandit\nsecurity scanner requirements. All exception handlers now catch only\nrelevant exceptions and include proper error handling fallbacks,\nimproving code robustness and security posture. Zero functional\nchanges to alignment behavior.\nv14.7.1-local: v14.7.0's Side-aware preview relied on\nQgsGeometry.singleSidedBuffer(), which turned out to silently\nfail on this QGIS/GEOS build (all three call-signature attempts\nraised/returned empty) and fall back to the full symmetric\nbuffer \u2014 i.e. exactly the \"shows both sides regardless of Side\"\nbug the user was still seeing. Replaced it with a\ngeometry-only approach that can't hit that failure mode:\n_side_mask_polygon() builds a generous one-sided mask polygon\nper path segment using the identical cross-product sign test\n_classify_vertex() uses for eligibility (same left/right\nconvention), then _make_side_buffer() intersects that mask with\nthe ordinary symmetric buffer. Only buffer/combine/intersection\nare used \u2014 no singleSidedBuffer call left at all \u2014 so the\npreview can no longer silently disagree with what Align will\nactually do.\nv14.7.0-local: Tolerance-buffer preview now honours the Side\n(Both/Left/Right) setting while drawing, requested directly by\nuser \u2014 previously it always showed the full both-sides corridor\nno matter what Side was set to, even though the actual Align\nstep already restricted itself to one side via SIDE_LEFT/\nSIDE_RIGHT in _classify_vertex(). Added _make_side_buffer() in\nalign_to_path_algorithm.py: for Both it's the same symmetric\nbuffer as before; for Left/Right it now uses QgsGeometry.\nsingleSidedBuffer(), which grows the buffer out from only one\nside of the digitised line direction \u2014 the exact same left/right\nconvention (sign of the (b-a) x (pt-a) cross product) the\nalignment eligibility test already uses, so the shaded zone the\nuser sees while walking the path forward is the same zone that\nwill actually be used, not a leftover mirror image on the other\nside. Wired into both the live drawing preview\n(_run_pending_path_preview) and the static preview shown once a\npath is finished (_update_tol_preview). Also made the Side\ntoggle itself live: ToggleGroup now supports an on_change\ncallback, so flipping Left/Right/Both instantly refreshes\nwhichever preview is currently showing (mid-draw or already\nfinished) instead of only updating on the next click/redraw.\nv14.6.0-local: Two follow-up fixes requested directly by user.\n(1) Shortcut simplified from Ctrl+M to plain M (setShortcut +\nregisterMainWindowAction updated together; tooltip text updated\nto match). Same safe-registration/try-except behaviour as before\nif \"M\" is already bound elsewhere.\n(2) User still felt lag and reported needing \"two clicks\" before\nthe path shows up. Root cause found in align_to_path_dialog.py,\nnot the map tool itself: pathUpdated only fires once the path has\n>=2 points (a 1-point line can't be buffered), and the tolerance-\nbuffer preview that renders around the path was, on top of that,\nalways debounced 120ms behind every click (_path_preview_timer) \u2014\nso the very first time a path becomes visible, the user was\npaying for both the 2-click minimum AND a 120ms delay after the\n2nd click, which read as \"laggy\". Fix: _on_path_updated now runs\nthe buffer preview immediately (no debounce) the first time the\npath reaches exactly 2 points, since a 2-point buffer is\nessentially free to compute; every later update (path actually\ngrowing, where re-buffering the whole thing click-by-click could\nget expensive) still goes through the debounce, now shortened\nfrom 120ms to 40ms so it also feels snappier during a normal\n(non-burst) drawing pace. The underlying map-tool drawing/snap\ncode (canvasMoveEvent, snap/trace caching) was already reviewed\nfor perf in v14.5.0 and is unchanged here.\nv14.5.0-local: Added a Ctrl+M keyboard shortcut to open/close the panel\nquickly, requested directly by user. Registered via\niface.registerMainWindowAction() (in addition to the action's own\nsetShortcut()) so it fires app-wide, not just when the toolbar\nbutton has focus, and unregistered cleanly in unload(). If Ctrl+M\nis already bound to something else, registration fails safely\n(caught and logged) and the toolbar/menu entry keeps working\nnormally instead of the clash breaking plugin load. Also reviewed\nfor stability/perf per user report of the panel \"feeling heavy\":\nno changes were needed there \u2014 the mouse-move handling, snap\nlookups and trace-graph building were already reworked in\nv14.0-14.4 to cache aggressively and skip sub-pixel jitter (see\ncanvasMoveEvent, _get_cached_snap_vertices, _get_cached_snap_segments,\n_get_trace_graph), and every QGIS-version-sensitive Qt/PyQt import\nalready has a 3.x/4.x compatibility fallback. Confirmed all five\nmodule files still compile cleanly.\nv14.4.1-local: Z curve mode COMMIT-time exact-closure fix, requested\ndirectly by user (\"corners leave breaks that ruin the geometry\").\nRoot cause: _arc_points_spiral()'s fallback (used whenever the\ncurvature-eased spiral solve can't reach the clicked point on the\ncurrent flip side) is _arc_points_true_round(), which applies a\n140 deg anti-hook SWEEP CLAMP. That clamp is correct for the LIVE\nPREVIEW (stops a dragged arc curling into a fish-hook) but was\nbeing carried into the COMMITTED vertex list too, silently\nlanding the new vertex short of the point the user actually\nclicked. The next segment then started from that short,\nun-signalled position instead of from the clicked corner -- a\nstray gap at exactly the corner the user was drawing.\nFix: on commit only, if the spiral (or its clamped fallback)\ndoes not land on the clicked point within tolerance, re-solve\nwith the unclamped closed-form circular arc (_arc_points), which\nalways reaches the clicked point exactly for any non-degenerate\ntangent/chord. The live preview is unchanged and still shows the\ngentler clamped shape while dragging. Verified in isolation\n(no QGIS) against a swept random sample of end points/flip\nsides: every previously-short commit (e.g. a 0.13 map-unit gap\nreproduced at pt=(-0.046,-0.505), flip=1 from tangent (1,0) at\norigin) now closes to zero gap; every already-exact commit is\nunaffected (identical output, since the fallback branch is\nskipped when the spiral already lands on the point).\nv14.4.0-local: New independent \"Edge Snap Engine\" (ArcGIS Pro-style\nedge snapping), requested directly by user because QGIS's own\nsnapping felt vertex-only and inconsistent. Adds a new toggle\nbutton/icon (\ud83e\uddf2 Edge Snap) in the panel, ON by default, that\ndrives a snapping engine fully independent of QGIS's project\nsnapping config: the cursor now snaps to the nearest point\nanywhere along a visible line/polygon edge, not only at its\nvertices, with the whole matched edge highlighted in green while\nhovering \u2014 matching ArcGIS Pro's snap feel. Vertices still take\npriority over edges within the same tolerance. Switching the\ntoggle OFF restores the previous QgsSnappingUtils-based behaviour.\nSee AlignmentPathTool.set_edge_snap_enabled() /\n_find_snap_point_edge_engine().\nv14.3.0-local: STRUCTURAL SIMPLIFICATION, requested directly by user\nafter v14.2 still showed geometry corruption in \"reshape\"-style\nedits. Root cause: v14.1's edge-angle classifier (FOLLOWING/\nAMBIGUOUS/CROSSING/TOO_FAR/NOISE) was a SECOND, independent gate\non top of plain buffer containment \u2014 a vertex could sit plainly\ninside the tolerance buffer and still be left raw, or only\npartially warped by the run/sub-run splitting that classifier\nneeded, whenever its local edge angle didn't clear an adaptive\nthreshold. That is what produced unpredictable \"reshape breaks\nthe geometry\" behaviour even after the v14.2 arc-length fix,\nwhich only fixed precision/ordering WITHIN that classifier's\ngated regions, not the gating itself.\nFix: removed the entire angle-classification layer\n(`_classify_edge`, `_smooth_edge_labels`, `_classify_edge_raw`,\n`_edge_angle_to_tangent_deg`, `_adaptive_angle_threshold_deg`\nand the FOLLOWING/AMBIGUOUS/CROSSING/TOO_FAR/NOISE labels \u2014 all\ndeleted). Eligibility is now the single, literal rule requested:\na vertex is eligible iff it lies inside the tolerance buffer of\nthe path (`_classify_vertex`, a real point-in-polygon test) \u2014\nfull stop. `_process_ring` now finds maximal runs of consecutive\nin-buffer vertices directly from that one test and replaces\n(Fit) or re-anchors (Preserve) each run, with entry/exit\ncrossings computed on the immediate flanking edge. Densification\n(`_densify_near_master`) dropped the same classifier call for\nthe same reason. This also deletes the whole \"sandwiched raw\ncorner\" special case from v14.1.7 \u2014 it cannot occur any more,\nsince a run is now defined purely by buffer membership, so a\nrun can never contain a non-eligible vertex to sandwich in the\nfirst place.\nVerified in isolation (no QGIS) against a synthetic polygon with\na transverse divider that pokes partway into the tolerance\nbuffer: the along-path stretches snap exactly onto the path,\nthe divider's in-buffer portion is pulled onto the path too\n(the literal requested behaviour), its out-of-buffer portion is\nleft completely untouched, and no self-crossing or duplicate\nvertices appear at either hand-off.\nv14.2.0-local: ROOT-CAUSE FIX, not another patch. Every version through\nv14.1.7 computed the correct continuous nearest-path position\n(segment + parameter t) for each vertex/crossing, then immediately\nrounded it down to the nearest whole MASTER-PATH VERTEX\n(`nearest_vertex_index`) before using it for anything \u2014 ordering,\nanchoring, span-filling. That rounding was the actual source of\nboth the v14.1.6 \"V spike on curves\" bug (a rounded vertex index\nis not a reliable stand-in for arc-length order on a bend) and,\nseparately, contributed to imprecise hand-off points generally.\nv14.1.6/7 each patched one symptom (a monotonic clamp on indices;\ndropping a sandwiched raw corner) without removing the rounding\nstep itself, so a new curve geometry could still expose a fresh\nvariant of the same root problem.\nFix: kept the exact continuous (seg_i, t) position, and its real\narc-length (\"station\"), all the way from projection through to\nthe emitted coordinate. Added `_MasterPath.point_at` /\n`station_at` (true interpolated point / arc length instead of a\nrounded vertex). `_master_span` now walks by real station order\n\u2014 always monotonic on any path shape, curved or not \u2014 instead of\nvertex-index comparison. Preserve Shape's monotonic clamp now\ncompares stations instead of indices, so it only fires on a\ngenuine backward jump, never on rounding noise. Verified in\nisolation against a synthetic curved master path (21-vertex\nbend): projected stations and a full `_master_span` walk across\nthe bend are confirmed monotonic with zero backward jumps.\nThe Global Master Path Snapping guarantee (adjacent parcels\nsharing a boundary get bitwise-identical coordinates) is\nunaffected \u2014 it only ever relied on the pipeline being a\ndeterministic function of identical shared input geometry, never\non the coarseness of the snap.\nv14.1.7-local: SECOND REAL BUG FIX (confirmed by user screenshots \u2014\nspike persisted after v14.1.6 even with Fit to Path). Distinct\nroot cause from v14.1.6: a ring corner sitting just outside the\ntolerance buffer, flanked on both sides by FOLLOWING-classified\nedges (typical right at the inside of a curved path bend, where\nthe buffer locally pinches), was split into two separate\nsub-runs by _process_ring's outer loop \u2014 and the corner's own\nRAW, unmoved coordinate was emitted between them. Since both\nsub-runs' own anchors (exit_cross / entry_cross) already sit\nright on the buffer edge near the curve, inserting the far-away\nraw corner between them produced: aligned point -> raw corner ->\naligned point, i.e. the line visibly darted out to the old\ncorner position and back (the exact spike shape reported).\nVerified the fix's branch logic in isolation against 6 run\npatterns (sandwiched gap, leading-approach gap, trailing-approach\ngap, all-eligible, all-ineligible, multiple gaps): the sandwiched\ncase now correctly drops the raw corner and bridges the two\nsub-runs directly, while every other pattern (crucially, the\nlegitimate \"long edge approaching the buffer from outside\" case)\nis untouched. Fix: in _process_ring's run-splitting loop, an\nineligible vertex with an eligible vertex before AND after it\nwithin the same alignable run is no longer emitted at its raw\ncoordinate; it is dropped and the flanking sub-runs bridge the\ngap via their own already-correct buffer-boundary anchors.\nv14.1.6-local: REAL BUG FIX (confirmed by user-reported screenshots +\nreproduced synthetically) \u2014 self-crossing \"V\" spike when a\nnear-parallel boundary edge is aligned against a CURVED stretch\nof the master path (round-joined corridor). Root cause: per-vertex\nsnapping (_snap_mi via _classify_vertex -> master.project) picks\neach point's globally-nearest master index independently, with no\nawareness of path direction; on a bend, two adjacent boundary\nvertices can have nearest-points that are OUT OF station order\n(confirmed synthetically: raw indices [...,30,34,29,...] \u2014 a\nforward-then-backward jump that manifests as the observed spike).\nReproduced in isolation with a mock curved master path + diagonal\ncrossing edge; index sequence was provably non-monotonic before\nthe fix and monotonic after. Fixed in _emit_subrun's Preserve\nShape branch: interior vertices are now clamped to progress\nmonotonically (in master-vertex-index terms) from the entry\nanchor toward the exit anchor, never backward, matching the\npath's own parameterisation. Fit to Path's _master_span was\nalready monotonic by construction and is unaffected structurally,\nbut entry/exit anchor selection on sharply curved paths uses the\nsame nearest-point search and has NOT yet been independently\nre-verified against this class of bug \u2014 flagged as open follow-up.\nv14.1.5-local: Verification pass over the v14.1 adaptive-classification\nfix \u2014 confirmed by direct unit testing of the pure classifier\nfunctions (_adaptive_angle_threshold_deg, _classify_edge_raw,\n_smooth_edge_labels) against the documented threshold curve,\ncontinuity rules and the old \"1-following-edge-triggers-whole-ring\"\nfailure mode (now correctly rejected). Static analysis (py_compile\n+ pyflakes) run across all modules \u2014 zero syntax errors; removed\none dead/unused local variable in align_to_path_dialog.py\n(result_map, never read). No behavioural change to alignment\noutput vs v14.1.4.\nv14.1.0-local: Geometry engine fix \u2014 hard-coded 30\u00b0 parallel cutoff\nreplaced with adaptive, distance/continuity-aware edge\nclassification (FOLLOWING/AMBIGUOUS/CROSSING/TOO_FAR/NOISE);\nstricter evidence bar before a whole ring is fast-path snapped;\nhigher-fidelity curve linearisation tolerance. UI unchanged.\nv14.0.1-local: \u0645\u062d\u0633\u0651\u0646 \u0644\u0644\u0639\u0645\u0644 \u0645\u062d\u0644\u064a - \u062a\u062d\u0633\u064a\u0646\u0627\u062a \u0627\u0644\u062b\u0628\u0627\u062a \u0648\u0627\u0644\u0623\u062f\u0627\u0621\u060c \u062f\u0639\u0645 \u0643\u0627\u0645\u0644 \u0644\u0640 QGIS 3.16-4.99\nv14.0.0: Trace mode rebuilt on a local edge graph (_TraceGraph)", "external_deps": null, "download_url": "https://plugins.qgis.org/plugins/align_features_to_path/version/14.7.7/download/"}