02CadGis
Architecture & Design
Overview & Design Philosophy
02CadGis converts CAD and GIS exchange files into clean, styled GeoPackage layers. It is built for planning, cadastral, and municipal workflows where AutoCAD DWG/DXF, Netcad NCZ/NCA, KML/KMZ, GML, GeoJSON, CSV/TSV, SpatiaLite, GPX, DGN, FileGDB, and Personal GDB (.mdb) files must become QGIS data quickly and without data loss.
The plugin rests on five principles:
- No silent data loss. Every readable feature is written. Problematic geometries are repaired, not dropped. Empty entities are filtered with a logged warning, never a fatal error.
- Selective conversion. The layer tree shows what is in the file before conversion. Unchecked layers cost zero decode time.
- Format-native parsers where GDAL falls short. The plugin carries its own NCZ parser, DGN v8 reader, CSV sniffer, and MS Access reader — each activating when the corresponding GDAL driver is absent or incomplete.
- Turkish planning data is a first-class citizen. The CRS detector knows every EPSG code in the Turkish survey projection families. The MPYY transfer writes an imar plan's tabaka into MPYY 1.1.7 feature types and draws them with the Ministry's UIP / NIP / CDP styles. The mojibake repairer recovers Turkish characters from mis-encoded CAD layers.
- Progressive disclosure. The dock shows only the controls relevant to the selected input type. Drag-and-drop auto-detects format and switches tabs.
Three-Engine Architecture
| Engine | Formats | Core Module | Parser |
|---|---|---|---|
| CAD | DXF, DWG, DGN | core/cad_engine.py | GDAL/OGR with CadCleanupEngine post-processing. DWG: 3-tier fallback (GDAL → ODA → LibreDWG). DGN: GDAL → pure-Python fallback. |
| GIS | KML, KMZ, GML, GeoJSON, CSV/TSV, SpatiaLite, GPX, FileGDB, Personal GDB | core/gis_engine.py | GDAL/OGR with format-specific pre-processing. CSV sniffer for delimited text. KMZ multi-document extraction. GDB live zero-copy mode. MS Access pure-Python reader. |
| NCZ v2 | NCZ, NCA | core/ncz_engine/v2/ | Independent block-oriented binary decoder: lazy catalog → selective decode → index cache. Five cooperating modules: binary reader, parser, geometry decoder, attribute decoder, block catalogue. |
Dock Panel & Drag-and-Drop
The dock has three stacked panels: CAD & GIS Converter (source selection, layer tree, output options), Netcad NCZ/NCA Importer (multi-file, metadata, CRS, MPYY transfer), and CAD & GIS Exporter (DXF/KML/KMZ/MBTiles output). Dropping any supported file onto the dock auto-detects the format and switches to the correct panel. Session preferences — target path, CRS, cleanup options, last-used folders — persist via QSettings.
Theoretical Background
CAD-to-GIS Conversion Theory
The conversion of data between Computer-Aided Design (CAD) and Geographic Information Systems (GIS) environments constitutes a well-recognised interoperability challenge. CAD systems model physical space through geometric primitives — points, lines, arcs, polylines, circles, and blocks — organised into named layers that often encode functional categories implicitly. GIS, by contrast, represents geographic phenomena as features with explicitly typed attribute schemas, governed by a coordinate reference system and stored in geo-relational or object-relational databases [Zhu et al. 2018; Liu et al. 2017].
The fundamental discrepancy arises from divergent data modelling paradigms. CAD employs a drawing-centric model in which geometry is the primary artefact and attributes (colours, line weights, layer names, text annotations) are decoration. GIS employs a feature-centric model in which each spatial object carries a structured set of properties and belongs to a formally typed geometry class. Bridging these paradigms requires solving four sub-problems:
- Geometry extraction — reading coordinate sequences from binary or text formats and constructing valid OGC Simple Features geometries.
- Layer/feature mapping — assigning CAD entities to GIS feature classes based on layer names, block references, or attribute tables.
- Coordinate transformation — resolving the source CRS (often implicit or locally defined in CAD) and transforming to a target CRS suitable for GIS analysis.
- Semantic enrichment — populating GIS attribute tables from CAD annotations, block attributes, embedded tables, or external catalogues.
The C2G framework proposed by Al-Sabban et al. (2022) formalises this as a five-stage pipeline: Pre-processing, Geometry Conversion, Attribute Mapping, Quality Assurance, and Post-processing. 02CadGis implements each stage, with the quality-assurance stage embodied in the collinear simplification engine and the feature-count verification gates that prevent silent data loss [Al-Sabban et al. 2022].
Let \(C = \{(\gamma_i, \ell_i, \alpha_i)\}\) be a CAD drawing, where \(\gamma_i\) is a geometric primitive, \(\ell_i \in L\) its layer assignment from the set of drawing layers \(L\), and \(\alpha_i\) its attribute vector (colour, line weight, text). A CAD-to-GIS converter is a function \(f: C \to G\) where \(G = \{(F_j, A_j)\}\) is a set of GIS feature classes \(F_j\) (each carrying a homogeneous geometry type and a CRS) with attribute schemas \(A_j\), such that every \(\gamma_i\) is assigned to exactly one \(F_j\) and its geometric fidelity is preserved within floating-point tolerance \(\varepsilon\).
Coordinate Reference Systems in CAD/GIS Conversion
Coordinate Reference Systems (CRS) present the most consequential failure mode in CAD-to-GIS conversion. A CAD drawing stores coordinates as absolute numeric values in a local Cartesian space, often with no explicit CRS metadata. When the drawing represents a real-world site, those coordinates are in some projected coordinate system — but identifying which one requires external knowledge.
In Turkish planning practice, the situation is especially acute. The national surveying infrastructure uses two datums (ED50 and TUREF/ITRF96) with two projection conventions (Transverse Mercator with 500,000 m false easting, and 3-degree Gauss-Krüger with zone-prefixed easting), spanning seven central meridians (27° through 45°). This yields 28 possible EPSG codes for projected data, plus UTM variants. A silent wrong CRS shifts data by 100–200 metres — enough to place buildings in the wrong parcel, or a municipal boundary on the wrong side of a river.
The PROJ library formalises coordinate operations as transformation pipelines: chains of elementary steps (inverse projection, datum shift via Helmert or grid, forward projection) each consuming the output of its predecessor [Knudsen & Evers 2017; PROJ Contributors 2024]. The plugin's CRS detector operates before this pipeline, determining the source CRS from drawing metadata and coordinate statistics.
Given a set of \(n\) coordinate pairs \(\{(x_k, y_k)\}_{k=1}^n\) drawn from a Turkish survey projection, and optionally a projection text \(T\) from drawing metadata, determine the unique EPSG code \(e^*\) such that the datum (ED50 or TUREF), projection type (TM or GK), and central meridian \(m \in \{27, 30, 33, 36, 39, 42, 45\}\) are correctly identified. The problem is underspecified when \(|T| = 0\) (no metadata) and the easting does not encode the zone (TM form, 6-digit easting), because easting alone cannot determine the central meridian.
Symbology & Cartographic Standards
The visual styling of geospatial data is governed by the OGC Symbology Encoding (SE) standard (OGC 05-077r4), which defines an XML grammar for specifying how features and coverages are portrayed on maps [OGC 2006]. SE describes five symbolizer types — PointSymbolizer, LineSymbolizer, PolygonSymbolizer, TextSymbolizer, and RasterSymbolizer — each applying a graphic (stroke, fill, marker, font) to a feature filtered by OGC Filter Encoding expressions.
The Turkish Ministry of Environment, Urbanisation and Climate Change defines an official symbology catalogue for spatial plans (the e-Plan gösterim kataloğu), encoded as Styled Layer Descriptor (SLD) files served from a GeoServer instance [T.C. ÇŞB 2024]. Each rule in this catalogue specifies, per plan type (UIP 1/1000, NIP 1/5000, CDP 1/25,000+):
- Fill — RGB colour with optional opacity for polygon tabaka.
- Stroke — line colour, width, and dash pattern.
- Tarama (hatch pattern) — a raster tile applied as a repeating fill pattern, at its native pixel resolution, per the Ministry's registered tile images.
- Label — font, size, placement for textual annotations.
02CadGis carries that gösterim as the MPYY style bundle under mpyy/ — the Ministry's e-Plan SLDs rewritten to the MPYY 1.1.7 schema, together with the tarama tiles and the plan symbol fonts they reference. The bundle travels inside the plugin: nothing is downloaded and no style server is needed. Resolving a drawing's tabaka onto it is deliberately conservative, because a wrong function is worse than an unresolved one. Each layer name is resolved by an exact match, by a mapping the user confirmed earlier and the plugin remembered, or by a spelling rule that cannot change the meaning (a copy number, an export suffix, the _ALANI ending, a PL_ prefix). Anything else is only proposed — ranked word by word against the Ek-1e function names and MPYY codes — and waits for confirmation. A tabaka that resolves to nothing receives the empty-code-cell policy (cells left blank, upper group set to DİĞER PLAN ALANLARI) rather than an invented code.
CAD vs. GIS Data Models
The semantic gap between CAD and GIS data models has been extensively studied in the context of BIM/GIS integration [Zhu et al. 2018; Sani & Abdul Rahman 2018]. The table below summarises the key structural differences that a converter must bridge.
| Aspect | CAD (DXF/DWG/DGN/NCZ) | GIS (GeoPackage/Shapefile/PostGIS) |
|---|---|---|
| Geometry model | Drawing primitives: LINE, CIRCLE, ARC, ELLIPSE, SPLINE, TEXT, MTEXT, INSERT (block), POLYLINE, 3DFACE, HATCH | OGC Simple Features: Point, LineString, Polygon, Multi* variants. Curved geometries (CircularString, CurvePolygon) only in extended profiles. |
| Coordinate space | Local Cartesian; CRS information is optional, often absent or vendor-specific (e.g. Netcad SRS id, not EPSG). | Explicit CRS via EPSG/SRID codes. Every geometry carries its CRS or inherits from the layer. |
| Layers as semantics | Layers are drawing organisational tools. A single layer may contain points, lines, polygons, and text simultaneously. Functional meaning is encoded in layer names. | Layers (feature classes) are homogeneous by geometry type. Meaning is encoded in attribute columns with formal types (integer, real, text, date). |
| Attributes | Implicit: colour (ACI/ARGB), line weight, linetype, layer name, block attributes, extended entity data (XDATA). | Explicit: user-defined schema of typed columns, populated per feature. Null values are legal and meaningful. |
| Text | Independent entities with insertion point, rotation, height, and content. Not linked to any geometry. | Labels derived from attribute columns or expressions; rendered by the symbology engine, not stored as geometry. |
| Blocks / Cells | Reusable geometry groups inserted at multiple locations with individual scale, rotation, and attributes. | No direct equivalent. Must be decomposed into constituent geometries or stored as a related table with point references. |
| Topology | Optional; polylines may be open or closed by convention. No enforcement of planar partition. | Optional but well-supported; topology rules (must not overlap, must not have gaps) are enforceable. |
Coordinate Operations and Transformation Accuracy
Coordinate transformation between projected CRS is performed by the PROJ library, which implements geodetic coordinate operations as transformation pipelines: chains of elementary steps (inverse projection → datum transformation → forward projection) that are composed at runtime [Knudsen & Evers 2017]. The accuracy of the transformation depends on the quality of the datum transformation parameters.
In Turkish practice, two datum transformation scenarios are prevalent:
- ED50 to TUREF/ITRF96. These datums differ by approximately 180–200 metres over Turkish territory. The transformation requires a 7-parameter Helmert transformation (3 translations, 3 rotations, 1 scale factor) or a grid-based correction. PROJ provides Helmert parameters for ED50-to-WGS84 and ITRF-to-WGS84 chains; the compound ED50-to-TUREF transformation is computed by chaining through WGS 84 as the pivot datum. Grid-based transformations (e.g. using the Turkish national geoid model TG-03) provide higher accuracy but require the grid file to be installed in PROJ's grid directory.
- 3-degree TM to 3-degree GK (same datum). These are mathematically equivalent projections differing only in false easting (500,000 m vs. zone × 1,000,000 + 500,000 m). The transformation is a simple easting offset: no datum shift is involved. The plugin handles this by selecting the correct EPSG code for the target CRS rather than computing a coordinate transformation.
The plugin's CRS detector avoids the transformation accuracy problem entirely: it identifies the correct source CRS so that PROJ can apply the best available transformation, rather than guessing and potentially applying a wrong or inaccurate shift. When the detector cannot determine the datum with confidence (projection text absent, coordinates in TM form without zone prefix), it leaves the CRS empty rather than assuming TUREF, because a 200-metre error from a wrong datum is far worse than asking the user to verify.
For 2D GIS analysis, the plugin flattens Z coordinates via dropZValue(). Vertical datums (orthometric heights from mean sea level vs. ellipsoidal heights from the reference ellipsoid) are not transformed; Z values are preserved as-is when present, and dropped only when the target GeoPackage layer requires 2D geometry. The GeoPackage standard supports Z and M coordinates in its geometry encoding, but many QGIS analysis tools expect 2D input, making flattening the pragmatic default.
Technical Formulation
Conversion Pipeline Formalization
The 02CadGis conversion pipeline can be expressed as a composition of five transformations. Let a source file \(S\) produce an ordered set of intermediate representations:
where:
- Read (\(\mathcal{R}\)): Parse the source format into a set of layers \(L_k\) each containing an ordered multiset of geometric entities \(\Gamma_k\). For GDAL-supported formats, \(\mathcal{R} = \text{ogr.Open}(S)\). For NCZ, \(\mathcal{R} = \text{NczCatalog}(S.\text{bytes}).\text{index}()\). For delimited text, \(\mathcal{R} = \text{sniff\_delimited\_dataset}(S)\).
- Split (\(\mathcal{S}\)): For CAD formats, partition the single GDAL entities layer by the
LayerorLevelfield. For non-CAD formats, \(\mathcal{S}\) is the identity. Where a CAD layer subset contains mixed geometry types, \(\mathcal{S}\) further partitions into homogeneous geometry type groups. - Clean (\(\mathcal{C}\)): Apply
CadCleanupEngine: duplicate vertex removal (\(\varepsilon_c = 10^{-4}\) map units) followed by collinear simplification (see below). - Transform (\(\mathcal{T}\)): Resolve source CRS \(\text{CRS}_S\) via the detection algorithm, then apply \(\text{QgsCoordinateTransform}(\text{CRS}_S, \text{CRS}_T)\) to all coordinates.
- Export (\(\mathcal{E}\)): Write each homogeneous layer to a GeoPackage table via
QgsVectorFileWriterwithCreateOrOverwriteLayersemantics, applying attribute schema expansion and mojibake repair. When TR-Only MPYY Style is enabled this stage is replaced entirely: the features are written into an MPYY workspace GeoPackage by function rather than by tabaka (see MPYY Transfer).
Collinear Simplification Algorithm
The collinear simplification implemented in CadCleanupEngine is an iterative greedy algorithm distinct from the Douglas-Peucker polyline simplification [Douglas & Peucker 1973]. While Douglas-Peucker selects a subset of vertices that preserves the line within a perpendicular distance tolerance, the collinear simplifier removes only vertices that lie on or very near the straight line between their immediate neighbours — vertices that contribute no directional information.
A vertex \(v_i\) in a polyline \(P = (v_0, v_1, \ldots, v_{n-1})\) is collinear with tolerance \(\tau\) if the normalised cross product of the incident edge vectors satisfies:
In 2D, \((a_x, a_y) \times (b_x, b_y) = a_x b_y - a_y b_x\). 02CadGis uses \(\tau = 0.02\), corresponding to a deviation angle of approximately \(1.15^\circ\).
The algorithm proceeds iteratively:
Input: Polyline vertices P = [v_0, ..., v_{n-1}], tolerance τ
Output: Simplified polyline P'
1. P' ← copy(P)
2. if |P'| ≤ 3: return P'
3. repeat
4. changed ← False
5. for i = 1 to |P'|-2:
6. compute sin θ_i from P'[i-1], P'[i], P'[i+1]
7. if sin θ_i ≤ τ:
8. remove P'[i]
9. changed ← True
10. break // restart scan after removal
11. until not changed
12. return P'
This algorithm is \(O(kn)\) where \(k\) is the number of vertices removed (at most \(n-3\)). In practice, CAD drawings contain long straight segments with many intermediate construction points, making this pass highly effective — vertex counts drop by 50–90% on typical municipal plan drawings. The simplification preserves polyline topology: endpoints and true corners (where \(\sin\theta_i > \tau\)) are never removed. A preceding duplicate-removal pass (\(|v_i - v_{i-1}| < 10^{-4}\)) handles co-located construction points.
CRS Detection Logic
The CRS detector in core/crs_detect.py implements a decision procedure combining two independent signals: drawing metadata and coordinate statistics. The procedure is formalised below.
Input: Projection text T (optional), sample coordinates C = {(x_k, y_k)}
Output: CRS detection result (epsg, label, confidence, reason)
1. Compute median easting ẽ ← median({|x_k|}) from C
2. Compute median northing ñ ← median({y_k}) from C
3. if ẽ ≤ 180 and ñ ≤ 90: return (4326, "high") // geographic
4. gk_flag ← ẽ ≥ 1,000,000 // zone-prefixed easting
5. Parse T: extract datum d (ED50 / TUREF / WGS84 / None)
6. Parse T: extract zone_width w (3 / 6 / None)
7. Parse T: extract zone_value z (27..45 or 9..15 or 35..38)
8. Compute cm ← central_meridian(z, w)
9. if gk_flag: cm ← int(ẽ / 1,000,000) × 3 // easting overrides text
10. if cm is None and d is None:
11. if not gk_flag: return ("none", "cannot determine zone from 6-digit easting")
12. cm ← int(ẽ / 1,000,000) × 3; d ← "TUREF" // assume modern datum
13. if d is None and not gk_flag: return ("none", "ambiguous datum")
14. epsg ← lookup(d, cm, gk_flag)
15. if ñ ∉ [3,800,000, 4,800,000]: confidence ← "medium"
16. return (epsg, "high" | "medium")
The detector's design philosophy is conservative: when insufficient information exists to name a unique EPSG code, it returns confidence "none" and explains what is missing, rather than guessing. A silent wrong CRS puts data in the wrong place; an explicitly empty CRS forces the user to verify. The northing band check (3.8–4.8M) catches coordinates that are outside Turkey's geographic extent, which typically indicates a non-Turkish projection or a coordinate system error.
NCZ Binary Decoding Methodology
The NCZ Engine v2 employs a two-phase, block-oriented decoding strategy. NCZ files consist of a flat sequence of variable-length blocks, each with a 1-byte kind tag and a 4-byte stored length:
Phase 1 — Index. The file is scanned once. At each block, if the kind is a known geometry block type (21 or 22), a RecordIndex is created storing the block's absolute position, size, geometry type (byte +6), and layer code (byte +7), without decoding any coordinates. If the kind is a container type ({0, 5, 14, 48, 108, 111, 132, 150, 180}), the payload is scanned for embedded geometry records (recognised by a kind byte 21/22 whose bytes at +5 and +6 are equal, confirming the length-prefix echo pattern). Metadata blocks (kind 6, 25, 28) update the accumulating DrawingMetadata.
Phase 2 — Decode. Records whose layer codes are in the selected set are dispatched to the geometry decoder registry. Decoders are registered by numeric type:
| Type | Decoder | Key Offsets |
|---|---|---|
| 1 | decode_point | Position at +8/+16 (northing-first f64 pair); name at G+86/+87 |
| 2 | decode_line | Start at +8/+16; end at size-19/size-11 |
| 3 | decode_circle | Centre at +8/+16; diameter from +50/+66 |
| 4 | decode_arc | Centre at +8/+16; radius at G+86; angles at G+104/+112 |
| 5 | decode_text | Insertion at +8/+16; text at G+97/+98; height at G+86 |
| 6 | decode_symbol | Position at +8/+16; code at G+94; size at G+86 |
| 7 | decode_polyline | Vertex count = (size+1-113-G)/24; vertices at G+113 |
| 9 | decode_compressed_curve | Origin at +8/+16; f32 delta pairs from G+122 |
| 10 | decode_box | Corner at +8/+16; opposite at G+104/+112; rotation at G+120 |
| 11 | decode_map_sheet | Corners at +50/+58 and +66/+74 |
| 12 | decode_triangle | Vertices at +8/+16, +86/+94, +106/+114 |
| 13 | decode_block_reference | Insertion at +8/+16; name at G+86; rotation at G+118 |
| 15 | decode_smart_object | Origin at +8/+16; width/height at +169/+177; angle at +82 (grads) |
Coordinates are stored northing-first (Netcad convention); the QGIS x-coordinate is the second stored f64 value. All reads are bounds-checked by the Cursor class: out-of-range reads return neutral defaults (0, 0.0, empty string) rather than raising, so decoders need no per-field guards. Coordinates outside \([-10^8, 10^8]\) are rejected.
Mojibake Recovery Algorithm
Turkish CAD files suffer from a systematic encoding problem: layer names and text entities containing Turkish characters (ç, ğ, ı, ö, ş, ü and their uppercase forms) are frequently misinterpreted through incorrect codec chains. The term mojibake (Japanese: "character transformation") describes the resulting garbled text.
Three failure modes are common: (a) CAD software writes OEM-codepage bytes (CP1254) that GDAL interprets as UTF-8, producing Latin-1 mojibake; (b) intermediate conversion tools double-encode CP1254 as UTF-8, producing sequences like "PL_KONUT" → "PL_KÜNÜT"; and (c) DXF files use \U+XXXX Unicode escape sequences that must be unescaped.
Input: Raw text string t
Output: Repaired text string t'
1. t' ← unescape_dxf(t) // replace \U+XXXX with chr()
2. if no mojibake markers in t': return t'
3. for src in ("latin1", "cp1252"):
4. for dst in ("utf-8", "cp1254", "iso-8859-9"):
5. try: t_candidate ← t'.encode(src).decode(dst)
6. if t_candidate has no mojibake markers: t' ← t_candidate; goto 8
7. catch: continue
8. // Direct replacement for stubborn byte sequences
9. for (bad, good) in REPLACEMENT_MAP:
10. t' ← t'.replace(bad, good)
11. return t'
The replacement map covers the most stubborn double-encoding patterns: "ç" → "ç", "ö" → "ö", "ü" → "ü", "ÄŸ" → "ğ", "ÅŸ" → "ş", "ı" → "ı", and their uppercase variants. These patterns are the bytewise consequence of CP1254 → UTF-8 double-encoding of Turkish characters and are not naturally occurring in any single encoding.
Geometry Coercion & Type Promotion
CAD layers routinely mix geometry types: a single DXF layer may contain points (text insertion), lines (walls), and polygons (parcels) simultaneously. GIS layers require a single geometry type. The coercion engine resolves this through a hierarchy of conversions:
3D (Z-bearing) geometries are flattened by calling dropZValue(). Curved geometries (CircularString, CurvePolygon) are segmentized via constrainedStraightSegmentedGeometry(). These operations are applied by _coerce_geometry_for_layer() before features are written to memory layers or GeoPackage, ensuring compatibility with the GDAL GeoPackage driver's geometry type constraints.
GML and XML Namespace Handling
GML (Geography Markup Language) is an XML grammar defined by ISO 19136:2007 and updated in ISO 19136-1:2020 for expressing geographical features. Unlike simpler formats (GeoJSON, KML), GML documents carry XML namespace declarations that associate element names with schema definitions. GDAL's GML driver requires these namespaces to be correctly declared and may fail when they are malformed, incomplete, or reference inaccessible schema URLs [ISO/TC 211 2020].
Common GML interoperability failures include: (a) the gml:id attribute being used as a feature ID when the dataset already has a non-integer fid column, causing GDAL to reject features; (b) application schemas defining custom geometry property names that GDAL does not recognise as spatial columns; (c) xsi:schemaLocation attributes pointing to URLs that no longer resolve, causing validation failures that GDAL treats as fatal. The plugin handles (a) by renaming the conflicting fid column to cadgis_fid in GeoPackage output; (b) and (c) are reported as warnings with guidance on pre-processing the GML with an XSLT transform or schema repair tool.
SpatiaLite and GeoPackage: The SQLite Container Duality
Both SpatiaLite and GeoPackage store geospatial data in SQLite database files, but they use incompatible metadata schemas. SpatiaLite records geometry columns in the geometry_columns table with an srid field referencing spatial_ref_sys, using its own spatial indexing (R*Tree over MBR). GeoPackage records geometry columns in gpkg_geometry_columns with an srs_id referencing gpkg_spatial_ref_sys, using the GeoPackage-specific RTree extension [Yutzler & Daisey 2024].
The plugin reads SpatiaLite files as general SQLite sources through GDAL's SQLite driver (which auto-detects the SpatiaLite metadata tables), but writes output exclusively as GeoPackage. This ensures that output files are readable by any OGC-compliant GeoPackage client, not just QGIS. The CRS is always stored in both EPSG authority form (e.g. EPSG:5257) and as a full WKT definition, satisfying both the GeoPackage standard's requirement for authority-based SRS identification and SpatiaLite's preference for PROJ.4/WKT definitions.
Delimited Text: Type Detection and CRS Inference
The CSV sniffer's type detection logic distinguishes between point geometry (X/Y column pairs), WKT geometry (a column containing Well-Known Text strings), and attribute-only tables (no detected geometry). The detection is a cascade of increasing specificity:
Input: Header fields H = [h_0, ..., h_{m-1}], sample data rows S
Output: Geometry profile (x_field, y_field, wkt_field, crs_authid)
1. // Phase 1: WKT column detection (highest priority)
2. for each field h_i in H:
3. if normalize(h_i) in WKT_FIELD_NAMES:
4. wkt_field ← h_i; break
5.
6. // Phase 2: Point geometry detection
7. if wkt_field is empty:
8. for each field h_i in H:
9. if normalize(h_i) in X_FIELD_NAMES and column_values_numeric(S, h_i):
10. x_field ← h_i
11. for each field h_i in H:
12. if normalize(h_i) in Y_FIELD_NAMES and column_values_numeric(S, h_i):
13. y_field ← h_i
14.
15. // Phase 3: CRS inference
16. if x_field and y_field:
17. if normalize(x_field) in {"lon","long","longitude","boylam"}:
18. crs_authid ← "EPSG:4326"
19. elif wkt_field:
20. crs_authid ← "" // CRS is embedded in WKT or must be user-specified
21. else:
22. geometry_type ← "none" // attribute-only table
23. return profile
Numeric validation (_looks_numeric) requires at least one value in the sample to parse as float; a column where all sample values fail to parse is excluded from geometry candidacy. This prevents non-numeric identifier columns from being mistaken for coordinates. CRS inference for point geometry is conservative: only columns with explicitly geographic names (lon/lat/boylam/enlem) receive EPSG:4326; all others leave the CRS unspecified for the user to configure. The WKT path defers CRS detection entirely to the user, since WKT strings may carry their own embedded SRID or may be in any projected system.
CAD Engine
DXF, DWG & DGN Pipeline
The CAD pipeline is: GDAL/OGR read → split by CAD layer → geometry coercion (3D→2D flattening, curve segmentization, single↔multi conversion) → collinear simplification → CRS transform → output.
Layer Splitting & Geometry Coercion
When Split into CAD layers is on, DXF Layer names or DGN Level numbers become separate checkable rows in the layer tree. Geometry coercion handles three compatibility issues: 3D → 2D flattening (Z dropped), curve segmentization (arcs, ellipses, splines → straight segments), and single↔multi conversion (convertToMultiType / convertToSingleType).
Collinear Simplification
The CadCleanupEngine reduces CAD vertex count by 50–90% in two passes: duplicate removal (points within 10−4 map units merged) and collinear removal (iterative — intermediate vertices on straight lines between neighbours are dropped until no more collinear triplets remain). Visual appearance is unchanged; GeoPackage size and render speed improve dramatically.
AutoCAD DWG: GDAL → ODA → LibreDWG
| Tier | DWG Versions | Mechanism |
|---|---|---|
| 1. GDAL libopencad | R2000 and earlier | GDAL's built-in CAD driver reads legacy DWG directly. |
| 2. ODA File Converter | R2004–R2024 | Free CLI tool from Open Design Alliance. Searched in: QSettings, QGIS settings, PATH, environment, Windows registry, common install paths. DWG → DXF via ASCII-safe temp filename → normal DXF read. Interactive setup dialog if not found. |
| 3. LibreDWG | Various | Open-source dwg2dxf fallback when ODA is unavailable. |
DGN v8: Pure-Python Reader
When GDAL's DGNv8 driver is absent, the plugin activates its own pure-Python DGN reader: OLE2 compound document → locate element streams → zlib decompress → parse by element type. Line (type 3), LineString (4), and Shape/Polygon (6) are fully supported. Complex containers and annotations contribute Level/colour/style attributes via placeholder geometry. Elements are grouped by DGN Level — same workflow as DXF.
GIS Engine
KML, GML, GeoJSON, CSV & GDB Pipeline
Format-specific pre-processing → OGR read → layer tree → CRS transform → attribute expansion → output. Each format has tailored pre-processing: KMZ is extracted and every KML document inside is read; KML balloon HTML is expanded into real attribute columns; GroundOverlay elements become georeferenced GeoTIFF files; CSV is auto-sniffed for delimiter, encoding, and geometry columns.
CSV/TSV Auto-Detection
The sniffer samples the first 100 lines and determines: delimiter (comma, tab, semicolon, pipe — most consistent column count wins), encoding (UTF-8 → system locale), X/Y columns (header search for x/lon/longitude/easting and y/lat/latitude/northing with numeric range validation), WKT column (header search for wkt/geom/geometry with WKT keyword check), and CRS suggestion (EPSG:4326 when X∈[−180,180] and Y∈[−90,90]). All values are overridable.
KMZ: Multi-Document & GroundOverlay
Standard OGR reads only doc.kml. 02CadGis extracts the entire KMZ and opens every .kml inside. <GroundOverlay> elements are converted to GeoTIFF via their <LatLonBox> bounds and added as raster layers.
Geodatabase: Live Mode & Catalog Cache
Live mode adds checked layers as zero-copy references — data stays in the .gdb/.mdb file; QGIS reads on demand. Benchmarked at ~0.27 seconds for 4.27M features (two layers from a municipal FileGDB). The catalog cache (core/ogr_catalog_cache.py) fingerprints each file (size + mtime) and caches its layer list locally — reopening an unchanged source is 100×+ faster than reopening the driver.
MS Access (.mdb) Reader
When GDAL's PGeo driver is unavailable, a pure-Python reader opens the .mdb as a Jet database, enumerates spatial tables, and reads features into QGIS layers. Requires the 64-bit Microsoft Access Database Engine ODBC driver.
NCZ Engine v2
Engine Architecture
The v2 engine is a ground-up rewrite — an independent, block-oriented
Netcad binary decoder with zero dependency on Netcad software. It is the
only decoder in the tree: the earlier implementation has been removed, and
core/netcad_parser.py is now a thin first-party facade that
re-exports the v2 result model and readers. Its correctness is guarded by a
synthetic fixture corpus that exercises the decoder paths and both block layouts,
and by an opt-in parity test against a real 8,163-entity municipal drawing.
| Module | File | Role |
|---|---|---|
| Binary Reader | binary.py | Bounds-checked cursor primitives. Every read validates offset and length — no buffer overrun possible. |
| Block Scanner | blocks.py | Walks the block chain and builds the drawing's metadata: layers, the LEX.ST2 style table (colours and pen widths), and the CRS hints. |
| Geometry Decoder | geometry.py | Registry of decoders keyed by entity kind (point, line, polyline, circle, arc, text, block reference, …), with the KIND_* vocabulary and each kind's geometry family. |
| Smart Object Properties | properties.py | Parses the Netcad 8 Smart Object property bag — the source of the zoning values the plan notation and the MPYY transfer read. |
| Attribute Decoder | attributes.py | Decodes @TAB attribute tables stored inside drawings. |
| Index Cache | cache.py | Fingerprinted on-disk cache of the catalog, keyed by file size and modification time and stamped with a cache version. |
| Parser | parser.py | Orchestrator: the two-phase index / selective-decode flow, and parse_file. Reports its backend as a constant. |
The result model itself (NetcadEntity,
NetcadAttributeTable, NetcadParseResult) lives one level
up in core/ncz_engine/model.py, shared by the engine and everything
that consumes it.
Lazy Catalog & Selective Decode
Selecting a drawing reads only the file header + block index. The layer tree (CAD layer names, entity counts, types) is built from the index — near-instant even for large municipal files. Geometry is decoded only for checked layers at import time. A 50-layer drawing where you need 5 costs only the decode time of those 5.
Fingerprinted Cache (~160×)
Layer catalogs are cached to disk, keyed by absolute path + file size + modification time. Reopening an unchanged drawing shows the layer tree from cache — benchmarked at ~160× faster on a real 1.2 MiB municipal file. Auto-invalidates on file change. Manual reset via "Clear cache" button.
CRS Detection: Turkish Projections
A Netcad drawing stores its own SRS id (e.g. SRS=7936) — this is not an EPSG code. The detector combines two signals:
- Projection text → datum (TUREF vs ED50 vs WGS 84) + zone/meridian hint. TUREF and ED50 differ ~200 m over the same ground — coordinates alone cannot distinguish them.
- Easting magnitude → axis convention. 6-digit easting (~500,000) = TM form. 8-digit easting (e.g. 3,542,000) = Gauss-Krüger form (zone baked into easting).
| Family | TM Form (EPSG) | GK Form (EPSG) | Zones |
|---|---|---|---|
| TUREF | 5253–5259 | 5269–5275 | 27, 30, 33, 36, 39, 42, 45 |
| ED50 | 2319–2325 | 2206–2212 | 27, 30, 33, 36, 39, 42, 45 |
| WGS 84 / UTM | 32635–32638 | — | 35N–38N |
| ED50 / UTM | 23035–23038 | — | 35N–38N |
Batch Import, @TAB Tables & Joins
Multiple NCZ/NCA files can be selected simultaneously. By default each file's
layers stay separate, under their own file-name prefix. Build unified upper
layers merges the tabaka into one layer per geometry family, across files if
you are importing more than one. @TAB tables (attribute tables stored
inside the drawing) are decoded and presented alongside CAD layers; checking both
a layer and its matching @TAB performs an automatic attribute join
on entity name or label. Optional geometry metrics add length, area and
centroid fields.
MPYY Transfer (Turkish İmar Plans)
TR-Only MPYY Style Overview
TR-Only MPYY Style is an opt-in mode that turns a Turkish implementation, master or environmental plan from a raw CAD drawing into an MPYY workspace: a GeoPackage whose layers are the MPYY 1.1.7 feature types, written with the plan's code values and drawn with the Ministry's own styles.
It is offered in two places, and it is off by default in both:
| Panel | Control | Applies to |
|---|---|---|
| Netcad NCZ/NCA importer | TR-Only MPYY Style: MPYY structure and styles (UİP / NİP / ÇDP) | Every checked drawing |
| CAD & GIS converter | TR-Only MPYY Style (DXF / DWG): MPYY structure and styles | DXF and DWG sources only; checking it for another format raises a warning and is ignored |
Switching the mode on also changes two neighbouring controls, because the transfer owns the layer structure: Build unified upper layers is disabled and unchecked while the mode is active, and Apply original ARGB colors is locked on. The ARGB lock is not cosmetic — the layers that cannot be transferred are handed back in the drawing's own colours, and those colours have to survive (see Unmatched Layers).
MPYY Styles & Reference Scale
The styling in this mode is MPYY Studio's MPYY UİP / NİP / ÇDP
style set, carried inside 02CadGis under mpyy/. Each level is one
Ministry e-Plan SLD per MPYY feature type, with the Ek-1e catalogue corrections
and the plan symbol fonts those styles reference. Nothing is downloaded at run
time and no style server is involved; the retired e-Plan database
(symbology-style.db) is not read by any code path. Appendix B lists
what the bundle contains.
Plan level. The Plan level selector offers Auto,
Implementation plan – UİP (1/1000), Master plan –
NİP (1/5000) and Environmental plan – ÇDP (1/25,000+).
Auto reads the level from the file name: the marker words
UIP/UYGULAMA/MUIP,
NIP/NAZIM/MNIP and
CDP/CEVRE/MCDP first, then a scale number
(500, 1000, 2000 → UİP;
5000, 10000 → NİP; 25000 and
above → ÇDP). The name is matched with Turkish letters folded, so
ÇDP and CDP both read as an environmental plan.
If a file name says nothing at all, Auto assumes UİP; if the level
still cannot be named, the import stops and says so rather than writing
the plan into the wrong style set.
Reference scale. UİP, NİP and ÇDP are drawn at 1/1000, 1/5000 and 1/25,000, and the styles scale with the view, so the on-screen plan looks like the printed sheet at that scale. Area pictograms are placed at the regulation's 10, 7 and 5 mm, and the legend is scoped to the plan in front of you: it lists only the values the drawing actually uses, not the whole catalogue.
The catalogue. The official tabaka identity — upper group, MPYY function and code, and the geometry the function is defined for — comes from a catalogue generated from the Mekânsal Planlar Yapım Yönetmeliği UİP database. A tabaka the catalogue does not know is given empty code cells rather than an invented code, and is placed in DİĞER PLAN ALANLARI — deliberately the only group name in the output that is not the Ministry's.
Layer-Name Resolution & Confirmation
Everything hinges on answering one question per CAD layer: which MPYY function
is PL_KONUT? The transfer answers it in four ways, and only the
first three can write an MPYY code without a person looking at it:
- Exact. The layer name is a key of the tabaka crosswalk table. Nothing is inferred.
- Confirmed before. The name was ticked in the confirmation table on an earlier drawing and is remembered (see below).
- Spelling rule. The name differs from a crosswalk key only in ways that cannot change its meaning: a trailing copy number (
_2), a Netcad export suffix (_NETCAD,_NETC,_NTC,_NET), the_ALANI/_ALAN/_TESISI/_TESIS/_TESending, thePL_prefix, or a compact versus underscored spelling. A rule is applied only when every rule that fires points at the same key; if two readings are possible, nothing is applied and the layer goes to the confirmation table instead. - Proposal. Anything else is only proposed. A proposal never becomes an MPYY code on its own, however confident the ranking is.
Proposals are ranked word by word against the Ek-1e function names and MPYY
codes: a synonym list, a stop-word list, common layer prefixes, Turkish plural
and possessive endings, run-together names split back into words, and an
inverse-document-frequency weight so that a rare word counts for more than a
common one. Geometry is used as a filter — a line tabaka is not proposed
against a polygon function. If a single word fits more than eight different
functions it is treated as uninformative and yields no proposal at all. Layer
names containing IPTAL or ITIRAZ (cancelled, objected)
are never resolved and never proposed.
The confirmation table. When anything is left unresolved, the import opens TR-Only MPYY Style {UİP/NİP/ÇDP} — match CAD layers. Its columns are Confirm, CAD layer, Geometry, Features, MPYY function (type to search) and Reason, and the reason column states which rule or ranking produced the row. The rows start unticked: a proposal is something you accept, not something you have to remember to reject, so that a drawing full of unrecognised tabaka cannot be transferred wholesale by clicking through. You can tick a proposal, or ignore the ranking entirely and type to search for any MPYY function by hand — doing so ticks the row for you. Rows with no proposal at all are hidden behind Also show the N layer(s) without a proposal. The dialog then offers Confirm ticked and transfer or Transfer without confirming, and the second is a deliberate, informed choice rather than the default.
Remembered mappings. A mapping you confirm is written to a per-user
file, <QGIS profile>/mpyy/tabaka_eslesmeleri.json, keyed by
plan level. The same tabaka name then resolves by itself on the next drawing, so
a municipal spelling you had to confirm once is only ever confirmed once. The
file is written atomically through a rename, so an interrupted write cannot
leave a half-file behind, and it is shared with the other plugins that carry the
same module. MPYY_TABAKA_ESLESME points the file somewhere else —
see Appendix F.
Plan Notation & Carried Zoning Values
An imar plan carries its zoning decisions in text: nizam, kat, TAKS, KAKS / emsal, Hmax, front and side setbacks. The transfer reads them from two places — the notation texts in the drawing and the property bags of Netcad 8 Smart Objects — and writes them into the MPYY fields, but only where the MPYY form accepts the value. A value no MPYY field can hold is dropped, not coerced into the nearest field. Where the drawing states a value more than once, it is kept only if every statement agrees; a contradiction is not resolved by picking one.
Plan notation. Rather than let the MPYY area layers label themselves,
the transfer redraws the planner's own notation where the planner placed it.
Every Smart Object whose properties carry a building-rights or road-width
parameter becomes a point in a <file>_PLAN_NOTATION group,
split into two layers:
| Layer | Carries |
|---|---|
| Building notation | Yapı düzeni (nizam), kat adedi, TAKS and its type, emsal / KAKS and its type, yapı yüksekliği and its type, ön and yan bahçe mesafeleri, and the symbol position — drawn as the Ek-1e building notation (the nizam / kat circle, the TAKS / KAKS circle, E =, Yençok). |
| Road widths | The road width from the Smart Object, drawn as the width in a circle. |
Empty layers are not created. To keep the plan from being drawn twice, the same transfer hides the Smart Object frames in the leftover drawing layers with a layer subset, and switches the building-notation labels of the MPYY area layers off. The plan areas keep their values as attributes either way — only the duplicate labelling is suppressed.
Unmatched Layers, Unfit Features & Pen Widths
Not every layer belongs in the MPYY workspace, and the transfer says so rather than absorbing it. Two things are kept out:
- Layers with no MPYY type — after resolution, confirmation and proposals, a tabaka that still has no function is left alone.
- Features whose geometry does not fit their type — a text or an open line inside a tabaka that transferred into a polygon function, for instance. These are counted per layer and reported.
Both are handed back as one layer-tree group named
<file>_UNMATCHED_LAYERS, drawn in the drawing's own ARGB
colours — which is why that control is locked on in this mode. The
import summary states how many layers and features went there, so the split is
never silent. Nothing is discarded and nothing is guessed: what the MPYY
workspace could not describe is still in front of you, in the colours it was
drawn in, ready to be classified by hand.
Pen widths. Netcad stores a pen width in millimetres per layer, in the
drawing's own style table, and 02CadGis carries it through: every feature gets a
line_width_mm attribute, lines are drawn at that width and polygon
outlines at that width as well. A layer that sets no pen falls back to
0.25 mm — chosen because a heavier default turned every contour and
helper line of a plan bold. In the MPYY transfer the same value fills the MPYY
CizgiKalinligi field, so a feature that keeps its drawing pen in
QGIS keeps it in the MPYY output, and önerilen / korunan / düzeltilen
cephe lines take their width from it.
Parameters
CAD Engine Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
Split into CAD layers | boolean | True | When enabled, each DXF Layer name or DGN Level number becomes a separate checkable row in the layer tree. When disabled, all entities appear as a single layer. |
Collinear simplification | boolean | True | Apply CadCleanupEngine: duplicate vertex removal (< 10−4 map units) followed by iterative collinear vertex removal (cross-product tolerance 0.02). Reduces vertex count 50–90% with no visible geometry change. |
Close polylines | boolean | False | When enabled, polylines whose first and last vertices are within 0.0001 map units are closed into polygons. Useful for CAD drawings where parcels or building footprints are drawn as open polylines. |
Polyline closure tolerance | float (map units) | 0.01 | Maximum gap between polyline endpoints that triggers automatic closure to a polygon. Larger values close more aggressively but may incorrectly close intended open lines. |
ODA File Converter path | file path | (auto-detected) | Path to ODAFileConverter.exe for modern DWG (R2004+) conversion. Auto-detected from QSettings, QGIS settings, PATH, Windows registry, and common install locations. Interactive setup dialog offered if not found. |
DWG target version for ODA | string | "ACAD2018" | Target DXF version for ODAFileConverter. Fallback chain: ACAD2018 → ACAD2013 → ACAD2010 → ACAD2000. Each version is tried in sequence until conversion succeeds. |
GIS Engine Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
Expand KML HTML descriptions | boolean | True | Parse HTML tables and list items from KML <description> balloon content into real attribute columns. Both <tr><td> and <li><b>key</b>: value</li> patterns are recognised. |
Extract GroundOverlay rasters | boolean | True | Convert KML <GroundOverlay> elements to georeferenced GeoTIFF raster layers. Each overlay's <LatLonBox> bounds define the geotransform; CRS is EPSG:4326. |
CSV delimiter | string | (auto-detected) | Field delimiter for CSV/TSV files. Auto-detected from {,, ;, \t, |} by Python's csv.Sniffer with majority-consistency tiebreaking. Manual override available. |
CSV X field / Y field | field name | (auto-detected) | Column names for point geometry coordinates. Auto-detected by matching header field names against known X/Y candidates (x/lon/longitude/easting/boylam/saga and y/lat/latitude/northing/enlem/yukari) with numeric value validation. |
CSV WKT field | field name | (auto-detected) | Column name for WKT geometry. Auto-detected from wkt/geometry/geom/the_geom/shape/wkt_geom. |
CSV source CRS | EPSG code | (auto-detected) | Source CRS for CSV geometry. Auto-set to EPSG:4326 when coordinate field names suggest geographic coordinates (lon/lat). Manual override available. |
CSV encoding | string | utf-8-sig | File encoding. Read with BOM detection (utf-8-sig); errors are replaced rather than raised. |
GDB/MDB Live mode | boolean | False | Load selected layers as zero-copy references instead of converting to GeoPackage. No conversion time or disk space; CRS transformation is not applied. Ideal for browsing large geodatabases. |
OGR catalog cache | boolean | True | Cache multi-layer source catalogs (GDB, MDB, SQLite) locally, keyed by file fingerprint (size + mtime). Controlled by ZERO2CADGIS_OGR_CACHE_DISABLE environment variable. |
NCZ Engine Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
Destination CRS: | CRS | (project CRS) | CRS written to the output layers. Netcad drawings store an SRS id rather than an EPSG code, so the panel preselects one from the drawing's projection text and a sample of its coordinates; the selection is only a preselection and your choice is what gets used. |
Simplify collinear vertices | boolean | True | Drop vertices that lie on the straight line between their neighbours, within tolerance. See Collinear Simplification. |
Clean duplicate nodes | boolean | True | Remove repeated consecutive nodes and near-zero segments left by the drawing. |
Calculate geometry metadata (Area, Length) | boolean | True | Add the geometry metric columns — length, area and centroid — computed from each feature's geometry in target CRS units. |
Polyline Closure Tolerance | double, 0.0–10.0 m | 0.10 m | Vertex gap below which an open polyline is closed into a polygon. Keep it small unless the drawing has known snap gaps: it is the control that decides whether a cadastral parcel closes. |
Apply original ARGB colors and line styles | boolean | True | Draw each layer with the drawing's ARGB colour and its pen width, as a categorised renderer. NCZ colour codes: 0 = by layer, 1 = forced blue, 255 = forced red; layer colours and pen widths come from the drawing's style table. Locked on while TR-Only MPYY Style is active. |
TR-Only MPYY Style: MPYY structure and styles (UİP / NİP / ÇDP) | boolean | False | Import as an MPYY workspace instead of raw CAD layers. See MPYY Transfer. Off by default and intended to stay off for anything that is not an imar plan. |
Plan level: | enum | Auto | Auto (detect from file name), Implementation plan – UİP (1/1000), Master plan – NİP (1/5000) or Environmental plan – ÇDP (1/25,000+). Read only when TR-Only MPYY Style is on. |
Convert text elements to map labels | boolean | True | Turn drawing text into QGIS labels on the layer that owns the text. Point layers keep a subtle anchor marker so an insertion point stays visible. |
Join attribute tables (@TAB) automatically | boolean | True | Link @TAB tables back to geometry where a matching name or label field exists. With it off, tables are still decoded and can be joined by hand. |
Attribute columns: | column set | (all) | Untick a column to leave it out of the written layers. Columns the styles, the labels, the three-layer categories and the MPYY transfer read are locked on and cannot be dropped; unticked columns are discarded only after every step that needs them has run. MPYY layers always carry their own MPYY 1.1.7 columns regardless. |
Build unified upper layers (Polygon / Line / Point) | boolean | True | Merge the drawings' tabaka into one layer per geometry family instead of one layer per tabaka. Disabled and unchecked while TR-Only MPYY Style is on, because the transfer defines the layer structure itself. |
Merge all layers into 3 layers (Polygon / Line / Point-Text) | boolean | False | Write every tabaka of a drawing into exactly three layers — _POLYGON, _LINE, _POINT/TEXT. Each feature keeps its tabaka in layer_name and the renderer is categorised by that field, so every tabaka keeps its own drawing colour; helper and pen tabaka are listed but switched off. With several drawings and unified upper layers on, they share the three layers. |
Import directly as temporary scratch layers (no GPKG) | boolean | False | Write to QGIS memory layers instead of a GeoPackage. In MPYY mode the workspace goes to a temporary file instead. |
Two engine behaviours are not switches. Selective decode always
applies: choosing a drawing indexes only its layers and metadata, so the layer
tree appears almost immediately even for large municipal files, and geometry is
decoded only for the layers checked at import time. The index cache is
likewise always on unless ZERO2CADGIS_NCZ_CACHE_DISABLE is set; it
is keyed to the drawing's size and modification time and rebuilds itself when the
drawing changes. Clear cache on the Netcad tab resets it by hand.
Output & Export Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
Output mode | enum | GeoPackage | One of: GeoPackage (permanent .gpkg, CRS transform applied), Scratch (temporary memory layer, CRS transform applied), Live (zero-copy reference, no CRS transform, for GDB/MDB only). |
Target GeoPackage | file path | (user-selected) | Destination .gpkg file. Created if absent; layers are added with CreateOrOverwriteLayer semantics. Existing layers with the same name are replaced. |
Target CRS | CRS | (project CRS) | Target coordinate reference system for GeoPackage and Scratch output modes. Source coordinates are transformed via QgsCoordinateTransform using the PROJ pipeline. |
Select Source Layer: | enum | (first layer) | One vector layer from the project. For MBTiles the list gains a first entry, [All Visible Canvas Layers / Project], which renders the whole canvas rather than one layer. |
Target Export Format: | enum | DXF | AutoCAD DXF (*.dxf), Google Earth KML (*.kml), Google Earth KMZ (*.kmz) or Web Map Tiles MBTiles (*.mbtiles). DXF is written through QgsVectorFileWriter with attribute creation skipped, so the drawing carries geometry and layer structure but no attribute table. KMZ is a KML written as doc.kml inside a DEFLATE zip. |
Output CRS: | CRS | (layer CRS) | Enabled for DXF only, where the engineering or project CRS is meaningful. The control is disabled and forced for the other two formats, and the hint under it says which: KML/KMZ is always EPSG:4326 for standards-compliant Google Earth positioning, and MBTiles is always EPSG:3857 (Web Mercator) with TMS/XYZ tiling. |
Feature Scope: Selected features only | boolean | False | Export only the features currently selected on the source layer. Hidden for MBTiles, which renders the canvas. Selecting this with nothing selected on the layer is an error rather than an empty export. |
Save Location: | file path | (user-selected) | Destination file. The write goes to a temporary file that is validated and only then published over the destination, so an interrupted export cannot replace an existing deliverable with a partial file. |
Tile Settings appear when MBTiles is chosen:
| Parameter | Range | Default | Description |
|---|---|---|---|
Min Zoom: | 0–24 | 14 | Lowest zoom level of the pyramid. Lower values add a wider overview and cost tiles fast. |
Max Zoom: | 0–24 | 16 | Highest zoom level. This is the one that decides whether a plan is legible when zoomed in. |
| Tile format | enum | PNG | PNG (Transparent) or JPEG (Opaque). PNG keeps transparency, which is what makes an overlay usable; JPEG is smaller. JPEG quality is 75. |
DPI: | 72–600 | 96 | Tile resolution. 96 is the standard web-map DPI and the right answer unless you have a reason. |
Metatile: | 1–8 | 1 | Metatile buffer. 1 is fastest and lightest on memory. |
Extent: | enum | Auto | CAD / Vector Data Extent (Auto) renders only the drawing area — fast and compact — or Current Map Canvas Extent renders what is on screen. |
An estimate label under these controls counts the tiles the current settings would produce and reports what to expect: Fast, < 5 sec up to about 250 tiles, Moderate, ~10–30 sec up to about 2,500, and a red warning above that. The exporter refuses to run above an estimated 25,000 tiles and says why, rather than filling a disk or freezing QGIS. The number of tiles actually written is read back from the output and reported with the feature count.
The Netcad tab carries a shortcut to this panel, Need raster tiles? Open MBTiles Exporter →, which opens the exporter format already set to MBTiles — the intended route for turning a converted plan into a web-map pyramid in one step.
Output, Export & Styling
GeoPackage, Scratch & Live
| Mode | Persistence | CRS Transform | Best For |
|---|---|---|---|
| GeoPackage | Permanent .gpkg | Yes | Durable deliverables, data exchange, archival |
| Scratch | Temporary memory layer | Yes | Quick inspection, "try before you commit" |
| Live | Zero-copy reference | No | Browsing large GDB/MDB. No conversion time or disk space. |
DXF / KML / KMZ Export
The exporter panel writes any active QGIS vector layer, or its current
selection, to DXF, KML or KMZ through QgsVectorFileWriter. DXF is
written with attribute creation skipped, so it carries geometry and layer names
for CAD collaborators but no attribute table; KML and KMZ are forced to WGS 84
(EPSG:4326) so Google Earth positions them correctly. Each write goes to a
temporary file that is validated first and only then published over the
destination, so an interrupted export cannot destroy an existing deliverable.
MBTiles / Tile Pyramid Export
The same panel writes a raster tile pyramid — .mbtiles, in
TMS or XYZ addressing — from the styled canvas, using QGIS's native tile
algorithm. Source selection differs from the vector exports: the layer list gains
[All Visible Canvas Layers / Project], which renders the whole canvas with
its real styling rather than one layer's geometry. The output is always
reprojected to EPSG:3857 (Web Mercator), which is what every web map
expects, and tiles are antialiased.
The controls are Min and Max Zoom (default 14 and 16), tile format (PNG (Transparent) or JPEG (Opaque), quality 75), DPI (default 96, the standard web-map value), Metatile (default 1, the fastest and lightest on memory) and Extent — the drawing's own extent or the current canvas. An estimate label counts the tiles the current settings imply and says what to expect: under about 250 tiles it reports Fast, < 5 sec; up to about 2,500, Moderate, ~10–30 sec; above that it warns. The exporter refuses a run estimated above 25,000 tiles rather than filling a disk or freezing QGIS, and reports the number of tiles actually written, read back from the output.
Transparency is the reason to prefer PNG here: a plan exported as an opaque JPEG cannot be laid over a basemap. Use JPEG only when file size matters more than overlaying. The Netcad tab's Need raster tiles? Open MBTiles Exporter → link jumps straight to this panel with MBTiles selected, which is the intended route from a converted plan to a web-map deliverable.
CAD Colors, Labels & Mojibake Repair
Netcad ARGB colours are preserved via categorised renderers (one symbol per colour). Text labels select a column that actually contains text (not merely exists while empty). Point layers with text draw a subtle 0.6 mm anchor. The mojibake repair engine applies multi-pass encoding recovery: UTF-8 → CP1254 → CP1252 → ISO-8859-9 → direct character replacement map for stubborn byte sequences. Applied to layer names, attributes, labels, and UI tree items. DXF \U+XXXX escapes are also unescaped.
Batch Tools
Batch Spatial Extent Filter
Surveying and municipal archives arrive as a directory of hundreds of sheets — paftas — and the task is usually to find the handful that cover one area. Opening them one at a time in QGIS is what the filter exists to replace. It scans a folder (recursively by default) or an explicit file list and reports which drawings intersect a boundary without loading any of them into memory: only the header and the extent are read, so an unmatched sheet costs nothing but its file read.
The extensions it understands are the ones the plugin imports:
.ncz .nca .dxf .dwg .dgn .kml .kmz .shp .gdb .geojson .json .gml .sqlite
.db .gpx .accdb .mdb .csv .tsv. File geodatabases are treated as one unit
each rather than as a folder of files. For NCZ and NCA the extent comes from the
drawing's own decoded coordinates, with origin-artefact points and non-finite or
oversized values discarded; for everything else it comes from the OGR layer
extents and the source CRS.
| Boundary source | Uses |
|---|---|
| Active Map Canvas Extent | Whatever the map canvas currently shows. The fastest way to say "here". |
| Selected Feature(s) in Polygon Layer | A polygon layer in the project. Use only selected polygon features (on by default) unions the current selection instead of the whole layer — a district boundary, an administrative area, a site outline. |
| Print Layout Map Extent | The extent of a print layout's map item. This is the one to use when the sheet boundary is the deliverable's frame rather than an arbitrary view. |
| Manual Bounding Box | A bounding box typed in directly, for an area you know the coordinates of. |
The match is either Intersects or Within, with an optional metre buffer so that a sheet whose edge only touches the boundary can be included or excluded deliberately. The comparison uses real geometry and CRS transforms when QGIS can build them and falls back to a plain bounding-box test when it cannot, so the filter still works on a layer whose CRS is unassigned. Results are timed and reported as Scan complete in N s: M matched out of K candidate files.
Three things consume the result. Preview Footprints on Canvas draws the
matched extents as a labelled overlay so you can see the coverage before
committing. Import Matched Files then takes exactly the matches through
the normal import path, in one of three output modes: Directly into QGIS
Canvas (the default), Unified GeoPackage (all matches into one
.gpkg), or Copy matched files to folder (the originals
copied out, converted by nothing). Send to CAD Tab hands the selection
back to the converter tab instead, so you can inspect it there first. This is
the intended way to pull a district's worth of sheets out of a provincial
archive without opening the ones you do not need.
Interpretation Guide
DXF / DWG Workflow
Step 1: Source selection. Drag a .dxf or .dwg file onto the dock, or click "Browse" on the CAD & GIS Converter tab. For DWG R2004+, the plugin searches for ODA File Converter; if not found, an interactive setup dialog guides installation from opendesign.com. Once configured, the file opens and the layer tree populates.
Step 2: Layer tree inspection. With "Split into CAD layers" enabled (default), each DXF Layer name becomes a row showing its geometry family and feature count. Uncheck layers you do not need — this eliminates their conversion time. The tree is built from GDAL's OGR driver, which reads the header only; feature counts may be −1 (unknown) for large files until conversion begins.
Step 3: Configure options. Keep "Collinear simplification" on unless you need exact vertex-level fidelity (e.g. for legal cadastral boundaries where every vertex matters). The "Close polylines" option is useful when CAD polylines represent parcels or building footprints but were drawn open. Set the tolerance conservatively (0.01–0.05 map units).
Step 4: CRS. DXF/DWG files carry no explicit CRS. The plugin attempts auto-detection from coordinate magnitudes, but in most cases you must select the CRS manually. If the coordinates look like projected values (6–8 digit eastings, 7-digit northings), select the appropriate projected CRS. If the drawing is in arbitrary local coordinates, convert without CRS and georeference later.
Step 5: Output. Choose GeoPackage for durable output or Scratch for quick inspection. Click "Convert". Output layers appear in the QGIS layer tree with CAD colours applied and mojibake-repaired names.
DXF Layer Name Conventions
DXF layer names in Turkish planning practice follow several common conventions that affect how they appear in the layer tree. Understanding these conventions helps in deciding whether to split by layer and which layers to import:
- Standardised MPYY names — layers named after official tabaka codes, e.g.
PL_KONUT,PL_YOL,PL_PARK. These resolve exactly when TR-Only MPYY Style is enabled, with no confirmation step. The underscore convention is significant:PL_is the MPYY prefix for planning layers;SNR_for boundary/limit layers; numeric prefixes (e.g.100_,200_) are upper-group codes. ThePL_prefix is also one of the spelling rules the transfer treats as meaning-preserving, soKONUTandPL_KONUTresolve to the same function. - Local municipal names — layers with descriptive Turkish names like
KONUT ALANI,MEVCUT YOL,PARK VE YESIL ALAN. These are proposed against the Ek-1e function names and MPYY codes in the confirmation table, never applied automatically. Turkish characters in layer names are normalised first, and the search box in the layer filter matches them loosely. - Numeric-only layer names — some CAD operators use layer names like
0,1,2or colour-based names. These layers convey no semantic meaning and must be manually classified after import. The plugin preserves them as-is; the user should rename them in QGIS or use the layer tree to identify their content before conversion. - Null or empty layer names — entities on AutoCAD layer
0(the default layer) or with an empty layer string appear as(no layer)in the tree. These entities are typically construction geometry or drafting artefacts; unless you specifically need them, uncheck this entry.
DGN Level Number Mapping
MicroStation DGN files use numeric levels (1–63 in older versions, up to 65,535 in v8) rather than named layers. When the GDAL DGNv8 driver is available, level names from the DGN's level table are displayed alongside numbers, e.g. Existing Buildings (Level 12). When using the pure-Python fallback reader, level names are extracted from the DGN's named level table if present; otherwise, only level numbers are shown. The plugin groups entities by level exactly as it groups DXF entities by layer name, making the workflow identical once the source is opened.
Handling Large CAD Files
For DXF files exceeding 50 MB or with more than 100 layers:
- Use the layer tree to uncheck all layers, then check only the 5–10 layers you need. This dramatically reduces conversion time because GDAL reads and filters at the driver level.
- Disable collinear simplification if you need every vertex (e.g. for legal cadastral boundaries). For visualisation and analysis, keeping it enabled reduces output file size by 50–90%.
- Use Scratch mode for first inspection — it creates temporary memory layers with no file I/O overhead. Once you've verified which layers contain useful data, re-import to GeoPackage with only those layers checked.
- For DWG files, the ODA File Converter step adds 5–30 seconds depending on file complexity. This cost is paid once per file; the converted DXF is cached in a temp directory and reused for subsequent imports.
DGN Workflow (Detailed)
DGN files require special attention because the GDAL build shipped with standard QGIS does not include the DGNv8 driver. The pure-Python fallback reader handles most planning-grade DGN files but has limitations that affect workflow decisions.
Step 1: Determine whether the fallback reader is needed. If GDAL opens the DGN file successfully (the layer tree shows non-zero feature counts for at least one layer), the GDAL driver is handling the file and full fidelity is available. If GDAL returns zero layers or 0 features, the pure-Python reader activates automatically. The plugin logs which reader is active.
Step 2: Understand fallback reader limitations. The pure-Python reader supports line (type 3), linestring (type 4), and shape/polygon (type 6) elements. Complex cell geometry, text elements as full text (not placeholder points), dimension elements, and custom line styles are not rendered as full geometry. These entities contribute placeholder points with their level, colour, weight, and style attributes preserved. If your workflow requires these element types as full geometry, convert the DGN to DXF using Bentley MicroStation or ODA Drawings Explorer (both free for viewing/conversion) before importing.
Step 3: Polygon detection. The reader classifies shape elements (type 6) as polygons when their vertex ring is closed (first and last points coincident within 10−6 map units). Open shape elements are imported as polylines. If your DGN uses open shapes to represent parcels or building footprints (a common MicroStation convention), those elements will import as lines. Enable "Close polylines" in the CAD options to auto-close them within the specified tolerance.
Step 4: Coordinate filtering. The fallback reader validates coordinates against realistic bounds: x and y must each be in [100,000, 16,000,000] and the absolute difference between x and y must be at least 1.0. This filters degenerate point clouds and corrupted elements. Elements entirely outside these bounds are skipped with a logged count. If legitimate data is being filtered (e.g. very small-scale regional maps with coordinates near the origin), check the coordinate system and consider adjusting the source.
GML and GeoJSON Workflow
GML and GeoJSON are both text-based OGC standard formats but have very different performance and usability characteristics in the conversion pipeline.
GML approach. GML files are XML documents that GDAL parses into a DOM before reading features. For files larger than 50 MB, this DOM construction can be slow and memory-intensive. Strategy: (a) if the GML contains many feature types, uncheck the ones you do not need to reduce the feature count; (b) if GDAL reports schema validation errors, the GML's xsi:schemaLocation URLs may be unreachable — try editing the GML header to remove or fix these URLs; (c) GML files carrying a fid attribute with non-integer values will have that column renamed to cadgis_fid in the output GeoPackage to avoid conflicting with the GeoPackage primary key.
GeoJSON approach. GeoJSON is simpler: it is a single JSON object with a features array. GDAL reads it efficiently, but RFC 7946 mandates WGS 84 (EPSG:4326). If your GeoJSON uses an alternative CRS (a legacy convention), GDAL reads the CRS from the crs member if present. Always verify the CRS after import: if the coordinates look like projected values (6–8 digit eastings) but the layer CRS is EPSG:4326, the GeoJSON was written with non-standard CRS and the coordinates were not reprojected. In this case, manually set the source CRS to the correct projected system and re-import.
NCZ / NCA Workflow
Step 1: File selection. Switch to the "Netcad NCZ/NCA Importer" tab. Use "Select Files" to choose one or more .ncz/.nca files. The plugin indexes each file (reading only the header + block index) and displays its metadata: version, projection text, SRS id, layer count, and entity count. With the v2 index cache enabled, reopening an unchanged file shows this instantly.
Step 2: CRS detection. The projection text is parsed, sample coordinates are read, and the detector proposes an EPSG code with a confidence level and explanation. Green (high confidence) means both datum and zone are certain. Yellow (medium confidence) means one signal is missing (typically the datum — TUREF is assumed for modern data). Red (none) means neither signal is sufficient; you must select manually. Always verify the proposed CRS against your knowledge of the data.
Step 3: Layer selection. The layer tree shows each CAD layer by name, geometry family and record count. Check only the layers you need. @TAB tables appear alongside layers; checking both a layer and its @TAB performs the automatic join. Use Select All / Deselect All for bulk operations.
Step 3a: Filtering the list. The box above the tree filters by name and by
geometry. Every word you type must match: LINE,
POLYGON, POINT or TEXT keep the layers
holding that geometry, and any other word must appear in the layer name. So
PL_ line lists the plan layers that contain lines. Turkish letters
are matched loosely — ı/i/İ/I
are the same letter and ş ç ğ ö ü match
s c g o u, so askeri finds PL_ASKERI_ALAN and
yapı finds SM_YAPILASMA. Select All / Deselect All act on
the listed layers only, so a filter is a safe way to bulk-check a subset; hidden
layers keep whatever state they had.
Step 3b: Attribute columns. Untick any column you do not want written.
The columns the styles, the labels, the three-layer categories and the MPYY
transfer read are locked on — dropping layer_name, the colour,
the label or the text height would silently change what you see. Unticked columns
are discarded only after every step that needs them has run, and MPYY layers keep
their own MPYY 1.1.7 columns regardless.
Step 4: TR-Only MPYY Style (optional). For an imar plan, check TR-Only MPYY Style: MPYY structure and styles (UİP / NİP / ÇDP) and leave Plan level on Auto unless the file name does not say which plan it is. The import then writes an MPYY workspace instead of raw CAD layers, and any tabaka it cannot resolve comes back to you in the confirmation table rather than being guessed. See MPYY Transfer Workflow. Leave this off for topographic, cadastral, utility and engineering drawings.
Step 5: Batch options. Build unified upper layers merges the tabaka into one layer per geometry family; Merge all layers into 3 layers goes further and writes exactly three. Geometry metadata adds the length, area and centroid columns, useful for quality checking. Both are covered in MPYY Transfer Workflow; the merge controls are disabled while the MPYY mode is on, because the transfer defines the layer structure itself.
KML / KMZ Workflow
Step 1: Source. Drag a .kml or .kmz file onto the dock. KMZ archives are fully extracted; all .kml documents inside are enumerated (not just doc.kml). Multi-document KMZ files have each document's layers prefixed with the document stem to prevent name collisions.
Step 2: Layers. The layer tree shows each KML folder/feature class as a row. KML sources typically carry EPSG:4326 (WGS 84 geographic). Enable "Expand HTML descriptions" to parse balloon content into attribute columns. Enable "Extract GroundOverlay rasters" for aerial imagery or scanned maps embedded as overlays.
Step 3: Output. Choose GeoPackage with a projected target CRS if you need metric geometry for analysis. KML's native geographic coordinates will be transformed. GroundOverlay rasters are written as separate GeoTIFF files in the same directory as the KML source.
GDB / MDB Workflow
Step 1: Source. Select a .gdb directory (File Geodatabase) or .mdb file (Personal Geodatabase / MS Access). The OGR catalog cache makes reopening instant after the first inspection.
Step 2: Mode choice. For browsing, use Live mode: layers load as zero-copy references in ~0.27 seconds regardless of size. For durable deliverables or CRS transformation, use GeoPackage mode. Live mode preserves the source CRS; if you need reprojection, you must use GeoPackage or Scratch.
Step 3: MS Access fallback. If GDAL's PGeo driver cannot open the .mdb, the plugin's pure-Python MS Access reader activates (requires 64-bit Microsoft Access Database Engine ODBC driver). It enumerates spatial tables via pyodbc and reads features directly.
CSV / TSV Workflow
Step 1: Source. Select a .csv, .tsv, or .txt file. The sniffer samples the first 100 lines and auto-detects delimiter, fields, point geometry columns, WKT column, and CRS.
Step 2: Verify detection. Review the auto-detected settings in the UI. The delimiter, X/Y fields, WKT field, geometry type, source CRS, and encoding are all overridable. If the sniffer misidentifies a column, correct it before conversion. The geometry summary line ("Point from 'longitude' / 'latitude'" or "WKT column 'geometry'") confirms what will be imported.
Step 3: Output. Delimited text with point geometry writes a Point layer. WKT geometry preserves whatever type the WKT strings describe (Point, LineString, Polygon, etc.). Files with no detected geometry become attribute-only tables. All output goes to the selected GeoPackage.
MPYY Transfer Workflow
Step 1: Decide that this is an imar plan. The mode is for Uygulama, Nazım and Çevre Düzeni plans. If the drawing is a topographic survey, a utility network, a cadastral sheet or an engineering drawing, stop here and import it with the mode off — the rest of this section does not apply to it, and forcing it through would replace its tabaka names and drawing colours with a classification that does not describe it.
Step 2: Enable the mode and pick the level. On the Netcad tab, check
TR-Only MPYY Style: MPYY structure and styles (UİP / NİP /
ÇDP); on the converter tab, the equivalent box applies to DXF and DWG
only. Leave Plan level on Auto in the normal case: a file named
1000_BAHCESARAY_IMAR.ncz resolves to
UİP because of the 1000, 5000_… resolves to
NİP and 25000_… to ÇDP, and a name containing
NAZIM resolves to NİP whatever its scale prefix says. Set the
level by hand when the file name is uninformative; if the level cannot be
determined at all, the import stops and tells you rather than styling the plan
as the wrong kind.
Step 3: Answer the confirmation table. Layers whose names match the
crosswalk exactly, were confirmed on an earlier drawing, or differ only by a
copy number, a Netcad export suffix, a PL_ prefix or an
_ALANI-type ending transfer without asking. Everything else arrives
in TR-Only MPYY Style {UİP/NİP/ÇDP} — match CAD
layers, unticked, with the reason each was proposed. Tick what is right, type
to pick a function by hand where the proposal is wrong, and leave the row
unticked where you would rather keep the drawing's own layer. Confirmed rows are
remembered for the next drawing, so this table shrinks as you work through an
archive.
Step 4: Read the result. The import produces an MPYY workspace
GeoPackage for the level, the layers styled at the plan's reference scale with a
legend scoped to the values the plan uses, and — where the drawing carried
the planner's own notation — a
<file>_PLAN_NOTATION group with Building notation and
Road widths. Anything the transfer could not place is in
<file>_UNMATCHED_LAYERS, in the drawing's own colours. The
summary confirms the split by name and by count. Check it before delivering: an
unmatched layer is a decision still to be made, not an error.
Step 5: Layer structure. Two controls interact with this mode. With
the mode off, Build unified upper layers merges the tabaka into one layer
per geometry family, and Merge all layers into 3 layers (Polygon / Line /
Point-Text) writes exactly three layers labelled
<owner>_POLYGON, <owner>_LINE and
<owner>_POINT/TEXT; each feature keeps its tabaka in
layer_name, the renderer is categorised by that field so every
tabaka keeps its own drawing colour, and helper and pen layers are listed but
switched off. With the mode on, those two are superseded and the first is
disabled outright — the MPYY workspace's layer structure is the MPYY
feature types, and tabaka that have no MPYY type are what ends up in the
unmatched group instead.
Troubleshooting
| Symptom | Likely Cause | Remedy |
|---|---|---|
| DWG file fails to open | Modern DWG (R2004+) with no ODA File Converter available | Install ODA File Converter from opendesign.com. The plugin's setup dialog guides this. Alternatively, convert the DWG to DXF in AutoCAD or a free viewer. |
| DGN file opens but returns 0 features | DGN v8 file; GDAL build lacks the DGNv8 driver (requires ODA Teigha) | The plugin's pure-Python DGN reader activates automatically. If it also fails, convert to DXF using Bentley MicroStation or ODA Drawings Explorer. |
| NCZ data appears in the wrong location | Wrong CRS selected. Common error: SRS id (e.g. 7936) used as EPSG code. | The SRS id is not an EPSG code. Use the auto-detected CRS or manually select the correct projected CRS for your region. Verify a few known point coordinates after import. |
| Turkish characters garbled (e.g. PL_KÜNÜT instead of PL_KONUT) | Mojibake: CP1254 bytes decoded as UTF-8 by intermediate tool or GDAL | The plugin's mojibake repair engine runs automatically. If some strings remain garbled, the layer name or attribute was corrupted beyond the known recovery patterns. Rename manually in QGIS. |
| KML GroundOverlay images not georeferenced | KML uses <Icon><href> with a relative path that cannot be resolved | Ensure the image file is present in the same directory as the KML. The plugin checks both relative path (including subdirectories) and basename-only fallback. |
| CSV imports with wrong delimiter or no geometry | First 100 lines are header/metadata; data structure differs afterward | Override the auto-detected settings manually. Specify delimiter, X/Y or WKT columns, and CRS explicitly. |
| GDB/MDB fails with "Unable to open" | Missing ODBC driver for .mdb; incompatible GDB version; file locked by another process | For .mdb: install 64-bit Microsoft Access Database Engine. For .gdb: ensure no other process (ArcGIS, ArcCatalog) has the GDB open. Try copying the GDB directory and opening the copy. |
| GeoPackage conversion succeeds but feature count is lower than expected | Features with no geometry (NULL geometry) are filtered. Empty geometries are skipped. | This is by design. Check the plugin's warning log for the count of skipped features. If many features were dropped, inspect the source in its native application to verify geometry presence. |
A tabaka that should be a known function comes back in the confirmation table, or lands in _UNMATCHED_LAYERS | The name matched no crosswalk key and no meaning-preserving spelling rule, so it was only proposed — the transfer never applies a proposal by itself | This is the intended behaviour, not a failure. Confirm the row in match CAD layers and the mapping is remembered for the next drawing. If the name is genuinely a local spelling, confirm it once; if the function does not exist, leave the row unticked and classify it by hand after import. Check the spelling against the Ek-1e function list — Turkish characters are folded for matching, but word order and abbreviations are not. |
| Imported layers are MPYY feature types instead of the drawing's own CAD layers | TR-Only MPYY Style was left on | Uncheck it. The mode is off by default and is meant for imar plans only; every other source should be imported with it off. |
| MPYY import stops with "the plan level (UİP / NİP / ÇDP) could not be determined" | Plan level is on Auto and the file name carries neither a recognisable marker word nor a scale number | Set the level explicitly in the Plan level selector. The import stops rather than styling the plan as the wrong kind. |
| Conversion is slow for a large file | All layers are selected for conversion; collinear simplification is heavy on very complex polylines | Uncheck layers you do not need. The NCZ v2 engine decodes only checked layers. For GDAL-based formats, use Live mode first to inspect the data, then convert only the layers you need. |
Performance Characteristics
The plugin employs a layered caching architecture to minimise repeated work on large datasets. Performance is characterised across three access patterns.
Cold Open (First Access)
On first access, the file must be parsed or opened through the appropriate driver. The dominant cost is I/O, not computation; therefore the plugin reads only what is necessary to build the layer tree. For NCZ drawings, the v2 engine reads just the file header and block index (Phase 1); geometry decoding (Phase 2) is deferred until import. For OGR-based formats, ogr.Open() is the unavoidable cost, but the catalog cache eliminates it on subsequent accesses. For CSV/TSV, the sniffer reads only the first 256 KB to determine structure.
| Format | Typical Cold Open | What Is Read | Bottleneck |
|---|---|---|---|
| NCZ (1.2 MiB, 8163 entities) | ~15 ms (index only) | Block headers + metadata | Sequential file read |
| NCZ full decode (same file) | ~160 ms | All geometry coordinates | f64 unpacking + dict construction |
| DXF (< 10 MiB) | ~1–3 s | Full text parse by GDAL | GDAL DXF driver text processing |
| FileGDB (municipal, 4.27M features) | ~2–5 s (catalog) | Table directory scan | File count walk in .gdb directory |
| KML/KMZ (< 50 MiB) | ~0.5–2 s | Full XML parse by GDAL | XML DOM construction |
| CSV/TSV (any size) | ~0.1–0.3 s | First 256 KB only | csv.Sniffer heuristics |
Warm Reopen (Catalog Cache Hit)
Reopening an unchanged file loads the layer catalog from the fingerprinted JSON cache. No driver is opened; no bytes are read from the source file. The NCZ index cache achieves ~160× speedup on a real 1.2 MiB municipal file (from ~15 ms to ~0.1 ms). The OGR catalog cache achieves 100×+ speedup on multi-layer geodatabases by avoiding ogr.Open() entirely. Cache invalidation is automatic on file size or modification time change; manual invalidation is available through the dock's "Clear cache" button and the ZERO2CADGIS_NCZ_CACHE_DISABLE / ZERO2CADGIS_OGR_CACHE_DISABLE environment variables.
Selective Import
The lazy catalog enables a decode-what-you-need strategy. Checking only 5 of 50 layers in an NCZ drawing decodes only those 5 layers' geometry records — about 10% of the file's entity count. Benchmark shows ~3.4× speedup over full decode for 1 of 5 layers. For GDAL-based CAD formats, the subset string ("Layer" = 'BUILDINGS') is pushed down to GDAL, which filters at read time.
Cross-Format Comparison
The table below summarises structural differences that affect conversion behaviour across the supported formats.
| Property | DXF/DWG | DGN v8 | NCZ/NCA | KML/KMZ | GeoJSON | GML | CSV/TSV | GDB/MDB |
|---|---|---|---|---|---|---|---|---|
| CRS in file | No | Optional | Partial (SRS id + projection text) | Yes (WGS 84) | Yes (WGS 84) | Yes | No | Yes |
| Geometry types per layer | Mixed | Mixed | Mixed | Homogeneous | Homogeneous | Homogeneous | One type | Homogeneous |
| Attributes | Implicit (Layer, colour, linetype) | Implicit (Level, colour, weight, style) | Implicit + @TAB tables | Explicit (HTML description, schema) | Explicit (properties object) | Explicit (feature-member properties) | Explicit (column headers) | Explicit (field definitions) |
| Text support | Native entities | Native elements | Native entities (Type 5) | Placemark name/description | Properties only | Properties only | Column values | Field values |
| 3D geometry | Yes (Z coordinates) | Yes (3D elements) | Yes (Z per vertex) | Yes (altitudeMode) | Yes (Z in coordinates) | Yes (3D geometry types) | Optional (Z column) | Yes (Z-enabled) |
| Curve support | Yes (ARC, ELLIPSE, SPLINE) | Yes (curve elements) | Yes (ARC type 4, compressed curve type 9) | No (segmentized) | No | Yes (Curve, ArcString) | No | Optional (CAD-only) |
| Block/cell support | Yes (INSERT) | Yes (shared cells) | Yes (BlockRef type 13, SmartObject type 15) | No | No | No | No | No |
| Multi-file support | Single file | Single file | Multiple files (batch) | KMZ: multi-KML archive | Single file | Single file | Single file | Directory-based (GDB) |
| Live mode | No | No | No | No | No | No | No | Yes |
| Export supported | DXF | No | No | KML, KMZ | No | No | No | No |
Encoding Recovery & Text Handling
Character Encoding in CAD Files
CAD systems and their exchange formats handle text encoding with varying degrees of rigour. The most severe problems arise in Turkish-language CAD data, where the Turkish alphabet introduces six characters (ç, ğ, ı, ö, ş, ü) not present in ASCII or ISO 8859-1 (Latin-1). The encoding chain from CAD authoring to QGIS display involves multiple transcoding steps, each of which can introduce corruption.
DXF files nominally use the system code page of the authoring machine. Turkish Windows uses code page 1254 (Turkish), but DXF readers often default to ASCII or Latin-1. DXF \U+XXXX Unicode escape sequences can represent any Unicode character but are not universally supported by GDAL's DXF driver. Netcad NCZ files store text in an OEM byte mapping that maps Turkish characters to non-standard byte values (221 → İ, 222 → Ş, 208 → Ğ, etc.).
The mojibake repair engine in core/qgis_compat.py addresses these systematically through a three-stage recovery pipeline:
- DXF unescape — regex replacement of
\U+XXXXand\u+XXXXpatterns with the corresponding Unicode character viachr(int(hex, 16)). This handles CAD software that writes Turkish characters as escapes rather than encoding them in the code page. - Encoding round-trip recovery — for each detected mojibake pattern (Latin-1 characters in the range 0xC0–0xFF that form plausible double-encoding signatures), the engine tries encoding to Latin-1 or CP1252 and decoding as UTF-8, CP1254, or ISO-8859-9. The first candidate that eliminates all known mojibake markers is accepted.
- Direct byte-pattern replacement — a fixed mapping of 8 stubborn byte sequences (
"ç" → "ç", etc.) that survive the round-trip recovery because the original encoding chain was more than two steps deep. These patterns are exhaustive for the CP1254 → UTF-8 double-encoding of all six Turkish characters plus their uppercase forms.
docs/NCZ_FORMAT.md and verified against real municipal drawings. The CP1254/CP1252/UTF-8 mojibake patterns were collected empirically from hundreds of real CAD files and verified by reversible encoding/decoding test cases.
Caching Architecture
The plugin implements two independent, fingerprinted on-disk caches for different data sources, sharing a common design but specialised for their respective access patterns.
NCZ Index Cache
Stores a drawing's decoded metadata (DrawingMetadata), per-layer catalog summaries, and decoded @TAB attribute tables as JSON. The cache key is SHA-256 of the absolute file path; invalidation uses a (size, mtime_ns) fingerprint plus CACHE_VERSION. Cache files live under %LOCALAPPDATA%/zero2cadgis/ncz_index/ (Windows) or $XDG_CACHE_HOME/zero2cadgis/ncz_index/ (Linux).
On a cache hit, the dock builds the layer tree without opening the NCZ file at all. Geometry is still decoded from the file at import time (Phase 2), so the cache never stores coordinate data — it is purely a metadata accelerator. Atomic writes (write to .tmp, then os.replace) prevent corruption on concurrent access.
OGR Catalog Cache
Stores multi-layer OGR source catalogs (layer names, geometry types, feature counts) as JSON. For directory-based datasets (File Geodatabase .gdb), the fingerprint aggregates file count, total byte size, and newest modification time across up to 4096 entries (to keep the stat walk cheap). For single-file datasets (.mdb, .sqlite, .gml), the fingerprint is simply (size, mtime_ns).
The OGR catalog cache is critical for multi-layer geodatabases where ogr.Open() on a large .mdb or .gdb takes several seconds just to enumerate layers. With a warm cache, the layer list appears instantly, and the driver is only opened when the user initiates conversion.
GDAL/OGR Driver Fallback Chain
Not all GDAL builds include all drivers. Standard OSGeo4W QGIS builds ship with the CAD (DXF), KML, GML, GeoJSON, GPKG, SQLite, OpenFileGDB, and CSV drivers, but may lack the PGeo (Personal Geodatabase), DGNv8, or libopencad (DWG) drivers. The plugin detects missing drivers and activates its own readers:
| Format | GDAL Driver | Availability in Standard QGIS | 02CadGis Fallback |
|---|---|---|---|
| DWG (R2000 and earlier) | libopencad (CAD) | Usually present | — |
| DWG (R2004+) | libopencad (CAD) | Usually fails on modern DWG | ODA File Converter → DXF → GDAL DXF driver. LibreDWG dwg2dxf as tertiary fallback. |
| DGN v8 | DGNv8 | Not included (requires ODA Teigha) | Pure-Python DgnV8Reader: OLE2 → zlib decompress → element parse |
| Personal GDB (.mdb) | PGeo | Sometimes absent | MsAccessDbReader: pyodbc → ODBC → spatial table scan |
| NCZ/NCA | None | No GDAL driver exists | NCZ Engine v2: pure-Python block-oriented binary decoder |
The fallback chain for each format is exercised automatically. The DGN v8 reader probes the OLE2 signature and falls back silently; the MS Access reader checks pyodbc availability and installed ODBC driver names; the ODA File Converter is location-discovered through a 7-step search. Users see only a clear error message when all tiers fail, with guidance on installing the missing component.
Spatial Data Quality and Validation
CAD-to-GIS conversion introduces several classes of potential data quality degradation. The plugin implements validation checks and corrective measures at each stage of the pipeline to minimise information loss.
Geometry Validity
QGIS memory providers and the GeoPackage driver enforce OGC Simple Features geometry validity rules. Invalid geometries (self-intersecting polygons, non-closed rings, zero-length segments) are rejected by the data provider. The plugin applies pre-write geometry repair through the coercion engine: curve segmentization eliminates curved geometries that are not supported by Simple Features; Z-coordinate dropping eliminates 3D geometries incompatible with 2D-only layers; single-to-multi conversion ensures type compatibility. The add_features_or_raise helper (in core/qgis_compat.py) wraps dataProvider().addFeatures() with a verification step: it compares the feature count before and after the add, and if fewer features were accepted than submitted, it attempts a second pass with geometry coercion (drop Z, segmentize curves, convert multi/single type) before raising a descriptive error.
Coordinate Range Validation
All decoded coordinates are validated against realistic bounds. The NCZ engine's Cursor class enforces \([-10^8, 10^8]\) for all coordinate values; values outside this range are rejected. The DGN v8 reader additionally validates that coordinates fall within [100,000, 16,000,000] and that the absolute difference between x and y coordinates is at least 1.0 — filtering out degenerate point clouds. The CRS detector's northing band check (3,800,000–4,800,000 m) catches coordinates that are in the correct numeric range but outside Turkey's geographic extent, flagging them as medium-confidence detections.
Feature Count Verification
Every stage that constructs QGIS layers tracks the number of features submitted vs. accepted. The conversion pipeline reports a summary: total entities in source, entities decoded (for NCZ selective decode), entities written to output, and entities skipped (with reasons). The NCZ v2 engine tracks unsupported geometry types in catalog.unsupported (a dict of {type: count}) and reports them in the parse result. Empty geometries and degenerate features (zero-length lines, zero-area polygons) are filtered with logged warnings, never as fatal errors.
Attribute Null Handling
CAD files frequently have attributes that exist on some entities but not others. The plugin preserves this faithfully: missing attributes become NULL in the GeoPackage output. The mojibake repair and the MPYY transfer operate only on non-null string values. The transfer's empty-cell policy deliberately leaves a code blank rather than filling it with an invented value, maintaining a clean distinction between “this tabaka is a catalogued function” and “this tabaka was left unresolved”. A blank code is a truthful statement about the input; a plausible-looking invented one is not, and it would survive into any downstream analysis that trusted it.
CRS Validation
After conversion, the output GeoPackage's CRS is verified to be valid and appropriate. The _effective_source_crs method applies a precedence chain: layer CRS (if valid and not EPSG:4326 when coordinates are clearly metric), explicit user-provided source CRS, coordinate-based auto-detection, target CRS, project CRS, and finally a safe default (EPSG:5253 for metric coordinates, EPSG:4326 for geographic). At each level, the CRS is validated before use; an invalid CRS at any level causes fallthrough to the next. This chain ensures that a CRS is always available, even when every signal fails, without silently applying a wrong one.
Memory Management for Large Datasets
Large CAD drawings and geodatabases present memory pressure challenges. The plugin uses several strategies to keep memory usage bounded:
- Streaming writes. Features are written to GeoPackage in batches via
add_features_or_raise. The NCZ v2 engine materialises decoded entities as Python dicts for the selected layers only; the CAD engine uses GDAL's iterator-basedgetFeatures()which reads one feature at a time from the driver. For the DGN v8 pure-Python reader, features are batched at 50,000 per write to keep the in-memory feature list bounded. - Lazy decoding. The NCZ v2 engine's Phase 1 (index) reads only block headers, not geometry. A 1.2 MiB file with 8,163 entities produces a catalog of ~200 record indices (a few KB). Geometry is decoded on demand for checked layers only.
- Live mode. For GDB and MDB sources, live mode adds zero-copy references. QGIS reads features lazily from the source file using GDAL's random-access capability; no features are materialised in plugin memory. A 4.27M-feature municipal FileGDB loads its two layers in ~0.27 seconds with negligible memory overhead.
- Temp file cleanup. Temporary directories created for KMZ extraction, DWG-to-DXF conversion, and KML/KMZ export are cleaned up via
shutil.rmtreein the engine'scleanup()method. The dock calls this after each conversion completes. Temp directories use the system temp path (tempfile.mkdtemp); leftover directories from crashes are harmless but consume disk space. - Catalog caches. Both the NCZ index cache and OGR catalog cache store only metadata (layer names, types, counts), not geometry. Cache files are typically < 10 KB for NCZ and < 5 KB for OGR sources.
Concurrency and Thread Safety
QGIS plugins run in the main thread, and all GUI operations must be dispatched on the Qt event loop. The conversion engines are single-threaded and not designed for concurrent use. However, the cache modules (cache.py, ogr_catalog_cache.py) are designed for multi-process safety: writes use atomic rename (os.replace of a tempfile), which is guaranteed atomic on POSIX and NTFS. Multiple QGIS instances reading the same cache files will not corrupt each other, though they may experience a stale read if one instance updates a cache entry while another reads it — a harmless condition that self-corrects on the next access when the fingerprint mismatch triggers a rescan.
DGN v8: OLE2 Compound Document Structure
The pure-Python DGN v8 reader operates on the OLE2 (Object Linking and Embedding) Compound Document format that MicroStation uses as its file container. Understanding this container is essential for diagnosing read failures.
An OLE2 file is a FAT (File Allocation Table) file system within a file. It contains: (a) a header (512 bytes) with magic number D0 CF 11 E0, sector size, and FAT sector count; (b) a directory (structured storage) enumerating named streams (equivalent to files); (c) a FAT chain linking data sectors; and (d) stream data in 512-byte or 4096-byte sectors. The DGN reader opens the OLE2 container, locates the design file stream, and passes its decompressed contents to the element parser.
Element data in DGN v8 is stored as a sequence of variable-length records. Each element begins with a 2-byte type field (line = 3, linestring = 4, shape = 6, text = 7/17) followed by a 2-byte level number, attributes (colour, weight, style), and coordinate data. Polygons are distinguished from polylines by element type: shape elements (type 6) whose vertex ring is closed (first and last points coincident within 10−6 map units). Complex elements (shared cells, text nodes, dimension elements) are represented as placeholder points with level/colour/style attributes preserved.
The reader handles two DGN v8 sub-formats: standard binary encoding and compressed (zlib) encoding. The olefile library (BSD-licensed, vendored) handles OLE2 parsing; zlib decompression is done via Python's built-in zlib module. Elements containing Unicode strings use the standard MicroStation UCS-2 or UTF-16 encoding in the element attributes.
KMZ Multi-Document Extraction Theory
The KMZ format is a ZIP archive (using DEFLATE compression) with a .kmz extension containing one or more KML documents and their referenced resources (images, 3D models, icons). The OGC KML 2.3 standard specifies that the root document must be named doc.kml, but does not restrict additional KML documents [OGC 2015]. Google Earth, the reference implementation, reads only doc.kml; any other KML files in the archive are ignored unless explicitly linked from the root document.
02CadGis departs from this convention to support multi-document KMZ files commonly produced by municipal GIS exports, where each thematic layer is stored as a separate KML document. The extraction algorithm:
- Extracts the entire KMZ to a temporary directory via
zipfile.ZipFile.extractall(). - Enumerates all
.kmlfiles (case-insensitive) in the extraction tree. - Prefers
doc.kmlas the primary document; if absent, chooses the first KML in sorted order. - Returns the primary document path for immediate GDAL reading; the remaining documents are accessed by
_kml_docs(), which walks the extraction directory and orders documents with the primary first. - In
_ogr_sources(), each KML document becomes an OGR source with a prefix derived from its stem ("boundaries.kml"→ prefix"boundaries_"). When only one document exists, the prefix is empty for backward compatibility.
This approach ensures that no KML data inside a KMZ is silently dropped. The multi-document prefix keeps layer names distinct when two documents define a layer with the same name. GroundOverlay images referenced by relative paths in any KML document are resolved against that document's location in the extraction tree.
DWG Conversion: ODA File Converter Discovery Algorithm
The search for ODAFileConverter.exe is exhaustive and ordered by decreasing likelihood, ensuring that the most common installation paths are checked first while still covering edge cases:
- QSettings (plugin custom path). The value of
zero2cadgis/oda_converter_pathis checked first; this is set when the user manually locates the executable through the interactive setup dialog. - QgsSettings (QGIS native settings). Three keys are probed:
/qgis/odaFileConverterPath(QGIS general setting),/dwg/odaConverterPath(DWG-specific setting), and/Processing/Configuration/ODA_FILE_CONVERTER_PATH(Processing framework setting). These capture installations configured through QGIS's own DWG import workflow. - Environment variables.
ODA_FILE_CONVERTER_PATH,ODA_PATH, andODA_CONVERTERare checked. These allow CI environments and containerised QGIS instances to point to the converter without interactive setup. - System PATH.
shutil.which("ODAFileConverter.exe")checks the executable search path. This covers installations that added the ODA directory to PATH during setup. - Static install paths. Five known installation directories under
C:\Program FilesandC:\Program Files (x86)are probed:ODA\ODAFileConverter\,ODAFileConverter\, andC:\ODA\ODAFileConverter\. - Glob search. A shallow glob in Program Files directories for
ODAFileConverter*directories captures versioned installations (e.g.ODAFileConverter 25.6.0). - Windows Registry. Both
HKLMandHKCUare searched underSOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall(and WOW6432Node for 32-bit on 64-bit) for entries whoseDisplayNamecontains "oda". Matching entries'InstallLocationvalues are checked for the executable. Direct registry keysSOFTWARE\OpenDesignandSOFTWARE\ODAare also probed.
The ODA File Converter invocation uses a safe ASCII filename (input_converted.dwg) to avoid Unicode/Turkish filename issues with the CLI tool. The target DXF version is attempted in descending order (ACAD2018 → ACAD2013 → ACAD2010 → ACAD2000) to maximise compatibility with GDAL's DXF reader. Each version is tried independently; the first successful conversion that produces a non-empty DXF file is used.
Format History and Provenance
| Format | Introduced | Standardising Body | Current Version | Status |
|---|---|---|---|---|
| DXF (Drawing Exchange Format) | 1982 | Autodesk (de facto) | R2024 (proprietary) | Active; widely supported |
| DWG | 1982 | Autodesk (proprietary) | R2024 | Active; requires external converter for modern versions |
| DGN v8 | 2000 | Bentley Systems | v8i / CONNECT | Active; GDAL driver requires ODA Teigha |
| NCZ/NCA | ~1990s | Netcad (proprietary) | Varies by producer version | Active in Turkey; no public specification |
| KML | 2004 (Keyhole) | OGC (since 2008) | 2.3 (OGC 12-007r2) | Active OGC standard |
| KMZ | 2004 (Keyhole) | OGC (KML 2.2 Annex) | ZIP container for KML | Active; de facto standard |
| GeoJSON | 2008 | IETF (RFC 7946, 2016) | RFC 7946 | Active IETF standard |
| GML | 2000 | OGC / ISO TC 211 | 3.2.1 (ISO 19136:2007) | Active ISO/OGC standard |
| GeoPackage | 2014 | OGC | 1.4.0 (OGC 12-128r19) | Active OGC standard |
| File Geodatabase | 2006 | Esri (proprietary) | ArcGIS 10.x / Pro | Active; GDAL OpenFileGDB driver reads v9/v10 |
| Shapefile | ~1994 | Esri (de facto, 1998 whitepaper) | Stable since 1998 | Legacy; superseded by GeoPackage |
| SpatiaLite | 2008 | Alessandro Furieri | 5.x | Active; OGC adopted SpatiaLite GeoPackage extension |
Format Reference
Complete Format Matrix
| Format | Extension | Engine | Layer Split | Live | Export |
|---|---|---|---|---|---|
| AutoCAD DXF | .dxf | CAD | ✓ | ✓ | |
| AutoCAD DWG | .dwg | CAD | ✓ | ||
| MicroStation DGN v8 | .dgn | CAD | ✓ | ||
| Netcad NCZ | .ncz | NCZ | ✓ | ||
| Netcad NCA | .nca | NCZ | ✓ | ||
| KML | .kml | GIS | ✓ | ||
| KMZ | .kmz | GIS | ✓ | ||
| GML | .gml | GIS | |||
| GeoJSON | .geojson | GIS | |||
| CSV / TSV / TXT | .csv, .tsv, .txt | GIS | |||
| SpatiaLite / SQLite | .sqlite, .db | GIS | |||
| GPX | .gpx | GIS | |||
| File Geodatabase | .gdb | GIS | ✓ | ||
| Personal Geodatabase | .mdb | GIS | ✓ |
Format-Specific Notes
- DWG R2004+ requires ODA File Converter or LibreDWG — neither is bundled. The plugin searches for them and guides the user through setup.
- DGN v8 pure-Python reader does not render complex cell geometry or text as full geometry — represented as placeholder points. Full fidelity requires the GDAL DGNv8 driver.
- NCZ/NCA Engine v2 is validated against real municipal drawings. Drawings from very old or very new Netcad versions may use unregistered block types — these are skipped with a warning.
- KMZ Only KML documents are read; other archive contents are ignored unless referenced by GroundOverlay.
- GDB/MDB Live mode uses native CRS without transformation. For reprojection, use GeoPackage or Scratch mode.
- CSV/TSV The sniffer reads the first 100 lines. Geometry columns beyond line 100 must be selected manually.
OGR Format Driver Reference
The following table lists the GDAL/OGR drivers used for each format, their availability in standard OSGeo4W QGIS builds, and any known limitations.
| Format | OGR Driver | Read Support | Write Support | CRS Awareness | Known Limitations |
|---|---|---|---|---|---|
| DXF | DXF | Full | Partial (via QgsVectorFileWriter) | No | Curved entities segmentized; HATCH entities read as outlines; MTEXT not fully parsed |
| DWG (R2000) | CAD (libopencad) | Full | No | No | R2004+ files return 0 features; ODA File Converter needed |
| DGN v7 | DGN | Full | No | Optional (header) | v8 files fail; DGNv8 driver needed for modern files |
| DGN v8 | DGNv8 | Full (if available) | No | Optional | Requires ODA Teigha libraries; not in standard QGIS GDAL builds |
| KML | KML (LIBKML) | Full | Full | EPSG:4326 only | Large files (>100 MB) may exceed DOM memory limits |
| KMZ | LIBKML (via ZIP extraction) | doc.kml only | Yes (via QgsVectorFileWriter) | EPSG:4326 only | GDAL reads only doc.kml; 02CadGis reads all KML documents |
| GML | GML | Full | Full | Full | Namespace-sensitive; malformed schemas or inaccessible schemaLocation URLs may fail |
| GeoJSON | GeoJSON | Full | Full | EPSG:4326 only (RFC 7946) | Non-WGS84 CRS is a convention extension, not guaranteed interoperable |
| CSV/TSV/TXT | CSV (delimitedtext in QGIS) | Full | Full | User-specified or auto-detected | Sniffer reads first 256 KB; geometry columns beyond this must be manually selected |
| SpatiaLite | SQLite | Full | Full (GPKG for output) | Full | Reads SpatiaLite metadata; output always GeoPackage, not SpatiaLite |
| GPX | GPX | Full | No | EPSG:4326 only | Track segments, waypoints, and routes read as separate layers |
| File Geodatabase | OpenFileGDB | Full (v9/v10) | No | Full | Pre-v9 GDBs fail; Esri proprietary extensions unsupported; directory-based |
| Personal Geodatabase | PGeo | Full (if ODBC available) | No | Full | Requires 64-bit MS Access Database Engine; .accdb support varies by ODBC driver version |
| NCZ/NCA | None (proprietary) | N/A | N/A | Partial (SRS id + projection text) | No GDAL driver exists; 02CadGis NCZ Engine v2 is the only open-source reader |
Detailed Format Comparison: Geometry Support
| Geometry Type | DXF/DWG | DGN v8 | NCZ/NCA | KML/KMZ | GeoJSON | GML | GPKG Output |
|---|---|---|---|---|---|---|---|
| Point | POINT, TEXT, MTEXT, INSERT | Type 2 (point), 7 (text), 17 (text node) | Type 1 (point), 5 (text), 6 (symbol), 13 (block ref) | Point Placemark | Point | gml:Point | Point / MultiPoint |
| LineString | LINE, POLYLINE, LWPOLYLINE | Type 3 (line), 4 (linestring) | Type 2 (line), 7 (polyline), 9 (compressed curve) | LineString Placemark | LineString | gml:LineString, gml:Curve | LineString / MultiLineString |
| Polygon | LWPOLYLINE (closed), HATCH, 3DFACE | Type 6 (shape, closed) | Type 7 (closed polyline), 10 (box), 11 (map sheet), 12 (triangle), 15 (smart object) | Polygon Placemark | Polygon | gml:Polygon, gml:Surface | Polygon / MultiPolygon |
| Circle/Arc | CIRCLE, ARC | Type 12 (arc), 14 (ellipse) | Type 3 (circle), 4 (arc) | N/A (must be segmentized) | N/A | gml:Circle, gml:Arc | Segmentized to LineString |
| Spline/Curve | SPLINE | Type 24 (B-spline), 25 (curve) | Type 9 (compressed curve) | N/A | N/A | gml:BSpline, gml:Bezier | Segmentized to LineString |
| Text/Label | TEXT, MTEXT, ATTDEF | Type 7 (text), 17 (text node) | Type 5 (text) | Placemark name/description | feature.properties | gml:featureMember attributes | Point + label column |
| Block/Cell/Insert | INSERT | Type 34 (shared cell), 35 (shared cell def) | Type 13 (block ref), 15 (smart object) | N/A | N/A | N/A | Decomposed or placeholder Point |
Format Size Characteristics
The following table provides guidance on expected file sizes and practical limits for each format, based on real-world municipal and planning datasets.
| Format | Typical Size Range | Practical Upper Limit | Encoding Efficiency | Notes |
|---|---|---|---|---|
| DXF (ASCII) | 100 KB – 500 MB | ~1 GB (GDAL memory) | Low (text-based, verbose) | ASCII DXF is 5–10× larger than binary equivalent. Binary DXF is rare. |
| DWG | 100 KB – 200 MB | ~500 MB (then ODA conversion) | High (binary, compressed) | DWG is compact; ODA DXF intermediate may be larger. |
| DGN v8 | 50 KB – 100 MB | ~200 MB (pure-Python reader memory) | Medium (binary with optional zlib compression) | Compressed DGN files are smaller. Element count, not byte size, determines read time. |
| NCZ/NCA | 50 KB – 20 MB | ~50 MB (municipal drawings) | High (binary, compact records) | Typical municipal drawing: 1–5 MB, 5,000–15,000 entities. |
| KML | 1 KB – 200 MB | ~64 MB (GroundOverlay scan limit) | Low (XML, verbose) | KML over 64 MB skips GroundOverlay scan for safety. |
| KMZ | 5 KB – 500 MB | ~1 GB (ZIP extraction) | Medium (ZIP compressed KML) | KMZ compression typically 5–10×. Temp extraction needs disk space. |
| GeoJSON | 1 KB – 500 MB | ~1 GB (GDAL memory) | Low (text-based) | GeoJSON is the least compact vector format. Use GeoPackage for large datasets. |
| GML | 10 KB – 1 GB | ~2 GB (DOM memory) | Very low (XML, extremely verbose) | GML can be 10–50× larger than equivalent GeoPackage. Schema validation adds overhead. |
| GeoPackage | 1 KB – 10 GB | ~140 TB (SQLite maximum) | High (binary, SQLite storage) | Recommended output format. Efficient storage, spatial index, portable. |
| File Geodatabase | 1 MB – 100 GB | ~1 TB (directory-based) | High (binary, Esri-proprietary) | Live mode avoids materialising. Conversion copies all features. |
| CSV/TSV | 1 KB – 1 GB | ~2 GB (GDAL text scan) | Very low (text-based, no compression) | Sniffer reads only first 256 KB. For files >100 MB, use database import instead. |
Interoperability Notes
- DXF to GeoPackage round-trip. DXF exported from 02CadGis preserves layer names but loses CAD-specific properties (colour index, linetype, block definitions). It is intended for GIS collaborators, not CAD round-tripping. For full-fidelity CAD exchange, use the original DWG/DXF.
- KML to GeoPackage CRS conversion. KML's fixed EPSG:4326 means all coordinates are in decimal degrees. Converting to a projected CRS (e.g. TUREF / TM39) requires a datum transformation from WGS 84 to the target datum, which introduces a small error (typically <1 m for Helmert transformation). For high-precision cadastral work, verify that the source KML coordinates meet your accuracy requirements before projection.
- GeoJSON and non-WGS84 CRS. RFC 7946 mandates WGS 84 (EPSG:4326). GeoJSON files with alternative CRS (a legacy convention from the 2008 specification) will be read by GDAL but may not be interoperable with other tools. 02CadGis reads the CRS as declared and transforms to the target CRS.
- Multi-geometry-type layers. No GIS format (except GeoPackage with generic geometry columns) stores mixed geometry types in a single layer. 02CadGis splits CAD layers with mixed types into separate output layers suffixed with the geometry type (e.g.
BUILDINGS_POINT,BUILDINGS_LINESTRING,BUILDINGS_POLYGON). This is deterministic and documented, but the suffix naming should be accounted for in downstream workflows.
Appendix A — CRS Quick Reference
| Drawing Says | Easting | EPSG | Label |
|---|---|---|---|
| ITRF / 3 / Zone 39 | 6 digits | 5257 | TUREF / TM39 |
| ITRF / 3 / Zone 39 | 8 digits | 5273 | TUREF / 3° GK zone 13 |
| ED50 / 3 / Zone 33 | 6 digits | 2321 | ED50 / TM33 |
| ED50 / 3 / Zone 33 | 8 digits | 2208 | ED50 / 3° GK zone 11 |
| WGS 84 / UTM zone 36N | 6 digits | 32636 | WGS 84 / UTM 36N |
| Geographic (lat/lon) | ≤3 digits | 4326 | WGS 84 |
| (empty / unrecognised) | — | — | User must select manually |
Complete EPSG code tables for all 28 Turkish projected CRS variants are maintained in core/crs_detect.py. The detector covers TUREF TM (5253–5259), TUREF GK (5269–5275), ED50 TM (2319–2325), ED50 GK (2206–2212), WGS 84 UTM (32635–32638), and ED50 UTM (23035–23038).
Appendix B — MPYY Style Bundle
The MPYY transfer draws plan layers with the Ministry's gösterim, rewritten to the MPYY 1.1.7 schema and carried inside the plugin under mpyy/. Three plan levels are covered:
| Level | Plan | Reference scale | SLD styles |
|---|---|---|---|
| UIP | Uygulama İmar Planı — implementation plan | 1/1000 | 94 |
| NIP | Nazım İmar Planı — master plan | 1/5000 | 86 |
| CDP | Çevre Düzeni Planı — environmental plan | 1/25,000 and above | 71 |
251 styles in total, in mpyy/styles/mpyy_sld/. The bundle also carries what those styles reference: the tarama tiles and the plan symbol fonts and catalogue symbols under mpyy/resources/ (131 font files, 45 catalogue symbols). mpyy/SYNC_MANIFEST.json records the sha256 of every file. No individual colour or width is reproduced here on purpose: the styles are applied from the bundle, and a value transcribed into prose is a value that can silently drift away from the one actually drawn.
Appendix C — Glossary
| Term | Definition |
|---|---|
| ACI | AutoCAD Color Index — 255 indexed colours in DXF/DWG. Mapped to RGB for QGIS rendering. |
| CAD layer / Level | Named grouping of entities within a CAD drawing. DXF: Layer; DGN: Level. The plugin splits by this grouping. |
| Collinear simplification | Removing intermediate vertices lying on a straight line between neighbours. Reduces vertex count without visual change. |
| e-Plan | The Turkish Ministry's electronic plan portal (eplan.csb.gov.tr), source of the official gösterim style set. The plugin ships that symbology rewritten to the MPYY schema, as the bundle under mpyy/. |
| Gösterim | Turkish: the official visual representation (colour, hatch, line type) of a plan function per Ministry standards. |
| Live mode | Zero-copy reference — data stays in the source file; QGIS reads on demand. |
| Mojibake | Garbled text from incorrect encoding interpretation. Turkish CAD files frequently exhibit CP1254↔CP1252↔UTF-8 mojibake. |
| MPYY | Mekânsal Planlar Yapım Yönetmeliği — Turkish Spatial Planning Regulation. Defines the official UIP tabaka catalog. |
| NCZ / NCA | Netcad's native binary drawing formats. NCZ is standard; NCA is a compatible variant. |
| ODA | Open Design Alliance — provides ODAFileConverter for modern DWG conversion. |
| MPYY transfer | The import mode that writes an imar plan's tabaka into MPYY 1.1.7 feature types and draws them with the Ministry's UIP / NIP / CDP styles. Replaced the earlier PlanGML styling mode at 4.0.0. |
| Plan level | Which of the three official style sets applies: UIP (implementation plan, 1/1000), NIP (master plan, 1/5000) or CDP (environmental plan, 1/25,000 and above). Auto reads it from the file name. |
| Plan notation | The drawing's own notation symbols — building-rights circles (nizam / kat, TAKS / KAKS, E =, Yençok) and road-width circles — written to a <file>_PLAN_NOTATION point layer where the planner placed them. |
| PlanGML | Turkish Ministry's XML-based spatial plan data standard. 02CadGis does not read or write PlanGML documents; the name survives only in the module that resolves a CAD tabaka to its official MPYY identity (core/plangml_schema.py) and in a few internal comments. The user-facing feature is MPYY transfer. |
| SRS id | Netcad-internal coordinate system identifier. Not an EPSG code — never use as one. |
| Tabaka | Turkish: layer. In planning, a named spatial feature category (e.g. PL_KONUT) per the MPYY. |
| Tarama | Turkish: hatch pattern. Official tile image used as polygon fill for certain plan functions. |
| @TAB | Netcad's internal attribute table format inside NCZ files. Linked to geometry by name/label. |
Appendix D — Bibliography & Third-Party Notices
CAD/GIS Conversion & Interoperability
Al-Sabban, W., Issa, R.R.A., & Olbina, S. (2022). The C2G Framework to Convert Infrastructure Data from Computer-Aided Design (CAD) to Geographic Information Systems (GIS). Informatics, 9(2), 42. DOI: 10.3390/informatics9020042
Zhu, J., Wright, G., Wang, J., & Wang, X. (2018). A Critical Review of the Integration of Geographic Information System and Building Information Modelling at the Data Level. ISPRS International Journal of Geo-Information, 7(2), 66. DOI: 10.3390/ijgi7020066
Liu, X., Wang, X., Wright, G., Cheng, J.C.P., Li, X., & Liu, R. (2017). A State-of-the-Art Review on the Integration of Building Information Modeling (BIM) and Geographic Information System (GIS). ISPRS International Journal of Geo-Information, 6(2), 53. DOI: 10.3390/ijgi6020053
Sani, M.J. & Abdul Rahman, A. (2018). GIS and BIM Integration at Data Level: A Review. International Archives of the Photogrammetry, Remote Sensing and Spatial Information Sciences, XLII-4/W9, 299–306. DOI: 10.5194/isprs-archives-XLII-4-W9-299-2018
Şenol, H.İ. & Gökgöz, T. (2024). Integration of Building Information Modeling (BIM) and Geographic Information System (GIS): A New Approach for IFC to CityJSON Conversion. Earth Science Informatics, 17, 3437–3454. DOI: 10.1007/s12145-024-01343-1
Line Simplification & Geometric Algorithms
Douglas, D.H. & Peucker, T.K. (1973). Algorithms for the Reduction of the Number of Points Required to Represent a Digitized Line or Its Caricature. Cartographica: The International Journal for Geographic Information and Geovisualization, 10(2), 112–122. DOI: 10.3138/FM57-6770-U75U-7727
Hershberger, J. & Snoeyink, J. (1992). Speeding Up the Douglas-Peucker Line-Simplification Algorithm. Proceedings of the 5th International Symposium on Spatial Data Handling, 134–143.
Coordinate Reference Systems & Geodesy
Knudsen, T. & Evers, K. (2017). Transformation Pipelines for PROJ.4. FIG Working Week 2017 Proceedings, Helsinki, Finland. URL: fig.net
Evers, K. & Knudsen, T. (2017). Transformation Pipelines for PROJ.4. Geophysical Research Abstracts, 19, EGU2017-8050. URL: copernicus.org
PROJ Contributors. (2024). PROJ — Coordinate Transformation Software Library. Open Source Geospatial Foundation. proj.org
ISO/TC 211. (2020). ISO 19136-1:2020 — Geographic Information — Geography Markup Language (GML) — Part 1: Fundamentals. International Organization for Standardization.
Geospatial Data Standards & Formats
OGC. (2015). OGC KML 2.3. OGC Standard 12-007r2. URL: docs.ogc.org
Butler, H., Daly, M., Doyle, A., Gillies, S., Hagen, S., & Schaub, T. (2016). The GeoJSON Format. RFC 7946, Internet Engineering Task Force. DOI: 10.17487/RFC7946
Yutzler, J. & Daisey, P. (Eds.). (2024). OGC GeoPackage Encoding Standard, Version 1.4.0. OGC Standard 12-128r19. URL: geopackage.org
OGC. (2006). OpenGIS Symbology Encoding Implementation Specification, Version 1.1.0. OGC Standard 05-077r4. URL: docs.ogc.org
Software & Tools
GDAL/OGR Contributors. (2024). GDAL — Geospatial Data Abstraction Library. OSGeo. gdal.org
Open Design Alliance. (2024). ODA File Converter. opendesign.com
Turkish Planning Regulation & Standards
T.C. Çevre, Şehircilik ve İklim Değişikliği Bakanlığı. (2024). Mekânsal Planlar Yapım Yönetmeliği (MPYY). Resmî Gazete.
T.C. Çevre, Şehircilik ve İklim Değişikliği Bakanlığı. (2024). e-Plan Gösterim Kataloğu. eplan.csb.gov.tr
MpyyUipDb_2026_02_27.gpkg catalog is compiled and maintained by Yusuf Eminoğlu from the Ministry's published tabaka lists. The style bundle under mpyy/ carries the tarama tiles and the plan symbol fonts those styles reference — among them font files whose redistribution terms are not established; the bundle's own notice records what it contains and does not assert a right to redistribute them. The NCZ decoder shipped in versions 0.1.0 through 4.1.2 was adapted from Jeomatik NCZ Reader (Copyright © 2026 Erdinç Örsan ÜNAL, GPL-2.0-or-later); the current tree carries only 02CadGis's own v2 engine. The vendored olefile library is used under its BSD license for DGN v8 OLE2 reading. Full attribution: THIRD_PARTY_NOTICES.md · THIRD_PARTY_NOTICES.md (GitLab).
Appendix E — NCZ Block Type Reference
The following table documents the known NCZ block types understood by Engine v2. Types not listed here are container blocks (kinds {0, 5, 14, 48, 108, 111, 132, 150, 180}) that may embed geometry records, or are unrecognised and skipped with a logged count.
| Kind | Name | Decoder | Key Geometric Semantics |
|---|---|---|---|
| 1 | Point | decode_point | Single coordinate pair (northing-first). Name string at G+86. Used for point features, survey markers, and CAD symbols. |
| 2 | Line | decode_line | Two-vertex segment: start at +8/+16, end at (size-19)/(size-11). Simplest CAD primitive. |
| 3 | Circle | decode_circle | Centre point + diameter (from f64 difference at +50 and +66). Segmentized to polygon in output. |
| 4 | Arc | decode_arc | Centre + radius + start/end angles (radians). Used for curved road alignments and parcel boundaries. |
| 5 | Text | decode_text | Insertion point + text string + height + rotation. Label field candidate in output. Multiple fallback text locations. |
| 6 | Symbol | decode_symbol | Insertion point + symbol code + size + rotation. Point marker from Netcad symbol library. |
| 7 | Polyline / Polygon | decode_polyline | Variable-length vertex array (24 bytes per vertex: 3×f64). Closure detected by endpoint proximity. Rectangle metrics computed for oriented boxes. |
| 9 | Compressed Curve | decode_compressed_curve | Origin + sequence of f32 delta pairs (18-byte records). Efficient storage for smooth curves; duplicates skipped by proximity check. |
| 10 | Box | decode_box | Two opposite corners defining an oriented rectangle. Rotation in radians. Plan name token extracted for labelling. |
| 11 | Map Sheet | decode_map_sheet | Four-corner bounding box. Sheet name extracted as first printable length-prefixed string. Used for map grid frames. |
| 12 | Triangle | decode_triangle | Three vertices with optional Z. Area validated (> 0.0001) to reject degenerate triangles. Used in TIN surfaces and 3D meshes. |
| 13 | Block Reference | decode_block_reference | Insertion point + optional name + rotation. References a block definition stored elsewhere in the file. |
| 15 | Smart Object | decode_smart_object | Complex compound entity: width, height, rotation (grads), scale, grid coordinates, label. Represents parametric CAD objects. Rotation conversion: grads × 0.9 = degrees. |
NCZ Coordinate Conventions
All coordinate pairs in NCZ geometry records are stored northing-first: the first f64 value at +8 is the northing (Y in GIS), and the second f64 value at +16 is the easting (X in GIS). The map_point(first, second) helper transposes these to GIS convention: {"x": second, "y": first, "z": z}. The transposition is applied once, at a single point in the decoder, so no downstream consumer sees drawing order. Z values are stored as f32 at offset +24; some record types store an alternative Z at +28 (used as fallback when +24 is 0.0). All coordinate values must be finite and within [−108, 108] to pass the range validation gate in finite_pair_in_range().
@TAB Attribute Table Variants
@TAB records are classified into three variants by the attribute decoder:
| Variant | Detection Criteria | Key Fields | Use Case |
|---|---|---|---|
| Label | Printable length-prefixed label at offset 28/29, all bytes in ASCII printable range | label text, prefix f32, code u16, style code u32, 3 coordinate pairs (f64) | Named entities with spatial reference: parcels, buildings, zones. Label links to geometry entity name. |
| Segment | Record ≥ 119 bytes, f64 pairs at 17/25, 45/53, 87/95, 103/111 all look like projected coordinates (|v| in [103, 108]) | 4 coordinate pairs, style code, 4 flag bytes | Linear referencing: road segments, pipeline sections, cadastral edges. |
| ASCII | Anything else. All printable length-prefixed ASCII fields collected | ascii_values (pipe-joined), table_ref_inline | Tabular metadata: material schedules, quantity takeoffs, code lists. |
Tables are grouped by their @TAB marker suffix (e.g. @TAB1, @TAB2) and presented as separate checkable rows in the dock's layer tree. Checking both a geometry layer and its matching @TAB table triggers an automatic attribute join on entity name (for label variants) or on spatial proximity (for segment variants, joining to the nearest polyline segment).
Producer-Specific Quirks in NCZ Files
Netcad's proprietary format exhibits several documented quirks that the engine handles transparently:
- Smart object S0 suppression. When a drawing contains at least one smart object (type 15), the producer emits "S0" symbol entities (type 6) on layer code 0 alongside each smart object. These are not real symbols; they are internal implementation artefacts. The
_drop_smart_object_artifactsfunction removes them when any SmartObject entity is present. - 1-based layer indexing. Some NCZ versions index layers from 1 rather than 0. The
DrawingMetadata.layer_name()andlayer_color()methods trylayer_codefirst, thenlayer_code - 1as a fallback. This handles both conventions without configuration. - Near-black-blue normalisation. A layer colour of ARGB (255, 0, 0, 1) — effectively pure black with a blue LSB — is a known Netcad producer artefact. The
_normalize_colorfunction maps this to pure black (255, 0, 0, 0). - Colour code 0 = by layer. A per-entity colour code of 0 means "use the layer colour." Colour code 1 forces blue; colour code 255 forces red. Any other non-zero colour code is passed through as-is (no lookup).
- Version string encoding. The producer version string (block kind 25) uses the Netcad OEM codepage for Turkish characters, decoded by
decode_oem_text()which maps byte values 208, 221, 222, 240, 253, 254 to their Turkish equivalents. - GIS layout shift. Geometry records of kind 22 (GIS layout) have all geometry-related fields shifted +28 bytes relative to kind 21 (plain layout). The
GeometryRecord.shiftfield encodes this (0 or 28), and all decoders addrecord.shiftto the relevant offsets. This is invisible to callers but critical for correct decoding.
Benchmark Reproducibility
All performance claims in this manual are reproducible. The benchmark script (benchmarks/ncz_engine_benchmark.py) records the drawing's SHA-256 and byte size, the Python runtime (version, implementation, platform, processor), warmup and run counts, p50 and p95 parse duration, MiB/s throughput, entities per second, peak Python allocation (via tracemalloc), entity and attribute-table counts, and a normalised output digest. Every measured run is digested, and a run raises rather than reporting if the digests differ — non-deterministic output is a failure, not a benchmark. Defaults are 2 warmups and 7 measured runs; --runs must be at least 3 for the p95 to mean anything. To reproduce:
python zero2cadgis/benchmarks/ncz_engine_benchmark.py \
C:/path/small.ncz C:/path/large.ncz \
--label release-4.1.2 --output C:/path/release-4.1.2.json
The output digest covers each entity's kind, layer, colour and label, every
coordinate to 17 significant digits, and every @TAB cell, so it is
sensitive to any decode change at all; the label field is free text for
before/after comparison. The synthetic fixture corpus
(tests/ncz_fixtures.py) exercises the decoder paths, both block
layouts, embedded containers, metadata blocks and @TAB tables.
Validation against real municipal drawings is opt-in: set
ZERO2CADGIS_NCZ_FIXTURE to a drawing you are licensed to use and the
parity test runs against it. That test was last validated on a 1.2 MiB /
8,163-entity municipal Netcad file (60 layers, ITRF / 3° zone 42).
Because the v1 decoder is no longer in the tree, the benchmark compares releases of the v2 engine against each other; the numbers are a regression guard for future work rather than a v1-versus-v2 comparison.
Appendix F — Configuration Reference
02CadGis keeps no configuration file of its own. Everything it remembers between
sessions lives either in QGIS's QSettings store or in the two caches
described below, and every override it honours is an environment variable. This
appendix lists the keys the shipped code actually reads and writes.
QSettings keys
All keys sit in the QSettings scope QGIS itself uses, so they are
per-user and survive plugin upgrades.
| Key | Default | Description |
|---|---|---|
zero2cadgis/oda_converter_path | (empty) | Path to ODAFileConverter.exe, set through the interactive setup dialog. When present it overrides every automatic ODA discovery path. |
zero2cadgis/opts/<widget> | (unset) | The checked state of each persistent checkbox, stored under that checkbox's own widget name. Written on every toggle; read once when the dock is built. The eleven persisted boxes are chk_conv_simplify, chk_conv_clean, chk_conv_kml_expand, chk_conv_raster, chk_conv_load, chk_ncz_simplify, chk_ncz_clean, chk_ncz_augment, chk_ncz_style, chk_ncz_label and chk_ncz_join. A key with no stored value leaves the widget at its built-in default. |
zero2cadgis/opts/ncz_tolerance | (widget default) | Closure tolerance of the Netcad tab, in drawing units. Persisted on every change. |
zero2cadgis/last_import_dir | (empty) | Folder the last source file was picked from; the next file dialog opens there. |
zero2cadgis/last_export_dir | (empty) | Folder the last export was written to; the next export dialog opens there. |
Option state is deliberately per-checkbox rather than one blob, so a key that
is missing, unparsable or written by an older version falls back to the widget's
own default instead of resetting the whole panel: the reader accepts only
true/1 as “checked” and ignores anything it
cannot parse.
Environment variables
| Variable | Read by | Effect |
|---|---|---|
ZERO2CADGIS_NCZ_CACHE_DISABLE | NCZ index cache | Set to 1, true or yes to stop reading and writing the per-drawing NCZ index cache. Every drawing is then indexed from scratch. |
ZERO2CADGIS_OGR_CACHE_DISABLE | OGR catalog cache | Same values; disables the Geodatabase / database layer-catalog cache. |
ZERO2CADGIS_NCZ_FIXTURE | tests/test_ncz_engine_v2.py | Path to a real NCZ drawing; the opt-in validation test is skipped unless it is set. No production code path reads it. |
ZERO2CADGIS_MPYY_DB | tests/test_plangml_schema.py | Path to the Ministry MpyyUipDb GeoPackage; the opt-in catalog test is skipped unless it is set. No production code path reads it. |
MPYY_TABAKA_ESLESME | Layer-name mapping | Overrides the location of the per-user file that remembers confirmed layer-name mappings (see below). Intended for tests and shared workstations. |
ODA_FILE_CONVERTER_PATH | ODA discovery | Path to ODAFileConverter.exe. Consulted during automatic discovery, for CI and containerised environments where the usual install locations are absent. |
ODA_PATH | ODA discovery | Alternative spelling for the ODA installation directory. |
ODA_CONVERTER | ODA discovery | Alternative spelling for the converter executable path. |
The three ODA spellings are discovery hints, not overrides: the
zero2cadgis/oda_converter_path setting above still wins, so a path
set in the dialog is what gets used.
Files and caches written outside QSettings
| Path | Contents |
|---|---|
%LOCALAPPDATA%\zero2cadgis\ncz_index\<hash>.json | The NCZ index cache: one JSON file per drawing, named by a hash of the drawing's absolute path and keyed to its size and modification time. Falls back to $XDG_CACHE_HOME and then ~/.cache where LOCALAPPDATA is unset. Rebuilt automatically when a drawing changes; Clear cache on the Netcad tab removes it. |
<QGIS profile>/mpyy/tabaka_eslesmeleri.json | The confirmed layer-name mappings — the ones a person ticked in the match dialog — so the same tabaka name resolves by itself on the next drawing. Written atomically through a temporary file and a rename, so an interrupted write cannot leave a half-file. With no QGIS the fallback is ~/.mpyy/. The file is deliberately shared with the other plugins that carry this module. |
Both are caches of one kind or another: deleting either costs time on the next run and nothing else. The mapping file is the exception — it holds decisions a person made, so back it up before clearing a QGIS profile.