[general]
name=STAT GEOM QC
qgisMinimumVersion=3.16
qgisMaximumVersion=3.99
description=Quality control and geometric statistics for vector layers, with a correctness score and exportable report.
about=STAT GEOM QC analyses QGIS vector layers and detects quality issues: null or empty geometries, invalid geometries, self-intersections, overlaps/intersections between polygons, duplicates, small polygons (optional, configurable m² threshold), duplicate vertices (optional), holes in polygons (optional, with an area threshold so that large justified holes are kept) and multipart features. Overlap detection is strictly topological — interiors that intersect, however slightly, with no metric tolerance — so a shared boundary or a single point of contact is never reported. An "Extras" section adds four optional checks: sharp angles (spike vertices), vertices that are too close together, the height of nested polygons - when a polygon lies entirely inside another, its elevation must be strictly greater than the containing polygon's - and, for line layers, unnoded crossings between two distinct line features (a crossing or a touch with no shared vertex at the meeting point, so a network tool cannot connect there); the check is silent on layers with no line features, and does not verify a line crossing itself. The AGL and HEIGHT fields are matched case-insensitively and each is compared with its own counterpart; only the inner polygon is flagged, a missing or non-numeric value makes the pair "not verifiable" rather than compliant, and a layer carrying neither field marks the check as not run instead of reporting zero. The overlap check has exactly two exceptions, both on by default and presented as sub-choices of the check itself: ignore overlaps caused by a missing vertex on the shared wall, and ignore polygons entirely contained in another. Neither has any threshold to set. Duplicate vertex detection is likewise threshold-free: only exactly superimposed vertices count. The panel header shows the installed version. Any indicator tied to a control that did not run is labelled "not requested" instead of a misleading zero, and one that ran without being able to conclude is labelled "not conclusive" instead of a misleading zero of its own; such a control is excluded from the correctness score and its breakdown, so a score is never a verdict on a dimension that was never measured. It computes a weighted correctness score (0-100) that never rounds up to a perfect mark, on the overall score or on any single sub-score, while any counted issue remains — shows a modern summary (gauge, indicators, breakdown) and produces an exportable report (HTML/CSV/JSON). Built-in QGIS actions: select flagged features, create a point error layer locating each issue exactly (self-intersection nodes for invalid geometries, representative point otherwise), and selective geometry repair that writes the result to a NEW file without modifying the source layer. Each correction type in the repair dialog shows an adaptive preview computed on the layer at hand before anything is written: how many will actually be fixed, how many are deliberately left untouched because fixing them would risk corrupting the geometry, and — for the two checks with no automatic fix at all (nested-height violations, unnoded line crossings) — a plain explanation of why, with the manual path to follow. Every adjustable tolerance (small-polygon threshold, overlap trim percentage, sharp-angle degree, close-vertex distance, hole area) can be tuned right there, with the preview recomputed on demand; the repair button stays disabled until every checked correction has an up-to-date preview, so nothing is ever applied against a stale estimate. Detection thresholds can only be TIGHTENED there, never widened past the analysis: repair only ever works on features the analysis already flagged, so widening would treat identical data two different ways. Only the repaired file is produced — nothing else is written, and no PARTIAL output is ever written: if a single feature is rejected the whole repair is refused rather than handing back an amputated file that reads as complete. A check that could examine nothing is declared not applicable or not conclusive and leaves the score entirely — a layer with no polygons no longer reports "0 overlaps" as if it had passed, an unreadable elevation (empty, or a non-finite number) makes a nested pair unverifiable rather than compliant, and a hole whose area cannot be measured in m² is kept rather than judged in the wrong unit. Editing the analysed layer marks the result stale: the actions that touch data refuse to run until a fresh analysis, feature ids from a bygone state being able to designate other features entirely. Anomalies with no automatic fix are listed together with their source FIDs in the repair summary. A background re-check automatically re-runs the same controls on the repaired file and reports whether anything remains. An optional ANALYSIS ZONE (AOI) restricts the whole analysis to a rectangle drawn on the map (or to the current map extent): quality control tile by tile on a layer of hundreds of thousands of features. A feature counts as soon as it INTERSECTS the zone, so a building straddling the edge is analysed whole, never clipped. Immediate neighbours outside the zone are still read for the pairwise checks - overlaps, nesting, line crossings - because a feature inside the zone overlapping its neighbour just outside is a real error; those neighbours contribute no anomaly of their own. The score and every counter are relative to the zone, and an EMPTY zone reports an explicit "Not evaluated" grade rather than a meaningless 100/100. Repairing under a zone writes a file covering exactly the same perimeter as the analysis - an extract, announced as such. The zone is never remembered between sessions, and the same optional extent parameter is available to the Processing algorithms, hence to batch runs and qgis_process. Native PyQGIS port of the STAT GEOM application, with no external dependencies.
version=2.9.44
author=Adel.bchini@gmail.com
email=adel.bchini@gmail.com
tags=quality,quality control,qc,geometry,validation,topology,statistics,vector,correctness,duplicates,overlaps,intersection,vertex,holes,multipart
category=Vector
icon=icon.svg
hasProcessingProvider=yes
experimental=False
deprecated=False
homepage=https://github.com/Bchini/stat-geom-qc
tracker=https://github.com/Bchini/stat-geom-qc/issues
repository=https://github.com/Bchini/stat-geom-qc
changelog=2.9.44
    Audit de la zone d'analyse (AOI) : corrections
    - Le BILAN de la zone etait produit a l'interieur du bloc qui indexe le voisinage, lequel ne tourne que si un controle de PAIRES est coche. Decocher chevauchements, hauteur imbriquee et croisements de lignes suffisait donc a faire disparaitre l'avertissement « analyse restreinte », a laisser le compte d'entites a 0 et l'etendue sur la couche entiere — le rapport annoncait « Restreinte : 0 entite(s) sur 7 » apres en avoir analyse 4. Une restriction muette est precisement ce que cette fonction doit empecher : le bilan ne depend plus d'aucun controle.
    - L'onglet « Attributs » lisait les N premieres entites de la COUCHE : il montrait des lignes qu'aucun controle n'avait examinees, et sur une couche triee geographiquement il pouvait n'en montrer AUCUNE de la zone. L'echantillon porte desormais sur la zone.
    - La regle « cette entite est-elle dans la zone » etait ecrite DEUX FOIS (analyse et reparation). Deux ecritures d'une meme regle finissent par diverger, et la reparation aurait alors produit un extrait d'un perimetre different de celui controle. Une seule definition partagee, feature_in_aoi().
    - Decharger le plugin laissait le rectangle bleu de la zone dessine sur la carte, sans plus rien pour l'expliquer ni personne pour l'effacer — le defaut meme que la fonction de nettoyage dit corriger pour la surbrillance. L'outil de trace et les signaux d'edition de la couche restaient eux aussi branches.
    - Deux clics sur « Dessiner… » enfermaient dans l'outil : le second relisait l'outil courant du canevas, qui etait l'outil de trace LUI-MEME ; il devenait « l'outil precedent », et le retablir en fin de trace remettait l'utilisateur en mode zone sans aucune sortie visible.
    - La verification automatique apres une reparation sous zone pouvait annoncer « 0 anomalie restante » a tort : le fichier verifie est l'EXTRAIT de la zone, les voisins n'y figurent pas, un chevauchement de bord n'a donc plus de second membre et ne peut pas etre recontrole. La reserve est desormais enoncee, et la zone n'est plus rejouee sur un extrait qui EST deja la zone.
    - Une note « Non evalue » (zone vide) vaut 0 sans rien avoir mesure : la comparer a l'analyse precedente affichait « -100 pts » en rouge, comme un effondrement de la qualite. L'ecart n'est plus calcule contre une note qui n'en est pas une.
    Reparation automatique : plus d'ecrasement silencieux
    - Depuis que la sortie est ecrite automatiquement a cote de la source, aucun dialogue d'enregistrement ne prevenait plus qu'un fichier du meme nom existait : deux reparations d'affilee remplacaient la premiere SANS RIEN DIRE, y compris si l'utilisateur avait travaille dessus entre-temps. Le choix est maintenant propose entre ecraser et ecrire a cote (_repare_2, _repare_3…), les deux menant quelque part.
    Verifie et non corrige
    - Le parametre d'etendue Processing non renseigne rend bien toute la couche (piege classique de l'etendue vide ecarte), une AOI couvrant toute la couche rend exactement le meme resultat que pas d'AOI, et le second anneau de voisinage reste borne (30 000 entites traitees en 0,4 s).
    Publication : durcissement securite
    - Trois try/except: pass introduits par le code recent (deux dans le nouvel outil de trace de zone, un dans le contexte de mesure Processing) sont remplaces par contextlib.suppress(Exception) : ce motif est bloque comme critique par le scanner de securite (Bandit) de plugins.qgis.org et n'aurait pas ete honore par un simple commentaire nosec. Verifie : Bandit rend « No issues identified » sur le zip extrait.
    - Cycle de vie reel valide sur le zip pret a publier : classFactory() -> initGui() -> ouverture du panneau -> unload(), avec un faux iface n'exposant que ce que le plugin utilise reellement ; tout est retire proprement (menu, icone de barre d'outils, panneau).
    - Injection de formule CSV et rapport HTML repasses au nom de couche/colonne malveillant (deja corriges en 2.9.21) : toujours sains, verifie par parsing reel du CSV et du HTML, pas par recherche de motif.
    Tests
    - 194 tests passent. Les huit correctifs AOI ci-dessus portent chacun un test verifie en deux temps : il echoue quand le bug est reintroduit, il passe sur le code corrige.
