Source code for sec_interp.core.utils.geometry_utils.measurement

from __future__ import annotations

"""Measurement calculation utilities for profile viewing."""

import math
from typing import Any

from qgis.core import QgsPointXY


[docs] def calculate_polyline_metrics(points: list[QgsPointXY]) -> dict[str, Any]: """Calculate comprehensive measurement metrics from a list of points. Args: points: List of QgsPointXY points defining the polyline on the profile plane. Returns: Dictionary containing: - total_distance: Accumulated 2D distance along all segments. - horizontal_distance: Total horizontal distance (X span). - elevation_change: Total elevation change (Y span from first to last). - avg_slope: Average slope in degrees. - segment_count: Number of segments. - segments: List of segment details with distance, dx, and dy. - point_count: Number of points. """ if len(points) < 2: return { "total_distance": 0.0, "horizontal_distance": 0.0, "elevation_change": 0.0, "avg_slope": 0.0, "segment_count": 0, "segments": [], "point_count": len(points), } total_dist = 0.0 total_dx = 0.0 segments = [] for i in range(len(points) - 1): p1 = points[i] p2 = points[i + 1] dx = abs(p2.x() - p1.x()) dy = p2.y() - p1.y() seg_dist = math.sqrt(dx * dx + dy * dy) total_dist += seg_dist total_dx += dx segments.append( { "distance": seg_dist, "dx": dx, "dy": dy, "start": (p1.x(), p1.y()), "end": (p2.x(), p2.y()), } ) # Total elevation change (first to last point) elevation_change = points[-1].y() - points[0].y() # Average slope avg_slope = 0.0 if total_dx > 0: avg_slope = math.degrees(math.atan(abs(elevation_change) / total_dx)) return { "total_distance": total_dist, "horizontal_distance": total_dx, "elevation_change": elevation_change, "avg_slope": avg_slope, "segment_count": len(segments), "segments": segments, "point_count": len(points), }