.. index:: single: Tunnel Analysis single: Coordinate Transformations Tunnel Analysis and Coordinate Transformations ============================================== .. index:: single: Tunnel Section Line — Measured Profile Tunnel Section Line — Measured Profile --------------------------------------- A Tunnel Section Line (``TAECC_TunnelSectionLine``) is a measured polyline representing the surveyed cross-section of a tunnel or excavation. It inherits from ``TIQCustomObject`` (the AEC base class) rather than ``TCADPolyline``, placing it in the civil entity hierarchy alongside survey points and surfaces. When linked to a theoretical profile it automatically computes and displays radial deviations. The entity lives in ``UAECC_TunnelSectionLine.pas`` under the ``cad/Civil/`` directory and is serialised as ```` in IQML. .. index:: single: Creating a Tunnel Section Line Creating a Tunnel Section Line ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1. Draw the **theoretical profile** as a normal closed polyline on a dedicated layer (e.g. ``Theoretical``). 2. Activate **Draw › TSLine** (or type ``TSLINE``) and click the measured survey points. Right-click to finish. 3. In the Object Inspector, set **SectionLine** to the theoretical polyline. 4. Enable **ShowDR** to display deviation annotations. .. index:: single: Tunnel Section Line Properties Tunnel Section Line Properties ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .. list-table:: :header-rows: 1 :widths: 25 75 * - Property - Description * - **SectionLine** - The theoretical polyline to compare against. * - **SplineFlag** - Renders the measured profile as a smooth spline curve. * - **SplineSteps** - Interpolation steps per segment (higher = smoother curve). * - **PointSize** - Size of the survey point markers along the profile. * - **ShowDR** - Show deviation (DR) annotation lines and values. * - **DRDecimals** - Number of decimal places in DR labels. * - **DRFontSize** - Label font size in world units. * - **DROffset** - Radial offset of the label from the profile line. * - **DRUnit** - Unit for DR values: ``mm``, ``cm``, or ``m``. * - **DROrientation** - ``Auto`` (follows deviation direction), ``Inside``, or ``Outside``. * - **DRAlignment** - ``Horizontal``, ``Vertical``, or ``Aligned`` (label follows the deviation line direction). * - **ShowAreaHatch** - Fills the area between the measured and theoretical profiles with a hatch pattern. * - **AreaBetween / AreaInner / AreaOuter** - Computed areas (read-only) between the two profiles. .. index:: single: DR Display Modes DR Display Modes ~~~~~~~~~~~~~~~~ The **DRDisplayMode** property controls how deviation labels are rendered: .. list-table:: :header-rows: 1 :widths: 25 75 * - Mode - Description * - **dmAll** (default) - Shows a deviation label at every measured point. * - **dmZoneExtremes** - Shows only the highest (most extreme) deviation per overbreak and underbreak zone. This reduces label clutter while highlighting the worst-case deviations in each zone. .. index:: single: Deviation Colour Coding Deviation Colour Coding ~~~~~~~~~~~~~~~~~~~~~~~ DR annotation lines are colour-coded automatically: - **Green** — measured profile is *outside* the theoretical (overbreak). - **Red** — measured profile is *inside* the theoretical (underbreak / intrusion). .. note:: Radial sorting is performed clockwise from the bottom (−Y direction), which corresponds to the invert of a tunnel cross-section. .. index:: single: Area Calculation Algorithm Area Calculation Algorithm ~~~~~~~~~~~~~~~~~~~~~~~~~~ The area computation between the measured and theoretical profiles uses the **Greiner-Hormann polygon intersection** algorithm (``UPolygonClip.pas``). **Step-by-step process:** 1. **Polygon densification** — both the measured Tunnel Section Line and the theoretical section are sampled into dense point arrays using ``DensifyPoly`` with a maximum step of ``SampleMaxStep`` (default 0.02 m). This ensures that spline curves and bulge arcs are accurately represented as polygons. For the measured profile, ``GetWorldPoly`` first produces the polyline's own sample points (including Catmull-Rom spline interpolation if ``SplineFlag`` is enabled); then ``DensifyPoly`` subdivides any segment longer than ``SampleMaxStep``. For the theoretical section, ``SampleSectionLine`` does the same two-pass process. 2. **Zone clipping** (optional) — if ``AreaLevels`` is non-zero, both polygons are clipped to the selected quadrant using **Sutherland-Hodgman** rectangle clipping (four successive half-plane clips: Left, Right, Bottom, Top). This allows reporting overbreak/underbreak per tunnel quadrant independently (e.g. crown only, or left wall only). 3. **Area computation** — three polygon areas are calculated: - **AM** = ``PolygonArea2D(MeasuredPoly)`` — measured polygon area (shoelace formula). - **AS** = ``PolygonArea2D(TheoreticalPoly)`` — theoretical polygon area. - **AI** = ``PolygonIntersectionArea(MeasuredPoly, TheoreticalPoly)`` — exact intersection area via Greiner-Hormann. 4. **Result derivation:** - **AreaOuter** (overbreak) = AM − AI — area of the measured profile that lies outside the theoretical section. - **AreaInner** (underbreak) = AS − AI — area of the theoretical section not covered by the measured profile. - **AreaBetween** = AreaOuter + AreaInner — total deviation area. 5. **Numerical guards** — AI is clamped to min(AM, AS) to prevent floating-point over-subtraction; negative results are clamped to zero. **Greiner-Hormann algorithm (six phases):** 1. **Build** — normalise both polygons to CCW orientation; build circular vertex linked lists. 2. **Intersect** — find all edge-edge intersections and insert intersection vertices with parametric *t* values along each edge. 3. **Mark** — classify each intersection vertex as Entry or Exit relative to the subject polygon. 4. **Containment check** — if no intersections exist, use ``PointInPolygon`` (winding number) to detect full containment. 5. **Trace** — walk the intersection-marked lists to extract the output polygon(s); sum their areas. 6. **Free** — release all linked-list memory. Numeric constants: ``GH_EPS = 1e-9`` (parallel guard), ``GH_CORNER_EPS = 5e-3`` (near-vertex rejection), ``MIN_REGION_AREA = 1e-4 m²`` (sliver filter). **Caching** — all area values are cached and only recomputed when the section geometry changes (``FAreaCacheDirty`` flag). **Hatch rendering** — the ``PolygonDifferenceRegions`` function traces the same Greiner-Hormann linked lists to extract the actual overbreak (outer) and underbreak (inner) polygon regions, which are then filled with colour-coded hatch patterns (green = overbreak, red = underbreak). .. _civil-coord-transforms: .. index:: single: Coordinate Transformations Coordinate Transformations -------------------------- IQcad provides two coordinate transformation commands for aligning drawings, survey data, and imported plans to a target coordinate system. Both commands use the IQCalc computation engine and share a common point-picking workflow. .. index:: single: CSTRANSFORM — Global Transformation CSTRANSFORM — Global Transformation ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ **Command:** ``CSTRANSFORM`` (alias ``CST``) Computes a single global transformation from common (control) point pairs and applies it to all selected entities. The transformation is solved by **least-squares adjustment**, producing residuals that allow you to identify and remove blunder points. **Supported transformation types:** .. list-table:: :header-rows: 1 :widths: 25 10 65 * - Type - Min Pts - Description * - **Helmert 2D** - 2 - 4-parameter similarity (conformal): translation, uniform scale, rotation. Preserves angles and shape. The standard choice for local survey alignment. * - **Affine 2D** - 3 - 6-parameter: translation, non-uniform scale (independent X/Y), shear, rotation. Does not preserve angles. Use for scanned plans with differential paper shrinkage. * - **Polynomial Deg 1** - 3 - 6-parameter 1st-degree polynomial (equivalent to affine). * - **Polynomial Deg 2** - 6 - 12-parameter 2nd-degree polynomial for modelling non-linear distortions across large areas. * - **Polynomial Deg 3** - 10 - 20-parameter 3rd-degree polynomial for complex systematic distortions. **Workflow:** 1. Select entities to transform (or type ``All`` for all entities in the drawing). 2. Pick common point pairs: - **Click** source point on canvas, then click target point - **Type coordinates**: ``1000.5,2000.3`` or ``1000.5,2000.3,100.0`` - **Type point number**: ``#123`` (looks up point 123 in the survey database) - **Load from file**: type ``F`` to open a ``.cpt`` or ``.csv`` file 3. Type ``D`` (Done) when all pairs are entered. 4. Choose the transformation type (``H`` = Helmert, ``A`` = Affine, ``P1``/``P2``/``P3`` = Polynomial). 5. Review the residual table printed in the command line. 6. Save the transformation report (``.trpt``) and common points (``.cpt``) when prompted. 7. Confirm ``Y`` to apply the transformation. **Residuals and quality control:** When more than the minimum number of points are provided, the system is over-determined and the least-squares solution produces **residuals** at each control point — the difference between the transformed source and the known target. Large residuals indicate: - A blunder in the control point pair (wrong target entered) - A point in a locally distorted area that the global model cannot fit Review the residuals, disable suspect points (re-enter the workflow), and re-solve until the RMS is acceptable. The report file records all residuals, statistics, and the computed parameters for archival. **Mathematical detail — Helmert 2D:** .. code-block:: text Model: X' = tx + a*X - b*Y Y' = ty + b*X + a*Y where a = scale * cos(rotation), b = scale * sin(rotation) Parameters: tx, ty (translations), scale, rotation (4 unknowns) Each control point provides 2 equations (X' and Y'), so n points give 2n equations. With n >= 2 the system is solved by least squares: A * p = b + v (design matrix A, parameter vector p, residuals v) p = (A'A)^(-1) * A'b (normal equations) RMSE = sqrt( v'v / n ) **Mathematical detail — Affine 2D:** .. code-block:: text Model: X' = tx + a11*X + a12*Y Y' = ty + a21*X + a22*Y Parameters: tx, ty, a11, a12, a21, a22 (6 unknowns) Minimum points: 3 (6 equations for 6 unknowns) Decomposition: Scale X = sqrt(a11^2 + a21^2) Scale Y = sqrt(a12^2 + a22^2) Rotation = atan2(a21, a11) Shear = (a11*a12 + a21*a22) / (Scale_X * Scale_Y) **Mathematical detail — Polynomial 2D:** .. code-block:: text Model (degree d): X' = SUM( c_ij * x'^i * y'^j ) for i+j <= d Y' = SUM( d_ij * x'^i * y'^j ) for i+j <= d where x' = x - cx, y' = y - cy (centroid-reduced for numerical stability) Terms per coordinate: (d+1)*(d+2)/2 Degree 1: 3 terms (1, x, y) Degree 2: 6 terms (1, x, y, x^2, xy, y^2) Degree 3: 10 terms (1, x, y, x^2, xy, y^2, x^3, x^2*y, xy^2, y^3) .. warning:: Polynomial transformations must not be used for extrapolation beyond the convex hull of the control points. The polynomial may oscillate wildly outside the fitted area (Runge's phenomenon). .. index:: single: RUBBERSHEET — Local Non-Uniform Transformation RUBBERSHEET — Local Non-Uniform Transformation ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ **Command:** ``RUBBERSHEET`` (alias ``RBS``) Applies a spatially-varying correction where the displacement at each point depends on its proximity to nearby control points. Unlike CSTRANSFORM, there is **no single global model** — the transformation varies continuously across the drawing. **Two modes:** **Linear (Delaunay Piecewise Affine)** The source control points are triangulated using the Bowyer-Watson Delaunay algorithm. For each triangle, a unique affine transformation is computed that maps its three source vertices exactly to their three target positions (6 equations, 6 unknowns — exact solution). For any query point, the algorithm locates the containing triangle and applies that triangle's affine. .. code-block:: text For each triangle T_k with source vertices (S0, S1, S2) mapping to target vertices (T0, T1, T2): X' = a11*X + a12*Y + tx Y' = a21*X + a22*Y + ty Solved by Cramer's rule: D = x0*(y1-y2) + x1*(y2-y0) + x2*(y0-y1) a11 = (X'0*(y1-y2) + X'1*(y2-y0) + X'2*(y0-y1)) / D ... (similarly for a12, tx, a21, a22, ty) Point location uses barycentric coordinates: Q is inside triangle ABC if u >= 0, v >= 0, (1-u-v) >= 0 Properties: C0 continuous (slope breaks at triangle edges), exact at control points, O(n log n) triangulation, brute-force O(m) point location. **Smooth (Thin Plate Spline)** The TPS minimizes the bending energy of a thin metal plate passing through prescribed displacements. Two independent TPS functions are solved — one for X displacement, one for Y displacement. .. code-block:: text f(x,y) = a0 + a1*x + a2*y + SUM_i( w_i * U(r_i) ) where U(r) = r^2 * ln(r) (radial basis function) r_i = distance from (x,y) to control point i Linear system (n+3 x n+3): | K P | | w | | v | K[i,j] = U(|Pi - Pj|) | P' 0 | | a | = | 0 | P[i] = [1, xi, yi] The constraint P'*w = 0 ensures affine far-field behavior: far from all control points, f reduces to a0 + a1*x + a2*y. Properties: C2 continuous everywhere, exact at control points, O(n^3) solve, O(n) per-point evaluation. Natural affine extrapolation in far field. **Workflow:** 1. Select entities (or ``All``). 2. Pick common point pairs (same methods as CSTRANSFORM). 3. Type ``D`` (Done). 4. Choose mode: ``L`` = Linear (default), ``S`` = Smooth. 5. Review displacement table and save report/points when prompted. 6. Confirm ``Y`` to apply. **Key differences from CSTRANSFORM:** - **No residuals** — rubber sheeting interpolates exactly through all control points, so there is no over-determined system and no residual analysis. Blunder points cannot be detected from the math — verify independently. - **Spatially varying** — different parts of the drawing are corrected differently based on proximity to control points. - **Outside convex hull** — points outside the control network are extrapolated (linear: nearest triangle, smooth: affine). A warning count is reported. **Elevation (Z) handling:** Both CSTRANSFORM and RUBBERSHEET preserve the original Z coordinate by default — only Easting (X) and Northing (Y) are transformed. .. index:: single: Common Points File Format (.cpt) Common Points File Format (.cpt) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Common point pairs can be saved and loaded in JSON format: .. code-block:: json { "version": 1, "description": "Site A to Grid transform", "coordinateOrder": "ENZ", "points": [ { "name": "CP1", "source": { "e": 1000.000, "n": 2000.000, "z": 100.000 }, "target": { "e": 1000.152, "n": 2000.318, "z": 100.023 }, "enabled": true } ] } Alternatively, CSV format is supported: .. code-block:: text Name,SrcE,SrcN,SrcZ,TgtE,TgtN,TgtZ,Enabled CP1,1000.000,2000.000,100.000,1000.152,2000.318,100.023,True .. index:: single: Transformation Report (.trpt) Transformation Report (.trpt) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ The ``Save Report`` dialog writes a detailed text report including: - Transformation type and date - Common point table with source/target coordinates - Computed parameters (for global transforms) - Per-point residuals with positional magnitude (for global transforms) - RMS statistics, redundancy, and degrees of freedom - Displacement table (for rubber sheet) - Number of entities transformed and locked points skipped - IQCalc engine version .. index:: single: Practical Guide: Which Transformation to Use Practical Guide: Which Transformation to Use ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Choosing the right transformation depends on the nature and magnitude of the coordinate differences, the number and distribution of control points, and whether the distortion is uniform or spatially varying. Decision Flowchart ^^^^^^^^^^^^^^^^^^ .. code-block:: text Do you have common points in both systems? │ ├─ No → You cannot compute a transformation. │ Obtain at least 2 common points first. │ └─ Yes │ Is the distortion uniform across the area? (i.e., a simple shift/rotate/scale explains the differences) │ ├─ Yes → Use CSTRANSFORM │ │ │ How many common points? │ ├─ 2 → Helmert 2D (exact fit, no residuals) │ ├─ 3-5 → Helmert 2D (least-squares, with residuals) │ ├─ 3+ → Affine 2D (if X/Y scales differ) │ └─ 6+ → Polynomial deg 2 (if residuals show spatial pattern) │ └─ No → The distortion varies across the area │ Use RUBBERSHEET ├─ Many control points (>20) → Linear mode └─ Few control points (<20) → Smooth (TPS) mode Common Survey Scenarios ^^^^^^^^^^^^^^^^^^^^^^^^ **Scenario 1: Aligning a total station survey to control points** You have a local total station survey (arbitrary setup) and 3-5 points with known coordinates in the national grid. *Recommended:* **CSTRANSFORM → Helmert 2D** This is the classic case: the local survey differs from the grid by a translation, rotation, and uniform scale. Helmert preserves angles (conformal) which is essential for survey data. .. code-block:: text Workflow: 1. Import your total station points into IQcad 2. Run CSTRANSFORM 3. For each control point: click the local position, then enter the known grid coordinate (e.g. #101 or 538345.12,4872341.56) 4. Type D (Done), select H (Helmert) 5. Check residuals — all should be < 0.01 m for a good survey 6. If one point has a much larger residual, investigate (blunder?) 7. Apply *Typical RMS:* 3-10 mm for a well-executed survey. **Scenario 2: Georeferencing a scanned cadastral plan** You digitised an old cadastral plan and need to bring it into the national grid. The paper has shrunk non-uniformly (different scale in X and Y). *Recommended:* **CSTRANSFORM → Affine 2D** (minimum 3 points) Affine allows independent X and Y scales and a shear component, which models paper shrinkage. Use at least 4 points for redundancy. .. code-block:: text Workflow: 1. Identify 4+ points on the plan that you can also locate in the national grid (road intersections, property corners, benchmarks) 2. Run CSTRANSFORM, pick the digitised positions and enter grid coords 3. Select A (Affine) 4. Check residuals — if they show a spatial pattern (e.g., all positive in one corner), the plan may have local folds → use RUBBERSHEET *Typical RMS:* 0.1-0.5 m depending on plan age and condition. **Scenario 3: Aligning an imported DXF from a different coordinate system** A colleague sent you a DXF in a local grid, and you need to merge it with your project in the national grid. You have 2-3 matching points. *Recommended:* **CSTRANSFORM → Helmert 2D** (2 points for exact fit, 3 for QC) With exactly 2 points, the Helmert gives an exact solution (no residuals). If you have 3 points, use all three — the third point's residual tells you whether the two coordinate systems are related by a simple similarity transform. If the residual is large, the systems may have different scales in X and Y (→ try Affine) or local distortions (→ try RUBBERSHEET). **Scenario 4: Correcting a drawing with known local distortions** Your drawing has localized errors: some areas are shifted by 0.2 m, others by 0.5 m in different directions. You have 10+ control points scattered across the project. *Recommended:* **RUBBERSHEET → Linear mode** The Delaunay triangulation adapts the correction locally — each triangle gets its own affine transform, so areas near a shifted control point are corrected by that point's displacement. With 10+ points the triangles are small enough that the C0 discontinuities at edges are negligible. .. code-block:: text Workflow: 1. Select All entities 2. Pick all 10+ control point pairs 3. Choose L (Linear) 4. Review the displacement table — are the magnitudes consistent? 5. Check the "outside hull" count — if high, add control points at the project boundary 6. Apply **Scenario 5: Deformation monitoring — comparing two epochs** You have two sets of measurements of the same points at different times and want to visualise the displacement field smoothly. *Recommended:* **RUBBERSHEET → Smooth (TPS) mode** TPS produces a C2-continuous displacement field ideal for deformation visualisation. The smooth gradient avoids artificial slope breaks that would appear with linear rubber sheeting. **Scenario 6: Large-area datum transformation (hundreds of km)** You have survey data in a local datum and need to convert to a national or global reference frame. The area is large enough that a simple 4-parameter transform leaves systematic residual patterns (bowl-shaped or tilted). *Recommended:* **CSTRANSFORM → Polynomial degree 2** (minimum 6 points) The 2nd-degree polynomial captures regional curvature that Helmert/Affine cannot model. Place control points at the edges and centre of the area. .. warning:: Never extrapolate polynomial transforms beyond the control network. Outside the convex hull, the polynomial may diverge rapidly. **Scenario 7: Quick approximate shift (no rotation/scale)** You just need to shift your drawing by a known offset (e.g., "everything is 100 m too far East"). *Recommended:* **CSTRANSFORM → Helmert 2D** with 1 point pair. Although Helmert needs 2 points, with 1 point it effectively computes a pure translation (scale = 1, rotation = 0). Alternatively, use the MOVE command with a known delta. Quality Control Checklist ^^^^^^^^^^^^^^^^^^^^^^^^^^ After any transformation, verify the result: 1. **Check the RMS** (CSTRANSFORM only). Compare with your expected survey accuracy. RMS >> expected accuracy suggests blunders or wrong model. 2. **Examine individual residuals**. A single large residual (> 3× RMS) suggests a blunder in that control point. Disable it and re-solve. 3. **Look for spatial patterns** in the residuals. If positive residuals cluster in one area and negative in another, the model may be too simple → try a higher-order transform. 4. **Check the outside-hull count** (RUBBERSHEET). A large number means many entities are being extrapolated — add boundary control points. 5. **Spot-check transformed points** against known coordinates not used in the transformation (independent check points). 6. **Save the report and common points** for audit trail and repeatability. 7. **Verify locked points** were correctly skipped (check the "locked skipped" count in the output). Control Point Distribution Tips ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ .. list-table:: :header-rows: 1 :widths: 35 65 * - Guideline - Reason * - Surround the project area - Minimises extrapolation; rubber sheet needs enclosing hull * - Distribute points evenly - Avoids poorly conditioned least-squares solutions * - Avoid collinear arrangements - Collinear points cannot define 2D transforms (singular matrix) * - Use more than the minimum - Extra points give redundancy for residual-based QC * - Include points at different elevations - Important for 3D transforms (Bursa-Wolf) * - Remove one point at a time - When testing outliers, remove one, re-solve, then evaluate * - Keep point names consistent - Helps match pairs when loading from files