# Cross-section line edits The Sections-view toolbar in the project frame includes six commands for editing the polyline data of a single line definition within a cross-section. Each command works either on the **active section only** or across a **chainage range** (batch mode). Both modes share the same dialog; selecting the chainage-range radio button enables the From/To fields. | Toolbar button | Effect | |---|---| | **Copy Line** | Copies the source line's points + bulges + closed-state into the target line. | | **Move Line** | Same as Copy, then clears the source line's data — a cut-and-paste between line slots. | | **Offset Line** | Computes a parallel offset of the source line and writes it into the target. Distance is signed: **+ moves outside (away from the alignment axis); − moves inside (toward the axis)**. | | **Delete Line** | Clears all points of one line. | | **Remove Duplicates** | Drops consecutive points whose 2D distance from the previous kept point is below a tolerance (metres). Preserves bulges of kept points and the line's closed-state. | | **Translate Line** | Shifts every point of one line by `(dX, dY)` in metres. Z, bulges, and closed-state unchanged. | ## Common dialog elements - **Source line / Target line** — dropdowns of all measured line definitions in the active alignment. For Move and Copy, source and target must be different. For Offset, source = target is permitted (in-place offset). For Delete, Remove Duplicates and Translate Line there is only one **Line** dropdown. - **Apply to** - **Active section only** — runs on the currently selected section in the Sections view. - **Chainage range** — iterates every cross-section whose station falls in the inclusive range. The From/To fields default to the alignment's first and last stations. - **Skip sections where target already has data** (Copy / Move / Offset) — when checked, sections whose target slot already has points are left untouched and counted in the post-run summary as "skipped". After OK, a summary box reports `Visited N section(s). Applied: M. Skipped: K (target had data) / L (source empty).` Counts equal `Visited` (every visited section is either applied or skipped). When the run touches the active cross-section, the section canvas reloads from the updated model immediately — no manual refresh, no need to switch sections and back. ## Offset side rule For each segment of the source polyline, "outside" is the perpendicular direction whose midpoint moves *farther* from the alignment axis (the `(0, 0)` point in the section's offset/elevation plane). For a tunnel polyline that wraps around the section interior, this consistently means away from the tunnel axis. For unusual line shapes (e.g., a short measured line off to one side) the rule may pick a counterintuitive side; in that case use a negative distance to flip. ## Behavior matrix | Pre-condition | Copy | Move | Offset | Delete | |---|---|---|---|---| | Source has no points | Skipped: source empty | Skipped: source empty | Skipped: source empty | Skipped: line already empty | | Target already has data, "Skip" checkbox on | Skipped: target had data | Skipped: target had data | Skipped: target had data | n/a | | Source = target | Rejected (OK disabled) | Rejected | In-place offset (allowed) | n/a | ## Remove Duplicates dialog - **Tolerance (m)** — the maximum 2D distance between consecutive points that still counts as a duplicate. Defaults to `0.005` (5 mm). The first point is always kept; subsequent points whose distance from the most recent kept point is **at or below** the tolerance are dropped. The bulge that travels with each kept point is preserved. - The summary reports `Visited N section(s). Modified: M. Skipped: K (line empty).` Sections where the scan finds no duplicates are counted as visited but not modified. ## Translate Line dialog - **dX (m) / dY (m)** — translation vector in the section's local offset/elevation plane. X follows the line-definition's offset axis (right-positive), Y follows elevation. Both can be negative. Translating by `(0, 0)` is rejected at the dialog (OK button stays disabled). - Every point of the chosen line is shifted by `(dX, dY)`; Z is preserved. Bulges and closed-state are unchanged. - The summary reports `Visited N section(s). Modified: M. Skipped: K (line empty).` ## Notes - **Bulges:** Copy, Move, Remove Duplicates, and Translate Line preserve bulges exactly. Offset drops bulges (output polyline is straight-segment only). Acceptable accuracy for tunnel measured lines; revisit if exact-arc lines start using these commands. - **Closed state:** Copy and Move mirror the source's `coDefault` / `coForceClosed` / `coForceOpen` override. Offset, Remove Duplicates, and Translate Line preserve the source's closed state. - **Self-intersection:** A closed polyline offset inward beyond its inradius will self-intersect. v1 emits the raw self-intersecting polyline; clean it up by hand or undo. - **Undo:** Batch operations are not undoable as a single transaction. Confirm the summary box's counts before continuing. ## Section metadata Each tunnel can declare a set of metadata fields (excavation date, blast number, crew name, free-form notes…). Field schema is defined per tunnel; values are entered per cross-section. ### Defining the schema 1. Open *Tunnel Settings…* on the active alignment. 2. Switch to the **Metadata Fields** tab. 3. Click **Add Field**, enter a name (`[A-Za-z0-9_]`), pick a Type. Optionally tick *Required* and fill *Default* / *Description*. 4. For *Enum* type, click **Edit Enum Values…** to add the allowed choices. 5. Buttons **Move Up** / **Move Down** reorder the schema; **Remove Field** drops a definition (with a confirm prompt that names how many sections have values to clear). New tunnels start with three example fields: `ExcavationDate` (date), `BlastNumber` (integer), `Notes` (text). Delete what you don't need. ### Entering values per section Right-click a cross-section in the project tree → **Edit Metadata…** to open the per-section editor. Each field renders its own widget: | Field type | Widget | |---|---| | Text | text edit | | Integer | number-only edit with up/down arrows | | Number | floating-point edit | | Date | date picker (`yyyy-mm-dd`) | | Boolean | checkbox | | Enum | dropdown of the allowed values | *OK* commits; *Cancel* discards every change made in the dialog. ### Using metadata in layouts Layout TEXT entities can inject metadata via the `META` field: | ProviderArgs | Result | |---|---| | `field=META, meta=ExcavationDate` | `2026-04-15` (default `yyyy-mm-dd`) | | `field=META, meta=ExcavationDate, fmt=dd/mm/yyyy` | `15/04/2026` | | `field=META, meta=BlastNumber, prefix=Blast #` | `Blast #42` | | `field=META, meta=Crew` | `Alpha` (the canonical case from the schema) | ### Activity log Schema mutations (add/rename/type-change/remove) and per-section value commits land in the project's activity log under the `metadata` category, viewable in the Calendar workspace. ### Round-tripping with LandXML Both the schema and the per-section values round-trip through LandXML import/export. The export dialog has an opt-out **"Include section metadata"** checkbox under TunnelCAD Extension Details (default on). Old LandXML files without metadata extensions load with the alignment's seeded defaults. ### Bulk editing (matrix view) For long station lists, the per-section editor is slow. Right-click a tunnel in the project tree → **Edit Metadata Matrix...** to open a spreadsheet-style grid: rows are sections in chainage order; columns are Station / Name / one per metadata field. Per-column editors switch automatically (text / number / date / checkbox / dropdown). Three helpers above the grid: - **Fill Down** copies the active cell's value into every selected row below it (single column at a time). - **Clear** wipes selected metadata cells back to empty. - **Paste** drops a tab-separated rectangular block from the clipboard — works for paste-from-Excel. OK commits; Cancel restores the snapshot taken when the dialog opened. The Metadata Fields tab in *Tunnel Settings* also has an **Edit Matrix...** button so you can jump straight from defining a new field to filling values across every section. ### Including metadata in DXF exports The Sections-to-DXF export dialog has a per-mode checkbox: - **Mode A** (per-section local plane) → captions appear on a `METADATA` layer below each section's bounding box. - **Mode C** (atlas / sheet layout) → captions appear inside each cell, stacked below the title line. - **Mode B** (combined world XYZ) does **not** offer the option — 3D-stacked text labels are illegible. Each non-empty metadata value emits one `Field: Value` line. Empty values are skipped. Off by default. ### Including metadata in PDF reports The three section-level PDF reports (Line Data / Line vs Theoretical / DR Trend) have a per-dialog checkbox **Include section metadata** (default off). When on: - The PDF gains a small two-column metadata table at the top of each per-section detail page (one row per non-empty value). - The XLSX export adds one column per metadata field at the right end of the per-section sheet — handy for pivot tables. ### Mass Table The Mass Table dialog has its own **Show metadata columns** checkbox. When on, the grid + every export (CSV / XLSX / PDF) gain one column per defined metadata field, formatted per the field's type. ## Edit Line Data For typing-based corrections to measured-line points (paste from Excel, fix a bad offset by typing, reorder rows), open the **Edit Line Data...** dialog from the section toolbar or the project-tree right-click on a cross-section. The dialog shows one cross-section's chosen line as a grid: | Column | Meaning | Editable | |-----------------|------------------------------------------------------------------------------------------|----------| | `#` | Point index (auto-numbered). | no | | `Offset (m)` | Lateral offset from the alignment axis. | yes | | `Elevation (m)` | Vertical position on the section's local plane. | yes | | `DR (mm)` | Computed deviation from the line's reference (template or measured). `--` when no reference is configured. Recomputes live as you type Offset/Elevation. | no | The `#` and `DR` columns are read-only — the in-cell editor will not open for them. Switch lines via the **Line** combo at the top — pending edits to the previous line are kept until you click OK or Cancel. Buttons on the right add/delete rows, move the active row up/down, reverse the whole point order, sort all rows by ascending Offset (**Sort by X**), or toggle the line's Closed flag. OK commits all changes; Cancel restores every line modified during the dialog session, including pre-existing bulges that the dialog doesn't surface as columns. Pasted values follow the standard `TStringGrid` paste path — copy a 2-column block from Excel and paste into the Offset/Elevation pair to bulk-update points.