Files
aiRtrafficNN/Code/cpp/src/csv-helpers.cpp
T
2025-11-19 11:57:59 +01:00

118 lines
4.2 KiB
C++

#include "csv-helpers.hpp"
// Parse a single CSV line into a CSVRow struct
CSVRow parse_csv_line(const std::string& line) {
CSVRow row;
std::istringstream ss(line);
std::string token;
std::getline(ss, row.icao, ',');
std::getline(ss, row.r, ',');
std::getline(ss, row.t, ',');
std::getline(ss, token, ','); row.timestamp = std::stod(token);
std::getline(ss, token, ','); row.lat = std::stod(token);
std::getline(ss, token, ','); row.lon = std::stod(token);
std::getline(ss, token, ','); row.alt = std::stod(token);
std::getline(ss, token, ','); row.ias = std::stod(token);
return row;
}
// Read the first row of a CSV file
CSVRow read_first_csv_row(const std::string& filepath) {
std::ifstream ifs(filepath);
if (!ifs.is_open()) {
throw std::runtime_error("Could not open file: " + filepath);
}
std::string line;
std::getline(ifs, line); // Skip header
std::getline(ifs, line); // Read first data row
ifs.close();
return parse_csv_line(line);
}
// Read the last row of a CSV file
CSVRow read_last_csv_row(const std::string& filepath) {
std::ifstream ifs(filepath);
if (!ifs.is_open()) {
throw std::runtime_error("Could not open file: " + filepath);
}
std::string line;
std::string last_line;
std::getline(ifs, line); // Skip header
while (std::getline(ifs, line)) {
last_line = line;
}
ifs.close();
return parse_csv_line(last_line);
}
// Haversine distance calculation
double haversine_distance(double lat1, double lon1, double lat2, double lon2) {
const double R = 6371.0; // Earth radius in kilometers
double dlat = (lat2 - lat1) * M_PI / 180.0;
double dlon = (lon2 - lon1) * M_PI / 180.0;
double a = std::sin(dlat / 2) * std::sin(dlat / 2) +
std::cos(lat1 * M_PI / 180.0) * std::cos(lat2 * M_PI / 180.0) *
std::sin(dlon / 2) * std::sin(dlon / 2);
double c = 2 * std::atan2(std::sqrt(a), std::sqrt(1 - a));
return R * c;
}
// Filter by aircraft type
bool aircraft_type_filter(const std::string& t) {
// Return true if type starts with 'A[2-3]' or 'B7' or 'A19N' or 'E'
if (t.size() < 2) return false;
if (t[0] == 'A' && (t[1] == '2' || t[1] == '3')) return true;
if (t[0] == 'B' && t[1] == '7') return true;
if (t.find("A19N") != std::string::npos) return true;
if (t[0] == 'E') return true;
return false;
}
// Filter by proximity to known airports
bool near_airport_filter(const double lat, const double lon, const double alt) {
// Known airports (lon, lat)
/*
OSLO_GARDERMOEN_AIRPORT = (11.0859718, 60.1902228)
BERGEN_FLESLAND_AIRPORT = (5.2201954, 60.293512)
STAVANGER_SOLA_AIRPORT = (5.667972, 58.876667)
UMEA_AIRPORT = (20.2840218, 63.7906151)
GOTHENBURG_LANDVETTER_AIRPORT = (12.2850909, 57.669275)
STOCKHOLM_ARLANDA_AIRPORT = (17.9185743, 59.6519444)
TRONDHEIM_VAERNES_AIRPORT = (10.9110182, 63.4577224)
TROMSO_LANGNES_AIRPORT = (18.910825, 69.683911)
*/
const std::vector<std::pair<double, double>> known_airports = {
{11.0859718, 60.1902228},
{5.2201954, 60.293512},
{5.667972, 58.876667},
{20.2840218, 63.7906151},
{12.2850909, 57.669275},
{17.9185743, 59.6519444},
{10.9110182, 63.4577224},
{18.910825, 69.683911}
};
for (const auto& airport : known_airports) {
double distance = haversine_distance(lat, lon, airport.second, airport.first);
if (distance <= AIRPORT_PROXIMITY_THRESHOLD_KM) {
if (std::isnan(alt) || alt <= AIRPORT_MAX_ALTITUDE_FT) {
return true;
}
}
}
return false;
}
// List all CSV files in a folder
std::vector<std::string> list_csv_files_in_folder(const std::string& folder_path) {
std::vector<std::string> csv_files;
for (const auto& entry : std::filesystem::directory_iterator(folder_path)) {
if (entry.path().extension() == ".csv") {
csv_files.push_back(entry.path().string());
} else if (std::filesystem::is_directory(entry.path())) {
auto nested_files = list_csv_files_in_folder(entry.path().string());
csv_files.insert(csv_files.end(), nested_files.begin(), nested_files.end());
}
}
return csv_files;
}