MapQuilt
06-plugin/help/mapquilt/en · online versionWhat MapQuilt is¶
MapQuilt is a QGIS plugin that turns a series of scanned cadastral plans (for example the ICPROM Iași 1:1000 plans, 1988–1990) into a single georeferenced vector drawing: parcels, buildings, annexes, streets and their codes, with shared boundaries exactly shared between neighbours, ready for DXF export to Rhino, AutoCAD or ArchiCAD.
The name comes from "quilt": each scanned sheet stays a patch with its original pixels and its own pixel → ground transformation; nothing is resampled, nothing is warped. The sheets are laid side by side from their map sheet nomenclature (the name of the trapezoid, for example L-35-32-A-c-4-III-3-c), each is vectorized at its original resolution, and the vectors are joined topologically across the seams.
Who made it¶
MapQuilt and Rhino Sync were created by Radu Andrei, of the "Gheorghe Asachi" Technical University of Iași, Faculty of Architecture "G. M. Cantacuzino", with the help of Claude, the AI model by Anthropic, which wrote the code, tests and documentation under the author's guidance, on the scans of the ICPROM Iași cadastral plans (1988–1990) and on the reference drawing the author made in Rhino. The research questions, the method decisions, the ground-truth verification and every confirmation on the real sheets are the author's; the test reports in the repository (T1–T19, in Romanian) record what was tried and with what figures.
What it does and what it does not do¶
- It does: sheet registration, frame confirmation (the border line), placing sheets on the map without control points, seam measurement, extraction of parcels / buildings / streets / codes with fixed rules and OCR, review of uncertain faces, joining across seams, DXF export, and the live link with Rhino.
- It does not: it does not "guess" what is not drawn; a mismatch between the plan and the satellite image is flagged, not corrected; the accuracy stays that of the drawing (≈ 0.5–0.8 m at the seams on ICPROM).
How it is split¶
| Part | What it is | Licence |
|---|---|---|
The QGIS plugin (mapquilt) |
the dock with the four tabs, the .mapquilt project, the transformation chains, the planar graph, the working GeoPackage, the export |
GPL-2+ |
MapQuilt Engine (07-engine) |
a local HTTP server (FastAPI, port 8765) with all the heavy work: tiled vectorization, OCR, seam matching; it runs on the same computer (or on one of yours) | Apache-2.0 |
| Rhino Sync | the live Rhino ↔ QGIS link through a shared folder; a standalone QGIS plugin, also built into the MapQuilt dock | GPL-2+ |
The plugin talks to the Engine over HTTP on 127.0.0.1: requests do not leave the computer, and the scans stay on disk. Internet is needed only for the reference layers (satellite, OSM), which are optional.
The workflow in seven steps¶
- Import — the folder of scans (or of already traced DXFs); the sheets get their nomenclature and neighbours from the file name.
- Rectify — the sheet frame (four corners), proposed automatically, confirmed by you; the learned pattern is applied to the others.
- Georeference — the pixel → Stereo 70 chain from the frame corners and the trapezoid corners; VRTs for display.
- Assemble — the sheets on the map; the seams measured (how well the lines on one sheet continue on the next).
- Extract — vectorization of each sheet through the Engine, in 1600 px tiles, with OSM footprints as a class hint; faces, edges and labels in
work.gpkg. - Review and Stitch — the uncertain faces, one by one; joining the faces cut by the sheet edge.
- Export DXF — one layer per class, plus the quality report.
Each step has a status dot (grey / blue / green / orange / red) and can be rerun; the project keeps its journal in project.json.
Two ideas to keep in mind¶
The nomenclature is the georeference. The trapezoid name says exactly which cell of the official grid is drawn on the sheet, and the cell corners have known coordinates. So once the frame is confirmed, the sheet is on the map without a single control point. A sheet lands wrong only if the name is wrong (the wrong cell), the scan is rotated, or the frame was confirmed on another line; for each case there is a tool: Move sheet, Check placement, Rectify / Refine.
The reference layer is the edge layer. Parcels and buildings are not separately drawn polygons but the regions enclosed by edges; two neighbouring parcels share exactly the same boundary, with no gaps or overlaps, by construction. That is why joining across a seam is just deleting an edge and recomputing the faces, and why simplifying outlines does not pull neighbours apart.
Installation¶
Requirements¶
- QGIS 3.40 or newer (tested in QGIS 4.2.3); the plugin is pure Python, with no dependencies beyond those shipped with QGIS (GDAL, NumPy; OpenCV and Shapely are used when present).
- For the Engine: Python 3.11+ with the packages in
07-engine/requirements.txt(OpenCV, Shapely, RapidOCR, FastAPI); no graphics card is needed (see "How long it takes"). - Disk space: the
.mapquiltproject keeps proxies (≈ 1200 px per side) and VRTs next to the scans; the scans are not copied.
The plugin¶
From the 06-plugin folder run install_plugin.bat: it copies the mapquilt folder into the QGIS profile (%APPDATA%\QGIS\QGIS4\profiles\default\python\plugins\ and, if it exists, into the QGIS 3 profile). Then restart QGIS and enable MapQuilt in Plugins › Manage and Install Plugins › Installed. The dock opens from the toolbar (the logo) or from the Plugins › MapQuilt menu.
To install the plugin by hand: copy the mapquilt folder to the same place, without __pycache__.
The Engine¶
- In
07-enginecreate a Python environment and install the dependencies (or use.venv-testfrom the repository). - Start it with
run_engine.bator withpython -m mapquilt_engine --port 8765 --workers auto.--workers autostarts one OCR process per core (at most 4): extracting a 1:1000 sheet takes ≈ 2.5 minutes instead of 12. - In the dock, the ⚙ tab: the address
http://127.0.0.1:8765, then Test connection. The dot turns green and the line below it gives the version, the available engines and how many OCR processes it has. Start Engine launches the Engine in its own console (it asks for the07-enginefolder only once).
The Engine can also run on another computer of yours: the Cloud mode in ⚙ keeps its address separately. The cadastral data leave the institution only if you decide so.
Rhino Sync (optional)¶
08-rhino\installer\dist\RhinoSyncSetup.exe installs the Rhino scripts, the aliases and the "Rhino Sync" QGIS plugin. When that plugin is installed, the MapQuilt dock also shows the Rhino sync tab; its manual is separate (the link on the left).
First check¶
Open a new project (⚙ › New…), choose the scans folder at Import (Raster tab) and look at the sheet list: each row shows F G X (frame confirmed, georeferenced, extracted) and the N / E / S / W neighbours read from the nomenclature. A sheet with its name in red has no readable nomenclature; see "Sheets without a nomenclature".
The ⚙ tab — Settings¶
The small tab with the gear holds everything you set once per project or per computer.
Project¶
- New… creates a
<name>.mapquiltfolder (withproject.json,sheets/,proxies/,cache/, andwork.gpkgafter Extract). The target CRS is that of the QGIS project if it is projected (metres); a geographic one is replaced with Stereo 70 (EPSG:3844), and the log says so. - Open… opens an existing
.mapquilt. The last project reopens by itself when QGIS starts, and its journal appears in the log: which step ran last, when, and with which plugin version. - Scans folder — the folder with the original scans, on this computer. Import sets it by itself; you change it with Set… when the project comes from another computer or the folder has moved. The plugin finds the files again by hash and name, so renaming the folder breaks nothing once you have pointed to the new location. The path is kept in
project.jsonseparately for each computer.
Engine¶
- Local / Cloud — where the Engine runs. Local: on this computer, default address
http://127.0.0.1:8765; Start Engine launches it in a console (and Stop Engine closes it). Cloud: the same application on a server of yours, at anhttps://…address; Start Engine is greyed out (a cloud Engine is started on its server). Each mode keeps its own address; the project remembers the chosen mode. - Test connection tries
/v1/healthand shows: the version, the engines (staged,classic…), the OCR processes and how many tiles are sent at once. Red means nothing answers at that address: the Engine is not running, or it is running on another port. - The steps that need the Engine: Assemble (the seams), Extract, Refine. Import, Rectify, Georeference, Move sheet, Check placement, Stitch and Export work without it.
Work: Online / Offline¶
- Online — Extract downloads the ticked external sources (by default the OpenStreetMap buildings and streets) once per sheet and keeps them in the project's
cache/; Satellite + OSM adds the Esri World Imagery and OpenStreetMap web layers, for checking. - Offline — nothing is downloaded: sources come only from the cache (local files are still read); a sheet with no cached response is extracted without the external hint, and Satellite + OSM politely declines. The Engine is not affected (it is local anyway).
If a source does not answer during a run, only the first sheet waits; the others use its cache, so you do not lose three minutes per sheet.
External sources¶
What Extract (and Check placement) asks the outside world for, sheet by sheet. Ticked sources are used by the open project; the choice is saved in the project.
| Source | Kind | What it does |
|---|---|---|
| OpenStreetMap buildings (ticked) | buildings | footprints traced by people; class hint (building vs parcel), one block one face (T19), Check placement |
| OpenStreetMap streets (ticked) | streets | street centrelines with their names; a face the centreline runs through is a street, and the faces of one street are united (T20) |
| OpenStreetMap green spaces (ticked) | greens | parks, gardens, playgrounds (landscaped); meadow, scrub, wood (unlandscaped); tree rows and grass on narrow bands (alignment). A face without a code mostly covered by one of them gets that green class (T21) |
| Overture Maps buildings | buildings | OSM plus Microsoft's machine-learning footprints where OSM has none (villages, unmapped quarters); downloaded by the Engine, slow (minutes per sheet) |
| Overture Maps streets | streets | Overture's road segments (mostly OSM), with names; downloaded by the Engine |
Hover over a source for its licence, attribution and notes. Each answer is kept in the project (cache/osm_buildings/, cache/sources/<id>/), once per sheet, so Extract works offline afterwards.
Add… opens a form started from a template:
- WFS (GeoJSON output), ArcGIS FeatureServer, OGC API Features — a URL that answers GeoJSON in WGS84; the sheet's box goes in place of
{west},{south},{east},{north}(or{bbox}= south,west,north,east). - Overpass query — your own OSM query, with
{bbox}. - File or QGIS data source — a GeoPackage, Shapefile, GeoJSON, or anything QGIS opens through a provider (
ogr,WFS,arcgisfeatureserver,oapif…), read by QGIS for each sheet; tick readable without internet for a local file. This is the way for data you downloaded yourself (Copernicus Urban Atlas, a municipal or cadastral export).
For streets, give the attribute that holds the street name (Street name field): faces are united street by street, by name. For green spaces, give the attribute that holds the category (Green category field: alignment, landscaped, unlandscaped or grass; a line counts as a tree row, i.e. alignment). Edit… changes one of yours (a built-in one is copied as yours), Remove deletes one of yours.
Sharing. Export… writes the selected source (or all of yours) as a small .json file; someone else adds it with Import…. To offer a source to every MapQuilt user, open an issue with the file in the MapQuilt repository; once checked, it goes into the shared list, which Shared downloads (shared sources come unticked). Say the licence: only sources whose terms allow it are listed.
Drawing: building outlines¶
How the outlines of the buildings come out of Extract and Shapes (the project remembers the choice; Shapes in the Vector tab applies a new choice to the sheets already extracted, in seconds). Every outline is first read as lines and arcs of a circle (Rosin & West 1995), then every wall is put in a family: on the building's axis or its perpendicular (90°), on a diagonal (45°), free (kept in its own direction) or an arc (kept as an arc). The vertices are then adjusted all at once by least squares, neighbours staying joined, no vertex moving more than 1 m (T22). A preset says which families a tissue may have:
| Preset | For | Families | Axis tolerance |
|---|---|---|---|
| Mixed (default) | anything: each building chooses from its own outline | 90°, 45°, free, curved | 12° |
| Planned 90° | blocks, grids, industry | 90° only: every wall goes on an axis | 15° |
| Planned 90° + 45° | interwar, modernist, chamfered corners, halls with 45° ends | 90°, 45° | 12° |
| Organic | old quarters, lots at odd angles: a wall more than 8° off the axis stays as drawn | 90°, 45°, free, curved | 8° |
| Curved | tanks, round halls, apses: arcs looked for harder (15 % of the outline is enough) | all | 12° |
| Squared / Straightened / As drawn | the older modes (0.3.27, T12, none) | — | — |
The family the Engine chose is written on each face (shape), the arcs it kept too (arcs, and their three points in arcs_json). An arc is a condition of the adjustment like a wall on its axis: every vertex of it is put on one circle whose centre and radius are solved with the vertices, and the wall leaving the arc is made tangent to it; Export DXF writes such faces as polylines with true arcs (bulges), so Rhino and AutoCAD read them as arcs. In Review the keys 9 4 F O set a family by hand (shape_set); it wins over the preset at the next Shapes and survives later Shapes runs. On the Țicău reference (all rectilinear) Mixed gives what Squared gave (9 vertices per building, 62 % of the near-right corners exactly square); on the Gara sheet the round tanks and C-shaped halls keep their arcs under Mixed and Curved and are flattened under Planned 90°. Needs Engine 0.8 or newer; an older one gets the plain modes.
? — the manual¶
The ? button next to the tabs opens this manual: the copy shipped with the plugin (mapquilt/help/index.html, works without internet), or, if it is missing, the online version.
The Raster tab — the scans¶
Everything about the sheets as images: registration, frame, placement on the map, placement check. The tab has three boxes:
- Steps — 1 Import, 2 Rectify, 3 Georeference, 4 Assemble. Each button shows its state on the right (3 sheets, 12/40 frames, 40/40 chains, 2 red seams…) and a coloured dot; the step to run next is outlined in blue.
- View — Show rasters (a toggle), Satellite + OSM, the opacity slider.
- Corrections — Check sheets, Move sheet with Undo last move beside it, Refine, Check placement.
Questions name their answers on the buttons ("Only the 5 others" / "All 40 again"), never a Yes / No whose meaning you have to read twice.
Progress on the button. A long step (Import, Georeference, Assemble, Show rasters, Refine, Check placement, Extract, Stitch, Export) draws its progress on the button you pressed: a blue fill growing from the left, the percentage on the right, and what it is doing now in a small second line. Click the same button to stop after the current tile / sheet; what is finished stays saved and pressing it again resumes. While a step runs, the other buttons wait. On another tab, the percentage is shown on the tab of the running button (Vector · 45 %).
The tab bar stays in place and the tabs take the whole dock. Each tab scrolls by itself. Under the tabs there is one line: how many sheets are selected (✕ clears), and what the plugin is doing now. The sheet list, the journal line and the log are at the end of the ⚙ tab.
1 · Import¶
Choose the folder of scans (JPG, TIF, PNG) or of already traced DXFs. For each file the plugin reads the nomenclature from the name, after cleaning it (….tif.jpg, …_, - Copy, (2), bis, _ instead of -); a name that does not match exactly is matched "fuzzily" against the gaps and neighbours of the series, and the probable names are flagged for checking. The N / E / S / W neighbours are computed from the nomenclature.
- Import run again on the same folder: sheets already registered, with the same content, are skipped and keep their frames, chains and extractions; only new sheets are added. A file with the same name but different content (a rescan) replaces the old sheet, which must be redone. Copies of a sheet (
- Copy) are not imported. - Import does not go into subfolders; a subfolder is imported separately.
- A DXF sheet (one per sheet, named after the nomenclature, with the border kept) is drawn once as an image in
rendered/and goes through the same steps as a scan; at Extract its lines are taken directly, without the Engine.
2 · Rectify — the sheet frame¶
The frame is a quadrilateral with four independent corners (a trapezoid, a rotated scan), not a rectangle. The dialog shows the sheet scaled down with the proposed quadrilateral, the four corners at 1:1 scale with a fixed crosshair (drag the image under the crosshair; the mouse wheel = zoom 1/2/4×) and the confidence for each corner. Clicking on the preview moves the nearest corner. The nomenclature can be corrected in the dialog.
- Confirm and next confirms and moves to the next sheet without a frame; Skip skips it; ◀ Previous goes back to the sheet you left last, with its frame, so you can correct it.
- AUTO confirms by itself the sheets with a reliable proposal; SEMI-AUTO learns the pattern from the first manual confirmation (which line from the edge, the distance from the border) and applies it where two readings agree. "Auto: remaining sheets" works only on the sheets without a frame.
- Scanner stripes are suppressed before detection (T16); otherwise the right side fell on a stripe.
- A frame confirmed on a line other than the border (a title block, an inner line) shows up after Georeference in the scale report: the two axes differ by 2–9 %. It is fixed here, not by moving the sheet.
3 · Georeference¶
The frame corners (pixels TL, TR, BR, BL) go to the trapezoid corners (NW, NE, SE, SW) from the nomenclature, computed on the Krasovski ellipsoid and transformed into the target CRS: one homography per sheet. VRTs with a GCP grid (no resampling) and VRTs clipped to the trapezoid are written, for display.
- With sheets already placed, it offers Only the N others (new sheets, frames confirmed again) or All N again. Placing again gives the same location: the corrections from Move sheet and Refine are the very data it is computed from.
- The per-sheet scale report (
quality.scale_report) gives metres per pixel on each axis.
4 · Assemble — the sheets on the map and the seams¶
After Georeference (the seams are measured on georeferenced sheets). Creates the MapQuilt sheets layer with the outline of each sheet (through the chain when it is georeferenced, otherwise the nominal trapezoid), coloured by status, with the neighbours and the missing sheets. With the Engine running it measures every seam: the segments that touch the frame are extracted from the edge band of the two scans, taken to ground coordinates and matched one to one across the common line. The MapQuilt seams layer shows them: green (median ≤ 0.75 m), yellow (≤ 1.5 m), red (worse, or fewer than 5 matched lines).
A red seam means a wrongly confirmed frame or a wrong nomenclature on one of the two sheets. No geometric adjustment is applied: the residual is the drawing's own accuracy (≈ 0.5–0.8 m on ICPROM).
Show rasters and opacity¶
Loads the scans of the sheets with a confirmed frame, clipped to the trapezoid, into the MapQuilt rasters group: the proxy at city scale, the full scan when you zoom in. It is a toggle: pressed in, the group is shown; out, it is hidden. The slider sets the opacity, so you can check the placement over the map or the satellite image.
Satellite + OSM¶
Esri World Imagery and OpenStreetMap as XYZ layers in a Reference group at the bottom of the layer tree. For checking only: between the 1980s plan and the satellite image there are 1–3 m of offset and changed buildings.
Check sheets — the audit¶
Compares the scans folder with the project and writes to the log and to audit.txt: files without a sheet, unrecognized names (with the names read or matched), rescans, copies, originals not found, sheets without a frame / chain / extraction, and the gaps in the grid (trapezoids that two sheets name as a neighbour and that are missing), with the probable file for each gap. Cells covered by sheets at another scale do not count as gaps. In the same window it offers Give the N nomenclatures for the reliable names.
Move sheet — moving a sheet on the map¶
For a sheet that its nomenclature put in the wrong place, or that is rotated, like "grab" in Blender. While sheets are selected or in hand, a small box beside the cursor lists the keys that act now:
| Key / action | Effect |
|---|---|
| click on a sheet | picks it up; the scan follows the mouse, semi-transparent, with a red outline |
| move | the nearest corner snaps (14 px) to the corners of the cells and of the other sheets; blue squares = targets, red cross = the one it snaps to |
| second click | drops it; on a grid cell (tolerance 2 % of the side, ≈ 12 m at 1:1000) the sheet takes the cell's nomenclature and the quarter turn, and is georeferenced again at once |
| R ↻ | turns 90° clockwise; with sheets selected and none in hand, turns them in place (Enter then confirms, a click drops them elsewhere); a block turns around its centre, cell by cell |
| Shift+R ↺ | turns back (90° counter-clockwise) |
| Enter · Space | drops the sheets in hand where they are (a turn in place: click the sheet, R, Enter) |
| Shift+click | adds a sheet to the selection (orange) or takes it out; then a click on one of them or G moves them as a block |
| A · Alt+A | selects every placed sheet · none |
| S | changes the grid scale for a sheet without a nomenclature (selected first in the list) |
| Ctrl+Z | undoes the last drop (as Undo last move) |
| Esc / right click | cancels the sheet in hand; again, clears the selection; again, leaves the tool |
There is no question at each drop: what the drop did is written in the log, and Undo last move (or Ctrl+Z on the map) puts the sheets back, with their old nomenclature, turn, seams and extraction state, up to the last 20 moves. A sheet dropped outside the grid keeps the corners you set by hand. The old nomenclature stays in label.moved_from; an extracted sheet must be extracted again, and the log says so.
Refine — the frame corrected from the seams¶
For a sheet in the right cell whose lines do not continue into its neighbours: the seams with each placed neighbour are measured again, and the four frame corners (pixels) are moved until the lines continue; the neighbours and the grid stay in place. First it chooses, on each side, the drawn line on which the frame was confirmed; then it fits the corners with a prior on the old frame and validates the fit on lines not used for fitting. A free fit of the four corners reduces the residual by moving a corner by 8 m: that is not a correction but a distortion, and it is refused. It shows the seams before and after and offers Keep the refined frames or Leave as they were; the old frame stays in the project.
It works on the selected sheets (the button says how many). With none selected it offers Refine the N red, worst first or Select sheets on the map.
Check placement — is the sheet right side up?¶
A witness from outside the series: the building outlines from OpenStreetMap, laid over the scan proxy for each of the four possible rotations of the frame in its cell. The score of a rotation is the lift: how many of the outline points fall on ink (the darkest 2 % of pixels, a one-pixel band) divided by how many would fall there by chance. On the test sheets, the right rotation has a lift of 1.9–2.5, the others 0.9–1.1.
- Sheets where a rotation other than the stored one clearly wins are listed and, after Turn N sheets, turned (exactly like R in Move sheet) and georeferenced again; Undo last move puts them back.
- A sheet that no rotation fits is probably in the wrong cell (Move sheet) or in a rebuilt area.
- The check is deliberately coarse: it tells rotations and cells apart, not metres; the fine accuracy stays with the seams and Refine.
The Vector tab — the drawing¶
Extract all / Extract selected¶
5 · Extract all vectorizes all sheets; with sheets already extracted it offers Extract the N others (or Resume with the N others after a Stop) and All N again. Extract selected extracts, again, only the selected sheets (in the sheet list with Shift / Ctrl+click, on the map with Select on map, the trapezoids selected in the MapQuilt sheets layer, or the sheet … rasters selected in Layers). Its label says how many sheets it will take (Extract 3 selected). With no selection it switches Select on map on by itself with the extraction pending: click the sheets on the map (the box at the cursor says so), then Enter or Space extracts them; Esc cancels.
For each sheet: the scan is read through GDAL at its original resolution, the OSM footprints for the sheet's extent are taken from the cache (or downloaded once), the sheet is cut into 1600 px tiles with a 160 px overlap, each tile goes to the Engine (staged), the results are merged per sheet (complete faces only once, the tile core decides), and everything is written to work.gpkg: the faces, edges, labels layers in the target CRS, styled by class in the MapQuilt group.
The classes: building, annex (sheds, garages, bodies marked with an X), amenity (exterior stairs, hatched strips: the AMENAJARI of the reference drawing), parcel, street, the three green-space classes (below), other (the tile edge). Each face carries why (why it got its class: label, indicator, footprint, island, symbol, shape, line width), confidence, review_score, needs_review, codes (the codes read by OCR: C 1900, DP 1901/1 …).
Lines before letters (Engine 0.10.1). Step 0 reads the codes (OCR), the circled numbers and the X symbols and masks them before the skeleton is built. From the codes it read, the Engine knows how tall the letters of the sheet are and how they are spaced; every letter-sized piece that is not a line and that continues a read code, stands right under it, or forms a row with letter rhythm is taken out of the ink too (letters glued to lines, digits OCR skipped, hollow digits that looked like small sheds), the line a code stands on staying whole. A thick line is one object: the short pieces between thick edges are thick, and a free end of a thick edge is bridged to the thick edge ahead of it when ink remains in the gap.
No face on a line (Engine 0.10). A wall drawn with its thickness, a party wall or a double fence gives a narrow face that is mostly the ink of its own two borders; it is never kept: a building beside it takes it, otherwise it is split along its axis between its two neighbours. A hatched ladder (exterior stairs, a hatched strip: parallel lines across a narrow band) becomes one amenity face. In the squared outline modes, a short segment of a 90° / 45° building that fits no axis is the corner the skeleton rounded off: it is collapsed, so the corner is where the two walls meet (⚙ › Drawing; corner_cut_m, 3 m).
With the Engine running 4 OCR processes, a 1:1000 sheet takes ≈ 2.5 minutes; two tiles are sent at once. A click on the running Extract button stops after the current tile; pressing Extract again resumes with the remaining sheets.
Shapes — squaring again, without extracting¶
Extract keeps, for every sheet, the raw faces of each tile (the drawing before squaring) in the project, under cache/raw/<sheet>/. Shapes sends them through the Engine's squaring step alone (/v1/regularize) with the outline mode of ⚙ › Drawing, and replaces the faces of the sheet: a few seconds per sheet instead of minutes, no OCR, no skeleton. Use it after changing Building outlines, or later, when a new outline mode exists.
- Works on the selected sheets, else on every extracted sheet with raw faces. A sheet extracted before 0.3.28 has none: Extract it again once.
- Review decisions (confirmed, edited, rejected) are carried over to the new face that overlaps the old one most; the log says how many were kept.
- The faces stitched across a seam of that sheet are dropped: run Stitch again afterwards. Edges and labels do not change.
- Needs Engine 0.7 or newer.
The selection bar — one selection for every tab¶
Under the tabs, one line: how many sheets are selected and a button that clears the selection. In the ⚙ tab, above the sheet list: Select on map. It selects sheets directly on the map (orange outline): click on a sheet, Shift+click adds or removes, drag a rectangle for several (Shift+rectangle adds), A all, Alt+A none, Esc clears; the small box at the cursor recalls the keys. The list, Move sheet's Shift+click and QGIS's own selection of MapQuilt sheets all land in the same selection, and the buttons that use it say how many sheets they will take: Extract 3 selected, Refine 3 selected, Check placement · 3 selected.
Under the list a line explains the codes F G X and the colours; the log is under it, in the same ⚙ tab. The progress of a step is drawn on its own button (see the Raster tab).
Edit — Join faces¶
Two faces that should be one (a parcel cut in two by a fence line, a block split by a drawn line, two pieces of the same green space): Join faces in the Edit box, then on the map press inside one face, drag onto its neighbour and release. While you drag, the face you started from is orange and the face under the cursor green when they can be joined, red when they cannot; the small box at the cursor says why (another class, not neighbours, touching only at a point).
- Only faces of the same class that touch (gaps up to 0.3 m left by simplification are closed) are joined. To join a building and a parcel, change one of them in Review first.
- The first face keeps its row: its geometry becomes the union, the codes of both are kept, buildings and annexes are counted together, the review state becomes edited, the note says which face was joined in. The other face is deleted.
- Ctrl+Z on the map, or Undo join, puts the two faces back (the last 50 joins). Esc cancels a drag, then leaves the tool. Every join and undo is written in the project journal.
- The drawn lines (the
edgeslayer) are not touched: only the faces are joined.
Green spaces — three categories¶
| Class | Romanian | What it is | From OSM |
|---|---|---|---|
green_alignment |
spațiu verde de aliniament | along a street: tree rows, grass strips between carriageway and sidewalk | natural=tree_row; landuse=grass on a band narrower than 8 m |
green_landscaped |
spațiu verde amenajat | laid out and kept: park, garden, square, playground, sports lawn | leisure=park/garden/playground/pitch, landuse=recreation_ground/village_green/flowerbed; landuse=grass wider than 8 m |
green_unlandscaped |
spațiu verde neamenajat | left to grow: meadow, scrub, wood, waste ground | landuse=meadow/forest, natural=scrub/grassland/heath/wood |
A face gets a green class only when it has no code (an uncoded parcel, or a strip found as a street by its shape) and at least half of it lies in green spaces of one category. A coded parcel stays a parcel: the cadastre says what it is, OSM only what grows on it, so it gets the category in the green attribute instead. Green faces come with a lower confidence and go into the review queue; there the keys 1 2 3 give them a category by hand (also to faces OSM does not know). In the DXF each category is a layer of its own.
Review — the uncertain faces¶
The Review box appears once a sheet is extracted. Next (N) jumps to the most uncertain face (by review_score), over the scan and the satellite image. Then you decide, with the button or its key (the keys work while a face is under review, on the map and in the dock; Esc stops):
| Button | What it means |
|---|---|
| Confirm Enter | the face is right as it is (also when it does not match the satellite image: the plan is the historical truth) |
| Building B / Parcel P / Annex A / Amenity M / Street S / Green 1 alignment, 2 landscaped, 3 unlandscaped | the shape is right, the class was wrong; the plugin changes it and marks the face as confirmed |
| Shape 9 90°, 4 45°, F free, O arc | the family of the building's walls, set by hand (⚙ › Drawing); Shapes squares it that way afterwards |
| Reject X | a vectorization error (a false island, an invented boundary); the face is removed from the result |
The decision is written to review_state and goes into the export. The plugin does not correct a mismatch with the satellite image by itself, because it cannot know whether it is a vectorization error or a change over time; it only puts the cases in front of you, the most uncertain first. A wrong shape (a missing or extra boundary) is corrected on the edges, with the QGIS tools, and the faces are recomputed.
6 · Stitch — joining across the seams¶
For each pair of neighbouring sheets, the faces that touch the seam band (± the tolerance, by default 1.5 m = the 90th percentile of the measured noise), of the same class and with overlapping intervals along the common line, are joined; the edges marked "seam" are deleted and the faces are re-polygonized. Nothing is moved, nothing is warped. On DXF sheets the line ends are joined too. Faces already joined are not matched a second time, so Stitch can be run again after a new Import.
7 · Export DXF¶
Writes the DXF with one layer per class (the faces with arcs as polylines with true arcs, see ⚙ › Drawing) (building, parcel, street, annex, amenity, other; on DXF sheets, also the lines), in the target CRS, plus a JSON report (the counts, the reviewed faces, the seams). The layers are first copied into memory, so that the GeoPackage in WAL mode does not produce an empty DXF.
Simplification and squaring of the outlines (⚙ › Drawing › Building outlines; the Engine's regularize: none, orthogonal, squared) are done on the shared edges, so that neighbours stay attached; Squared, the default, adjusts every vertex at once and squares the corners at lot limits too (23 → 9 vertices per building at the same quality).
The journal, the status bar, Stop¶
The project journal¶
Each run of a step is written to project.json (journal: step, date, plugin version, a one-line summary; steps: the last run of each step). In the ⚙ tab, above the sheet list, the "Last … · Next …" line says how far you have got, each button has its last run in its tooltip, and when the project opens the journal appears in the log. The state of the coloured dots comes from the sheet data (frames, chains, extractions), not from the journal, so a project written by an old version is described correctly.
The status bar and Stop¶
Under the tabs: what the plugin is doing now; the percentage and Stop are on the button that started the step (a click on it stops). Stop halts the step after the current tile / sheet / seam; what is finished stays saved, the journal notes where it stopped, and running the same step again resumes with what is left (the sheet in progress is redone).
The sheet list and the log¶
Each row: F G X (frame, georeference, extraction), the sheet id, the N E S W neighbours. Green = nomenclature read, red = no nomenclature. The log below the list repeats the messages from QGIS's Log Messages › MapQuilt.
Workflows¶
A sheet found later¶
Put the file in the same folder as the scans and press Import on it again: the old sheets are skipped, only the new one is added. Then Rectify (the dialog opens on the first sheet without a frame, i.e. the new one; "Auto: remaining sheets" applies the learned pattern to it), Georeference (only the new sheets), Assemble, Extract (the button Extract the N others: only the sheets not yet extracted), Stitch, Export. A subfolder works too, but Import must be run on it, and Check sheets counts only the main folder.
A sheet in the wrong cell, or rotated¶
Signs: on the map the sheet sits over another one or in a gap, its seams are red, Check placement says another rotation fits. Rotation: Check placement turns it after Turn N sheets. Wrong cell: Move sheet, drag the sheet onto its cell; it takes the cell's nomenclature. Then Extract again on it, if it had been extracted.
A frame confirmed on the wrong line¶
Signs: the scale report shows a 2–9 % difference between the axes, the seams are yellow or red on all sides. Hundreds of pixels off: Rectify again on the sheet (◀ Previous gets to it). A few pixels: Refine.
Sheets without a nomenclature¶
The name is red in the list. Either correct the name in the Rectify dialog, or select the sheet in the list and place it with Move sheet cell by cell (S changes the grid scale). Check sheets shows the gaps in the grid: the cells that the neighbours name and that are missing are the candidates.
The project moved to another computer¶
Copy the .mapquilt folder and the scans. In ⚙ set Scans folder; the plugin finds the files again by hash and name. Start the Engine locally on the new computer. The OSM footprints are already in the project cache, so Extract also works offline.
How long it takes¶
| Step | Typical duration (1:1000 sheet, ≈ 5000 × 5000 px) |
|---|---|
| Import | seconds per folder |
| Rectify | 10–20 s per sheet manually; AUTO instant |
| Assemble with seams | ≈ 10 s per seam (Engine) |
| Georeference | under a second per sheet |
| Extract | ≈ 2.5 min per sheet with 4 OCR processes (12 min with one); ≈ 7 hours for 160 sheets |
| Stitch, Export | seconds to minutes |
A graphics card does not help: the rule engine uses no neural networks apart from OCR, and the time goes into image and graph operations, which were sped up in code (T18).
The Rhino sync tab¶
It appears when the Rhino Sync plugin is installed in the QGIS profile (the RhinoSyncSetup.exe installer puts it there). The box is the same as in the standalone plugin: Project folder (the shared folder next to the .3dm file), the lamp (green while Rhino is also on Play), Play / Stop, Send to Rhino, Get now, Send context, Promote to project, Fields…, Send image.
The typical cycle: in Rhino RhinoSync › Play, in QGIS Play, then draw on the SCHITA::… layers; a second or two after you lift your hand, the parcel appears in QGIS over the plan sheet and the satellite image. Correct a face in QGIS, Send to Rhino, and you see it on QGIS::….
Everything about conventions (layers, the SCHITA / CONTEXT / QGIS families, fills, fields, sync-config.json, CLI, limits) is in the separate Rhino Sync manual: the link on the left or the ? button in the Rhino Sync dock.
Troubleshooting¶
The Engine dot is red. The Engine is not running, or it is running on another port. Start it (⚙ › Start, or run_engine.bat) and press Check; the address in ⚙ must be the one shown in the Engine console (8765 by default). An old project may hold another address: Check rewrites it.
Extract is very slow. Restart the Engine with --workers auto (Check shows "4 OCR processes"); with a single OCR process a sheet takes 4–5 times longer. A graphics card does not help.
The sheet does not appear on the map after Georeference. It has no nomenclature (red name) or no confirmed frame. Run Rectify on it; for the name, use the Rectify dialog or Move sheet.
Sheets overlap on the map. Two sheets have the same nomenclature (Check sheets lists them) or one is in the wrong cell: Move sheet.
The seams of one sheet are red. The frame is on the wrong line (Rectify / Refine), the scan is rotated (Check placement) or the nomenclature is wrong (Move sheet). A single red seam between two good sheets can also be an old sheet scanned from a different original.
Apartment blocks appear as parcels (blue) or cut into pieces. The plan draws the block with a double line and one code per stairwell, while OSM knows it as a single polygon. Since the Engine version with T19, building faces from the same OSM footprint are merged, and the 1500 m² cap of the footprint rule no longer exists; restart the Engine so it picks up the new code, and extract the sheet again.
"original not found". The scans have moved: ⚙ › Scans folder › Set…. Check sheets tells you which sheets cannot be found.
A street comes out in several pieces. Since the Engine version with T20, the faces a street's centreline runs through are united street by street. Check that OpenStreetMap streets is ticked in ⚙ › External sources, restart the Engine, and extract the sheet again. A street missing from OSM, or a street that did not exist when the plan was drawn, stays as the plan has it; so does a piece where OSM rides on the kerb (the drawing wins over OSM).
Overpass does not answer, Extract waits. Only the first sheet in the run waits; the others use the cache. Set Work: Offline so that it does not wait at all. Overpass sometimes answers 'at capacity' for a few minutes; Extract the sheet again later.
The DXF comes out empty. Versions before 0.3.14 exported directly from the GeoPackage in WAL mode; now the layers are copied into memory. If it persists, close the work.gpkg layers in other applications.
The Rectify dialog confirmed a wrong frame and I moved on. ◀ Previous goes back to the sheet you left last, with its frame; correct it and confirm again (the SEMI-AUTO pattern is relearned from it).
Where are the data? In the .mapquilt folder: project.json (project, journal, roots), sheets/<id>.json (source, frame, chain, neighbours, seams, quality, review), proxies/, rendered/ (rendered DXFs), cache/osm_buildings/, matches/ (the seams), work.gpkg, audit.txt. Nothing is written next to the scans except the VRTs.
How it works¶
The staged engine (Engine staged)¶
Vectorization is a chain of fixed rules, not a neural network; the only learned model is the OCR (RapidOCR) for the codes. On each 1600 px tile:
- Annotations — texts and indicator circles are detected and masked; the lines they interrupt are restored ("bridging").
- Line width — the distance to the background on the cleaned ink, before thinning; the Otsu threshold separates thick lines (building outlines) from thin ones (boundaries).
- Skeleton → shared edges — thinning, pruning of short branches (vectorized: 340 s → 2 s per sheet), snapping of loose ends, pixel segments joined into polylines between junctions, simplified with fixed ends.
- Faces and classes — polygonization of the edges; each face gets its class from, in order: the label inside (C → building, DS/DP → street, CR/CC/CAT → parcel), the circled indicator, a street centreline running through the face along its length and away from its edges (T20), the coverage by the OSM footprint (registered locally on the skeleton), topology (an island in a void is a building), shape (long strips = streets), the outline width; small faces with an X are annexes. 3a (T19): building faces from the same OSM footprint are merged. 3a′ (T20): the street faces of one street (same name, else same way) that touch are merged — only across a line the centreline crosses at 45° or more, so a kerb or sidewalk line along the street stays even where OSM rides on it (T20b); a band narrower than 3.5 m (a sidewalk) is never called a street by the centreline alone, and sidewalk strips are not joined to the carriageway. 3c (T21): a face without a code, at least half in OSM green spaces of one category, becomes
green_alignment,green_landscapedorgreen_unlandscaped; a coded parcel only gets the category as an attribute. 3b (T12, T22, T23): simplification on the graph; every edge read as lines and arcs; a shape family per building from a preset (⚙ › Drawing) or set by hand; then squaring: by default a least-squares adjustment of every vertex (junctions included) with the condition "exactly on the building's axis" on every wall within 12° of it, no vertex moving more than 1 m; the older mode keeps the junctions fixed. - Dissolve — buildings are attached to the host parcel with the longest shared side; uncoded strips are merged into their neighbour.
Measured on the Țicău tile against the reference drawing made in Rhino: building PQ 0.64 (precision 0.80, recall 0.66, mean IoU 0.89); parcels 0.34; the fraction of shared outline went from 0 to 0.63 with the move to the planar graph (T6b).
The transformation chain¶
Each sheet has a declarative pixel → ground chain (transforms.Chain): lens (for photographs), homography from the four corners, optionally a bounded TPS residual. The chain is serialized to JSON and exported as an 8 × 8 GCP grid for GDAL, which reproduces the transformation exactly on the VRT without resampling the original. The vectors extracted per tile go through the chain into the target CRS.
The seams¶
From the edge band of each scan (25–320 px inside the frame) the segments that touch the frame are extracted, taken to ground coordinates and matched one to one across the common line (Engine /v1/match/pair). The median deviation is the seam; on ICPROM, 0.76 and 0.81 m on the test sheets. No adjustment is applied: a minimal joint adjustment over three sheets (T-compensare) showed that there is no distortion signal above the drawing noise, and a free fit of the corners overfits.
Checking against OSM and satellite¶
OSM footprints are a hint, not the truth: between the plan and OSM there are 1–3 m of offset and changed buildings. They serve for the class (building vs parcel: AUC 0.9 on the true faces), for merging apartment blocks and for checking the sheet rotation; not for the geometry. A footprint detector on satellite imagery (hotosm/dinov3s) was compared with OSM and Overture (T11): OSM remains the best for Iași.
The test reports¶
Every decision of the project has a report in 01-cercetare/ (T1–T19): what was tried, on what data, with what figures. Their synthesis, with the full bibliography, is sinteza_cercetare_MapQuilt.md, and the academic presentation is prezentare_cercetare_MapQuilt_RhinoSync.md.
Literature¶
The works the method relies on, in the order in which they come into the workflow. The internal test reports (T1–T19) are in 01-cercetare/ in the repository.
The data model and digital cartography¶
- Thomas K. Peucker and Nicholas Chrisman, "Cartographic Data Structures", The American Cartographer 2, no. 1 (1975): 55–69, https://doi.org/10.1559/152304075784447289. The topological model (edges → faces) that MapQuilt uses.
- M. R. G. Conzen, Alnwick, Northumberland: A Study in Town-Plan Analysis, Institute of British Geographers Publication 27 (London: George Philip, 1960). The plot as the unit of morphological analysis.
- Anne Vernez Moudon, "Urban Morphology as an Emerging Interdisciplinary Field", Urban Morphology 1, no. 1 (1997): 3–10.
- Martin Fleischmann, "momepy: Urban Morphology Measuring Toolkit", Journal of Open Source Software 4, no. 43 (2019): 1807, https://doi.org/10.21105/joss.01807. What can be measured on the vectorized result.
Vectorization of historical maps¶
- Yizi Chen, Joseph Chazalon, Edwin Carlinet, Minh Ôn Vũ Ngoc, Clément Mallet and Julien Perret, "Automatic Vectorization of Historical Maps: A Benchmark", PLOS ONE 19, no. 2 (2024): e0297361, https://doi.org/10.1371/journal.pone.0297361. Edge filter → watershed → planar partition, with "strong topological guarantees"; the line the staged engine follows.
- Xue Xia, Daiwei Zhang, Wenxuan Song, Wei Huang and Lorenz Hurni, "MapSAM: Adapting Segment Anything Model for Automated Feature Detection in Historical Maps", IEEE Transactions on Geoscience and Remote Sensing 63 (2025), https://doi.org/10.1109/TGRS.2025.3528931. Learned masks as a source of edges, not of final polygons.
- Zsombor Bartos-Elekes, Gábor Timár and Ioan Rus, "Historical Cadastral Maps of Cluj-Napoca", Geographia Technica no. 1 (2008): 1–6. Georeferencing of Romanian cadastral plans.
- IOGP, "EPSG:3844 Pulkovo 1942(58) / Stereo70", https://epsg.io/3844.
Image processing¶
- Nobuyuki Otsu, "A Threshold Selection Method from Gray-Level Histograms", IEEE Transactions on Systems, Man, and Cybernetics 9, no. 1 (1979): 62–66, https://doi.org/10.1109/TSMC.1979.4310076. The threshold between thick and thin lines.
- T. Y. Zhang and C. Y. Suen, "A Fast Parallel Algorithm for Thinning Digital Patterns", Communications of the ACM 27, no. 3 (1984): 236–239, https://doi.org/10.1145/357994.358023. Skeleton thinning (NumPy implementation in the plugin).
- Nghia T. Vo, Robert C. Atwood and Michael Drakopoulos, "Superior Techniques for Eliminating Ring Artifacts in X-Ray Micro-Tomography", Optics Express 26, no. 22 (2018): 28396–28412, https://doi.org/10.1364/OE.26.028396. Detection of scanner stripes (T16).
- Fred L. Gadallah, Ferenc Csillag and Elizabeth J. M. Smith, "Destriping Multisensor Imagery with Moment Matching", International Journal of Remote Sensing 21, no. 12 (2000): 2505–2511, https://doi.org/10.1080/01431160050030592. The additive per-column correction.
- Richard Hartley and Andrew Zisserman, Multiple View Geometry in Computer Vision, 2nd ed. (Cambridge University Press, 2004). The homography from four points (normalized DLT), the transformation chain.
- Fred L. Bookstein, "Principal Warps: Thin-Plate Splines and the Decomposition of Deformations", IEEE Transactions on Pattern Analysis and Machine Intelligence 11, no. 6 (1989): 567–585, https://doi.org/10.1109/34.24792. The bounded TPS residual in the chain.
Measuring the result¶
- Alexander Kirillov, Kaiming He, Ross Girshick, Carsten Rother and Piotr Dollár, "Panoptic Segmentation", in CVPR 2019 (IEEE, 2019), 9396–9405, https://doi.org/10.1109/CVPR.2019.00963. PQ = SQ × RQ, the per-class metric against the reference drawing.
- OpenStreetMap contributors, OpenStreetMap, https://www.openstreetmap.org, ODbL. Building footprints as a class hint and as a witness for the sheet rotation; street centrelines for the street faces (T20); green spaces in three categories (T21).
- Overture Maps Foundation, Overture Maps data (buildings, transportation), https://overturemaps.org, ODbL / CDLA-Permissive-2.0. Optional external source.
- RapidOCR, https://github.com/RapidAI/RapidOCR. Code recognition (ONNX, on the CPU).
Tools¶
- QGIS Development Team, QGIS Geographic Information System, https://qgis.org. GDAL/OGR, https://gdal.org. Shapely, https://shapely.readthedocs.io. OpenCV, https://opencv.org. FastAPI, https://fastapi.tiangolo.com.
Changelog¶
From the plugin's metadata.txt, newest first.
- 0.3.352026-11-06 — Engine 0.10.1: a thick line is one object (short pieces between thick edges are thick; a free end of a thick edge is bridged to the thick edge ahead when ink remains in the gap); text by experience - letters are recognised by the size and rhythm of the codes OCR read (letters glued to lines, digits OCR skipped, hollow digits) and taken out of the ink before the skeleton, the line a code stands on staying whole.
- 0.3.342026-11-05 — Engine 0.10.0: no face on a line - the gap of a double line (a wall drawn with its thickness, a party wall, a double fence) goes to the building beside it or is split between its neighbours; hatched ladders (exterior stairs, hatched strips) become one face of the new class amenity (Review key M, teal); squared outlines no longer fall back to the older method when a simplified edge crosses another (that edge keeps its vertices), and short off-axis segments of 90/45 buildings collapse into true corners (corner_cut_m 3 m).
- 0.3.332026-11-05 — The tabs take the whole dock: the sheet list, the journal line and the log moved to the end of the Settings tab; under the tabs one line (sheets selected, status). Extract selected with nothing selected: click the sheets on the map, Enter / Space extracts them, Esc cancels (the box at the cursor says so). Move sheet: Enter / Space drops the sheets in hand where they are, so a turn is click, R, Enter.
- 0.3.322026-11-05 — Fix: Extract and Shapes on a project whose work.gpkg was written by a plugin older than 0.3.29 (no shape / shape_set / arcs_json columns) failed with KeyError 'shape' when copying the other sheets' faces; missing columns are now read as empty.
- 0.3.312026-11-05 — Engine 0.9.1: a face holding both a building code (C) and a parcel code (CAT, CC, CR, DP...) is a building when its outline is thick or an OSM footprint covers it - institutional buildings and blocks carry their lot code inside the outline - and a parcel otherwise (a lot whose house outline is not closed); before, such faces fell to the later rules and the university buildings on Copou came out as parcels. DP (domeniu public) is read as a lot code, no longer as a street: it is written beside the building code of institutions. Labels can also be given to the Engine from outside (extra_labels).
- 0.3.302026-11-05 — Arcs as true arcs (Engine 0.9.0, T23 step D): an arc found on a building is a condition of the least-squares adjustment - its vertices are put on one circle whose centre and radius are solved with them, the walls leaving it tangent; the face keeps its arcs (arcs_json) and Export DXF writes such faces as polylines with bulges, read as arcs by Rhino and AutoCAD.
- 0.3.292026-11-05 — Shape families and presets (Engine 0.8.0, T23 steps B and C). Every outline is read as lines and arcs of a circle; every building gets a family - 90 degrees, 45 degrees, free or curved - written on the face (shape, arcs); arcs are kept as arcs, 45-degree walls on their diagonals, oblique walls in their own direction. Settings > Drawing: presets Mixed (default; each building chooses), Planned 90, Planned 90 + 45, Organic, Curved, plus the older modes. Review: keys 9 / 4 / F / O set a family by hand; Shapes sends it to the Engine and it survives later runs.
- 0.3.282026-11-05 — Shapes (Vector tab; Engine 0.7.0, T23 step A): the squaring becomes a step of its own, repeatable without extracting. Extract keeps the raw faces of every tile in the project (cache/raw/<sheet>/); Shapes sends them through the Engine's squaring step alone (/v1/regularize) with the outline mode of Settings > Drawing and replaces the sheet's faces in seconds, review decisions carried over to the overlapping faces, edges and labels untouched; stitched faces of the sheet are dropped (run Stitch again).
- 0.3.272026-11-05 — Squared building outlines (Engine 0.6.0, T22): a least-squares adjustment of every vertex of the drawing at once, junctions included - walls within 12 degrees of the building's axis exactly parallel or perpendicular, corners on lot limits square too, neighbours stay joined, no vertex moves more than 1 m. Settings > Drawing > Building outlines: Squared (default), Straightened (the older T12 method), As drawn. Țicău: 9 vertices per building (reference 8), 62 % of the near-right corners exactly square (Straightened 41 %), same PQ, lot limits no longer pushed (parcel PQ 0.337 vs 0.321). An older Engine falls back to Straightened.
- 0.3.262026-11-05 — Join faces (Vector tab, Edit box): press inside a face, drag onto a neighbour of the same class and release - the two become one (codes of both, buildings counted together, review state edited); green while they can be joined, red with the reason in the box at the cursor when not; gaps up to 0.3 m closed; Ctrl+Z on the map or Undo join puts them back (last 50); every join in the journal.
- 0.3.252026-11-05 — Green spaces in three categories (Engine T21): green_alignment (tree rows, grass strips along streets), green_landscaped (parks, gardens, playgrounds), green_unlandscaped (meadow, scrub, wood). New external source OpenStreetMap green spaces (ticked); a face without a code at least half in one category gets that class, a coded parcel keeps its class and gets the category in the attribute 'green'. Own green sources with a category field. Review: buttons and keys 1 / 2 / 3; each category styled and written as its own DXF layer.
- 0.3.242026-11-05 — The progress of a long step is drawn on the button that started it (blue fill, percent, what it does now in a second line); a click on that button stops it; meanwhile the other buttons wait; on another tab the percent is on the tab of the running button. The tab bar stays in place: every tab page scrolls by itself, and the tabs, the sheet list and the log share the dock through splitters. Engine T20b: OSM centrelines no longer spoil the drawing where they ride on kerbs and sidewalks - street faces are united only across lines the centreline crosses at 45 degrees or more, a band under 3.5 m is never a street by the centreline alone, sidewalk strips are not joined to the carriageway.
- 0.3.232026-11-05 — Dock made easier to use. Steps numbered 1-7 in their real order (Georeference before Assemble), each with its state written on the button (12/40 frames, 2 red seams...) and the next step outlined. Raster tab in three boxes: Steps, View (Show rasters as a toggle, Satellite + OSM, opacity), Corrections (Check sheets, Move sheet, Undo last move, Refine, Check placement) with QGIS icons. One selection bar under the tabs (Select on map, how many selected, clear), and the buttons say how many sheets they take (Extract 3 selected). Questions name their answers on the buttons instead of Yes / No / Cancel; Move sheet and Check placement turns are applied at once and put back by Undo last move (Ctrl+Z on the map, last 20). Move sheet / Select on map: a small box beside the cursor lists the keys - R turns 90 (with a selection it picks it up and turns it), Shift+R back, G, A all, Alt+A none, Esc, Ctrl+Z. Review appears after Extract, with keys (N next, Enter confirm, B P A S class, X reject, Esc). Progress bar and Stop only while a step runs; the log can be made taller; a legend under the sheet list. Engine: Test connection, Start Engine / Stop Engine on their own row; ? opens the manual without freezing QGIS; Rhino sync buttons in a 2 x 2 grid.
- 0.3.222026-11-05 — External sources (⚙ Settings): building footprints and street centrelines chosen per project - OpenStreetMap buildings and streets (ticked), Overture Maps buildings and streets (through the Engine), and your own: WFS, ArcGIS FeatureServer, OGC API Features, an Overpass query, or any file / QGIS data source; Add / Edit / Remove, Import / Export as .json to give to others, Shared downloads the list other users sent in. Every answer cached per sheet in the project. Streets (Engine T20): a face the centreline runs through, along its length and away from its edges, is a street, and the street faces of one street (same name) are united with their sidewalk strips, one street one face per tile.
- 0.3.212026-11-04 — The dock in tabs: the gear (Settings: project, scans folder with Set..., Engine local / cloud with its own address, Check with what the Engine answered, Start; work mode Online / Offline, offline = OSM footprints from the project cache only and no web layers), Raster, Vector (with the Review box), Rhino sync (only when the Rhino Sync plugin is installed), and a '?' button beside the tabs that opens the manual shipped in mapquilt/help (generated from 06-plugin/help with build_help.py: sections, literature, changelog; also published with GitHub Pages).
- 0.3.202026-11-04 — Check placement (Raster column): is each scan the right way up in its cell? The OSM building outlines are laid over the scan's proxy for the four quarter turns; the turn that puts them on ink wins (lift against chance). Sheets where another turn clearly wins are listed and, after Yes, turned (label quarters, as Move sheet + R) and georeferenced again; a sheet no turn fits is reported as probably in the wrong cell. Selected sheets, or all placed sheets; journal step 'placement'.
- 0.3.192026-11-04 — Refine / Extract selected with nothing selected switch Select sheets on and say to click the sheets on the map, then press the button again.
- 0.3.182026-11-04 — Select sheets (next to Extract selected): select sheets directly on the map like Move sheet - click, Shift+click to add or take out, drag a rectangle, Esc to clear; orange outlines, the sheet list follows and keeps it for Extract selected and Refine.
- 0.3.172026-11-04 — Extract selected (and Refine, Move sheet) take the selection wherever it was made: the dock's sheet list, the trapezoids of 'MapQuilt sheets' selected with QGIS's own selection tools, the 'sheet …' rasters selected in the Layers panel.
- 0.3.162026-11-04 — Untidy file names: the nomenclature is read once the name is tidied ('….tif.jpg', '…', ' - Copy', ' (2)', 'bis', '' for '-'), else by a fuzzy match with the holes and neighbours when one is clearly closest; Import applies the tidied ones (to be checked), skips copies of a sheet already in the project; Check sheets lists copies, the names read or matched, the probable file of each hole, no longer counts as holes the cells covered by sheets of another scale, and offers to apply the sure names.
- 0.3.152026-11-04 — Georeference with sheets already placed asks whether to place only the others (new sheets, frames confirmed again, chains in another CRS); headless the default is only those. Placing all again keeps every Move sheet / Refine correction (they are its input).
- 0.3.142026-11-04 — DXF sheets: Import takes DXF files (one per sheet, named by nomenclature, frame kept); each is drawn once as a picture in its own units (rendered/<id>.tif; the scan's pixels on the Iași tracings), so Rectify, Georeference, Show rasters, Move sheet, Refine and the seam check work on it as on a scan; Rectify proposes the neat line from the DXF's own straight lines (tilt removed, the line where the drawing stops); Extract takes the DXF lines cut at the frame through the chain (edges 'line', faces closed by them; no Engine); Stitch also joins line ends across the seams; Export DXF writes the lines. Export fix: layers copied to memory first (QgsDxfExport + GeoPackage in WAL mode gave 'unable to open database file' and an empty DXF), explicit extent, empty label layer left out.
- 0.3.132026-11-04 — Refine (Raster column): the sheet selected in the list (or the sheets with red seams) re-measured against its placed neighbours through the Engine's seam matcher; first the drawn line of each side is chosen among Rectify's candidates by the seams, then the four frame corners (pixels) are fitted robustly on half of the matched lines and kept only when the other half improves clearly; neighbours and grid never move; old frame kept in quality.frame_before_refine; asks before keeping; seams written on both sheets. Move sheet: R turns a whole block about its centre, the sheets going round it cell by cell (cells are not squares) and every scan turning with it. Extract all / Extract selected (the sheets selected); the sheet list selects several (Shift = range, Ctrl = one more) and follows the Shift+click selection of Move sheet on the map; Refine works on the selection.
- 0.3.122026-11-04 — Move sheet moves several sheets as a block: Shift+click adds a sheet to the selection (orange) or takes it out, a click on a selected sheet (or G) grabs them all, they move by one offset and the nearest corner of any of them snaps to the grid around each sheet and to the corners of the sheets outside the block; R turns every scan in its outline; one drop, one confirmation for the whole block (changes, nomenclature clashes after the move, sheets to extract again), one journal entry. Dock: apply_moves(moves) (apply_move kept for one sheet).
- 0.3.112026-11-04 — Move sheet (Raster column): a Blender-style grab for the few sheets placed in the wrong cell or turned: click a sheet, the scan follows the mouse drawn from its proxy, its nearest corner snaps to the corners of the grid cells and of the other sheets (markers on the map), R turns it 90°, click to drop; on a grid cell the sheet takes that cell's nomenclature and quarter turn (old name kept as moved_from) and is georeferenced again, elsewhere it keeps hand-set corners; a sheet without nomenclature is taken from the sheet list and dropped cell by cell (S = grid scale). OSM building footprints kept in the project (cache/osm_buildings): a sheet is fetched from Overpass once, Extract runs again offline, and after one Overpass failure the rest of the run reads the cache only. Extract keeps EngineClient.tile_concurrency() tiles in flight.
- 0.3.102026-11-03 — Faster Extract on the CPU, same geometry (T18): the Engine's staged extraction vectorised (spur pruning, per-component tests on crops, buffers computed once) and OCR read in worker processes (python -m mapquilt_engine --workers auto|N, default 4); sheet 4-c 711 s -> 154 s, identical output; extract_sheet(workers=k) keeps k tiles in flight for an Engine that reports concurrent_tiles (EngineClient.tile_concurrency); an Engine slow to answer /health while starting is reported unavailable instead of raising TimeoutError. Restart the Engine to get the speed-up.
- 0.3.92026-11-03 — Status bar (text, percent, Stop) moved above the sheet list, visible without scrolling.
- 0.3.82026-11-03 — Stop button in the status bar: the running step (Import, Rectify auto, Assemble seams, Georeference, Show rasters, Extract, Stitch) stops after the current tile / sheet / seam, what is finished stays saved, the journal records where it stopped and the progress line says the step resumes; Extract pressed again offers to resume with the sheets not yet extracted (the sheet in progress at the stop is redone).
- 0.3.72026-11-03 — "Check sheets" (Raster column): the scans folder compared with the project; lists image files without a sheet in the project (and names that are no nomenclature), rescanned files, sheets whose original is not found, sheets without frame / chain / extraction, and the holes in the grid (nomenclatures named as neighbour by two or more sheets but absent); log + audit.txt in the project folder.
- 0.3.62026-11-03 — Dock in two columns, Raster (Import, Rectify, Assemble, Georeference, Show rasters + opacity, Satellite + OSM) and Vector (Extract, Stitch, Export DXF); Review and Rhino sync collapsible (collapsed by default); project journal: every step run is recorded in project.json with date and plugin version (progress line under the steps, last run in each button's tooltip), the last project is reopened when QGIS starts; Rectify has Previous (back to the sheet just confirmed or skipped, correct and confirm again); Import skips the sheets already in the project (a sheet found later is imported from the same folder, the others keep their frames; a rescan replaces the old sheet); Extract offers to run only the sheets not yet extracted.
- 0.3.52026-11-03 — Assemble measures the seams: for every adjacent pair with a confirmed frame and a chain, the Engine (/v1/match/pair, line-segment matcher of T-cusaturi) reports how well the drawn lines continue across the shared edge; layer "MapQuilt seams" (green median <= 0.75 m, yellow <= 1.5 m, red worse or < 5 matched lines, labelled with the median). The residual is the drawing's own precision at the seam; no geometric adjustment is applied; a red seam means a wrong frame or nomenclature on one of the two sheets.
- 0.3.42026-11-03 — Status bar at the bottom of the dock: what the plugin is doing and the percentage (Import, Rectify auto, Georeference, Assemble, Show rasters, Extract per tile, Stitch per seam, Export).
- 0.3.32026-11-03 — "Show rasters" button + opacity slider: the scans of every sheet with a confirmed frame (georeferenced on the fly) are loaded clipped to their trapezoid in the group "MapQuilt rasters", a small proxy per sheet at city scale and the full scan under 1:4000, to check the placement against the map.
- 0.3.22026-11-03 — Frame proposal: scanner streaks suppressed before candidate extraction (both-ends rule on the ink mask, after Vo et al. 2018 / moment matching), candidate grouping fixed, strength tie-break; 8 -> 11 of 12 sides right on the ICPROM sheets.
- 0.3.12026-11-03 — Rectify: the frame is four independent corners (trapezoid, no crop), corner views with a fixed cross (drag the image, wheel zoom), AUTO and SEMI-AUTO (pattern learned from the first hand-confirmed sheet); sheets displayed clipped to their frame trapezoid (warped VRT with cutline).
- 0.3.02026-11-03 — All seven steps wired: Rectify dialog (frame proposal, four editable lines, corners at full resolution, click-to-set), Assemble (sheet footprints by nomenclature coloured by status, neighbours, GCP VRTs of the scans), Georeference writes the VRTs, Stitch merges faces across sheet seams within the seam tolerance; compact dock (step buttons with status dots in a flow layout, narrower minimum width); a geographic target CRS is switched to EPSG:3844. Verified headless in QGIS 4.2.3 on the three ICPROM sheets.
- 0.2.02026-10-31 — Extract wired end to end: tiles through the Engine (staged, with OSM footprints as class prior), merge into sheet faces/edges/labels, work.gpkg with class styling, review queue ordered by uncertainty (Confirm / Building / Parcel / Annex / Street / Reject), DXF export with one layer per class and a quality report; satellite + OSM reference layers; Rhino live sync box. Verified headless in QGIS 4.2.3 on sheet 4-c.
- 0.1.02026-10-23 — core modules: nomenclature, transform chain, sheet registry, frame proposal/confirmation, planar graph with seam stitching, Engine client; dock with the seven steps (Import, Rectify, Assemble, Georeference, Extract, Stitch, Export).
MapQuilt
06-plugin/help/mapquilt/ro · varianta onlineCe este MapQuilt¶
MapQuilt este un plugin QGIS care transformă o serie de planuri cadastrale scanate (de pildă planurile ICPROM Iași 1:1000, 1988–1990) într-un singur desen vectorial georeferențiat: parcele, clădiri, anexe, străzi și codurile lor, cu limitele comune exact partajate între vecini, gata de export în DXF pentru Rhino, AutoCAD sau ArchiCAD.
Numele vine de la „quilt”: fiecare foaie scanată rămâne o bucată cu pixelii ei originali și cu propria transformare pixel → teren; nimic nu se reeșantionează, nimic nu se deformează. Foile se așază una lângă alta din nomenclatura lor (numele trapezului, de pildă L-35-32-A-c-4-III-3-c), se vectorizează fiecare la rezoluția originală, iar vectorii se unesc topologic peste cusături.
Cine l-a făcut¶
MapQuilt și Rhino Sync sunt create de Radu Andrei, de la Universitatea Tehnică „Gheorghe Asachi” din Iași, Facultatea de Arhitectură „G. M. Cantacuzino”, cu ajutorul lui Claude, modelul de inteligență artificială al companiei Anthropic, care a scris codul, testele și documentația sub îndrumarea autorului, pe scanările planurilor cadastrale ICPROM Iași (1988–1990) și pe etalonul desenat de autor în Rhino. Întrebările cercetării, deciziile de metodă, verificarea adevărului din teren și fiecare confirmare pe foile reale sunt ale autorului; rapoartele de test din depozit (T1–T19) consemnează ce s-a încercat și cu ce cifre.
Ce face și ce nu face¶
- Face: înregistrarea foilor, confirmarea cadrului (linia chenarului), așezarea pe hartă fără puncte de control, măsurarea cusăturilor, extragerea parcelelor / clădirilor / străzilor / codurilor cu reguli fixe și OCR, revizuirea fețelor nesigure, unirea peste cusături, exportul DXF, și legătura live cu Rhino.
- Nu face: nu „ghicește” ce nu e desenat; o nepotrivire între plan și satelit e semnalată, nu corectată; precizia rămâne cea a desenului (≈ 0,5–0,8 m la cusături pe ICPROM).
Cum e împărțit¶
| Partea | Ce este | Licență |
|---|---|---|
Pluginul QGIS (mapquilt) |
dock-ul cu cele patru taburi, proiectul .mapquilt, lanțurile de transformare, graful planar, GeoPackage-ul de lucru, exportul |
GPL-2+ |
MapQuilt Engine (07-engine) |
server HTTP local (FastAPI, port 8765) cu tot ce e greu: vectorizarea pe dale, OCR, potrivirea cusăturilor; rulează pe același calculator (sau pe unul al dvs.) | Apache-2.0 |
| Rhino Sync | legătura live Rhino ↔ QGIS printr-un folder comun; plugin QGIS de sine stătător, încorporat și în dock-ul MapQuilt | GPL-2+ |
Pluginul vorbește cu Engine-ul prin HTTP pe 127.0.0.1: cererile nu părăsesc calculatorul, iar scanările rămân pe disc. Nu e nevoie de internet decât pentru straturile de referință (satelit, OSM), opționale.
Fluxul de lucru în șapte pași¶
- Import — folderul cu scanări (sau cu DXF-uri deja trasate); foile primesc nomenclatura și vecinii din numele fișierului.
- Rectify — cadrul foii (patru colțuri), propus automat, confirmat de dvs.; tiparul învățat se aplică pe celelalte.
- Georeference — lanțul pixel → Stereo 70 din colțurile cadrului și colțurile trapezului; VRT-uri pentru vizualizare.
- Assemble — foile pe hartă; cusăturile măsurate (cât de bine continuă liniile de pe o foaie pe cealaltă).
- Extract — vectorizarea fiecărei foi prin Engine, pe dale de 1600 px, cu amprentele OSM ca indiciu de clasă; fețe, muchii și etichete în
work.gpkg. - Review și Stitch — fețele nesigure, una câte una; unirea fețelor tăiate de linia foii.
- Export DXF — câte un strat pe clasă, plus raportul de calitate.
Fiecare pas are numărul lui, un punct de stare (gri / albastru / verde / portocaliu / roșu) și starea scrisă pe buton; pasul următor e conturat cu albastru și orice pas se poate relua; proiectul își ține jurnalul în project.json.
Două idei de ținut minte¶
Nomenclatura este georeferențierea. Numele trapezului spune exact ce celulă din caroiajul oficial e desenată pe foaie, iar colțurile celulei au coordonate cunoscute. Deci, odată confirmat cadrul, foaia e pe hartă fără niciun punct de control. O foaie iese greșit doar dacă numele e greșit (celula greșită), scanarea e rotită sau cadrul a fost confirmat pe altă linie; pentru fiecare caz există o unealtă: Move sheet, Check placement, Rectify / Refine.
Stratul de referință este cel al muchiilor. Parcelele și clădirile nu sunt poligoane desenate separat, ci regiunile închise de muchii; două parcele vecine împart exact aceeași limită, fără goluri și suprapuneri, prin construcție. De aceea unirea peste cusătură e doar ștergerea unei muchii și recalcularea fețelor, iar simplificarea contururilor nu desparte vecinii.
Instalare¶
Cerințe¶
- QGIS 3.40 sau mai nou (verificat în QGIS 4.2.3); pluginul e Python pur, fără dependențe în afara celor din QGIS (GDAL, NumPy; OpenCV și Shapely sunt folosite când există).
- Pentru Engine: Python 3.11+ cu pachetele din
07-engine/requirements.txt(OpenCV, Shapely, RapidOCR, FastAPI); nu e nevoie de placă grafică (vezi „Cât durează”). - Spațiu pe disc: proiectul
.mapquiltține proxy-uri (≈ 1200 px pe latură) și VRT-uri lângă scanări; scanările nu se copiază.
Pluginul¶
Din folderul 06-plugin rulați install_plugin.bat: copiază folderul mapquilt în profilul QGIS (%APPDATA%\QGIS\QGIS4\profiles\default\python\plugins\ și, dacă există, în profilul QGIS 3). Apoi reporniți QGIS și activați MapQuilt din Plugins › Manage and Install Plugins › Installed. Dock-ul se deschide din bara de unelte (sigla) sau din meniul Plugins › MapQuilt.
Pluginul instalat pe mână: copiați folderul mapquilt în același loc, fără __pycache__.
Engine-ul¶
- În
07-enginecreați un mediu Python și instalați dependențele (sau folosiți.venv-testdin depozit). - Porniți-l cu
run_engine.batsau cupython -m mapquilt_engine --port 8765 --workers auto.--workers autopornește câte un proces OCR pe nucleu (cel mult 4): extragerea unei foi 1:1000 durează ≈ 2,5 minute în loc de 12. - În dock, tabul ⚙: adresa
http://127.0.0.1:8765, apoi Test connection. Punctul devine verde și rândul de sub el spune versiunea, motoarele disponibile și câte procese OCR are. Start Engine pornește Engine-ul într-o consolă proprie (cere o singură dată folderul07-engine).
Engine-ul poate rula și pe alt calculator al dvs.: modul Cloud din ⚙ ține adresa lui separat. Datele cadastrale nu părăsesc instituția decât dacă decideți dvs. astfel.
Rhino Sync (opțional)¶
08-rhino\installer\dist\RhinoSyncSetup.exe instalează scripturile Rhino, aliasurile și pluginul QGIS „Rhino Sync”. Când pluginul e instalat, dock-ul MapQuilt arată și tabul Rhino sync; manualul lui e separat (linkul din stânga).
Prima verificare¶
Deschideți un proiect nou (⚙ › New…), alegeți folderul cu scanări la Import (tabul Raster) și urmăriți lista foilor: fiecare rând arată F G X (cadru confirmat, georeferențiată, extrasă) și vecinii N / E / S / V citiți din nomenclatură. O foaie cu numele roșu nu are nomenclatură lizibilă; vezi „Foi fără nomenclatură”.
Tabul ⚙ — Settings¶
Tabul mic cu rotiță ține tot ce se setează o dată pe proiect sau pe calculator.
Project¶
- New… creează un folder
<nume>.mapquilt(cuproject.json,sheets/,proxies/,cache/,work.gpkgdupă Extract). CRS-ul țintă e cel al proiectului QGIS dacă e proiectat (metri); unul geografic e înlocuit cu Stereo 70 (EPSG:3844) și se spune în log. - Open… deschide un
.mapquiltexistent. Ultimul proiect se redeschide singur la pornirea QGIS, iar jurnalul lui apare în log: ce pas a rulat ultima dată, când și cu ce versiune a pluginului. - Scans folder — folderul cu scanările originale, pe acest calculator. Import îl setează singur; îl schimbați cu Set… când proiectul vine de pe alt calculator sau folderul s-a mutat. Pluginul regăsește fișierele după hash și nume, deci o redenumire a folderului nu strică nimic odată ce ați arătat locul nou. Calea e ținută în
project.jsonpe fiecare calculator în parte.
Engine¶
- Local / Cloud — unde rulează Engine-ul. Local: pe acest calculator, adresa implicită
http://127.0.0.1:8765, Start Engine îl pornește într-o consolă (și Stop Engine îl închide). Cloud: aceeași aplicație pe un server al dvs., la adresahttps://…; Start Engine e gri (un Engine în cloud se pornește pe serverul lui). Fiecare mod își ține adresa; proiectul reține modul ales. - Test connection încearcă
/v1/healthși arată: versiunea, motoarele (staged,classic…), procesele OCR și câte dale se trimit deodată. Roșu înseamnă că nimic nu răspunde la adresa aceea: Engine-ul nu rulează, sau rulează pe alt port. - Pașii care au nevoie de Engine: Assemble (cusăturile), Extract, Refine. Import, Rectify, Georeference, Move sheet, Check placement, Stitch și Export merg și fără el.
Work: Online / Offline¶
- Online — Extract descarcă o singură dată, pe foaie, sursele externe bifate (implicit clădirile și străzile din OpenStreetMap) și le ține în
cache/din proiect; Satellite + OSM adaugă straturile web Esri World Imagery și OpenStreetMap, pentru verificare. - Offline — nu se descarcă nimic: sursele vin doar din cache (fișierele locale se citesc în continuare); o foaie fără răspuns în cache e extrasă fără indiciul extern, iar Satellite + OSM refuză politicos. Engine-ul nu e afectat (e oricum local).
Dacă o sursă nu răspunde într-o rulare, doar prima foaie mai așteaptă; celelalte folosesc cache-ul ei, ca să nu pierdeți câte trei minute pe foaie.
External sources (surse externe)¶
Ce cere Extract (și Check placement) din afară, foaie cu foaie. Sursele bifate sunt folosite de proiectul deschis; alegerea se salvează în proiect.
| Sursă | Tip | Ce face |
|---|---|---|
| OpenStreetMap buildings (bifată) | clădiri | amprente trasate de oameni; indiciu de clasă (clădire sau parcelă), un bloc o față (T19), Check placement |
| OpenStreetMap streets (bifată) | străzi | axele străzilor, cu numele lor; o față străbătută de axă e stradă, iar fețele aceleiași străzi se unesc (T20) |
| OpenStreetMap green spaces (bifată) | spații verzi | parcuri, grădini, locuri de joacă (amenajate); pajiști, tufărișuri, păduri (neamenajate); șiruri de arbori și iarbă pe fâșii înguste (de aliniament). O față fără cod acoperită în mare parte de una dintre ele primește clasa verde respectivă (T21) |
| Overture Maps buildings | clădiri | OSM plus amprentele Microsoft detectate automat unde OSM nu are (sate, cartiere necartate); descărcate de Engine, lent (minute pe foaie) |
| Overture Maps streets | străzi | segmentele de drum Overture (în mare parte din OSM), cu nume; descărcate de Engine |
Cu mouse-ul pe o sursă vedeți licența, atribuirea și notele. Fiecare răspuns se păstrează în proiect (cache/osm_buildings/, cache/sources/<id>/), o dată pe foaie, deci Extract merge apoi și offline.
Add… deschide un formular pornit dintr-un șablon:
- WFS (GeoJSON output), ArcGIS FeatureServer, OGC API Features — o adresă care răspunde GeoJSON în WGS84; cutia foii intră în locul lui
{west},{south},{east},{north}(sau{bbox}= south,west,north,east). - Overpass query — o interogare OSM proprie, cu
{bbox}. - File or QGIS data source — un GeoPackage, Shapefile, GeoJSON sau orice deschide QGIS printr-un furnizor (
ogr,WFS,arcgisfeatureserver,oapif…), citit de QGIS pentru fiecare foaie; bifați readable without internet pentru un fișier local. Așa intră datele descărcate de dvs. (Copernicus Urban Atlas, un export al primăriei sau al cadastrului).
La străzi, dați atributul care ține numele străzii (Street name field): fețele se unesc stradă cu stradă, după nume. La spațiile verzi, dați atributul care ține categoria (Green category field: alignment, landscaped, unlandscaped sau grass; o linie contează ca șir de arbori, adică de aliniament). Edit… modifică una de-a dvs. (una din plugin se copiază ca a dvs.), Remove șterge una de-a dvs.
Partajare. Export… scrie sursa selectată (sau toate ale dvs.) ca un fișier .json mic; altcineva o adaugă cu Import…. Ca să oferiți o sursă tuturor utilizatorilor MapQuilt, deschideți un issue cu fișierul în depozitul MapQuilt; după verificare, intră în lista comună, pe care Shared o descarcă (sursele comune vin nebifate). Spuneți licența: se listează doar sursele ai căror termeni permit asta.
Drawing: contururile clădirilor¶
Cum ies contururile clădirilor din Extract și Shapes (proiectul ține minte alegerea; Shapes din tabul Vector aplică o alegere nouă pe foile deja extrase, în câteva secunde). Fiecare contur e citit întâi ca linii și arce de cerc (Rosin & West 1995), apoi fiecare perete primește o familie: pe axa clădirii sau pe perpendiculara ei (90°), pe o diagonală (45°), liber (păstrat în direcția lui) sau arc (păstrat ca arc). Vârfurile se ajustează apoi toate deodată prin metoda celor mai mici pătrate, vecinii rămân lipiți, niciun vârf nu se mută mai mult de 1 m (T22). Un preset spune ce familii poate avea un țesut:
| Preset | Pentru | Familii | Toleranța la axă |
|---|---|---|---|
| Mixed (implicit) | orice: fiecare clădire alege din propriul contur | 90°, 45°, liber, curb | 12° |
| Planned 90° | blocuri, grile, industrie | doar 90°: orice perete merge pe o axă | 15° |
| Planned 90° + 45° | interbelic, modernist, colțuri teșite, hale cu capete în 45° | 90°, 45° | 12° |
| Organic | cartiere vechi, loturi strâmbe: un perete la peste 8° de axă rămâne cum e desenat | 90°, 45°, liber, curb | 8° |
| Curved | rezervoare, hale rotunde, abside: arcele sunt căutate mai insistent (15 % din contur ajunge) | toate | 12° |
| Squared / Straightened / As drawn | modurile vechi (0.3.27, T12, fără) | — | — |
Familia aleasă de Engine se scrie pe fiecare față (shape), și arcele păstrate (arcs, cu cele trei puncte ale fiecăruia în arcs_json). Un arc e o condiție a compensării la fel ca un perete pe axa lui: toate vârfurile lui sunt puse pe un singur cerc, al cărui centru și rază se rezolvă odată cu vârfurile, iar peretele care pleacă din arc e făcut tangent la el; Export DXF scrie astfel de fețe ca polilinii cu arce adevărate (bulge), pe care Rhino și AutoCAD le citesc ca arce. În Review, tastele 9 4 F O pun o familie de mână (shape_set); ea are întâietate față de preset la următorul Shapes și rezistă la rulările următoare. Pe etalonul Țicău (toate drepte) Mixed dă ce dădea Squared (9 vârfuri pe clădire, 62 % din colțurile aproape drepte exact drepte); pe foaia Gării, rezervoarele rotunde și halele în formă de C își păstrează arcele sub Mixed și Curved și sunt aplatizate sub Planned 90°. Are nevoie de Engine 0.8 sau mai nou; unul mai vechi primește modurile simple.
? — manualul¶
Butonul ? de lângă taburi deschide acest manual: copia livrată cu pluginul (mapquilt/help/index.html, merge fără internet), iar dacă lipsește, varianta online.
Tabul Raster — scanările¶
Tot ce privește foile ca imagini: înregistrare, cadru, așezare pe hartă, verificarea așezării.
Tabul are trei casete:
- Steps — 1 Import, 2 Rectify, 3 Georeference, 4 Assemble. Fiecare buton își scrie starea în dreapta (3 sheets, 12/40 frames, 40/40 chains, 2 red seams…) și are un punct colorat; pasul de rulat acum e conturat cu albastru.
- View — Show rasters (buton care rămâne apăsat), Satellite + OSM, cursorul de opacitate.
- Corrections — Check sheets, Move sheet cu Undo last move alături, Refine, Check placement.
Întrebările își scriu răspunsurile pe butoane („Only the 5 others” / „All 40 again”), nu mai e nicio întrebare Yes / No care trebuie citită de două ori.
Progresul pe buton. Un pas lung (Import, Georeference, Assemble, Show rasters, Refine, Check placement, Extract, Stitch, Export) își desenează progresul chiar pe butonul apăsat: o umplere albastră care crește de la stânga, procentul în dreapta și, pe un al doilea rând mic, ce face acum. Un clic pe același buton oprește după dala / foaia curentă; ce s-a terminat rămâne salvat, iar o nouă apăsare continuă. Cât rulează un pas, celelalte butoane așteaptă. Pe alt tab, procentul apare pe tabul butonului care rulează (Vector · 45 %).
Bara de taburi stă pe loc, iar taburile iau tot dock-ul. Fiecare tab derulează singur. Sub taburi e un singur rând: câte foi sunt selectate (✕ golește) și ce face pluginul acum. Lista de foi, rândul jurnalului și log-ul sunt la capătul tabului ⚙.
1 · Import¶
Alegeți folderul scanărilor (JPG, TIF, PNG) sau al DXF-urilor deja trasate. Pentru fiecare fișier pluginul citește nomenclatura din nume, după ce îl curăță (….tif.jpg, …_, - Copy, (2), bis, _ în loc de -); un nume care nu se potrivește exact e potrivit „fuzzy” cu golurile și vecinii seriei, iar numele probabile se marchează pentru verificare. Vecinii N / E / S / V se calculează din nomenclatură.
- Import rulat din nou pe același folder: foile deja înregistrate, cu același conținut, sunt sărite și își păstrează cadrele, lanțurile și extragerile; doar foile noi se adaugă. Un fișier cu același nume dar alt conținut (o rescanare) înlocuiește foaia veche, care trebuie refăcută. Copiile unei foi (
- Copy) nu se importă. - Import nu intră în subfoldere; un subfolder se importă separat.
- O foaie DXF (una pe foaie, numită după nomenclatură, cu chenarul păstrat) e desenată o dată ca imagine în
rendered/și trece prin aceiași pași ca o scanare; la Extract se iau liniile ei direct, fără Engine.
2 · Rectify — cadrul foii¶
Cadrul este un patrulater cu patru colțuri independente (un trapez, o scanare rotită), nu un dreptunghi. Dialogul arată foaia micșorată cu patrulaterul propus, cele patru colțuri la scară 1:1 cu reticul fix (trageți imaginea sub reticul; rotița = zoom 1/2/4×) și încrederea pe fiecare colț. Clic pe previzualizare mută colțul cel mai apropiat. Nomenclatura se poate corecta în dialog.
- Confirm and next confirmă și trece la foaia următoare fără cadru; Skip o sare; ◀ Previous se întoarce la foaia părăsită ultima dată, cu cadrul ei, ca să-l corectați.
- AUTO confirmă singur foile cu propunere sigură; SEMI-AUTO învață tiparul din prima confirmare manuală (a câta linie dinspre margine, distanța față de chenar) și îl aplică unde două citiri coincid. „Auto: remaining sheets” lucrează doar pe foile fără cadru.
- Dungile scanerului sunt suprimate înainte de detecție (T16), altfel latura din dreapta cădea pe dungă.
- Un cadru confirmat pe altă linie decât chenarul (un bloc de titlu, o linie interioară) se vede după Georeference în raportul scărilor: cele două axe diferă cu 2–9 %. Se repară aici, nu prin mutare.
3 · Georeference¶
Colțurile cadrului (pixeli TL, TR, BR, BL) merg pe colțurile trapezului (NV, NE, SE, SV) din nomenclatură, calculate pe elipsoidul Krasovski și transformate în CRS-ul țintă: o omografie pe foaie. Se scriu VRT-uri cu rețea de GCP-uri (fără reeșantionare) și VRT-uri tăiate la trapez, pentru afișare.
- Cu foi deja așezate, oferă Only the N others (foi noi, cadre confirmate din nou) sau All N again. Așezarea din nou dă același loc: corecțiile din Move sheet și Refine sunt chiar datele din care se calculează.
- Raportul scărilor pe foaie (
quality.scale_report) spune metri pe pixel pe fiecare axă.
4 · Assemble — foile pe hartă și cusăturile¶
După Georeference (cusăturile se măsoară pe foi georeferențiate). Creează stratul MapQuilt sheets cu conturul fiecărei foi (prin lanț când e georeferențiată, altfel trapezul nominal), colorat după stare, cu vecinii și foile lipsă. Cu Engine-ul pornit măsoară fiecare cusătură: segmentele care ating cadrul sunt extrase din banda de margine a celor două scanări, duse în teren și potrivite una la una peste linia comună. Stratul MapQuilt seams le arată: verde (mediana ≤ 0,75 m), galben (≤ 1,5 m), roșu (mai rău sau sub 5 linii potrivite).
O cusătură roșie înseamnă un cadru confirmat greșit sau o nomenclatură greșită pe una din cele două foi. Nu se aplică nicio compensare geometrică: reziduul este precizia proprie a desenului (≈ 0,5–0,8 m pe ICPROM).
Show rasters și opacitatea¶
Încarcă scanările foilor cu cadru confirmat, decupate la trapez, în grupul MapQuilt rasters: proxy-ul la scara orașului, scanarea întreagă când apropiați. E un buton care rămâne apăsat: apăsat, grupul se vede; ridicat, se ascunde. Cursorul de dedesubt setează opacitatea, ca să verificați așezarea peste hartă sau satelit.
Satellite + OSM¶
Esri World Imagery și OpenStreetMap ca straturi XYZ într-un grup Reference la baza arborelui. Numai pentru verificare: între planul anilor '80 și satelit sunt 1–3 m de decalaj și clădiri schimbate.
Check sheets — auditul¶
Compară folderul scanărilor cu proiectul și scrie în log și în audit.txt: fișiere fără foaie, nume nerecunoscute (cu numele citite sau potrivite), rescanări, copii, originale negăsite, foi fără cadru / lanț / extragere și golurile caroiajului (trapeze pe care două foi le numesc drept vecin și care lipsesc), cu fișierul probabil al fiecărui gol. Celulele acoperite de foi la altă scară nu se numără ca goluri. În aceeași fereastră oferă Give the N nomenclatures pentru numele sigure.
Move sheet — mutarea pe hartă¶
Pentru o foaie pe care nomenclatura a pus-o în alt loc, sau care e rotită, ca „grab” din Blender. Cât timp sunt foi selectate sau o foaie în mână, o casetă mică lângă cursor arată tastele care acționează acum:
| Tastă / acțiune | Efect |
|---|---|
| clic pe o foaie | o ia; scanarea urmează mouse-ul, semi-transparentă, cu contur roșu |
| mișcare | colțul cel mai apropiat se prinde (14 px) de colțurile celulelor și ale celorlalte foi; pătrate albastre = ținte, crucea roșie = cea de care se prinde |
| al doilea clic | o lasă; pe o celulă a caroiajului (toleranță 2 % din latură, ≈ 12 m la 1:1000) foaia ia nomenclatura celulei și sfertul de rotire și se georeferențiază imediat |
| R ↻ | rotește 90° în sensul acelor de ceasornic; cu foi selectate și niciuna în mână, le rotește pe loc (Enter confirmă, un clic le lasă în altă parte); un bloc se rotește în jurul centrului, celulă cu celulă |
| Shift+R ↺ | rotește înapoi (90° invers) |
| Enter · Space | lasă foile din mână acolo unde sunt (o rotire pe loc: clic pe foaie, R, Enter) |
| Shift+clic | adaugă o foaie la selecție (portocaliu) sau o scoate; apoi un clic pe una dintre ele sau G le mută ca bloc |
| A · Alt+A | selectează toate foile așezate · niciuna |
| S | schimbă scara caroiajului pentru o foaie fără nomenclatură (selectată întâi în listă) |
| Ctrl+Z | anulează ultima mutare (ca Undo last move) |
| Esc / clic dreapta | renunță la foaia din mână; din nou, golește selecția; din nou, iese din unealtă |
Nu mai apare nicio întrebare la fiecare mutare: ce a făcut mutarea se scrie în log, iar Undo last move (sau Ctrl+Z pe hartă) pune foile înapoi, cu nomenclatura, rotirea, cusăturile și starea extragerii de dinainte, până la ultimele 20 de mutări. O foaie lăsată în afara caroiajului își păstrează colțurile puse de mână. Nomenclatura veche rămâne în label.moved_from; o foaie deja extrasă trebuie extrasă din nou, iar log-ul spune asta.
Refine — cadrul corectat din cusături¶
Pentru o foaie în celula bună, ale cărei linii nu continuă în vecini: cusăturile cu fiecare vecin așezat se măsoară din nou, iar cele patru colțuri ale cadrului (pixeli) se mută până când liniile continuă; vecinii și grila rămân pe loc. Întâi alege, pe fiecare latură, linia desenată pe care a fost confirmat cadrul; apoi face o potrivire a colțurilor cu prior pe cadrul vechi și o validează pe linii neutilizate la potrivire. O potrivire liberă a celor patru colțuri reduce reziduul mutând un colț cu 8 m: aceea nu e corecție, ci deformare, și e refuzată. Arată cusăturile înainte și după și oferă Keep the refined frames sau Leave as they were; cadrul vechi rămâne în proiect.
Lucrează pe foile selectate (butonul spune câte). Fără foi selectate oferă Refine the N red, worst first sau Select sheets on the map.
Check placement — foaia stă cu susul în sus?¶
Un martor din afara seriei: contururile clădirilor din OpenStreetMap, puse peste proxy-ul scanării pentru fiecare din cele patru rotiri posibile ale cadrului în celulă. Scorul rotirii este liftul: cât din punctele conturului cad pe cerneală (cei mai întunecați 2 % din pixeli, bandă de un pixel) împărțit la cât ar cădea din întâmplare. Pe foile de probă, rotirea bună are lift 1,9–2,5, celelalte 0,9–1,1.
- Foile la care câștigă clar altă rotire decât cea stocată sunt listate și, după Turn N sheets, întoarse (exact ca R în Move sheet) și georeferențiate din nou; Undo last move le pune înapoi.
- O foaie pe care nu o potrivește nicio rotire e probabil în celula greșită (Move sheet) sau într-o zonă reconstruită.
- Verificarea e grosieră cu bună știință: deosebește rotirile și celula, nu metrii; precizia fină rămâne la cusături și Refine.
Tabul Vector — desenul¶
Extract all / Extract selected¶
5 · Extract all vectorizează toate foile; cu foi deja extrase oferă Extract the N others (sau Resume with the N others după un Stop) și All N again. Extract selected extrage, din nou, doar foile selectate (în lista de foi cu Shift / Ctrl+clic, pe hartă cu Select on map, trapezele selectate în stratul MapQuilt sheets sau rasterele sheet … selectate în Layers). Eticheta lui spune câte foi ia (Extract 3 selected). Fără selecție pornește singur Select on map, cu extragerea în așteptare: clic pe foi pe hartă (caseta de lângă cursor o spune), apoi Enter sau Space le extrage; Esc renunță.
Pentru fiecare foaie: scanarea e citită prin GDAL la rezoluția originală, amprentele OSM ale întinderii foii se iau din cache (sau se descarcă o dată), foaia se taie în dale de 1600 px cu suprapunere de 160 px, fiecare dală merge la Engine (staged), rezultatele se unesc pe foaie (fețele complete o singură dată, nucleul dalei decide), și totul se scrie în work.gpkg: straturile faces, edges, labels în CRS-ul țintă, stilizate pe clase în grupul MapQuilt.
Clasele: building, annex (șoproane, garaje, corpuri cu X), amenity (scări exterioare, fâșii hașurate: AMENAJĂRI din desenul de referință), parcel, street, cele trei clase de spații verzi (mai jos), other (marginea dalei). Fiecare față poartă why (de ce a primit clasa: etichetă, indicator, amprentă, insulă, simbol, formă, grosimea liniei), confidence, review_score, needs_review, codes (codurile citite prin OCR: C 1900, DP 1901/1 …).
Liniile după litere (Engine 0.10.1). Pasul 0 citește codurile (OCR), numerele în cerc și simbolurile X și le maschează înainte de schelet. Din codurile citite, Engine-ul știe cât de înalte sunt literele foii și cum sunt distanțate; orice bucată de mărimea literei care nu e linie și care continuă un cod citit, stă exact sub el sau formează un rând cu ritm de litere e scoasă și ea din cerneală (litere lipite de linii, cifre sărite de OCR, cifre goale luate drept șoproane), linia pe care stă codul rămânând întreagă. O linie groasă e un obiect: bucățile scurte dintre muchii groase sunt groase, iar capătul liber al unei muchii groase e podit până la muchia groasă din față când în gol mai e cerneală.
Nicio față pe o linie (Engine 0.10). Un perete desenat cu grosimea lui, un calcan sau un gard dublu dau o față îngustă care e mai mult cerneala propriilor două margini; ea nu rămâne niciodată: o ia clădirea de lângă ea, altfel e împărțită pe axă între cei doi vecini. O scară hașurată (scări exterioare, fâșie hașurată: linii paralele peste o bandă îngustă) devine o singură față amenity. În modurile de contur „squared”, un segment scurt al unei clădiri la 90° / 45° care nu se așază pe nicio axă e colțul rotunjit de schelet: e strâns într-un punct, deci colțul e acolo unde se întâlnesc cei doi pereți (⚙ › Drawing; corner_cut_m, 3 m).
Cu Engine-ul cu 4 procese OCR, o foaie 1:1000 durează ≈ 2,5 minute; se trimit două dale deodată. Un clic pe butonul Extract care rulează oprește după dala curentă; Extract apăsat din nou reia cu foile rămase.
Shapes — îndreptare din nou, fără extragere¶
Extract păstrează, pentru fiecare foaie, fețele brute ale fiecărei dale (desenul dinainte de îndreptare) în proiect, în cache/raw/<foaie>/. Shapes le trimite doar prin pasul de îndreptare al Engine-ului (/v1/regularize), cu modul de contur din ⚙ › Drawing, și înlocuiește fețele foii: câteva secunde pe foaie în loc de minute, fără OCR, fără schelet. Folosiți-l după ce schimbați Building outlines, sau mai târziu, când apare un mod nou de contur.
- Lucrează pe foile selectate, altfel pe toate foile extrase care au fețe brute. O foaie extrasă înainte de 0.3.28 nu are: extrageți-o o dată din nou.
- Deciziile din Review (confirmed, edited, rejected) trec pe fața nouă care se suprapune cel mai mult peste cea veche; log-ul spune câte s-au păstrat.
- Fețele unite peste o cusătură a foii se șterg: rulați din nou Stitch. Muchiile și etichetele nu se schimbă.
- Are nevoie de Engine 0.7 sau mai nou.
Bara de selecție — o singură selecție pentru toate taburile¶
Sub taburi, un singur rând: câte foi sunt selectate și un buton care golește selecția. În tabul ⚙, deasupra listei de foi: Select on map. El selectează foile direct pe hartă (contur portocaliu): clic pe o foaie, Shift+clic adaugă sau scoate, trageți un dreptunghi pentru mai multe (Shift+dreptunghi adaugă), A toate, Alt+A niciuna, Esc golește; caseta mică de lângă cursor amintește tastele. Lista, Shift+clic din Move sheet și selecția QGIS pe MapQuilt sheets ajung în aceeași selecție, iar butoanele care o folosesc spun câte foi iau: Extract 3 selected, Refine 3 selected, Check placement · 3 selected.
Sub listă, un rând explică codurile F G X și culorile; log-ul e sub ea, în același tab ⚙. Progresul unui pas se desenează pe butonul lui (vezi tabul Raster).
Edit — Join faces (unirea fețelor)¶
Două fețe care ar trebui să fie una (o parcelă tăiată în două de linia unui gard, un bloc despărțit de o linie desenată, două bucăți ale aceluiași spațiu verde): Join faces din caseta Edit, apoi pe hartă apăsați într-o față, trageți peste vecina ei și eliberați. Cât trageți, fața de pornire e portocalie, iar fața de sub cursor verde când se pot uni și roșie când nu; caseta mică de lângă cursor spune de ce (altă clasă, nu sunt vecine, se ating doar într-un punct).
- Se unesc doar fețe din aceeași clasă care se ating (golurile de până la 0,3 m lăsate de simplificare se închid). Ca să uniți o clădire cu o parcelă, schimbați întâi clasa uneia în Review.
- Prima față își păstrează rândul: geometria devine reuniunea, codurile amândurora rămân, clădirile și anexele se adună, starea de revizuire devine edited, iar nota spune ce față s-a unit cu ea. Cealaltă față se șterge.
- Ctrl+Z pe hartă, sau Undo join, pune cele două fețe la loc (ultimele 50 de uniri). Esc renunță la o tragere, apoi iese din unealtă. Fiecare unire și anulare se scrie în jurnalul proiectului.
- Liniile desenate (stratul
edges) nu se ating: se unesc doar fețele.
Spațiile verzi — trei categorii¶
| Clasă | În română | Ce este | Din OSM |
|---|---|---|---|
green_alignment |
spațiu verde de aliniament | de-a lungul străzii: șiruri de arbori, fâșii de iarbă între carosabil și trotuar | natural=tree_row; landuse=grass pe o fâșie mai îngustă de 8 m |
green_landscaped |
spațiu verde amenajat | amenajat și întreținut: parc, grădină, scuar, loc de joacă, gazon de sport | leisure=park/garden/playground/pitch, landuse=recreation_ground/village_green/flowerbed; landuse=grass mai lat de 8 m |
green_unlandscaped |
spațiu verde neamenajat | lăsat să crească: pajiște, tufăriș, pădure, teren viran | landuse=meadow/forest, natural=scrub/grassland/heath/wood |
O față primește o clasă verde doar dacă nu are cod (o parcelă necodată, sau o fâșie găsită ca stradă după formă) și cel puțin jumătate din ea stă în spații verzi de aceeași categorie. O parcelă codată rămâne parcelă: cadastrul spune ce este, OSM doar ce crește pe ea, așa că primește categoria în atributul green. Fețele verzi au o încredere mai mică și intră în coada de revizuire; acolo tastele 1 2 3 le dau categoria de mână (și fețelor pe care OSM nu le știe). În DXF fiecare categorie are stratul ei.
Review — fețele nesigure¶
Caseta Review apare după ce o foaie e extrasă. Next (N) sare la fața cea mai incertă (după review_score), peste scanare și satelit. Apoi decideți, cu butonul sau cu tasta lui (tastele merg cât timp o față e în revizuire, pe hartă și în dock; Esc oprește):
| Buton | Ce înseamnă |
|---|---|
| Confirm Enter | fața e bună așa cum e (și atunci când nu se potrivește cu satelitul: planul e adevărul istoric) |
| Building B / Parcel P / Annex A / Amenity M / Street S / Green 1 aliniament, 2 amenajat, 3 neamenajat | forma e bună, clasa era greșită; pluginul o schimbă și marchează fața confirmată |
| Shape 9 90°, 4 45°, F liber, O arc | familia pereților clădirii, pusă de mână (⚙ › Drawing); Shapes o îndreaptă apoi așa |
| Reject X | o eroare de vectorizare (o insulă falsă, o limită inventată); fața iese din rezultat |
Decizia se scrie în review_state și ajunge în export. Pluginul nu corectează singur o nepotrivire cu satelitul, pentru că nu poate ști dacă e eroare de vectorizare sau schimbare în timp; el doar pune cazurile în fața dvs., cele mai nesigure primele. O formă greșită (limită lipsă sau în plus) se corectează pe muchii, cu uneltele QGIS, iar fețele se recalculează.
6 · Stitch — unirea peste cusături¶
Pentru fiecare pereche de foi vecine, fețele care ating banda cusăturii (± toleranța, implicit 1,5 m = percentila 90 a zgomotului măsurat), de aceeași clasă și cu intervale suprapuse pe linia comună, se unesc; muchiile marcate „cusătură” se șterg și fețele se repoligonizează. Nimic nu se mută, nimic nu se deformează. Pe foile DXF se unesc și capetele liniilor. Fețele deja unite nu se mai potrivesc a doua oară, deci Stitch se poate rula iar după un Import nou.
7 · Export DXF¶
Scrie DXF-ul cu câte un strat pe clasă (fețele cu arce ca polilinii cu arce adevărate, vezi ⚙ › Drawing) (building, parcel, street, annex, amenity, other; pe foile DXF și liniile), în CRS-ul țintă, plus un raport JSON (numărătorile, fețele revizuite, cusăturile). Straturile se copiază întâi în memorie, ca GeoPackage-ul în mod WAL să nu dea un DXF gol.
Simplificarea și îndreptarea contururilor (⚙ › Drawing › Building outlines; parametrul regularize al Engine-ului: none, orthogonal, squared) se fac pe muchiile comune, ca vecinii să rămână lipiți; Squared, implicit, ajustează toate vârfurile deodată și face drepte și colțurile de pe limitele de lot (23 → 9 vârfuri pe clădire la aceeași calitate).
Jurnalul, bara de stare, Stop¶
Jurnalul proiectului¶
Fiecare rulare a unui pas se scrie în project.json (journal: pas, dată, versiunea pluginului, un rând de rezumat; steps: ultima rulare a fiecărui pas). În tabul ⚙, deasupra listei de foi, rândul „Last … · Next …” spune unde s-a ajuns, fiecare buton are în tooltip ultima lui rulare, iar la deschiderea proiectului jurnalul apare în log. Starea punctelor colorate vine din datele foilor (cadre, lanțuri, extrageri), nu din jurnal, deci un proiect scris de o versiune veche e descris corect.
Bara de stare și Stop¶
Sub taburi: ce face pluginul acum; procentul și Stop sunt pe butonul care a pornit pasul (un clic pe el oprește). Stop oprește pasul după dala / foaia / cusătura curentă; ce e terminat rămâne salvat, jurnalul notează unde s-a oprit, iar rularea aceluiași pas reia cu ce a rămas (foaia în curs se reface).
Lista foilor și logul¶
Fiecare rând: F G X (cadru, georeferențiere, extragere), id-ul foii, vecinii N E S V. Verde = nomenclatură citită, roșu = fără nomenclatură. Logul de sub listă repetă mesajele din Log Messages › MapQuilt al QGIS.
Fluxuri de lucru¶
O planșă găsită mai târziu¶
Puneți fișierul în același folder cu scanările și apăsați din nou Import pe el: foile vechi sunt sărite, doar cea nouă se adaugă. Apoi Rectify (dialogul se deschide pe prima foaie fără cadru, adică pe cea nouă; „Auto: remaining sheets” îi aplică tiparul învățat), Georeference (doar foile noi), Assemble, Extract (butonul Extract the N others: doar foile neextrase), Stitch, Export. Un subfolder merge și el, dar Import trebuie rulat pe el, iar Check sheets numără doar folderul principal.
O foaie în celula greșită sau rotită¶
Semne: pe hartă foaia stă peste alta sau într-un gol, cusăturile ei sunt roșii, Check placement spune că o altă rotire se potrivește. Rotire: Check placement o întoarce după Turn N sheets. Celulă greșită: Move sheet, trageți foaia pe celula ei; primește nomenclatura celulei. Apoi Extract din nou pe ea, dacă fusese extrasă.
Un cadru confirmat pe linia greșită¶
Semne: raportul scărilor arată 2–9 % diferență între axe, cusăturile sunt galbene sau roșii pe toate laturile. Sute de pixeli: Rectify din nou pe foaie (◀ Previous ajunge la ea). Câțiva pixeli: Refine.
Foi fără nomenclatură¶
Numele roșu în listă. Fie corectați numele în dialogul Rectify, fie o selectați în listă și o așezați cu Move sheet celulă cu celulă (S schimbă scara grilei). Check sheets arată golurile caroiajului: celulele pe care vecinii le numesc și care lipsesc sunt candidatele.
Proiectul mutat pe alt calculator¶
Copiați folderul .mapquilt și scanările. În ⚙ setați Scans folder; pluginul regăsește fișierele după hash și nume. Engine-ul se pornește local pe calculatorul nou. Amprentele OSM sunt deja în cache-ul proiectului, deci Extract merge și offline.
Cât durează¶
| Pas | Durată tipică (foaie 1:1000, ≈ 5000 × 5000 px) |
|---|---|
| Import | secunde pe folder |
| Rectify | 10–20 s pe foaie manual; AUTO instant |
| Assemble cu cusături | ≈ 10 s pe cusătură (Engine) |
| Georeference | sub o secundă pe foaie |
| Extract | ≈ 2,5 min pe foaie cu 4 procese OCR (12 min cu unul); ≈ 7 ore pentru 160 de foi |
| Stitch, Export | secunde–minute |
O placă grafică nu ajută: motorul de reguli nu folosește rețele neuronale în afara OCR-ului, iar timpul se consumă în operații pe imagine și pe graf, care au fost accelerate prin cod (T18).
Tabul Rhino sync¶
Apare când pluginul Rhino Sync e instalat în profilul QGIS (instalatorul RhinoSyncSetup.exe îl pune). Caseta e aceeași ca în pluginul de sine stătător: Project folder (folderul comun de lângă fișierul .3dm), lampa (verde cât Rhino e și el pe Play), Play / Stop, Send to Rhino, Get now, Send context, Promote to project, Fields…, Send image.
Ciclul tipic: în Rhino RhinoSync › Play, în QGIS Play, apoi desenați pe straturile SCHITA::…; la o secundă-două după ce ridicați mâna, parcela apare în QGIS peste planșă și satelit. Corectați o față în QGIS, Send to Rhino, și o vedeți pe QGIS::….
Tot ce ține de convenții (straturi, familii SCHITA / CONTEXT / QGIS, umpleri, câmpuri, sync-config.json, CLI, limite) este în manualul Rhino Sync, separat: linkul din stânga sau butonul ? din dock-ul Rhino Sync.
Probleme frecvente¶
Punctul Engine e roșu. Engine-ul nu rulează sau rulează pe alt port. Porniți-l (⚙ › Start, sau run_engine.bat) și apăsați Check; adresa din ⚙ trebuie să fie cea din consola Engine-ului (implicit 8765). Un proiect vechi poate ține altă adresă: Check o rescrie.
Extract e foarte lent. Reporniți Engine-ul cu --workers auto (Check arată „4 OCR processes”); cu un singur proces OCR o foaie durează de 4–5 ori mai mult. Placa grafică nu ajută.
Foaia nu apare pe hartă după Georeference. Nu are nomenclatură (numele roșu) sau nu are cadru confirmat. Rectify pe ea; pentru nume, dialogul Rectify sau Move sheet.
Foile se suprapun pe hartă. Două foi au aceeași nomenclatură (Check sheets le listează) sau una e în celula greșită: Move sheet.
Cusăturile sunt roșii pe o foaie. Cadrul e pe linia greșită (Rectify / Refine), scanarea e rotită (Check placement) sau nomenclatura e greșită (Move sheet). O singură cusătură roșie între două foi bune poate fi și o foaie veche scanată de pe un original diferit.
Blocurile apar ca parcele (albastre) sau tăiate în bucăți. Planul desenează blocul cu linie dublă și un cod pe scară, iar OSM îl știe ca un poligon. Din versiunea Engine cu T19, fețele clădire din aceeași amprentă OSM se unesc, iar plafonul de 1500 m² al regulii amprentei nu mai există; reporniți Engine-ul ca să ia codul nou și extrageți din nou foaia.
„original not found”. Scanările s-au mutat: ⚙ › Scans folder › Set…. Check sheets spune care foi nu se regăsesc.
O stradă iese în mai multe bucăți. Din versiunea Engine cu T20, fețele străbătute de axa unei străzi se unesc stradă cu stradă. Verificați că OpenStreetMap streets e bifată în ⚙ › External sources, reporniți Engine-ul și extrageți din nou foaia. O stradă care lipsește din OSM, sau care nu exista când s-a desenat planul, rămâne cum o are planul; la fel o bucată pe care OSM calcă bordura (desenul are întâietate față de OSM).
Overpass nu răspunde, Extract așteaptă. Doar prima foaie din rulare mai așteaptă; celelalte folosesc cache-ul. Setați Work: Offline ca să nu aștepte deloc. Overpass răspunde uneori „at capacity” câteva minute; extrageți foaia din nou mai târziu.
DXF-ul iese gol. Versiunile dinainte de 0.3.14 exportau direct din GeoPackage-ul în mod WAL; acum straturile se copiază în memorie. Dacă persistă, închideți straturile work.gpkg din alte aplicații.
Dialogul Rectify a confirmat un cadru greșit și am trecut mai departe. ◀ Previous se întoarce la foaia părăsită ultima dată, cu cadrul ei; corectați și confirmați din nou (tiparul SEMI-AUTO se reînvață de pe ea).
Unde sunt datele? În folderul .mapquilt: project.json (proiect, jurnal, roots), sheets/<id>.json (sursă, cadru, lanț, vecini, cusături, calitate, revizuire), proxies/, rendered/ (DXF-uri desenate), cache/osm_buildings/, matches/ (cusăturile), work.gpkg, audit.txt. Nimic nu se scrie lângă scanări în afară de VRT-uri.
Cum funcționează¶
Motorul etapizat (Engine staged)¶
Vectorizarea e un lanț de reguli fixe, nu o rețea neuronală; singurul model învățat e OCR-ul (RapidOCR) pentru coduri. Pe fiecare dală de 1600 px:
- Adnotări — textele și cercurile-indicator se detectează și se mască; liniile întrerupte de ele se refac („bridging”).
- Grosimea liniei — distanța până la fundal pe cerneala curățată, înainte de subțiere; pragul Otsu desparte liniile groase (contur de clădire) de cele subțiri (limite).
- Scheletul → muchii comune — subțiere, tăierea ramurilor scurte (vectorizat: 340 s → 2 s pe foaie), lipirea capetelor libere, segmente de pixeli unite în polilinii între joncțiuni, simplificate cu capetele fixe.
- Fețe și clase — poligonizarea muchiilor; fiecare față primește clasa după, în ordine: eticheta din interior (C → clădire, DS/DP → stradă, CR/CC/CAT → parcelă), indicatorul în cerc, axa unei străzi care străbate fața pe lungime, departe de margini (T20), acoperirea amprentei OSM (înregistrată local pe schelet), topologia (o insulă într-un gol e clădire), forma (benzi lungi = străzi), grosimea conturului; fețele mici cu X sunt anexe. 3a (T19): fețele clădire din aceeași amprentă OSM se unesc. 3a′ (T20): fețele stradă ale aceleiași străzi (același nume, altfel aceeași cale OSM) care se ating se unesc — doar peste o linie pe care axa o taie la 45° sau mai mult, așa că o bordură sau linia unui trotuar de-a lungul străzii rămâne și acolo unde OSM o calcă (T20b); o fâșie mai îngustă de 3,5 m (un trotuar) nu devine stradă doar din axă, iar trotuarele nu se lipesc de carosabil. 3c (T21): o față fără cod, cel puțin pe jumătate în spații verzi OSM de aceeași categorie, devine
green_alignment,green_landscapedsaugreen_unlandscaped; o parcelă codată primește doar categoria ca atribut. 3b (T12, T22, T23): simplificare pe graf; fiecare muchie citită ca linii și arce; o familie de formă pe clădire, din preset (⚙ › Drawing) sau pusă de mână; apoi îndreptare: implicit o compensare prin metoda celor mai mici pătrate a tuturor vârfurilor (și a joncțiunilor), cu condiția „exact pe axa clădirii” pe fiecare perete aflat la cel mult 12° de ea, niciun vârf mutat mai mult de 1 m; modul vechi ține joncțiunile fixe. - Dizolvare — clădirile se atașează parcelei-gazdă cu latura comună cea mai lungă; fâșiile necodate se varsă în vecin.
Măsurat pe dala Țicău față de etalonul desenat în Rhino: PQ clădiri 0,64 (precizie 0,80, regăsire 0,66, IoU mediu 0,89); parcele 0,34; fracția de contur partajat 0 → 0,63 prin trecerea la graful planar (T6b).
Lanțul de transformare¶
Fiecare foaie are un lanț declarativ pixel → teren (transforms.Chain): lentilă (pentru fotografii), omografie din cele patru colțuri, opțional un rest TPS mărginit. Lanțul se serializează în JSON și se exportă ca rețea de GCP-uri 8 × 8 pentru GDAL, care reproduce exact transformarea pe VRT fără a reeșantiona originalul. Vectorii extrași pe dală trec prin lanț în CRS-ul țintă.
Cusăturile¶
Din banda de margine a fiecărei scanări (25–320 px în interiorul cadrului) se extrag segmentele care ating cadrul, se duc în teren și se potrivesc una la una peste linia comună (Engine /v1/match/pair). Mediana abaterii este cusătura; pe ICPROM 0,76 și 0,81 m pe foile de probă. Nu se aplică nicio compensare: o compensare comună minimală pe trei foi (T-compensare) a arătat că nu există un semnal de deformare peste zgomotul desenului, iar o potrivire liberă a colțurilor supraînvață.
Verificarea cu OSM și satelit¶
Amprentele OSM sunt un indiciu, nu adevărul: între plan și OSM sunt 1–3 m de decalaj și clădiri schimbate. Ele servesc la clasă (clădire vs parcelă: AUC 0,9 pe fețele adevărate), la unirea blocurilor și la verificarea rotirii foii; nu la geometrie. Un detector de amprente pe satelit (hotosm/dinov3s) a fost comparat cu OSM și Overture (T11): OSM rămâne cel mai bun pe Iași.
Rapoartele de test¶
Fiecare decizie a proiectului are un raport în 01-cercetare/ (T1–T19): ce s-a încercat, pe ce date, cu ce cifre. Sinteza lor, cu bibliografia completă, este sinteza_cercetare_MapQuilt.md, iar prezentarea academică prezentare_cercetare_MapQuilt_RhinoSync.md.
Literatură¶
Lucrările pe care se sprijină metoda, în ordinea în care intervin în flux. Rapoartele interne de test (T1–T19) sunt în 01-cercetare/ din depozit.
Modelul de date și cartografia digitală¶
- Thomas K. Peucker și Nicholas Chrisman, „Cartographic Data Structures”, The American Cartographer 2, nr. 1 (1975): 55–69, https://doi.org/10.1559/152304075784447289. Modelul topologic (muchii → fețe) pe care îl folosește MapQuilt.
- M. R. G. Conzen, Alnwick, Northumberland: A Study in Town-Plan Analysis, Institute of British Geographers Publication 27 (Londra: George Philip, 1960). Parcela ca unitate a analizei morfologice.
- Anne Vernez Moudon, „Urban Morphology as an Emerging Interdisciplinary Field”, Urban Morphology 1, nr. 1 (1997): 3–10.
- Martin Fleischmann, „momepy: Urban Morphology Measuring Toolkit”, Journal of Open Source Software 4, nr. 43 (2019): 1807, https://doi.org/10.21105/joss.01807. Ce se poate măsura pe rezultatul vectorizat.
Vectorizarea hărților istorice¶
- Yizi Chen, Joseph Chazalon, Edwin Carlinet, Minh Ôn Vũ Ngoc, Clément Mallet și Julien Perret, „Automatic Vectorization of Historical Maps: A Benchmark”, PLOS ONE 19, nr. 2 (2024): e0297361, https://doi.org/10.1371/journal.pone.0297361. Filtru de muchii → watershed → partiție plană, cu „garanții topologice puternice”; linia pe care o urmează motorul etapizat.
- Xue Xia, Daiwei Zhang, Wenxuan Song, Wei Huang și Lorenz Hurni, „MapSAM: Adapting Segment Anything Model for Automated Feature Detection in Historical Maps”, IEEE Transactions on Geoscience and Remote Sensing 63 (2025), https://doi.org/10.1109/TGRS.2025.3528931. Măștile învățate ca sursă de muchii, nu de poligoane finale.
- Zsombor Bartos-Elekes, Gábor Timár și Ioan Rus, „Historical Cadastral Maps of Cluj-Napoca”, Geographia Technica nr. 1 (2008): 1–6. Georeferențierea planurilor cadastrale românești.
- IOGP, „EPSG:3844 Pulkovo 1942(58) / Stereo70”, https://epsg.io/3844.
Prelucrarea imaginii¶
- Nobuyuki Otsu, „A Threshold Selection Method from Gray-Level Histograms”, IEEE Transactions on Systems, Man, and Cybernetics 9, nr. 1 (1979): 62–66, https://doi.org/10.1109/TSMC.1979.4310076. Pragul liniilor groase / subțiri.
- T. Y. Zhang și C. Y. Suen, „A Fast Parallel Algorithm for Thinning Digital Patterns”, Communications of the ACM 27, nr. 3 (1984): 236–239, https://doi.org/10.1145/357994.358023. Subțierea scheletului (implementare NumPy în plugin).
- Nghia T. Vo, Robert C. Atwood și Michael Drakopoulos, „Superior Techniques for Eliminating Ring Artifacts in X-Ray Micro-Tomography”, Optics Express 26, nr. 22 (2018): 28396–28412, https://doi.org/10.1364/OE.26.028396. Detecția dungilor de scaner (T16).
- Fred L. Gadallah, Ferenc Csillag și Elizabeth J. M. Smith, „Destriping Multisensor Imagery with Moment Matching”, International Journal of Remote Sensing 21, nr. 12 (2000): 2505–2511, https://doi.org/10.1080/01431160050030592. Corecția aditivă pe coloană.
- Richard Hartley și Andrew Zisserman, Multiple View Geometry in Computer Vision, ed. a 2-a (Cambridge University Press, 2004). Omografia din patru puncte (DLT normalizat), lanțul de transformare.
- Fred L. Bookstein, „Principal Warps: Thin-Plate Splines and the Decomposition of Deformations”, IEEE Transactions on Pattern Analysis and Machine Intelligence 11, nr. 6 (1989): 567–585, https://doi.org/10.1109/34.24792. Restul TPS mărginit din lanț.
Măsurarea rezultatului¶
- Alexander Kirillov, Kaiming He, Ross Girshick, Carsten Rother și Piotr Dollár, „Panoptic Segmentation”, în CVPR 2019 (IEEE, 2019), 9396–9405, https://doi.org/10.1109/CVPR.2019.00963. PQ = SQ × RQ, metrica pe clase față de etalon.
- OpenStreetMap contributors, OpenStreetMap, https://www.openstreetmap.org, ODbL. Amprentele clădirilor ca indiciu de clasă și martor pentru rotirea foii; axele străzilor pentru fețele stradă (T20); spațiile verzi în trei categorii (T21).
- Overture Maps Foundation, Overture Maps data (clădiri, transport), https://overturemaps.org, ODbL / CDLA-Permissive-2.0. Sursă externă opțională.
- RapidOCR, https://github.com/RapidAI/RapidOCR. Recunoașterea codurilor (ONNX, pe procesor).
Instrumente¶
- QGIS Development Team, QGIS Geographic Information System, https://qgis.org. GDAL/OGR, https://gdal.org. Shapely, https://shapely.readthedocs.io. OpenCV, https://opencv.org. FastAPI, https://fastapi.tiangolo.com.
Jurnalul versiunilor (changelog)¶
Din metadata.txt al pluginului, cea mai nouă versiune prima (în engleză).
- 0.3.352026-11-06 — Engine 0.10.1: a thick line is one object (short pieces between thick edges are thick; a free end of a thick edge is bridged to the thick edge ahead when ink remains in the gap); text by experience - letters are recognised by the size and rhythm of the codes OCR read (letters glued to lines, digits OCR skipped, hollow digits) and taken out of the ink before the skeleton, the line a code stands on staying whole.
- 0.3.342026-11-05 — Engine 0.10.0: no face on a line - the gap of a double line (a wall drawn with its thickness, a party wall, a double fence) goes to the building beside it or is split between its neighbours; hatched ladders (exterior stairs, hatched strips) become one face of the new class amenity (Review key M, teal); squared outlines no longer fall back to the older method when a simplified edge crosses another (that edge keeps its vertices), and short off-axis segments of 90/45 buildings collapse into true corners (corner_cut_m 3 m).
- 0.3.332026-11-05 — The tabs take the whole dock: the sheet list, the journal line and the log moved to the end of the Settings tab; under the tabs one line (sheets selected, status). Extract selected with nothing selected: click the sheets on the map, Enter / Space extracts them, Esc cancels (the box at the cursor says so). Move sheet: Enter / Space drops the sheets in hand where they are, so a turn is click, R, Enter.
- 0.3.322026-11-05 — Fix: Extract and Shapes on a project whose work.gpkg was written by a plugin older than 0.3.29 (no shape / shape_set / arcs_json columns) failed with KeyError 'shape' when copying the other sheets' faces; missing columns are now read as empty.
- 0.3.312026-11-05 — Engine 0.9.1: a face holding both a building code (C) and a parcel code (CAT, CC, CR, DP...) is a building when its outline is thick or an OSM footprint covers it - institutional buildings and blocks carry their lot code inside the outline - and a parcel otherwise (a lot whose house outline is not closed); before, such faces fell to the later rules and the university buildings on Copou came out as parcels. DP (domeniu public) is read as a lot code, no longer as a street: it is written beside the building code of institutions. Labels can also be given to the Engine from outside (extra_labels).
- 0.3.302026-11-05 — Arcs as true arcs (Engine 0.9.0, T23 step D): an arc found on a building is a condition of the least-squares adjustment - its vertices are put on one circle whose centre and radius are solved with them, the walls leaving it tangent; the face keeps its arcs (arcs_json) and Export DXF writes such faces as polylines with bulges, read as arcs by Rhino and AutoCAD.
- 0.3.292026-11-05 — Shape families and presets (Engine 0.8.0, T23 steps B and C). Every outline is read as lines and arcs of a circle; every building gets a family - 90 degrees, 45 degrees, free or curved - written on the face (shape, arcs); arcs are kept as arcs, 45-degree walls on their diagonals, oblique walls in their own direction. Settings > Drawing: presets Mixed (default; each building chooses), Planned 90, Planned 90 + 45, Organic, Curved, plus the older modes. Review: keys 9 / 4 / F / O set a family by hand; Shapes sends it to the Engine and it survives later runs.
- 0.3.282026-11-05 — Shapes (Vector tab; Engine 0.7.0, T23 step A): the squaring becomes a step of its own, repeatable without extracting. Extract keeps the raw faces of every tile in the project (cache/raw/<sheet>/); Shapes sends them through the Engine's squaring step alone (/v1/regularize) with the outline mode of Settings > Drawing and replaces the sheet's faces in seconds, review decisions carried over to the overlapping faces, edges and labels untouched; stitched faces of the sheet are dropped (run Stitch again).
- 0.3.272026-11-05 — Squared building outlines (Engine 0.6.0, T22): a least-squares adjustment of every vertex of the drawing at once, junctions included - walls within 12 degrees of the building's axis exactly parallel or perpendicular, corners on lot limits square too, neighbours stay joined, no vertex moves more than 1 m. Settings > Drawing > Building outlines: Squared (default), Straightened (the older T12 method), As drawn. Țicău: 9 vertices per building (reference 8), 62 % of the near-right corners exactly square (Straightened 41 %), same PQ, lot limits no longer pushed (parcel PQ 0.337 vs 0.321). An older Engine falls back to Straightened.
- 0.3.262026-11-05 — Join faces (Vector tab, Edit box): press inside a face, drag onto a neighbour of the same class and release - the two become one (codes of both, buildings counted together, review state edited); green while they can be joined, red with the reason in the box at the cursor when not; gaps up to 0.3 m closed; Ctrl+Z on the map or Undo join puts them back (last 50); every join in the journal.
- 0.3.252026-11-05 — Green spaces in three categories (Engine T21): green_alignment (tree rows, grass strips along streets), green_landscaped (parks, gardens, playgrounds), green_unlandscaped (meadow, scrub, wood). New external source OpenStreetMap green spaces (ticked); a face without a code at least half in one category gets that class, a coded parcel keeps its class and gets the category in the attribute 'green'. Own green sources with a category field. Review: buttons and keys 1 / 2 / 3; each category styled and written as its own DXF layer.
- 0.3.242026-11-05 — The progress of a long step is drawn on the button that started it (blue fill, percent, what it does now in a second line); a click on that button stops it; meanwhile the other buttons wait; on another tab the percent is on the tab of the running button. The tab bar stays in place: every tab page scrolls by itself, and the tabs, the sheet list and the log share the dock through splitters. Engine T20b: OSM centrelines no longer spoil the drawing where they ride on kerbs and sidewalks - street faces are united only across lines the centreline crosses at 45 degrees or more, a band under 3.5 m is never a street by the centreline alone, sidewalk strips are not joined to the carriageway.
- 0.3.232026-11-05 — Dock made easier to use. Steps numbered 1-7 in their real order (Georeference before Assemble), each with its state written on the button (12/40 frames, 2 red seams...) and the next step outlined. Raster tab in three boxes: Steps, View (Show rasters as a toggle, Satellite + OSM, opacity), Corrections (Check sheets, Move sheet, Undo last move, Refine, Check placement) with QGIS icons. One selection bar under the tabs (Select on map, how many selected, clear), and the buttons say how many sheets they take (Extract 3 selected). Questions name their answers on the buttons instead of Yes / No / Cancel; Move sheet and Check placement turns are applied at once and put back by Undo last move (Ctrl+Z on the map, last 20). Move sheet / Select on map: a small box beside the cursor lists the keys - R turns 90 (with a selection it picks it up and turns it), Shift+R back, G, A all, Alt+A none, Esc, Ctrl+Z. Review appears after Extract, with keys (N next, Enter confirm, B P A S class, X reject, Esc). Progress bar and Stop only while a step runs; the log can be made taller; a legend under the sheet list. Engine: Test connection, Start Engine / Stop Engine on their own row; ? opens the manual without freezing QGIS; Rhino sync buttons in a 2 x 2 grid.
- 0.3.222026-11-05 — External sources (⚙ Settings): building footprints and street centrelines chosen per project - OpenStreetMap buildings and streets (ticked), Overture Maps buildings and streets (through the Engine), and your own: WFS, ArcGIS FeatureServer, OGC API Features, an Overpass query, or any file / QGIS data source; Add / Edit / Remove, Import / Export as .json to give to others, Shared downloads the list other users sent in. Every answer cached per sheet in the project. Streets (Engine T20): a face the centreline runs through, along its length and away from its edges, is a street, and the street faces of one street (same name) are united with their sidewalk strips, one street one face per tile.
- 0.3.212026-11-04 — The dock in tabs: the gear (Settings: project, scans folder with Set..., Engine local / cloud with its own address, Check with what the Engine answered, Start; work mode Online / Offline, offline = OSM footprints from the project cache only and no web layers), Raster, Vector (with the Review box), Rhino sync (only when the Rhino Sync plugin is installed), and a '?' button beside the tabs that opens the manual shipped in mapquilt/help (generated from 06-plugin/help with build_help.py: sections, literature, changelog; also published with GitHub Pages).
- 0.3.202026-11-04 — Check placement (Raster column): is each scan the right way up in its cell? The OSM building outlines are laid over the scan's proxy for the four quarter turns; the turn that puts them on ink wins (lift against chance). Sheets where another turn clearly wins are listed and, after Yes, turned (label quarters, as Move sheet + R) and georeferenced again; a sheet no turn fits is reported as probably in the wrong cell. Selected sheets, or all placed sheets; journal step 'placement'.
- 0.3.192026-11-04 — Refine / Extract selected with nothing selected switch Select sheets on and say to click the sheets on the map, then press the button again.
- 0.3.182026-11-04 — Select sheets (next to Extract selected): select sheets directly on the map like Move sheet - click, Shift+click to add or take out, drag a rectangle, Esc to clear; orange outlines, the sheet list follows and keeps it for Extract selected and Refine.
- 0.3.172026-11-04 — Extract selected (and Refine, Move sheet) take the selection wherever it was made: the dock's sheet list, the trapezoids of 'MapQuilt sheets' selected with QGIS's own selection tools, the 'sheet …' rasters selected in the Layers panel.
- 0.3.162026-11-04 — Untidy file names: the nomenclature is read once the name is tidied ('….tif.jpg', '…', ' - Copy', ' (2)', 'bis', '' for '-'), else by a fuzzy match with the holes and neighbours when one is clearly closest; Import applies the tidied ones (to be checked), skips copies of a sheet already in the project; Check sheets lists copies, the names read or matched, the probable file of each hole, no longer counts as holes the cells covered by sheets of another scale, and offers to apply the sure names.
- 0.3.152026-11-04 — Georeference with sheets already placed asks whether to place only the others (new sheets, frames confirmed again, chains in another CRS); headless the default is only those. Placing all again keeps every Move sheet / Refine correction (they are its input).
- 0.3.142026-11-04 — DXF sheets: Import takes DXF files (one per sheet, named by nomenclature, frame kept); each is drawn once as a picture in its own units (rendered/<id>.tif; the scan's pixels on the Iași tracings), so Rectify, Georeference, Show rasters, Move sheet, Refine and the seam check work on it as on a scan; Rectify proposes the neat line from the DXF's own straight lines (tilt removed, the line where the drawing stops); Extract takes the DXF lines cut at the frame through the chain (edges 'line', faces closed by them; no Engine); Stitch also joins line ends across the seams; Export DXF writes the lines. Export fix: layers copied to memory first (QgsDxfExport + GeoPackage in WAL mode gave 'unable to open database file' and an empty DXF), explicit extent, empty label layer left out.
- 0.3.132026-11-04 — Refine (Raster column): the sheet selected in the list (or the sheets with red seams) re-measured against its placed neighbours through the Engine's seam matcher; first the drawn line of each side is chosen among Rectify's candidates by the seams, then the four frame corners (pixels) are fitted robustly on half of the matched lines and kept only when the other half improves clearly; neighbours and grid never move; old frame kept in quality.frame_before_refine; asks before keeping; seams written on both sheets. Move sheet: R turns a whole block about its centre, the sheets going round it cell by cell (cells are not squares) and every scan turning with it. Extract all / Extract selected (the sheets selected); the sheet list selects several (Shift = range, Ctrl = one more) and follows the Shift+click selection of Move sheet on the map; Refine works on the selection.
- 0.3.122026-11-04 — Move sheet moves several sheets as a block: Shift+click adds a sheet to the selection (orange) or takes it out, a click on a selected sheet (or G) grabs them all, they move by one offset and the nearest corner of any of them snaps to the grid around each sheet and to the corners of the sheets outside the block; R turns every scan in its outline; one drop, one confirmation for the whole block (changes, nomenclature clashes after the move, sheets to extract again), one journal entry. Dock: apply_moves(moves) (apply_move kept for one sheet).
- 0.3.112026-11-04 — Move sheet (Raster column): a Blender-style grab for the few sheets placed in the wrong cell or turned: click a sheet, the scan follows the mouse drawn from its proxy, its nearest corner snaps to the corners of the grid cells and of the other sheets (markers on the map), R turns it 90°, click to drop; on a grid cell the sheet takes that cell's nomenclature and quarter turn (old name kept as moved_from) and is georeferenced again, elsewhere it keeps hand-set corners; a sheet without nomenclature is taken from the sheet list and dropped cell by cell (S = grid scale). OSM building footprints kept in the project (cache/osm_buildings): a sheet is fetched from Overpass once, Extract runs again offline, and after one Overpass failure the rest of the run reads the cache only. Extract keeps EngineClient.tile_concurrency() tiles in flight.
- 0.3.102026-11-03 — Faster Extract on the CPU, same geometry (T18): the Engine's staged extraction vectorised (spur pruning, per-component tests on crops, buffers computed once) and OCR read in worker processes (python -m mapquilt_engine --workers auto|N, default 4); sheet 4-c 711 s -> 154 s, identical output; extract_sheet(workers=k) keeps k tiles in flight for an Engine that reports concurrent_tiles (EngineClient.tile_concurrency); an Engine slow to answer /health while starting is reported unavailable instead of raising TimeoutError. Restart the Engine to get the speed-up.
- 0.3.92026-11-03 — Status bar (text, percent, Stop) moved above the sheet list, visible without scrolling.
- 0.3.82026-11-03 — Stop button in the status bar: the running step (Import, Rectify auto, Assemble seams, Georeference, Show rasters, Extract, Stitch) stops after the current tile / sheet / seam, what is finished stays saved, the journal records where it stopped and the progress line says the step resumes; Extract pressed again offers to resume with the sheets not yet extracted (the sheet in progress at the stop is redone).
- 0.3.72026-11-03 — "Check sheets" (Raster column): the scans folder compared with the project; lists image files without a sheet in the project (and names that are no nomenclature), rescanned files, sheets whose original is not found, sheets without frame / chain / extraction, and the holes in the grid (nomenclatures named as neighbour by two or more sheets but absent); log + audit.txt in the project folder.
- 0.3.62026-11-03 — Dock in two columns, Raster (Import, Rectify, Assemble, Georeference, Show rasters + opacity, Satellite + OSM) and Vector (Extract, Stitch, Export DXF); Review and Rhino sync collapsible (collapsed by default); project journal: every step run is recorded in project.json with date and plugin version (progress line under the steps, last run in each button's tooltip), the last project is reopened when QGIS starts; Rectify has Previous (back to the sheet just confirmed or skipped, correct and confirm again); Import skips the sheets already in the project (a sheet found later is imported from the same folder, the others keep their frames; a rescan replaces the old sheet); Extract offers to run only the sheets not yet extracted.
- 0.3.52026-11-03 — Assemble measures the seams: for every adjacent pair with a confirmed frame and a chain, the Engine (/v1/match/pair, line-segment matcher of T-cusaturi) reports how well the drawn lines continue across the shared edge; layer "MapQuilt seams" (green median <= 0.75 m, yellow <= 1.5 m, red worse or < 5 matched lines, labelled with the median). The residual is the drawing's own precision at the seam; no geometric adjustment is applied; a red seam means a wrong frame or nomenclature on one of the two sheets.
- 0.3.42026-11-03 — Status bar at the bottom of the dock: what the plugin is doing and the percentage (Import, Rectify auto, Georeference, Assemble, Show rasters, Extract per tile, Stitch per seam, Export).
- 0.3.32026-11-03 — "Show rasters" button + opacity slider: the scans of every sheet with a confirmed frame (georeferenced on the fly) are loaded clipped to their trapezoid in the group "MapQuilt rasters", a small proxy per sheet at city scale and the full scan under 1:4000, to check the placement against the map.
- 0.3.22026-11-03 — Frame proposal: scanner streaks suppressed before candidate extraction (both-ends rule on the ink mask, after Vo et al. 2018 / moment matching), candidate grouping fixed, strength tie-break; 8 -> 11 of 12 sides right on the ICPROM sheets.
- 0.3.12026-11-03 — Rectify: the frame is four independent corners (trapezoid, no crop), corner views with a fixed cross (drag the image, wheel zoom), AUTO and SEMI-AUTO (pattern learned from the first hand-confirmed sheet); sheets displayed clipped to their frame trapezoid (warped VRT with cutline).
- 0.3.02026-11-03 — All seven steps wired: Rectify dialog (frame proposal, four editable lines, corners at full resolution, click-to-set), Assemble (sheet footprints by nomenclature coloured by status, neighbours, GCP VRTs of the scans), Georeference writes the VRTs, Stitch merges faces across sheet seams within the seam tolerance; compact dock (step buttons with status dots in a flow layout, narrower minimum width); a geographic target CRS is switched to EPSG:3844. Verified headless in QGIS 4.2.3 on the three ICPROM sheets.
- 0.2.02026-10-31 — Extract wired end to end: tiles through the Engine (staged, with OSM footprints as class prior), merge into sheet faces/edges/labels, work.gpkg with class styling, review queue ordered by uncertainty (Confirm / Building / Parcel / Annex / Street / Reject), DXF export with one layer per class and a quality report; satellite + OSM reference layers; Rhino live sync box. Verified headless in QGIS 4.2.3 on sheet 4-c.
- 0.1.02026-10-23 — core modules: nomenclature, transform chain, sheet registry, frame proposal/confirmation, planar graph with seam stitching, Engine client; dock with the seven steps (Import, Rectify, Assemble, Georeference, Extract, Stitch, Export).