// shape.cpp - Implementació del sistema de formes vectorials // © 2026 JailDesigner #include "core/graphics/shape.hpp" #include #include #include #include #include namespace Graphics { Shape::Shape(const std::string& filepath) : center_({.x = 0.0F, .y = 0.0F}), nom_("unnamed") { load(filepath); } auto Shape::load(const std::string& filepath) -> bool { // Llegir file std::ifstream file(filepath); if (!file.is_open()) { std::cerr << "[Shape] Error: no es pot obrir " << filepath << '\n'; return false; } // Llegir todo el contingut std::stringstream buffer; buffer << file.rdbuf(); std::string contingut = buffer.str(); file.close(); // Parsejar return parseFile(contingut); } auto Shape::parseFile(const std::string& contingut) -> bool { std::istringstream iss(contingut); std::string line; while (std::getline(iss, line)) { // Trim whitespace line = trim(line); // Skip comments and blanks if (line.empty() || line[0] == '#') { continue; } // Parse command if (startsWith(line, "name:")) { nom_ = trim(extractValue(line)); } else if (startsWith(line, "scale:")) { try { escala_defecte_ = std::stof(extractValue(line)); } catch (...) { std::cerr << "[Shape] Warning: scale invàlida, usant 1.0" << '\n'; escala_defecte_ = 1.0F; } } else if (startsWith(line, "center:")) { parseCenter(extractValue(line)); } else if (startsWith(line, "polyline:")) { auto points = parsePoints(extractValue(line)); if (points.size() >= 2) { primitives_.push_back({PrimitiveType::POLYLINE, points}); } else { std::cerr << "[Shape] Warning: polyline con menys de 2 points ignorada" << '\n'; } } else if (startsWith(line, "line:")) { auto points = parsePoints(extractValue(line)); if (points.size() == 2) { primitives_.push_back({PrimitiveType::LINE, points}); } else { std::cerr << "[Shape] Warning: line ha de tenir exactament 2 points" << '\n'; } } // Comandes desconegudes ignorades silenciosament } if (primitives_.empty()) { std::cerr << "[Shape] Error: sin primitiva carregada" << '\n'; return false; } bounding_radius_ = computeBoundingRadius(primitives_, center_); return true; } auto Shape::computeBoundingRadius(const std::vector& primitives, const Vec2& center) -> float { float max_dist_sq = 0.0F; for (const auto& prim : primitives) { for (const auto& p : prim.points) { const float DX = p.x - center.x; const float DY = p.y - center.y; max_dist_sq = std::max(max_dist_sq, (DX * DX) + (DY * DY)); } } return std::sqrt(max_dist_sq); } // Helper: trim whitespace auto Shape::trim(const std::string& str) -> std::string { const char* whitespace = " \t\n\r"; size_t start = str.find_first_not_of(whitespace); if (start == std::string::npos) { return ""; } size_t end = str.find_last_not_of(whitespace); return str.substr(start, end - start + 1); } // Helper: startsWith auto Shape::startsWith(const std::string& str, const std::string& prefix) -> bool { if (str.length() < prefix.length()) { return false; } return str.starts_with(prefix); } // Helper: extract value after ':' auto Shape::extractValue(const std::string& line) -> std::string { size_t colon = line.find(':'); if (colon == std::string::npos) { return ""; } return line.substr(colon + 1); } // Helper: parse center "x, y" void Shape::parseCenter(const std::string& value) { std::string val = trim(value); size_t comma = val.find(','); if (comma != std::string::npos) { try { center_.x = std::stof(trim(val.substr(0, comma))); center_.y = std::stof(trim(val.substr(comma + 1))); } catch (...) { std::cerr << "[Shape] Warning: centro invàlid, usant (0,0)" << '\n'; center_ = {.x = 0.0F, .y = 0.0F}; } } } // Helper: parse points "x1,y1 x2,y2 x3,y3" auto Shape::parsePoints(const std::string& str) -> std::vector { std::vector points; std::istringstream iss(trim(str)); std::string pair; while (iss >> pair) { // Whitespace-separated size_t comma = pair.find(','); if (comma != std::string::npos) { try { float x = std::stof(pair.substr(0, comma)); float y = std::stof(pair.substr(comma + 1)); points.push_back({x, y}); } catch (...) { std::cerr << "[Shape] Warning: point invàlid ignorat: " << pair << '\n'; } } } return points; } } // namespace Graphics