class_name SonarSample extends RefCounted const SonarMaterial = preload("res://game/domain/sonar/sonar_material.gd") var position_m: Vector3 var normal: Vector3 var intensity: float var elevation_m: float var material: SonarMaterial.Value var observed: bool func _init( p_position_m: Vector3 = Vector3.ZERO, p_normal: Vector3 = Vector3.UP, p_intensity: float = 0.0, p_elevation_m: float = 0.0, p_material: SonarMaterial.Value = SonarMaterial.Value.UNKNOWN, p_observed: bool = false ) -> void: position_m = p_position_m normal = p_normal intensity = p_intensity elevation_m = p_elevation_m material = p_material observed = p_observed static func unknown() -> SonarSample: return new() func validation_error() -> String: if not observed: if material != SonarMaterial.Value.UNKNOWN: return "unobserved sonar sample has a material" return "" if not _vector_is_finite(position_m): return "sonar sample position is not finite" if not _vector_is_finite(normal) or normal.length_squared() < 0.25: return "sonar sample normal is invalid" if not is_finite(intensity) or intensity < 0.0 or intensity > 1.0: return "sonar sample intensity must be between 0 and 1" if not is_finite(elevation_m): return "sonar sample elevation is not finite" if material == SonarMaterial.Value.UNKNOWN or not SonarMaterial.is_valid(material): return "observed sonar sample material is invalid" return "" func _vector_is_finite(value: Vector3) -> bool: return is_finite(value.x) and is_finite(value.y) and is_finite(value.z)