/* * @Description: * @Version: 1.0 * @Autor: Sun Yalun * @Date: 2024-11-04 15:37:55 * @LastEditors: Sun Yalun * @LastEditTime: 2024-11-08 14:41:50 */ #include "utils.h" #include #include #include #include #include #include #include #include BoundingBox createBoundingBox(const Point &p1, const Point &p2) { BoundingBox box; box.min_x = std::min(p1.pos_x, p2.pos_x); box.max_x = std::max(p1.pos_x, p2.pos_x); box.min_y = std::min(p1.pos_y, p2.pos_y); box.max_y = std::max(p1.pos_y, p2.pos_y); return box; } bool isPointInBoundingBox(const Point &p, const BoundingBox &box) { return (p.pos_x >= box.min_x && p.pos_x <= box.max_x && p.pos_y >= box.min_y && p.pos_y <= box.max_y); } std::vector parseRef(const std::string &ref_str) { std::vector refs; std::string s = ref_str; if (s.size() >= 2 && s.front() == '[' && s.back() == ']') { s = s.substr(1, s.size() - 2); } std::stringstream ss(s); std::string token; while (std::getline(ss, token, ',')) { try { refs.push_back(std::stoi(token)); } catch (const std::invalid_argument &e) { std::cerr << "Invalid ref value: " << token << std::endl; } } return refs; } std::vector parseCoords(const std::string &coords_str) { std::vector points; std::string s = coords_str; // 移除最外层的中括号 if (!s.empty() && s.front() == '[' && s.back() == ']') { s = s.substr(1, s.size() - 2); } std::stringstream ss(s); std::string point_str; while (std::getline(ss, point_str, ']')) { // 每个点以 '[' 开始,移除它 size_t start = point_str.find('['); if (start != std::string::npos) { std::string coords = point_str.substr(start + 1); // 将逗号替换为空格,以便于后续解析 std::replace(coords.begin(), coords.end(), ',', ' '); std::stringstream coord_ss(coords); double x, y; coord_ss >> x >> y; Point p(0.0, 0.0, 0.0); p.pos_x = x; p.pos_y = y; points.push_back(p); } // 忽略逗号 ss.ignore(1, ','); } return points; } double calculateDistance(double x1, double y1, double x2, double y2) { double dx = x1 - x2; double dy = y1 - y2; return std::sqrt(dx * dx + dy * dy); } double pointToSegmentDistance(const Point &p, const Point &p1, const Point &p2) { double x0 = p.pos_x; double y0 = p.pos_y; double x1 = p1.pos_x; double y1 = p1.pos_y; double x2 = p2.pos_x; double y2 = p2.pos_y; double dx = x2 - x1; double dy = y2 - y1; double mag = dx * dx + dy * dy; if (mag == 0.0) { return std::sqrt((x0 - x1) * (x0 - x1) + (y0 - y1) * (y0 - y1)); } double u = ((x0 - x1) * dx + (y0 - y1) * dy) / mag; u = std::max(0.0, std::min(1.0, u)); double x = x1 + u * dx; double y = y1 + u * dy; return std::sqrt((x - x0) * (x - x0) + (y - y0) * (y - y0)); } double computeMinDistanceToCurve(const Point &queryPoint, const std::vector &curve, size_t window_size) { if (curve.size() < 2) { // std::cerr << "曲线点不足以形成线段。" << std::endl; return std::numeric_limits::max(); } double min_distance = std::numeric_limits::max(); // 初始滑动窗口范围 for (size_t i = 0; i < curve.size() - 1; ++i) { BoundingBox box = createBoundingBox(curve[i], curve[i + 1]); if (!isPointInBoundingBox(queryPoint, box)) { continue; } // 如果在窗口范围内,计算距离 double dist = pointToSegmentDistance(queryPoint, curve[i], curve[i + 1]); if (dist < min_distance) { min_distance = dist; } // 滑动窗口: 超出窗口范围的段不计算 if (i >= window_size && dist > min_distance) { break; } } return min_distance; } double computeBazierDistanceToCurve(const Point &queryPoint, const std::vector &coords) { double min_dist = std::numeric_limits::max(); if (coords.size() < 2) { // std::cerr << "曲线点不足以形成线段。" << std::endl; return std::numeric_limits::max(); } for (int i = 0; i < coords.size() - 1; ++i) { double dist1 = pointToSegmentDistance(queryPoint, coords[i], coords[i + 1]); min_dist = std::min(min_dist, dist1); } return min_dist; } Point calculateCentroid(const std::vector &coords) { double sum_x = 0.0, sum_y = 0.0; int n = coords.size(); for (const auto &p : coords) { sum_x += p.pos_x; sum_y += p.pos_y; } return Point{sum_x / n, sum_y / n, 0.0}; } std::vector readIntersectionsFromCSV(const std::string &csvPath) { std::vector intersections; std::ifstream csvFile(csvPath); if (!csvFile.is_open()) { std::cerr << "无法打开路口信息csv文件: " << csvPath << std::endl; return intersections; } std::string line; // 读取表头 if (!std::getline(csvFile, line)) { std::cerr << "路口信息csv文件为空或无法读取表头。" << std::endl; return intersections; } // 解析表头,建立列名到索引的映射 std::unordered_map headerMap; std::stringstream headerStream(line); std::string headerField; int index = 0; while (std::getline(headerStream, headerField, ',')) { // 去除可能的引号和空格 headerField.erase(std::remove(headerField.begin(), headerField.end(), '\"'), headerField.end()); headerField.erase(std::remove(headerField.begin(), headerField.end(), ' '), headerField.end()); headerMap[headerField] = index++; } // 检查是否存在所有必要的列 std::vector requiredColumns = {"inter_id", "inter_type", "inter_in_shape", "inter_ref_link", "inter_coords"}; for (const auto &col : requiredColumns) { if (headerMap.find(col) == headerMap.end()) { std::cerr << "路口信息csv文件中未找到列名为 " << col << " 的列。" << std::endl; return intersections; } } int inter_id_idx = headerMap["inter_id"]; int inter_type_idx = headerMap["inter_type"]; int inter_in_shape_idx = headerMap["inter_in_shape"]; int inter_ref_link_idx = headerMap["inter_ref_link"]; int inter_coords_idx = headerMap["inter_coords"]; // 读取每一行 while (std::getline(csvFile, line)) { std::stringstream ss(line); std::string field; std::vector fields; bool in_quotes = false; std::string token; for (size_t i = 0; i < line.size(); ++i) { char c = line[i]; if (c == '\"') { in_quotes = !in_quotes; } else if (c == ',' && !in_quotes) { fields.push_back(token); token.clear(); } else { token += c; } } fields.push_back(token); // 检查字段数是否足够 if (fields.size() < requiredColumns.size()) { std::cerr << "字段数量不足,跳过行: " << line << std::endl; continue; } InterInfo inter; try { inter.inter_id = std::stoi(fields[inter_id_idx]); inter.inter_type = std::stoi(fields[inter_type_idx]); inter.inter_in_shape = std::stoi(fields[inter_in_shape_idx]); inter.inter_ref_link = parseRef(fields[inter_ref_link_idx]); inter.inter_coords = parseCoords(fields[inter_coords_idx]); } catch (const std::exception &e) { std::cerr << "解析错误,跳过行: " << line << "\n错误信息: " << e.what() << std::endl; continue; } intersections.push_back(inter); } csvFile.close(); return intersections; } std::vector readCrosswalksFromCSV(const std::string &csvPath) { std::vector crosswalks; std::ifstream csvFile(csvPath); if (!csvFile.is_open()) { std::cerr << "无法打开人行横道信息csv文件: " << csvPath << std::endl; return crosswalks; } std::string line; // 读取表头 if (!std::getline(csvFile, line)) { std::cerr << "人行横道信息csv文件为空或无法读取表头。" << std::endl; return crosswalks; } // 解析表头,建立列名到索引的映射 std::unordered_map headerMap; std::stringstream headerStream(line); std::string headerField; int index = 0; while (std::getline(headerStream, headerField, ',')) { // 去除可能的引号和空格 headerField.erase(std::remove(headerField.begin(), headerField.end(), '\"'), headerField.end()); headerField.erase(std::remove(headerField.begin(), headerField.end(), ' '), headerField.end()); headerMap[headerField] = index++; } // 检查是否存在所有必要的列 std::vector requiredColumns = {"cross_id", "cross_coords"}; for (const auto &col : requiredColumns) { if (headerMap.find(col) == headerMap.end()) { std::cerr << "人行横道信息csv文件中未找到列名为 " << col << " 的列。" << std::endl; return crosswalks; } } int cross_id_idx = headerMap["cross_id"]; int cross_coords_idx = headerMap["cross_coords"]; // 读取每一行 while (std::getline(csvFile, line)) { std::stringstream ss(line); std::string field; std::vector fields; bool in_quotes = false; std::string token; for (size_t i = 0; i < line.size(); ++i) { char c = line[i]; if (c == '\"') { in_quotes = !in_quotes; } else if (c == ',' && !in_quotes) { fields.push_back(token); token.clear(); } else { token += c; } } fields.push_back(token); // 检查字段数是否足够 if (fields.size() < requiredColumns.size()) { std::cerr << "字段数量不足,跳过行: " << line << std::endl; continue; } CrosswalkInfo cross; try { cross.cross_id = std::stoi(fields[cross_id_idx]); cross.cross_coords = parseCoords(fields[cross_coords_idx]); } catch (const std::exception &e) { std::cerr << "解析错误,跳过行: " << line << "\n错误信息: " << e.what() << std::endl; continue; } crosswalks.push_back(cross); } csvFile.close(); return crosswalks; } std::vector readTrafficlightsFromCSV(const std::string &csvPath) { std::vector trafficlights; std::ifstream csvFile(csvPath); if (!csvFile.is_open()) { std::cerr << "无法打开交通信号灯信息csv文件: " << csvPath << std::endl; return trafficlights; } std::string line; // 读取表头 if (!std::getline(csvFile, line)) { std::cerr << "交通信号灯信息csv文件为空或无法读取表头。" << std::endl; return trafficlights; } // 解析表头,建立列名到索引的映射 std::unordered_map headerMap; std::stringstream headerStream(line); std::string headerField; int index = 0; while (std::getline(headerStream, headerField, ',')) { // 去除可能的引号和空格 headerField.erase(std::remove(headerField.begin(), headerField.end(), '\"'), headerField.end()); headerField.erase(std::remove(headerField.begin(), headerField.end(), ' '), headerField.end()); headerMap[headerField] = index++; } // 检查是否存在所有必要的列 std::vector requiredColumns = {"trafficlight_id", "trafficlight_ref_link", "trafficlight_ref_lane", "trafficlight_type", "trafficlight_head", "trafficlight_coords"}; for (const auto &col : requiredColumns) { if (headerMap.find(col) == headerMap.end()) { std::cerr << "交通信号灯信息csv文件中未找到列名为 " << col << " 的列。" << std::endl; return trafficlights; } } int trafficlight_id_idx = headerMap["trafficlight_id"]; int trafficlight_ref_link_idx = headerMap["trafficlight_ref_link"]; int trafficlight_ref_lane_idx = headerMap["trafficlight_ref_lane"]; int trafficlight_type_idx = headerMap["trafficlight_type"]; int trafficlight_head_idx = headerMap["trafficlight_head"]; int trafficlight_coords_idx = headerMap["trafficlight_coords"]; // 读取每一行 while (std::getline(csvFile, line)) { std::stringstream ss(line); std::string field; std::vector fields; bool in_quotes = false; std::string token; for (size_t i = 0; i < line.size(); ++i) { char c = line[i]; if (c == '\"') { in_quotes = !in_quotes; } else if (c == ',' && !in_quotes) { fields.push_back(token); token.clear(); } else { token += c; } } fields.push_back(token); // 检查字段数是否足够 if (fields.size() < requiredColumns.size()) { std::cerr << "字段数量不足,跳过行: " << line << std::endl; continue; } TrafficlightInfo trafficlight; try { trafficlight.trafficlight_id = std::stoi(fields[trafficlight_id_idx]); trafficlight.trafficlight_ref_link = std::stoi(fields[trafficlight_ref_link_idx]); trafficlight.trafficlight_ref_lane = parseRef(fields[trafficlight_ref_lane_idx]); trafficlight.trafficlight_type = std::stoi(fields[trafficlight_type_idx]); trafficlight.trafficlight_head = parseRef(fields[trafficlight_head_idx]); trafficlight.trafficlight_coords = parseCoords(fields[trafficlight_coords_idx]); } catch (const std::exception &e) { std::cerr << "解析错误,跳过行: " << line << "\n错误信息: " << e.what() << std::endl; continue; } trafficlights.push_back(trafficlight); } csvFile.close(); return trafficlights; } std::vector readRoadsFromCSV(const std::string &csvPath) { std::vector roads; std::ifstream csvFile(csvPath); if (!csvFile.is_open()) { std::cerr << "无法打开道路信息csv文件: " << csvPath << std::endl; return roads; } std::string line; // 读取表头 if (!std::getline(csvFile, line)) { std::cerr << "道路信息csv文件为空或无法读取表头。" << std::endl; return roads; } // 解析表头,建立列名到索引的映射 std::unordered_map headerMap; std::stringstream headerStream(line); std::string headerField; int index = 0; while (std::getline(headerStream, headerField, ',')) { // 去除可能的引号和空格 headerField.erase(std::remove(headerField.begin(), headerField.end(), '\"'), headerField.end()); headerField.erase(std::remove(headerField.begin(), headerField.end(), ' '), headerField.end()); headerMap[headerField] = index++; } // 检查是否存在所有必要的列 std::vector requiredColumns = {"link_id", "link_fc", "link_type", "link_speed_max", "link_speed_min", "link_direction", "link_lanenum", "link_coords"}; for (const auto &col : requiredColumns) { if (headerMap.find(col) == headerMap.end()) { std::cerr << "道路信息csv文件中未找到列名为 " << col << " 的列。" << std::endl; return roads; } } int link_id_idx = headerMap["link_id"]; int link_fc_idx = headerMap["link_fc"]; int link_type_idx = headerMap["link_type"]; int link_speed_max_idx = headerMap["link_speed_max"]; int link_speed_min_idx = headerMap["link_speed_min"]; int link_direction_idx = headerMap["link_direction"]; int link_lanenum_idx = headerMap["link_lanenum"]; int link_coords_idx = headerMap["link_coords"]; // 读取每一行 while (std::getline(csvFile, line)) { std::stringstream ss(line); std::string field; std::vector fields; bool in_quotes = false; std::string token; for (size_t i = 0; i < line.size(); ++i) { char c = line[i]; if (c == '\"') { in_quotes = !in_quotes; } else if (c == ',' && !in_quotes) { fields.push_back(token); token.clear(); } else { token += c; } } fields.push_back(token); // 检查字段数是否足够 if (fields.size() < requiredColumns.size()) { std::cerr << "字段数量不足,跳过行: " << line << std::endl; continue; } RoadInfo road; try { road.link_id = std::stoi(fields[link_id_idx]); road.link_fc = std::stoi(fields[link_fc_idx]); road.link_type = std::stoi(fields[link_type_idx]); road.link_speed_max = std::stod(fields[link_speed_max_idx]); road.link_speed_min = std::stod(fields[link_speed_min_idx]); road.link_direction = std::stoi(fields[link_direction_idx]); road.link_lanenum = std::stoi(fields[link_lanenum_idx]); road.link_coords = parseCoords(fields[link_coords_idx]); } catch (const std::exception &e) { std::cerr << "解析错误,跳过行: " << line << "\n错误信息: " << e.what() << std::endl; continue; } roads.push_back(road); } csvFile.close(); return roads; } std::vector readLanesFromCSV(const std::string &csvPath) { std::vector lanes; std::ifstream csvFile(csvPath); if (!csvFile.is_open()) { std::cerr << "无法打开车道信息csv文件: " << csvPath << std::endl; return lanes; } std::string line; // 读取表头 if (!std::getline(csvFile, line)) { std::cerr << "车道信息csv文件为空或无法读取表头。" << std::endl; return lanes; } // 解析表头,建立列名到索引的映射 std::unordered_map headerMap; std::stringstream headerStream(line); std::string headerField; int index = 0; while (std::getline(headerStream, headerField, ',')) { // 去除可能的引号和空格 headerField.erase(std::remove(headerField.begin(), headerField.end(), '\"'), headerField.end()); headerField.erase(std::remove(headerField.begin(), headerField.end(), ' '), headerField.end()); headerMap[headerField] = index++; } // 检查是否存在所有必要的列 std::vector requiredColumns = {"lane_id", "lane_length", "lane_type", "lane_width", "lane_turn", "lane_ref_link", "lane_speed_max", "lane_speed_min", "lane_coords"}; for (const auto &col : requiredColumns) { if (headerMap.find(col) == headerMap.end()) { std::cerr << "车道信息csv文件中未找到列名为 " << col << " 的列。" << std::endl; return lanes; } } int lane_id_idx = headerMap["lane_id"]; int lane_length_idx = headerMap["lane_length"]; int lane_type_idx = headerMap["lane_type"]; int lane_width_idx = headerMap["lane_width"]; int lane_turn_idx = headerMap["lane_turn"]; int lane_ref_link_idx = headerMap["lane_ref_link"]; int lane_speed_max_idx = headerMap["lane_speed_max"]; int lane_speed_min_idx = headerMap["lane_speed_min"]; int lane_coords_idx = headerMap["lane_coords"]; // 读取每一行 while (std::getline(csvFile, line)) { std::stringstream ss(line); std::string field; std::vector fields; bool in_quotes = false; std::string token; for (size_t i = 0; i < line.size(); ++i) { char c = line[i]; if (c == '\"') { in_quotes = !in_quotes; } else if (c == ',' && !in_quotes) { fields.push_back(token); token.clear(); } else { token += c; } } fields.push_back(token); // 检查字段数是否足够 if (fields.size() < requiredColumns.size()) { std::cerr << "字段数量不足,跳过行: " << line << std::endl; continue; } LaneInfo lane; try { lane.lane_id = std::stoi(fields[lane_id_idx]); lane.lane_length = std::stod(fields[lane_length_idx]); lane.lane_type = std::stoi(fields[lane_type_idx]); lane.lane_width = std::stod(fields[lane_width_idx]); lane.lane_turn = std::stoi(fields[lane_turn_idx]); lane.lane_ref_link = std::stoi(fields[lane_ref_link_idx]); lane.lane_speed_max = std::stoi(fields[lane_speed_max_idx]); lane.lane_speed_min = std::stoi(fields[lane_speed_min_idx]); lane.lane_coords = parseCoords(fields[lane_coords_idx]); } catch (const std::exception &e) { std::cerr << "解析错误,跳过行: " << line << "\n错误信息: " << e.what() << std::endl; continue; } lanes.push_back(lane); } csvFile.close(); return lanes; } std::vector readSignalsFromCSV(const std::string &csvPath) { std::vector signs; std::ifstream csvFile(csvPath); if (!csvFile.is_open()) { std::cerr << "无法打开交通标牌信息csv文件: " << csvPath << std::endl; return signs; } std::string line; // 读取表头 if (!std::getline(csvFile, line)) { std::cerr << "交通标牌信息csv文件为空或无法读取表头。" << std::endl; return signs; } // 解析表头,建立列名到索引的映射 std::unordered_map headerMap; std::stringstream headerStream(line); std::string headerField; int index = 0; while (std::getline(headerStream, headerField, ',')) { // 去除可能的引号和空格 headerField.erase(std::remove(headerField.begin(), headerField.end(), '\"'), headerField.end()); headerField.erase(std::remove(headerField.begin(), headerField.end(), ' '), headerField.end()); headerMap[headerField] = index++; } // 检查是否存在所有必要的列 std::vector requiredColumns = {"sign_id", "sign_type", "sign_type1", "sign_ref_link", "sign_coords"}; for (const auto &col : requiredColumns) { if (headerMap.find(col) == headerMap.end()) { std::cerr << "交通标牌信息csv文件中未找到列名为 " << col << " 的列。" << std::endl; return signs; } } int sign_id_idx = headerMap["sign_id"]; int sign_type_idx = headerMap["sign_type"]; int sign_type1_idx = headerMap["sign_type1"]; int sign_ref_link_idx = headerMap["sign_ref_link"]; int sign_coords_idx = headerMap["sign_coords"]; // 读取每一行 while (std::getline(csvFile, line)) { std::stringstream ss(line); std::string field; std::vector fields; bool in_quotes = false; std::string token; for (size_t i = 0; i < line.size(); ++i) { char c = line[i]; if (c == '\"') { in_quotes = !in_quotes; } else if (c == ',' && !in_quotes) { fields.push_back(token); token.clear(); } else { token += c; } } fields.push_back(token); // 检查字段数是否足够 if (fields.size() < requiredColumns.size()) { std::cerr << "字段数量不足,跳过行: " << line << std::endl; continue; } SignalInfo sign; try { sign.sign_id = std::stoi(fields[sign_id_idx]); sign.sign_type = std::stoi(fields[sign_type_idx]); sign.sign_type1 = std::stoi(fields[sign_type1_idx]); sign.sign_ref_link = std::stoi(fields[sign_ref_link_idx]); sign.sign_coords = parseCoords(fields[sign_coords_idx]); } catch (const std::exception &e) { std::cerr << "解析错误,跳过行: " << line << "\n错误信息: " << e.what() << std::endl; continue; } signs.push_back(sign); } csvFile.close(); return signs; } // 从csv文件中读取停止线信息 std::vector readStopLinesFromCSV(const std::string &csvPath) { std::vector stopLines; std::ifstream csvFile(csvPath); if (!csvFile.is_open()) { std::cerr << "无法打开停止线信息csv文件: " << csvPath << std::endl; return stopLines; } std::string line; // 读取表头 if (!std::getline(csvFile, line)) { std::cerr << "停止线信息csv文件为空或无法读取表头。" << std::endl; return stopLines; } // 解析表头,建立列名到索引的映射 std::unordered_map headerMap; std::stringstream headerStream(line); std::string headerField; int index = 0; while (std::getline(headerStream, headerField, ',')) { // 去除可能的引号和空格 headerField.erase(std::remove(headerField.begin(), headerField.end(), '\"'), headerField.end()); headerField.erase(std::remove(headerField.begin(), headerField.end(), ' '), headerField.end()); headerMap[headerField] = index++; } // 检查是否存在所有必要的列 std::vector requiredColumns = {"stopline_id", "stopline_ref_link", "stopline_ref_lane", "stopline_color", "stopline_type", "stopline_coords"}; for (const auto &col : requiredColumns) { if (headerMap.find(col) == headerMap.end()) { std::cerr << "停止线信息csv文件中未找到列名为 " << col << " 的列。" << std::endl; return stopLines; } } int stop_id_idx = headerMap["stopline_id"]; int stop_ref_link_idx = headerMap["stopline_ref_link"]; int stop_ref_lane_idx = headerMap["stopline_ref_lane"]; int stop_color_idx = headerMap["stopline_color"]; int stop_type_idx = headerMap["stopline_type"]; int stop_coords_idx = headerMap["stopline_coords"]; // 读取每一行 while (std::getline(csvFile, line)) { std::stringstream ss(line); std::string field; std::vector fields; bool in_quotes = false; std::string token; for (size_t i = 0; i < line.size(); ++i) { char c = line[i]; if (c == '\"') { in_quotes = !in_quotes; } else if (c == ',' && !in_quotes) { fields.push_back(token); token.clear(); } else { token += c; } } fields.push_back(token); // 检查字段数是否足够 if (fields.size() < requiredColumns.size()) { std::cerr << "字段数量不足,跳过行: " << line << std::endl; continue; } StoplineInfo stopLine; try { stopLine.stopline_id = std::stoi(fields[stop_id_idx]); stopLine.stopline_ref_link = std::stoi(fields[stop_ref_link_idx]); stopLine.stopline_ref_lane = parseRef(fields[stop_ref_lane_idx]); stopLine.stopline_color = std::stoi(fields[stop_color_idx]); stopLine.stopline_type = std::stoi(fields[stop_type_idx]); stopLine.stopline_coords = parseCoords(fields[stop_coords_idx]); } catch (const std::exception &e) { std::cerr << "解析错误,跳过行: " << line << "\n错误信息: " << e.what() << std::endl; continue; } stopLines.push_back(stopLine); } csvFile.close(); return stopLines; } // 从csv文件中读取箭头信息 std::vector readArrowsFromCSV(const std::string &csvPath) { std::vector arrows; std::ifstream csvFile(csvPath); if (!csvFile.is_open()) { std::cerr << "无法打开箭头信息csv文件: " << csvPath << std::endl; return arrows; } std::string line; // 读取表头 if (!std::getline(csvFile, line)) { std::cerr << "箭头信息csv文件为空或无法读取表头。" << std::endl; return arrows; } // 解析表头,建立列名到索引的映射 std::unordered_map headerMap; std::stringstream headerStream(line); std::string headerField; int index = 0; while (std::getline(headerStream, headerField, ',')) { // 去除可能的引号和空格 headerField.erase(std::remove(headerField.begin(), headerField.end(), '\"'), headerField.end()); headerField.erase(std::remove(headerField.begin(), headerField.end(), ' '), headerField.end()); headerMap[headerField] = index++; } // 检查是否存在所有必要的列 std::vector requiredColumns = {"arrow_id", "arrow_ref_lane", "arrow_direction"}; for (const auto &col : requiredColumns) { if (headerMap.find(col) == headerMap.end()) { std::cerr << "箭头信息csv文件中未找到列名为 " << col << " 的列。" << std::endl; return arrows; } } int arrow_id_idx = headerMap["arrow_id"]; int arrow_lane_idx = headerMap["arrow_ref_lane"]; int arrow_direction_idx = headerMap["arrow_direction"]; // 读取每一行 while (std::getline(csvFile, line)) { std::stringstream ss(line); std::string field; std::vector fields; bool in_quotes = false; std::string token; for (size_t i = 0; i < line.size(); ++i) { char c = line[i]; if (c == '\"') { in_quotes = !in_quotes; } else if (c == ',' && !in_quotes) { fields.push_back(token); token.clear(); } else { token += c; } } fields.push_back(token); // 检查字段数是否足够 if (fields.size() < requiredColumns.size()) { std::cerr << "字段数量不足,跳过行: " << line << std::endl; continue; } ArrowInfo arrow; try { arrow.arrow_id = std::stoi(fields[arrow_id_idx]); arrow.arrow_ref_lane = std::stoi(fields[arrow_lane_idx]); arrow.arrow_direction = parseRef(fields[arrow_direction_idx]); } catch (const std::exception &e) { std::cerr << "解析错误,跳过行: " << line << "\n错误信息: " << e.what() << std::endl; continue; } arrows.push_back(arrow); } csvFile.close(); return arrows; }