# Compass Traverse GIS Manual

QGIS プラグイン `Compass Traverse GIS` の基本操作と、野帳・計算・レイヤ管理の考え方をまとめた簡易マニュアルです。

A quick reference for `Compass Traverse GIS` — field notebook entry, traverse computation, layer management, and export.

## 1. 概要

このプラグインは、コンパス測量の野帳入力、接続点・閉合点管理、トラバース計算、レイヤ生成、帳票エクスポートを QGIS 上で一体的に扱うための作業画面です。

レイヤはプラグイン管理レイヤとして生成されます。必要に応じてシンボロジ変更はできますが、元データ編集は野帳テーブル側で行ってください。

## 2. 基本構成

左パネル | `データ状態`、`プロジェクト` / `作業名` 切替、`ブロック名称`、`成果物`
野帳 タブ | 野帳入力、測量設定、接続点・閉合点、除外区間、位置入力
`プロジェクト` タブ | `プロジェクト管理`、`計算サマリー`、言語切替

## 3. `プロジェクト` / `作業名` の考え方

このプラグインでは、`プロジェクト` が親グループ、`作業名` が個別の測量データです。`プロジェクト` では実データの一覧表示や新規登録・削除を行い、`作業名` で現在扱う実データを切り替えます。

`プロジェクト` | 複数の `作業名` をまとめる親グループです。左パネルの `プロジェクト` コンボから、実データの一覧表示や新規登録・削除を行います。
`作業名` | 実際の測量データ単位です。野帳、位置情報、計算状態、`プロジェクト` タブの表示内容は `作業名` ごとに保存されます。
切替時の動作 | `作業名` を切り替えると、その実データに保存されている野帳・位置・計算状態・`プロジェクト` タブの内容が表示されます。

`プロジェクト` / `作業名` の内容は、QGIS プロジェクトと同じフォルダに作られる SQLite に保存されます。QGIS プロジェクト未保存時は保存先が確定しないため、先に QGIS プロジェクトを保存してください。
図解: `プロジェクト` と `作業名` の関係
プロジェクト
道路改良A
作業名
道路改良A / 右岸測量

### プロジェクト一覧

道路改良A
森林境界B
新規プロジェクトを追加...

### 作業名一覧

道路改良A / 右岸測量
道路改良A / 横断追加
作業名を削除...
`プロジェクト` では実データの一覧表示や新規登録を行い、`作業名` を切り替えるとその実データに保存されている野帳・位置・`プロジェクト` タブの内容が表示されます。

## 4. `データ状態`

左パネル上部の `データ状態` には、現在の保存先とワークスペース切替機能が表示されます。

`現行データ` | 現在読み込まれている SQLite ファイル名です。QGIS プロジェクト未保存時は `データ未作成` と表示されます。
`切替` | 退避済みデータがある場合に有効になります。保存済みの別ワークスペースへ切り替えます。
`新規作成` | 現在の SQLite をアーカイブし、新しいワークスペースを作成します。実行前に QGIS プロジェクトを保存してください。

## 5. `プロジェクト` タブの編集

`プロジェクト管理` の表は、左列が `項目`、右列が `値` です。基本的には右列の `値` 側を編集しますが、`完了フラグ` だけは通常入力ではなく、該当セルのダブルクリックで状態を切り替えます。

値を入力する項目 | `プロジェクト名`, `作業名`, `測定者`, `測定日時`, `年度基準日`, `事業年度`, `年度繰越`, `事業樹別`
`完了フラグ` | 右列セルをダブルクリックして、編集中と完了を切り替えます。
保存単位 | 現在選択中の `作業名` に対して保存されます。
注意 | 名称を変更したあとは、必要に応じて `レイヤ更新` を実行して表示や出力を更新してください。

図解: `プロジェクト管理` のどこを編集するか

項目 | 値
--- | ---
プロジェクト名 | 道路改良A ← ここを書き換える
作業名 | 右岸測量 ← ここを書き換える
測定者 | 空欄または入力済みの値 ← ここを書き換える
完了フラグ | 編集中 / 完了 ← ここをダブルクリック

左列の `項目` は見出しです。右列の `値` を編集します。`完了フラグ` だけはダブルクリックで切り替えます。

### 操作手順

値の変更は次の流れで行います。

1. `プロジェクト` タブを開く
2. `プロジェクト管理` テーブルの変更したい行を探す
3. 名称や属性を変更するときは、右列の `値` セルをクリック、またはダブルクリックして編集する
4. `完了フラグ` を切り替えるときは、その右列セルをダブルクリックする
5. 表示名を出力へ反映したい場合は `レイヤ更新` を押す

## 6. 野帳入力

- 測量点（`測量点`）と目標点（`目標点`）は、数値に限らず自由な文字列で入力できます。
- `接続点` と `閉合点` は、ダブルクリックで測点候補から選択できます。
- `位置` 列はダブルクリックで緯度経度入力モーダルを開きます。
- `除外区間` 列は、出力から除外する区間を表します。右クリックメニューから `開始` / `終了` / `単独` を設定できます。
- 空行は視認上の区切りとして使用できます。

測点番号そのものが順序を表すとは限りません。プラグインはテーブル上の接続関係を使って連続区間を解釈します。

### 操作手順

野帳の入力や各セルの設定は次の流れで行います。

1. 野帳テーブルのセルをクリックして、`測量点`、`目標点`、`SD`、`INC`、`AZ` などを直接入力する
2. `接続点` または `閉合点` を設定したい行は、そのセルをダブルクリックして候補一覧から選ぶ
3. `位置` を設定したい行は、そのセルをダブルクリックして緯度経度入力画面を開く
4. `除外区間` を設定したい行は、その行を右クリックして `開始にする`、`終了にする`、`単独で除外` を選ぶ
5. 入力や設定を変更したあと、必要に応じて `レイヤ更新` を押して計算と表示へ反映する

## 7. 野帳インポート

`測量テーブル読込` を押すと、CSV または Excel 形式の測量表を野帳へ読み込みます。

- 対応形式は `.csv`, `.xlsx`, `.xls`, `.xlsm` です。
- CSV は `utf-8-sig`, `cp932`, `utf-8` を順に試して読み込みます。
- 区切り文字は自動判定され、判定できない場合はカンマ区切りとして扱います。

### 自動検知される列名

読込時はヘッダ名を見て、対応列の候補を自動検知します。空白、記号、大小文字の差はある程度吸収されます。

野帳列 | 自動検知キーワード例
--- | ---
測量点 | 測量点, 測点, 起点, from
目標点 | 目標点, 目標, 到達点, target, to
接続点 | 接続点, 接続
閉合点 | 閉合点, 閉合
SD | SD, 斜距離, 射距離, 実測距離
INC | INC, 高低, 高低角, 鉛直角
AZ | AZ, 方角, 方位角, 方位, 方向角
HD | HD, 水平距離
緯度 | 緯度, lat, latitude
経度 | 経度, lon, lng, longitude

上の表は自動検知の目安です。実際の読込操作は次の流れで進みます。

1. `測量テーブル読込` ボタンを押す
2. ファイル選択ダイアログで CSV または Excel ファイルを選ぶ
3. 列対応ダイアログで、自動検知結果を確認する
4. 必要ならプルダウンを変更して対応列を指定する
5. 「測量点」と「目標点」に相当する列が設定されていれば読み込む
6. 読込後に内容を確認し、必要に応じて `レイヤ更新` を押す

必須列: 少なくとも「測量点」と「目標点」の対応が必要です。これらが未設定のままでは読み込みできません。

緯度・経度列を対応させた場合は、野帳の「位置」列に内部データとして保存され、セル表示は「設定済」になります。

読み込み後は野帳テーブルがその内容で置き換わります。必要に応じて `レイヤ更新` を実行して計算とレイヤへ反映してください。

## 8. 行の表示ルール

- 赤字の行には2つの意味があります。(a) `除外区間` に設定された行 — この行の距離は総延長や一部の出力集計から除外されます。(b) 自動判定で接続線候補（Branch）のままの行 — こちらは除外区間ではなく、`除外区間` の設定とは無関係に総延長から自動的には除外されません。
- 緑字の行は、自動判定では接続線候補だが、右クリックメニューの `Treat as Line (include)` により通常ラインとして扱う設定が入っている行です。
- 測量点セルのオレンジ背景は接続不一致の警告、水色背景は不一致を承認した状態を表します。

接続線候補（赤字・未設定）を集計から除外したい場合は `Exclude Connecting Lines` チェックを有効にしてください。個々の行を確実に除外するには、赤字だけで判断せず各行の `除外区間` 設定を確認してください。

## 9. 位置と開始座標

- 測量を計算させるために、測量の最初の測量点には `位置` の設定が必須です。
- `位置` 列で強めの緑背景になっている行は必須行、薄い緑背景になっている行は各ブロックの開始行です。
- 薄い緑背景の行の `位置` は任意ですが、設定するとそのブロックを独自の位置で配置できます。
- 必須行の `位置` が未設定のままでは、計算やレイヤ更新は停止します。
- 同一ブロック内に `位置` が複数設定されている場合は、計算順で最初に見つかった有効な `位置` が開始座標の逆算に使われます。

## 10. 計算・レイヤ更新

`レイヤ更新` を押すと、現在の野帳内容から計算を行い、管理レイヤを再生成します。

- `HD`、`ΔX`、`ΔY` を更新
- 点・線・面レイヤを生成
- ブロック名ごとの表示や、除外区間の表示色をプレビューへ反映

### 実行の目安

`レイヤ更新` は、次のようなタイミングで実行します。

1. 野帳を手入力したあと
2. `接続点`、`閉合点`、`位置`、`除外区間` を変更したあと
3. `プロジェクト管理` の名称を変更し、表示や出力へ反映したいとき

接続不一致が残っている場合や、開始座標が確定できない場合は、内容を確認してから再実行してください。

## 11. エクスポート

- `エクスポート` は `完了フラグ` が未完了（編集中）の間だけ実行できます。`完了` にすると出力ボタンは無効化されます。
- HTML 帳票、地図 PDF、関連出力をまとめて生成します。
- 出力先フォルダはエクスポートダイアログで指定します。

### 操作手順

出力するときは、次の流れで確認します。

1. `プロジェクト` タブで `完了フラグ` が未完了（編集中）であることを確認する
2. 必要なら `レイヤ更新` を押して最新状態にする
3. 左パネルの `エクスポート` を押す
4. 出力設定ダイアログで出力先や用紙設定を確認する
5. 出力前に赤字行と `除外区間` の設定を見直す

除外区間は HTML 帳票や集計にも反映されます。出力前に、赤字行と `除外区間` 列の設定内容を確認してください。`完了` にすると `エクスポート` は無効化されるため、出力し終えてから完了に切り替えてください。

## 12. 運用メモ

- 測点名を変更した場合、参照している接続点・閉合点は自動追従します。
- `プロジェクト` タブのサマリーや備考は、現在選択中の `作業名` ごとに保存・表示されます。
- どうしてもレイヤを自由編集したい場合は、別レイヤへ複製して使用してください。
- `プラグインを隠す` ボタンでプラグインを非表示にし、QGISキャンバスを広く使えます。ツールバーアイコンで再表示できます。

## 技術仕様

このページは、`Compass Traverse GIS` が内部でどのように計算を行うかを、実装に基づいて整理した技術仕様です。提出時の説明根拠として使えるよう、式・処理順・補正方法を明示します。

以下の内容は、主に `survey_model.py`、`compass_traverse_gis_dockwidget.py`、`export_html.py` の実装に基づいています。

## 1. 入力と前提

対象列 | `測量点`, `目標点`, `接続点`, `閉合点`, `除外区間`, `SD`, `INC`, `AZ`, `HD`, `位置`
距離単位 | `m` または `ft`。内部計算時はメートルへ変換します。
高低角単位 | `deg` または `pct`。`pct` は勾配百分率として扱います。
方位角の基準 | 北を 0° とし、時計回りに増加する方位角として扱います。

## 2. 単位変換

距離と高低角は、計算前に次の規則で正規化されます。

距離: if unit == m: distance_m = value if unit == ft: distance_m = value × 0.3048 高低角: if unit == deg: inclination_deg = value if unit == pct: inclination_deg = atan(value / 100) × 180 / π

## 3. 磁気偏差の扱い

野帳で入力された `AZ` は、プラグイン側で磁気偏差を加算した値を計算用方位角として使います。

true_azimuth = (raw_azimuth + magnetic_declination) mod 360

設定位置 | `測量設定` の `磁気偏差`
符号 | 実装上は `+ 東偏 / - 西偏` として加算します。

## 4. 水平距離の決定

各行の水平距離は、`SD + INC` がある場合はそれを優先し、無い場合は `HD` を使います。

if SD and INC are present: HD = SD_m × cos(inclination_deg × π / 180) else if HD is present: HD = convert_to_meters(HD) else: calculation error
`SD` と `INC` はペアで必要です。片方だけでは計算できません。

## 5. 平面座標差の計算

水平距離と方位角から、各観測行の `ΔX` と `ΔY` を求めます。

ΔX = HD × sin(AZ) ΔY = HD × cos(AZ)

X | 東西方向（Easting）
Y | 南北方向（Northing）

## 6. 開始座標の決定

開始座標は、明示入力された `開始X` / `開始Y` がある場合はそれを使います。無い場合は、`位置` 列にある最初の有効な緯度経度を基準に逆算します。

1. 緯度経度を QGIS プロジェクト CRS へ変換 2. 開始座標を (0, 0) とした相対トラバースを一度計算 3. 位置が入っている行の from_coordinate を求める 4. start_coordinate = anchor_coordinate - anchor_leg.from_coordinate
`位置` が無く、`開始X` / `開始Y` も未設定の場合は、計算と出力を停止します。

## 7. 行順処理と測点ラベル

計算はテーブル行順で進みます。測点ラベルは識別に使いますが、並び順そのものはテーブル順が基準です。

基本 | 各行の `測量点 → 目標点` を順に展開します。
測量点欠番 | `from_station` が既知座標に無い場合、その時点の最後の計算座標を引き継いで続行します。
不一致検知 | 同一ブロック内で、前行の `目標点` と次行の `測量点` が一致しない場合は不一致として検出します。

## 8. 閉合差の計算

`閉合点` が指定された行では、その行で計算された目標点座標と、参照先閉合点の既知座標との差を閉合差として求めます。

error_x = computed_target.x - reference_coordinate.x error_y = computed_target.y - reference_coordinate.y error_distance = √(error_x² + error_y²)
closure_ratio = closure_span_distance / error_distance

ここで `closure_span_distance` は、開始点からその閉合行までの水平距離合計です。

## 9. 閉合補正

閉合がある場合は、最新の閉合に対して Bowditch（コンパス則）補正を適用します。補正対象は開始点からその閉合行までです。

ratio_i = leg_i.horizontal_distance / span_distance correction_x_i = closure.error_x × ratio_i correction_y_i = closure.error_y × ratio_i corrected_ΔX_i = ΔX_i - correction_x_i corrected_ΔY_i = ΔY_i - correction_y_i
corrected_target_i.x = corrected_from_i.x + corrected_ΔX_i corrected_target_i.y = corrected_from_i.y + corrected_ΔY_i
閉合行より後ろの行は、その時点までの補正済み座標を起点として、元の `ΔX`, `ΔY` をそのまま加算して続行します。

## 10. 面積と周囲延長

閉合が成立した場合、補正後座標を使って面積と周囲延長を求めます。

Area = |Σ(x_i × y_{i+1} - x_{i+1} × y_i)| / 2

面積 | 補正後座標列に対して shoelace formula を適用します。
周囲延長 | 開始点から閉合行までの水平距離合計です。

## 11. 面積計算簿の式

HTML の面積計算簿では、倍横距法による表も出力します。ここでは補正済みの `ΔX` / `ΔY` を優先して使用します。

Departure_i = corrected_ΔX_i (補正が無い場合は ΔX_i) Latitude_i = corrected_ΔY_i (補正が無い場合は ΔY_i) DMD_1 = Departure_1 DMD_i = DMD_{i-1} + Departure_{i-1} + Departure_i DoubleArea_i = DMD_i × Latitude_i Area = |Σ DoubleArea_i| / 2

## 12. 除外区間と接続線を除く

`除外区間` は、主に出力集計で使用する除外指定です。各行の `exclude_from_output` として保持され、延長集計や HTML の備考に反映されます。

幾何計算 | 行そのもののトラバース計算、座標展開、閉合差計算からは除外しません。
延長集計 | 除外行は、延長計や一部出力の合計から除外されます。
`接続線を除く` | 出力エントリの `block_kind == branch` を、集計上「計算から除外」として扱います。

## 1. Overview

This plugin provides an integrated QGIS workspace for compass survey entry, connecting-point and closure management, traverse computation, layer generation, and report export.

Layers are managed by the plugin. You may change symbology, but edit source data in the field notebook table, not in the QGIS layer.

## 2. Layout

Left panel | Workspace Status, Project / Work Name selection, Block Name, Deliverables
Notebook tab | Field notebook entry, survey settings, Connect To / Close To, Excl. Seg., Geo coordinates
Project tab | Project Details, Calculation Summary, language toggle

## 3. Project / Work Structure

In this plugin, Project is the parent group and Work Name is the individual survey dataset. Use Project to view the list of datasets and add or delete records, then use Work Name to switch the active dataset.

Project | Parent group that can contain multiple work records. Use the Project selector to view the dataset list and add or delete records.
Work Name | The actual survey record unit. Notebook data, Geo values, calculation state, and Project tab display are stored per work record.
Switching | When you switch Work Name, the notebook, Geo values, calculation state, and Project tab values stored for that dataset are shown.

Project / Work data is stored in a SQLite file created next to the QGIS project. Save the QGIS project first so the storage location is fixed.
Diagram: relationship between Project and Work Name

### Project

`Road Improvement A`

`Forest Boundary B`

### Work Name

`Road Improvement A / Right Bank Survey`

`Road Improvement A / Cross Section Add-on`

`Forest Boundary B / 2026-07-31`

Use Project to manage the dataset list and create records. Switching Work Name shows the notebook, Geo data, and Project tab values stored for that dataset.

## 4. Workspace Status

The Workspace Status group at the top of the left panel shows the current storage target and workspace switching tools.

Current Data | The currently loaded SQLite file. Shows "Not Created" when the QGIS project has not been saved yet.
Switch | Enabled when archived data exists. Switches to another saved workspace dataset.
New | Archives the current SQLite and creates a new workspace. Save the QGIS project first.

## 5. Editing the Project Tab

In Project Details, the left column is the item label and the right column is the value. Most fields are edited in the Value column, but Completion is toggled by double-clicking its value cell rather than typing into it.

Typed fields | Project Name, Work Name, Surveyor, Measurement Date, Fiscal Start, Fiscal Year, Year Carryover, Tree Type
Completion | Double-click the value cell to toggle between editing and complete.
Stored per | The currently selected Work Name.
Note | After changing names, run `Update Layers` if you need refreshed display or export output.

Diagram: where to edit in Project Details

Item | Value
Project Name | Road Improvement A ← edit here
Work Name | Right Bank Survey ← edit here
Surveyor | Blank or existing value ← edit here
Completion | Editing / Complete ← double-click here

The Item column is a label. Edit the Value column for normal fields, and double-click the Completion cell to toggle its state.

### Editing Flow

Use the following flow when editing these values.

1. Open the `Project` tab
2. Find the row you want to change in `Project Details`
3. For normal fields, click or double-click the cell in the `Value` column and edit it
4. For `Completion`, double-click the value cell to toggle the state
5. If you changed names used in output, run `Update Layers`

## 6. Field Notebook Entry

- `From` and `To` accept any string, not just numbers.
- `Connect To` and `Close To`: double-click to pick from a station list.
- `Geo` column: double-click to open the latitude/longitude entry dialog.
- `Excl. Seg.` marks segments to exclude from output totals. Use the context menu to set `Start`, `End`, or `Single`.
- Blank rows are allowed as visual separators.

Station labels do not necessarily define sequence. The plugin interprets continuous segments from the connection flow in the table.

### Input and Setting Flow

The typical input and setting flow is as follows.

1. Click a notebook cell to enter `From`, `To`, `SD`, `INC`, `AZ`, and related values directly
2. Double-click a `Connect To` or `Close To` cell to choose a station from the candidate list
3. Double-click a `Geo` cell to open the latitude/longitude input dialog
4. Right-click a row to open the context menu and set `Start`, `End`, or `Single` for `Excl. Seg.`
5. Run `Update Layers` after changes when you want the calculation and preview refreshed

## 7. Import Survey Table

Click `Import Survey Table` to load a CSV or Excel file into the notebook.

- Supported formats: `.csv`, `.xlsx`, `.xls`, `.xlsm`.
- CSV encoding is tried in order: `utf-8-sig`, `cp932`, `utf-8`.
- Delimiter is auto-detected; falls back to comma.

### Auto-detected column keywords

Notebook column | Example keywords
--- | ---
From | from, 測量点, 測点, 起点
To | to, target, 目標点, 目標
Connect To | connect, 接続点, 接続
Close To | close, 閉合点, 閉合
SD | SD, slope distance, 斜距離
INC | INC, inclination, 高低角
AZ | AZ, azimuth, 方位角
HD | HD, horizontal distance, 水平距離
Latitude | lat, latitude, 緯度
Longitude | lon, lng, longitude, 経度

The table above is only a guide for automatic column detection. The actual import flow is below.

1. Click `Import Survey Table`
2. Select a CSV or Excel file in the file dialog
3. Review auto-detected column mappings in the dialog
4. Adjust mappings manually if needed
5. Import proceeds when at least `From` and `To` are mapped
6. Review the imported table, then run `Update Layers` if needed

Required: At least the From and To columns must be mapped. Import is blocked otherwise.

If latitude/longitude columns are mapped, the data is stored internally in the `Geo` column and the cell shows "Set".

The notebook table is replaced on import. Run `Update Layers` to apply the changes to the calculation and layers.

## 8. Row Display Rules

- Red text has two distinct causes: (a) the row is set as an `Excl. Seg.` — its distance is omitted from total-length style summaries; (b) the row is still an auto-detected connecting-line candidate (Branch) — this is not an excluded segment and, on its own, is not omitted from totals.
- Rows shown in green are auto-detected connecting-line candidates that have been explicitly treated as normal lines.
- An orange background on the From cell indicates a connection mismatch warning. A light blue background indicates the mismatch has been acknowledged.

To exclude unresolved connecting-line candidates (red, not yet set) from totals, enable `Exclude Connecting Lines`. Do not rely on red text alone — check each row's `Excl. Seg.` setting for the definitive exclusion state.

## 9. Geo and Start Coordinate

- To run the calculation, the very first survey point must have a `Geo` value set.
- In the `Geo` column, a row with a strong green background is the required row; rows with a light green background are each block's start row.
- Geo on a light-green (block-start) row is optional, but setting it lets that block be placed at its own independent position.
- A row with a `Geo` value is used as an anchor to back-calculate the start coordinate. If multiple Geo values exist within the same block, the first valid one encountered in calculation order is used.
- If the required row's `Geo` is left unset, computation and layer update will stop.

## 10. Update Layers

Click `Update Layers` to run the traverse computation and regenerate managed layers.

- Updates `HD`, `dX`, and `dY`
- Generates point, line, and polygon layers
- Reflects block naming and excluded-segment display colors in the preview

### When to Run It

Run `Update Layers` at times like the following.

1. After manual notebook edits
2. After changing `Connect To`, `Close To`, `Geo`, or `Excl. Seg.`
3. After changing names in `Project Details` when output or display should be refreshed

If connection mismatches remain or the start coordinate cannot be resolved, review the notebook before running the update again.

## 11. Export

- `Export` is only available while `Completion` is not yet complete (still editing). Setting it to complete disables the export button.
- Generates HTML report, map PDF, and related outputs together.
- The output folder is specified in the Export dialog.

### Pre-Export Checklist

Before exporting, check the following flow.

1. Check that `Completion` in the `Project` tab is not yet complete (still editing)
2. Run `Update Layers` if the latest edits are not yet reflected
3. Click `Export` in the left panel
4. Review the output settings dialog, including output folder and paper settings
5. Confirm red rows and `Excl. Seg.` settings before final output

Excluded segments are reflected in the HTML report and summary values. Check the red rows and the `Excl. Seg.` column before export. Setting `Completion` to complete disables `Export`, so export first and mark it complete afterward.

## 12. Notes

- When a station name is changed, Connect To and Close To references update automatically.
- Summary values and notes on the Project tab are stored and displayed per selected Work Name.
- If you need to freely edit a layer, duplicate it to a separate layer first.
- The `Hide Plugin` button hides the plugin panel so you can use the full QGIS canvas. Click the toolbar icon to restore it.

## Technical Specification

This page documents how `Compass Traverse GIS` performs its internal calculations. It is intended to clarify the basis of the plugin's output and provide a defensible explanation for exported deliverables.

The statements below are derived from the implementation in `survey_model.py`, `compass_traverse_gis_dockwidget.py`, and `export_html.py`.

## 1. Inputs and Assumptions

Columns | `From`, `To`, `Connect To`, `Close To`, `Excl. Seg.`, `SD`, `INC`, `AZ`, `HD`, `Geo`
Distance units | `m` or `ft`; converted to meters internally.
Inclination units | `deg` or `pct`; percent is treated as grade percentage.
Azimuth basis | Clockwise from north.

## 2. Unit Conversion

Distance: if unit == m: distance_m = value if unit == ft: distance_m = value × 0.3048 Inclination: if unit == deg: inclination_deg = value if unit == pct: inclination_deg = atan(value / 100) × 180 / π

## 3. Magnetic Declination

The entered azimuth is adjusted in the plugin before traverse computation.

true_azimuth = (raw_azimuth + magnetic_declination) mod 360

Set at | `Declination` in `Survey Settings`
Sign | Added as `+ East / − West`.

## 4. Horizontal Distance

`SD + INC` is preferred when both are present. Otherwise, explicit `HD` is used.

if SD and INC are present: HD = SD_m × cos(inclination_deg × π / 180) else if HD is present: HD = convert_to_meters(HD) else: calculation error

## 5. Planar Deltas

ΔX = HD × sin(AZ) ΔY = HD × cos(AZ)

## 6. Start Coordinate

If no explicit start coordinate is given, the first valid `Geo` anchor is used to back-calculate the start point.

1. Transform latitude/longitude into the QGIS project CRS 2. Compute a relative traverse from (0, 0) 3. Find the from_coordinate of the anchored row 4. start_coordinate = anchor_coordinate - anchor_leg.from_coordinate

## 7. Row-Order Processing

Primary rule | Rows are processed in table order.
Station labels | Used as identifiers, not as the primary ordering rule.
Missing from-station coordinate | If a `from_station` is unknown, the computation inherits the most recently computed coordinate and continues.

## 8. Closure Error

error_x = computed_target.x - reference_coordinate.x error_y = computed_target.y - reference_coordinate.y error_distance = √(error_x² + error_y²) closure_ratio = closure_span_distance / error_distance

## 9. Closure Correction

When a closure exists, Bowditch correction is applied to the latest closed span.

ratio_i = leg_i.horizontal_distance / span_distance correction_x_i = closure.error_x × ratio_i correction_y_i = closure.error_y × ratio_i corrected_ΔX_i = ΔX_i - correction_x_i corrected_ΔY_i = ΔY_i - correction_y_i

## 10. Area and Perimeter

Area = |Σ(x_i × y_{i+1} - x_{i+1} × y_i)| / 2

The perimeter reported for a closed traverse is the horizontal-distance sum from the start through the closure leg.

## 11. Double Meridian Distance Sheet

Departure_i = corrected_ΔX_i (or raw ΔX_i) Latitude_i = corrected_ΔY_i (or raw ΔY_i) DMD_1 = Departure_1 DMD_i = DMD_{i-1} + Departure_{i-1} + Departure_i DoubleArea_i = DMD_i × Latitude_i Area = |Σ DoubleArea_i| / 2

## 12. Excluded Segments and Exclude Connecting Lines

Geometry calculation | Excluded segments are still used in traverse expansion and coordinate computation.
Totals and output | Excluded rows are omitted from selected distance totals and are marked in output notes.
`Exclude Connecting Lines` | Entries classified as `branch` are treated as excluded in output summaries.