From 7ef2f561408ee8fe54c54e509967ac3b2325baa7 Mon Sep 17 00:00:00 2001 From: "tlepoix@localhost" Date: Thu, 4 Sep 2025 16:27:49 +0200 Subject: [PATCH 01/14] add Polygon::z_placement --- src/domain/board.cpp | 15 +-- src/domain/geometrics/polygon.cpp | 12 ++- src/domain/geometrics/polygon.hpp | 10 +- src/infra/parsers/parser_from_csx.cpp | 8 +- test/unit/domain/geometrics/test_polygon.cpp | 66 +++++++++--- test/unit/domain/test_board.cpp | 101 +++++++++++-------- test/unit/infra/serializers/lpf.hpp | 15 +-- test/unit/infra/serializers/stub.hpp | 33 +++--- 8 files changed, 171 insertions(+), 89 deletions(-) diff --git a/src/domain/board.cpp b/src/domain/board.cpp index 370c40e9..859531ca 100644 --- a/src/domain/board.cpp +++ b/src/domain/board.cpp @@ -88,24 +88,24 @@ void Board::Builder::add_fixed_meshline_policy(Axis const axis, Coord const coor } //****************************************************************************** -void Board::Builder::add_polygon(Plane const plane, Polygon::Type const type, string const& name, initializer_list points) { - polygons[plane].push_back(make_shared(plane, type, name, from_init_list(points), Caretaker::singleton().get_history_root())); +void Board::Builder::add_polygon(Plane plane, Polygon::Type type, string const& name, Polygon::RangeZ const& z_placement, initializer_list points) { + polygons[plane].push_back(make_shared(plane, type, name, z_placement, from_init_list(points), Caretaker::singleton().get_history_root())); } //****************************************************************************** -void Board::Builder::add_polygon(Plane const plane, Polygon::Type const type, string const& name, vector>&& points) { - polygons[plane].push_back(make_shared(plane, type, name, std::move(points), Caretaker::singleton().get_history_root())); +void Board::Builder::add_polygon(Plane plane, Polygon::Type type, string const& name, Polygon::RangeZ const& z_placement, vector>&& points) { + polygons[plane].push_back(make_shared(plane, type, name, z_placement, std::move(points), Caretaker::singleton().get_history_root())); } //****************************************************************************** -void Board::Builder::add_polygon_from_box(Plane const plane, Polygon::Type const type, string const& name, Point const p1, Point const p3) { +void Board::Builder::add_polygon_from_box(Plane plane, Polygon::Type type, string const& name, Polygon::RangeZ const& z_placement, Point const p1, Point const p3) { vector> points(4); points[0] = make_unique(p1.x, p1.y); points[1] = make_unique(p1.x, p3.y); points[2] = make_unique(p3.x, p3.y); points[3] = make_unique(p3.x, p1.y); - polygons[plane].push_back(make_shared(plane, type, name, std::move(points), Caretaker::singleton().get_history_root())); + polygons[plane].push_back(make_shared(plane, type, name, z_placement, std::move(points), Caretaker::singleton().get_history_root())); } //****************************************************************************** @@ -169,6 +169,9 @@ void Board::detect_edges_in_polygons(Plane const plane) { if(poly_b == poly_a) continue; + if(!does_overlap(poly_b->z_placement, poly_a->z_placement)) + continue; + for(auto const& edge_a : poly_a->edges) { struct RangeBtwIntersections { diff --git a/src/domain/geometrics/polygon.cpp b/src/domain/geometrics/polygon.cpp index 5b4813f5..7a846680 100644 --- a/src/domain/geometrics/polygon.cpp +++ b/src/domain/geometrics/polygon.cpp @@ -15,10 +15,11 @@ namespace domain { using namespace std; //****************************************************************************** -Polygon::Polygon(Plane const plane, Type const type, string const& name, vector>&& points, Timepoint* t) +Polygon::Polygon(Plane const plane, Type const type, string const& name, RangeZ const& z_placement, vector>&& points, Timepoint* t) : Originator(t) , rotation(detect_rotation(points)) , type(type) +, z_placement(z_placement) , plane(plane) , bounding(detect_bounding(points)) , name(name) @@ -193,4 +194,13 @@ relation::PolygonPoint Polygon::relation_to(Point const& point) const noexcept { return relation::PolygonPoint::OUT; } +/// Check if two Z ranges overlap or just touch each other. +///***************************************************************************** +bool does_overlap(Polygon::RangeZ const& a, Polygon::RangeZ const& b) noexcept { + return (b.min >= a.min && b.min <= a.max) + || (b.max >= a.min && b.max <= a.max) + || (a.min >= b.min && a.min <= b.max) + || (a.max >= b.min && a.max <= b.max); +} + } // namespace domain diff --git a/src/domain/geometrics/polygon.hpp b/src/domain/geometrics/polygon.hpp index 83b17abd..5ec70b46 100644 --- a/src/domain/geometrics/polygon.hpp +++ b/src/domain/geometrics/polygon.hpp @@ -55,6 +55,11 @@ class Polygon SUBSTRATE } const type; + struct RangeZ { + Coord min; + Coord max; + } const z_placement; + Plane const plane; Bounding2D const bounding; std::string const name; @@ -66,7 +71,7 @@ class Polygon ///************************************************************************* std::vector> const edges; - Polygon(Plane plane, Type type, std::string const& name, std::vector>&& points, Timepoint* t); + Polygon(Plane plane, Type type, std::string const& name, RangeZ const& z_placement, std::vector>&& points, Timepoint* t); ~Polygon() override; // relation::PolygonEdge relation_to(Edge const* edge); @@ -85,4 +90,7 @@ Bounding2D detect_bounding(std::vector> const& poin //****************************************************************************** std::vector> detect_edges(std::vector> const& points, Plane plane, Timepoint* t); +//****************************************************************************** +bool does_overlap(Polygon::RangeZ const& a, Polygon::RangeZ const& b) noexcept; + } // namespace domain diff --git a/src/infra/parsers/parser_from_csx.cpp b/src/infra/parsers/parser_from_csx.cpp index be808ac5..a3c9f6a0 100644 --- a/src/infra/parsers/parser_from_csx.cpp +++ b/src/infra/parsers/parser_from_csx.cpp @@ -165,11 +165,11 @@ void ParserFromCsx::Pimpl::parse_primitive_box(pugi::xml_node const& node, strin node_p2.attribute("Y").as_double(), node_p2.attribute("Z").as_double()); if(params.with_yz) - board.add_polygon_from_box(YZ, type.value(), name, { p1.y, p1.z }, { p2.y, p2.z }); + board.add_polygon_from_box(YZ, type.value(), name, { p1.x, p2.x }, { p1.y, p1.z }, { p2.y, p2.z }); if(params.with_zx) - board.add_polygon_from_box(ZX, type.value(), name, { p1.z, p1.x }, { p2.z, p2.x }); + board.add_polygon_from_box(ZX, type.value(), name, { p1.y, p2.y }, { p1.z, p1.x }, { p2.z, p2.x }); if(params.with_xy) - board.add_polygon_from_box(XY, type.value(), name, { p1.x, p1.y }, { p2.x, p2.y }); + board.add_polygon_from_box(XY, type.value(), name, { p1.z, p2.z }, { p1.x, p1.y }, { p2.x, p2.y }); // TODO if property == ConductingSheet : add_fixed_meshline_policy() } @@ -196,7 +196,7 @@ void ParserFromCsx::Pimpl::parse_primitive_linpoly(pugi::xml_node const& node, s Bounding2D bounding(detect_bounding(points)); - board.add_polygon(plane.value(), type.value(), name, std::move(points)); + board.add_polygon(plane.value(), type.value(), name, { elevation, elevation + length }, std::move(points)); if(length == 0) { board.add_fixed_meshline_policy(normal.value(), elevation); // switch(plane.value()) { diff --git a/test/unit/domain/geometrics/test_polygon.cpp b/test/unit/domain/geometrics/test_polygon.cpp index 1a9b9611..fe2e4c8c 100644 --- a/test/unit/domain/geometrics/test_polygon.cpp +++ b/test/unit/domain/geometrics/test_polygon.cpp @@ -18,6 +18,7 @@ /// @test template Polygon::Rotation detect_rotation(T& points) noexcept /// @test void Polygon::detect_edge_normal() noexcept /// @test relation::PolygonPoint Polygon::relation_to(Point const* point) const noexcept +/// @test bool does_overlap(Polygon::RangeZ const& a, Polygon::RangeZ const& b) noexcept ///***************************************************************************** using namespace domain; @@ -63,7 +64,7 @@ SCENARIO("template Polygon::Rotation detect_rotation(T& points) noexcep Timepoint t; GIVEN("A polygon or a bunch of points") { WHEN("Points order is oriented clockwise") { - Polygon a(XY, Polygon::Type::SHAPE, "", from_init_list({{ 1, 2 }, { 1, 4 }, { 4, 4 }}), &t); + Polygon a(XY, Polygon::Type::SHAPE, "", { 0, 0 }, from_init_list({{ 1, 2 }, { 1, 4 }, { 4, 4 }}), &t); std::vector b({a.points[0].get(), a.points[1].get(), a.points[2].get()}); THEN("Should be detected as CW") { REQUIRE(detect_rotation(a.points) == Polygon::Rotation::CW); @@ -72,7 +73,7 @@ SCENARIO("template Polygon::Rotation detect_rotation(T& points) noexcep } WHEN("Points order is oriented counter clockwise") { - Polygon a(XY, Polygon::Type::SHAPE, "", from_init_list({{ 1, 2 }, { 4, 4 }, { 1, 4 }}), &t); + Polygon a(XY, Polygon::Type::SHAPE, "", { 0, 0 }, from_init_list({{ 1, 2 }, { 4, 4 }, { 1, 4 }}), &t); std::vector b({a.points[0].get(), a.points[1].get(), a.points[2].get()}); THEN("Should be detected as CCW") { REQUIRE(detect_rotation(a.points) == Polygon::Rotation::CCW); @@ -81,8 +82,8 @@ SCENARIO("template Polygon::Rotation detect_rotation(T& points) noexcep } WHEN("Points are all aligned in an axis") { - Polygon a(XY, Polygon::Type::SHAPE, "", from_init_list({{ 1, 2 }, { 1, 4 }, { 1, 1 }}), &t); - Polygon b(XY, Polygon::Type::SHAPE, "", from_init_list({{ 51.3539, -44.8024 }, { 120.0290, -44.8024 }, { 140.2830, -44.8024 }}), &t); + Polygon a(XY, Polygon::Type::SHAPE, "", { 0, 0 }, from_init_list({{ 1, 2 }, { 1, 4 }, { 1, 1 }}), &t); + Polygon b(XY, Polygon::Type::SHAPE, "", { 0, 0 }, from_init_list({{ 51.3539, -44.8024 }, { 120.0290, -44.8024 }, { 140.2830, -44.8024 }}), &t); std::vector c({a.points[0].get(), a.points[1].get(), a.points[2].get()}); std::vector d({b.points[0].get(), b.points[1].get(), b.points[2].get()}); THEN("Should be detected as COLINEAR") { @@ -94,7 +95,7 @@ SCENARIO("template Polygon::Rotation detect_rotation(T& points) noexcep } WHEN("Points are all aligned in diagonal") { - Polygon a(XY, Polygon::Type::SHAPE, "", from_init_list({{ 1, 2 }, { 4, 4 }, { 2.5, 3 }}), &t); + Polygon a(XY, Polygon::Type::SHAPE, "", { 0, 0 }, from_init_list({{ 1, 2 }, { 4, 4 }, { 2.5, 3 }}), &t); std::vector b({a.points[0].get(), a.points[1].get(), a.points[2].get()}); THEN("Should be detected as COLINEAR") { REQUIRE(detect_rotation(a.points) == Polygon::Rotation::COLINEAR); @@ -103,7 +104,7 @@ SCENARIO("template Polygon::Rotation detect_rotation(T& points) noexcep } WHEN("Two points of a triangle are at the same place") { - Polygon a(XY, Polygon::Type::SHAPE, "", from_init_list({{ 1, 2 }, { 4, 4 }, { 1, 2 }}), &t); + Polygon a(XY, Polygon::Type::SHAPE, "", { 0, 0 }, from_init_list({{ 1, 2 }, { 4, 4 }, { 1, 2 }}), &t); std::vector b({a.points[0].get(), a.points[1].get(), a.points[2].get()}); THEN("Should be detected as COLINEAR") { REQUIRE(detect_rotation(a.points) == Polygon::Rotation::COLINEAR); @@ -118,7 +119,7 @@ SCENARIO("void Polygon::detect_edge_normal() noexcept", "[polygon]") { Timepoint t; GIVEN("An octogon : 2 horizontal edges, 2 verticals, 4 diagonals") { WHEN("Points order is oriented clockwise") { - Polygon a(XY, Polygon::Type::SHAPE, "", from_init_list({ + Polygon a(XY, Polygon::Type::SHAPE, "", { 0, 0 }, from_init_list({ { 2, 1 }, { 1, 2 }, { 1, 3 }, { 2, 4 }, { 3, 4 }, { 4, 3 }, { 4, 2 }, { 3, 1 }}), &t); THEN("For edges going down to the X axis, the normal should go down to the Y") { @@ -150,7 +151,7 @@ SCENARIO("void Polygon::detect_edge_normal() noexcept", "[polygon]") { } WHEN("Points order is oriented counter clockwise") { - Polygon a(XY, Polygon::Type::SHAPE, "", from_init_list({ + Polygon a(XY, Polygon::Type::SHAPE, "", { 0, 0 }, from_init_list({ { 2, 1 }, { 3, 1 }, { 4, 2 }, { 4, 3 }, { 3, 4 }, { 2, 4 }, { 1, 3 }, { 1, 2 }}), &t); THEN("For edges going down to the X axis, the normal should go up to the Y") { @@ -182,7 +183,7 @@ SCENARIO("void Polygon::detect_edge_normal() noexcept", "[polygon]") { } WHEN("Points are all aligned or at the same position") { - Polygon a(XY, Polygon::Type::SHAPE, "", from_init_list({{ 1, 2 }, { 1, 4 }, { 1, 1 }, { 1, 1 }}), &t); + Polygon a(XY, Polygon::Type::SHAPE, "", { 0, 0 }, from_init_list({{ 1, 2 }, { 1, 4 }, { 1, 1 }, { 1, 1 }}), &t); THEN("There should not be any normal") { REQUIRE(a.rotation == Polygon::Rotation::COLINEAR); REQUIRE(a.edges[0]->normal == Normal::NONE); @@ -198,7 +199,7 @@ SCENARIO("void Polygon::detect_edge_normal() noexcept", "[polygon]") { SCENARIO("relation::PolygonPoint Polygon::relation_to(Point const* point) const noexcept", "[polygon]") { Timepoint t; GIVEN("A simple polygon") { - Polygon poly(XY, Polygon::Type::SHAPE, "", from_init_list({{ 1, 1 }, { 1, 3 }, { 3, 3 }, { 3, 1 }}), &t); + Polygon poly(XY, Polygon::Type::SHAPE, "", { 0, 0 }, from_init_list({{ 1, 1 }, { 1, 3 }, { 3, 3 }, { 3, 1 }}), &t); WHEN("A point is inside the polygon") { Point p(2, 2); THEN("Should be detected as IN") { @@ -255,7 +256,7 @@ SCENARIO("relation::PolygonPoint Polygon::relation_to(Point const* point) const GIVEN("A polygon with vertices on the firsts rays") { WHEN("The polygon have 4 edge colinear to the 4 first rays") { - Polygon poly(XY, Polygon::Type::SHAPE, "", from_init_list({ + Polygon poly(XY, Polygon::Type::SHAPE, "", { 0, 0 }, from_init_list({ { 3, 1 }, { 3, 2 }, { 4, 3 }, { 5, 3 }, { 3, 5 }, { 3, 4 }, { 2, 3 }, { 1, 3 }}), &t); Point p(3, 3); @@ -265,7 +266,7 @@ SCENARIO("relation::PolygonPoint Polygon::relation_to(Point const* point) const } WHEN("The polygon have 4 angles on the 4 first rays") { - Polygon poly(XY, Polygon::Type::SHAPE, "", from_init_list({{ 2, 1 }, { 3, 2 }, { 2, 3 }, { 1, 2 }}), &t); + Polygon poly(XY, Polygon::Type::SHAPE, "", { 0, 0 }, from_init_list({{ 2, 1 }, { 3, 2 }, { 2, 3 }, { 1, 2 }}), &t); Point p(2, 2); THEN("Should be detected as IN") { REQUIRE(poly.relation_to(p) == relation::PolygonPoint::IN); @@ -275,7 +276,7 @@ SCENARIO("relation::PolygonPoint Polygon::relation_to(Point const* point) const GIVEN("A simple polygon that flirt with floating points calculus imprecision") { WHEN("A point is outside the polygon, but colinear to an edge") { - Polygon poly(XY, Polygon::Type::SHAPE, "", from_init_list({ + Polygon poly(XY, Polygon::Type::SHAPE, "", { 0, 0 }, from_init_list({ { 120.0290, -44.8024 }, { 120.0290, -42.0164 }, { 140.2830, -42.0164 }, @@ -289,3 +290,42 @@ SCENARIO("relation::PolygonPoint Polygon::relation_to(Point const* point) const } } } + +//****************************************************************************** +SCENARIO("bool does_overlap(Polygon::RangeZ const& a, Polygon::RangeZ const& b) noexcept", "[polygon]") { + GIVEN("Two Z ranges that do not overlap") { + Polygon::RangeZ a { 1, 4 }; + Polygon::RangeZ b { 5, 6 }; + THEN("Should not be detected as overlapping") { + REQUIRE_FALSE(does_overlap(a, b)); + REQUIRE_FALSE(does_overlap(b, a)); + } + } + + GIVEN("Two Z ranges that overlap") { + Polygon::RangeZ a { 1, 4 }; + Polygon::RangeZ b { 2, 5 }; + THEN("Should be detected as overlapping") { + REQUIRE(does_overlap(a, b)); + REQUIRE(does_overlap(b, a)); + } + } + + GIVEN("A Z range that is totally inside an other") { + Polygon::RangeZ a { 1, 4 }; + Polygon::RangeZ b { 2, 3 }; + THEN("Should be detected as overlapping") { + REQUIRE(does_overlap(a, b)); + REQUIRE(does_overlap(b, a)); + } + } + + GIVEN("Two Z ranges that just touch each other") { + Polygon::RangeZ a { 1, 4 }; + Polygon::RangeZ b { 4, 5 }; + THEN("Should be detected as overlapping") { + REQUIRE(does_overlap(a, b)); + REQUIRE(does_overlap(b, a)); + } + } +} diff --git a/test/unit/domain/test_board.cpp b/test/unit/domain/test_board.cpp index 0d9a69c1..bf5755c4 100644 --- a/test/unit/domain/test_board.cpp +++ b/test/unit/domain/test_board.cpp @@ -16,9 +16,9 @@ #include "domain/board.hpp" /// @test void sort_points_by_vector_orientation(std::vector& points, Point const& vector) -/// @test void Board::Builder::add_polygon(std::string const& name, std::initializer_list points) -/// @test void Board::Builder::add_polygon(std::string const& name, std::vector>&& points) -/// @test void Board::Builder::add_polygon_from_box(std::string const& name, Point const p1, Point const p3) +/// @test void Board::Builder::add_polygon(Plane plane, std::string const& name, Polygon::RangeZ const& z_placement, std::initializer_list points) +/// @test void Board::Builder::add_polygon(Plane plane, std::string const& name, Polygon::RangeZ const& z_placement, std::vector>&& points) +/// @test void Board::Builder::add_polygon_from_box(Plane plane, std::string const& name, Polygon::RangeZ const& z_placement, Point const p1, Point const p3) /// @test std::unique_ptr Board::Builder::build() /// @test void Board::detect_edges_in_polygons() /// @test void Board::detect_colinear_edges() @@ -136,12 +136,12 @@ SCENARIO("void sort_points_by_vector_orientation(std::vector& points, Poi //****************************************************************************** -SCENARIO("void Board::Builder::add_polygon(std::string const& name, std::initializer_list points)", "[board]") { +SCENARIO("void Board::Builder::add_polygon(Plane plane, std::string const& name, Polygon::RangeZ const& z_placement, std::initializer_list points)", "[board]") { GIVEN("A Board Builder") { Board::Builder b; REQUIRE(b.polygons[XY].empty()); WHEN("Adding a polygon as an initializer_list of Points") { - b.add_polygon(XY, Polygon::Type::SHAPE, "MS13", { + b.add_polygon(XY, Polygon::Type::SHAPE, "MS13", { 0, 0 }, { { 70.3673, -42.8674 }, { 62.1753, -42.8674 }, { 62.1753, -43.9276 }, @@ -163,7 +163,7 @@ SCENARIO("void Board::Builder::add_polygon(std::string const& name, std::initial } //****************************************************************************** -SCENARIO("void Board::Builder::add_polygon(std::string const& name, std::vector>&& points)", "[board]") { +SCENARIO("void Board::Builder::add_polygon(Plane plane, std::string const& name, Polygon::RangeZ const& z_placement, std::vector>&& points)", "[board]") { GIVEN("A Board Builder") { Board::Builder b; REQUIRE(b.polygons[XY].empty()); @@ -175,8 +175,8 @@ SCENARIO("void Board::Builder::add_polygon(std::string const& name, std::vector< { 66.2713, -43.9276 }, { 66.2713, -43.9514 }, { 70.3673, -43.9514 }})); - b.add_polygon(XY, Polygon::Type::SHAPE, "MS13", std::move(points)); - b.add_polygon(XY, Polygon::Type::SHAPE, "MS15", from_init_list({ + b.add_polygon(XY, Polygon::Type::SHAPE, "MS13", { 0, 0 }, std::move(points)); + b.add_polygon(XY, Polygon::Type::SHAPE, "MS15", { 0, 0 }, from_init_list({ { 70.3673, -42.8674 }, { 62.1753, -42.8674 }, { 62.1753, -43.9276 }, @@ -205,12 +205,12 @@ SCENARIO("void Board::Builder::add_polygon(std::string const& name, std::vector< } //****************************************************************************** -SCENARIO("void Board::Builder::add_polygon_from_box(std::string const& name, Point const p1, Point const p3)", "[board]") { +SCENARIO("void Board::Builder::add_polygon_from_box(Plane plane, std::string const& name, Polygon::RangeZ const& z_placement, Point const p1, Point const p3)", "[board]") { GIVEN("A Board Builder") { Board::Builder b; REQUIRE(b.polygons[XY].empty()); WHEN("Adding a rectangle polygon as a box of opposite Points") { - b.add_polygon_from_box(XY, Polygon::Type::SHAPE, "MS1", { 16.1, -26.5 }, { 20.6, -26 }); + b.add_polygon_from_box(XY, Polygon::Type::SHAPE, "MS1", { 0, 0 }, { 16.1, -26.5 }, { 20.6, -26 }); THEN("Should add a Polygon in the inner vector") { REQUIRE(b.polygons[XY].size() == 1); REQUIRE(b.polygons[XY][0]->name == "MS1"); @@ -228,15 +228,15 @@ SCENARIO("std::unique_ptr Board::Builder::build()", "[board]") { GIVEN("A Board Builder previously fed of polygons") { Board::Builder b; REQUIRE(b.polygons[XY].empty()); - b.add_polygon_from_box(XY, Polygon::Type::SHAPE, "MS1", { 16.1, -26.5 }, { 20.6, -26 }); - b.add_polygon(XY, Polygon::Type::SHAPE, "MS15", from_init_list({ + b.add_polygon_from_box(XY, Polygon::Type::SHAPE, "MS1", { 0, 0 }, { 16.1, -26.5 }, { 20.6, -26 }); + b.add_polygon(XY, Polygon::Type::SHAPE, "MS15", { 0, 0 }, from_init_list({ { 70.3673, -42.8674 }, { 62.1753, -42.8674 }, { 62.1753, -43.9276 }, { 66.2713, -43.9276 }, { 66.2713, -43.9514 }, { 70.3673, -43.9514 }})); - b.add_polygon(XY, Polygon::Type::SHAPE, "MS13", { + b.add_polygon(XY, Polygon::Type::SHAPE, "MS13", { 0, 0 }, { { 70.3673, -42.8674 }, { 62.1753, -42.8674 }, { 62.1753, -43.9276 }, @@ -284,8 +284,8 @@ SCENARIO("void Board::detect_edges_in_polygons()", "[board]") { std::unique_ptr b; { PlaneSpace>> tmp; - tmp[XY].push_back(std::make_shared(XY, Polygon::Type::SHAPE, "", from_init_list({{ 1, 1 }, { 4, 1 }, { 4, 4 }, { 1, 4 }}), t)); - tmp[XY].push_back(std::make_shared(XY, Polygon::Type::SHAPE, "", from_init_list({{ 2, 2 }, { 2, 3 }, { 3, 3 }, { 3, 2 }}), t)); + tmp[XY].push_back(std::make_shared(XY, Polygon::Type::SHAPE, "", Polygon::RangeZ { 0, 0 }, from_init_list({{ 1, 1 }, { 4, 1 }, { 4, 4 }, { 1, 4 }}), t)); + tmp[XY].push_back(std::make_shared(XY, Polygon::Type::SHAPE, "", Polygon::RangeZ { 0, 0 }, from_init_list({{ 2, 2 }, { 2, 3 }, { 3, 3 }, { 3, 2 }}), t)); b = std::make_unique(std::move(tmp), Params(), t); } b->detect_edges_in_polygons(); @@ -361,8 +361,8 @@ SCENARIO("void Board::detect_edges_in_polygons()", "[board]") { std::unique_ptr b; { PlaneSpace>> tmp; - tmp[XY].push_back(std::make_shared(XY, Polygon::Type::SHAPE, "", from_init_list({{ 1, 2 }, { 3, 2 }, { 3, 4 }, { 1, 4 }}), t)); - tmp[XY].push_back(std::make_shared(XY, Polygon::Type::SHAPE, "", from_init_list({{ 2, 1 }, { 4, 1 }, { 4, 3 }, { 2, 3 }}), t)); + tmp[XY].push_back(std::make_shared(XY, Polygon::Type::SHAPE, "", Polygon::RangeZ { 0, 0 }, from_init_list({{ 1, 2 }, { 3, 2 }, { 3, 4 }, { 1, 4 }}), t)); + tmp[XY].push_back(std::make_shared(XY, Polygon::Type::SHAPE, "", Polygon::RangeZ { 0, 0 }, from_init_list({{ 2, 1 }, { 4, 1 }, { 4, 3 }, { 2, 3 }}), t)); b = std::make_unique(std::move(tmp), Params(), t); } b->detect_edges_in_polygons(); @@ -439,8 +439,8 @@ SCENARIO("void Board::detect_edges_in_polygons()", "[board]") { std::unique_ptr b; { PlaneSpace>> tmp; - tmp[XY].push_back(std::make_shared(XY, Polygon::Type::SHAPE, "", from_init_list({{ 1, 2 }, { 4, 2 }, { 4, 4 }, { 1, 4 }}), t)); - tmp[XY].push_back(std::make_shared(XY, Polygon::Type::SHAPE, "", from_init_list({{ 2, 1 }, { 3, 1 }, { 3, 3 }, { 2, 3 }}), t)); + tmp[XY].push_back(std::make_shared(XY, Polygon::Type::SHAPE, "", Polygon::RangeZ { 0, 0 }, from_init_list({{ 1, 2 }, { 4, 2 }, { 4, 4 }, { 1, 4 }}), t)); + tmp[XY].push_back(std::make_shared(XY, Polygon::Type::SHAPE, "", Polygon::RangeZ { 0, 0 }, from_init_list({{ 2, 1 }, { 3, 1 }, { 3, 3 }, { 2, 3 }}), t)); b = std::make_unique(std::move(tmp), Params(), t); } b->detect_edges_in_polygons(); @@ -517,8 +517,8 @@ SCENARIO("void Board::detect_edges_in_polygons()", "[board]") { std::unique_ptr b; { PlaneSpace>> tmp; - tmp[XY].push_back(std::make_shared(XY, Polygon::Type::SHAPE, "", from_init_list({{ 1, 1 }, { 4, 1 }, { 4, 4 }, { 1, 4 }}), t)); - tmp[XY].push_back(std::make_shared(XY, Polygon::Type::SHAPE, "", from_init_list({{ 2, 3 }, { 3, 2 }, { 5, 4 }, { 4, 5 }}), t)); + tmp[XY].push_back(std::make_shared(XY, Polygon::Type::SHAPE, "", Polygon::RangeZ { 0, 0 }, from_init_list({{ 1, 1 }, { 4, 1 }, { 4, 4 }, { 1, 4 }}), t)); + tmp[XY].push_back(std::make_shared(XY, Polygon::Type::SHAPE, "", Polygon::RangeZ { 0, 0 }, from_init_list({{ 2, 3 }, { 3, 2 }, { 5, 4 }, { 4, 5 }}), t)); b = std::make_unique(std::move(tmp), Params(), t); } b->detect_edges_in_polygons(); @@ -608,8 +608,8 @@ SCENARIO("void Board::detect_edges_in_polygons()", "[board]") { std::unique_ptr b; { PlaneSpace>> tmp; - tmp[XY].push_back(std::make_shared(XY, Polygon::Type::SHAPE, "", from_init_list({{ 1, 2 }, { 4, 2 }, { 4, 4 }, { 1, 4 }}), t)); - tmp[XY].push_back(std::make_shared(XY, Polygon::Type::SHAPE, "", from_init_list({{ 2, 1 }, { 3, 1 }, { 3, 2 }, { 2, 2 }}), t)); + tmp[XY].push_back(std::make_shared(XY, Polygon::Type::SHAPE, "", Polygon::RangeZ { 0, 0 }, from_init_list({{ 1, 2 }, { 4, 2 }, { 4, 4 }, { 1, 4 }}), t)); + tmp[XY].push_back(std::make_shared(XY, Polygon::Type::SHAPE, "", Polygon::RangeZ { 0, 0 }, from_init_list({{ 2, 1 }, { 3, 1 }, { 3, 2 }, { 2, 2 }}), t)); b = std::make_unique(std::move(tmp), Params(), t); } b->detect_edges_in_polygons(); @@ -661,8 +661,8 @@ SCENARIO("void Board::detect_edges_in_polygons()", "[board]") { std::unique_ptr b; { PlaneSpace>> tmp; - tmp[XY].push_back(std::make_shared(XY, Polygon::Type::SHAPE, "", from_init_list({{ 1, 2 }, { 2, 2 }, { 2, 3 }, { 1, 3 }}), t)); - tmp[XY].push_back(std::make_shared(XY, Polygon::Type::SHAPE, "", from_init_list({{ 2, 1 }, { 3, 1 }, { 3, 2 }, { 2, 2 }}), t)); + tmp[XY].push_back(std::make_shared(XY, Polygon::Type::SHAPE, "", Polygon::RangeZ { 0, 0 }, from_init_list({{ 1, 2 }, { 2, 2 }, { 2, 3 }, { 1, 3 }}), t)); + tmp[XY].push_back(std::make_shared(XY, Polygon::Type::SHAPE, "", Polygon::RangeZ { 0, 0 }, from_init_list({{ 2, 1 }, { 3, 1 }, { 3, 2 }, { 2, 2 }}), t)); b = std::make_unique(std::move(tmp), Params(), t); } b->detect_edges_in_polygons(); @@ -675,8 +675,8 @@ SCENARIO("void Board::detect_edges_in_polygons()", "[board]") { std::unique_ptr b; { PlaneSpace>> tmp; - tmp[XY].push_back(std::make_shared(XY, Polygon::Type::SHAPE, "", from_init_list({{ 1, 1 }, { 2, 1 }, { 2, 2 }, { 2, 1 }}), t)); - tmp[XY].push_back(std::make_shared(XY, Polygon::Type::SHAPE, "", from_init_list({{ 3, 3 }, { 3, 4 }, { 4, 4 }, { 4, 3 }}), t)); + tmp[XY].push_back(std::make_shared(XY, Polygon::Type::SHAPE, "", Polygon::RangeZ { 0, 0 }, from_init_list({{ 1, 1 }, { 2, 1 }, { 2, 2 }, { 2, 1 }}), t)); + tmp[XY].push_back(std::make_shared(XY, Polygon::Type::SHAPE, "", Polygon::RangeZ { 0, 0 }, from_init_list({{ 3, 3 }, { 3, 4 }, { 4, 4 }, { 4, 3 }}), t)); b = std::make_unique(std::move(tmp), Params(), t); } b->detect_edges_in_polygons(); @@ -687,13 +687,32 @@ SCENARIO("void Board::detect_edges_in_polygons()", "[board]") { } GIVEN("A board holding two complex polygons") { - WHEN("Polygons overlap by many segments") { + WHEN("Polygons overlap by many segments but not by Z placement") { std::unique_ptr b; { PlaneSpace>> tmp; - tmp[XY].push_back(std::make_shared(XY, Polygon::Type::SHAPE, "", from_init_list({ + tmp[XY].push_back(std::make_shared(XY, Polygon::Type::SHAPE, "", Polygon::RangeZ { 0, 1 }, from_init_list({ { 1, 1 }, { 10, 1 }, { 10, 10 }, { 1, 10 }}), t)); - tmp[XY].push_back(std::make_shared(XY, Polygon::Type::SHAPE, "", from_init_list({ + tmp[XY].push_back(std::make_shared(XY, Polygon::Type::SHAPE, "", Polygon::RangeZ { 2, 3 }, from_init_list({ + { 11, 4 }, { 9, 3 }, { 13, 2 }, { 5, 2 }, + { 5, 11 }, { 4, 11.3 }, { 3, 10 }, { 2, 10 }, + { 2.3, 12 }, { 6, 11.3 }, { 6, 9 }, { 10, 10 }, + { 11, 9 }, { 9, 7 }, { 10, 6.3 }, { 10, 5 }}), t)); + b = std::make_unique(std::move(tmp), Params(), t); + } + b->detect_edges_in_polygons(); + THEN("There should not be any conflict registered") { + REQUIRE_FALSE(b->conflict_manager->get_current_state().all_edge_in_polygons[XY].size()); + } + } + + WHEN("Polygons overlap by many segments and by Z placement") { + std::unique_ptr b; + { + PlaneSpace>> tmp; + tmp[XY].push_back(std::make_shared(XY, Polygon::Type::SHAPE, "", Polygon::RangeZ { 0, 0 }, from_init_list({ + { 1, 1 }, { 10, 1 }, { 10, 10 }, { 1, 10 }}), t)); + tmp[XY].push_back(std::make_shared(XY, Polygon::Type::SHAPE, "", Polygon::RangeZ { 0, 0 }, from_init_list({ { 11, 4 }, { 9, 3 }, { 13, 2 }, { 5, 2 }, { 5, 11 }, { 4, 11.3 }, { 3, 10 }, { 2, 10 }, { 2.3, 12 }, { 6, 11.3 }, { 6, 9 }, { 10, 10 }, @@ -829,9 +848,9 @@ SCENARIO("void Board::detect_colinear_edges()", "[board]") { std::unique_ptr b; { PlaneSpace>> tmp; - tmp[XY].push_back(std::make_shared(XY, Polygon::Type::SHAPE, "", from_init_list({{ 1, 1 }, { 2, 1 }, { 2, 2 }, { 1, 2 }}), t)); - tmp[XY].push_back(std::make_shared(XY, Polygon::Type::SHAPE, "", from_init_list({{ 0.5, 3 }, { 2, 3 }, { 2, 4 }, { 0.5, 4 }}), t)); - tmp[XY].push_back(std::make_shared(XY, Polygon::Type::SHAPE, "", from_init_list({{ 3, 5 }, { 2, 5 }, { 2, 6 }, { 3, 6 }}), t)); + tmp[XY].push_back(std::make_shared(XY, Polygon::Type::SHAPE, "", Polygon::RangeZ { 0, 0 }, from_init_list({{ 1, 1 }, { 2, 1 }, { 2, 2 }, { 1, 2 }}), t)); + tmp[XY].push_back(std::make_shared(XY, Polygon::Type::SHAPE, "", Polygon::RangeZ { 0, 0 }, from_init_list({{ 0.5, 3 }, { 2, 3 }, { 2, 4 }, { 0.5, 4 }}), t)); + tmp[XY].push_back(std::make_shared(XY, Polygon::Type::SHAPE, "", Polygon::RangeZ { 0, 0 }, from_init_list({{ 3, 5 }, { 2, 5 }, { 2, 6 }, { 3, 6 }}), t)); b = std::make_unique(std::move(tmp), Params(), t); } b->detect_colinear_edges(); @@ -872,9 +891,9 @@ SCENARIO("void Board::detect_colinear_edges()", "[board]") { std::unique_ptr b; { PlaneSpace>> tmp; - tmp[XY].push_back(std::make_shared(XY, Polygon::Type::SHAPE, "", from_init_list({{ 1, 1 }, { 2, 1 }, { 2, 2 }, { 1, 2 }}), t)); - tmp[XY].push_back(std::make_shared(XY, Polygon::Type::SHAPE, "", from_init_list({{ 3, 0.5 }, { 3, 2 }, { 4, 2 }, { 4, 0.5 }}), t)); - tmp[XY].push_back(std::make_shared(XY, Polygon::Type::SHAPE, "", from_init_list({{ 5, 3 }, { 5, 2 }, { 6, 2 }, { 6, 3 }}), t)); + tmp[XY].push_back(std::make_shared(XY, Polygon::Type::SHAPE, "", Polygon::RangeZ { 0, 0 }, from_init_list({{ 1, 1 }, { 2, 1 }, { 2, 2 }, { 1, 2 }}), t)); + tmp[XY].push_back(std::make_shared(XY, Polygon::Type::SHAPE, "", Polygon::RangeZ { 0, 0 }, from_init_list({{ 3, 0.5 }, { 3, 2 }, { 4, 2 }, { 4, 0.5 }}), t)); + tmp[XY].push_back(std::make_shared(XY, Polygon::Type::SHAPE, "", Polygon::RangeZ { 0, 0 }, from_init_list({{ 5, 3 }, { 5, 2 }, { 6, 2 }, { 6, 3 }}), t)); b = std::make_unique(std::move(tmp), Params(), t); } b->detect_colinear_edges(); @@ -915,9 +934,9 @@ SCENARIO("void Board::detect_colinear_edges()", "[board]") { std::unique_ptr b; { PlaneSpace>> tmp; - tmp[XY].push_back(std::make_shared(XY, Polygon::Type::SHAPE, "", from_init_list({{ 1, 1 }, { 1, 2 }, { 2, 2 }}), t)); - tmp[XY].push_back(std::make_shared(XY, Polygon::Type::SHAPE, "", from_init_list({{ 3, 3 }, { 3, 4 }, { 4, 4 }}), t)); - tmp[XY].push_back(std::make_shared(XY, Polygon::Type::SHAPE, "", from_init_list({{ 5, 5 }, { 5, 6 }, { 6, 6 }}), t)); + tmp[XY].push_back(std::make_shared(XY, Polygon::Type::SHAPE, "", Polygon::RangeZ { 0, 0 }, from_init_list({{ 1, 1 }, { 1, 2 }, { 2, 2 }}), t)); + tmp[XY].push_back(std::make_shared(XY, Polygon::Type::SHAPE, "", Polygon::RangeZ { 0, 0 }, from_init_list({{ 3, 3 }, { 3, 4 }, { 4, 4 }}), t)); + tmp[XY].push_back(std::make_shared(XY, Polygon::Type::SHAPE, "", Polygon::RangeZ { 0, 0 }, from_init_list({{ 5, 5 }, { 5, 6 }, { 6, 6 }}), t)); b = std::make_unique(std::move(tmp), Params(), t); } b->detect_colinear_edges(); @@ -937,8 +956,8 @@ SCENARIO("void Board::detect_non_conflicting_edges()", "[board]") { std::unique_ptr b; { PlaneSpace>> tmp; - tmp[XY].push_back(std::make_shared(XY, Polygon::Type::SHAPE, "", from_init_list({{ 1, 1 }, { 1, 2 }, { 2, 2 }}), t)); - tmp[XY].push_back(std::make_shared(XY, Polygon::Type::SHAPE, "", from_init_list({{ 3, 3 }, { 3, 4 }, { 4, 4 }}), t)); + tmp[XY].push_back(std::make_shared(XY, Polygon::Type::SHAPE, "", Polygon::RangeZ { 0, 0 }, from_init_list({{ 1, 1 }, { 1, 2 }, { 2, 2 }}), t)); + tmp[XY].push_back(std::make_shared(XY, Polygon::Type::SHAPE, "", Polygon::RangeZ { 0, 0 }, from_init_list({{ 3, 3 }, { 3, 4 }, { 4, 4 }}), t)); b = std::make_unique(std::move(tmp), Params(), t); } REQUIRE(b->get_current_state().edges[XY].size() == 6); diff --git a/test/unit/infra/serializers/lpf.hpp b/test/unit/infra/serializers/lpf.hpp index f4dd6594..c9c0fbea 100644 --- a/test/unit/infra/serializers/lpf.hpp +++ b/test/unit/infra/serializers/lpf.hpp @@ -12,15 +12,16 @@ std::shared_ptr create_lpf() { using namespace domain; using Type = Polygon::Type; + using RangeZ = Polygon::RangeZ; Board::Builder builder; - builder.add_polygon_from_box(XY, Type::SHAPE, "MS1", { 16.1, -26.5 }, { 20.6, -26 }); - builder.add_polygon_from_box(XY, Type::SHAPE, "MS2", { 20.6, -36.5 }, { 22.1, -16 }); - builder.add_polygon_from_box(XY, Type::SHAPE, "MS3", { 22.1, -26.5 }, { 40.1, -26 }); - builder.add_polygon_from_box(XY, Type::SHAPE, "MS4", { 40.1, -36.5 }, { 42.6, -16 }); - builder.add_polygon_from_box(XY, Type::SHAPE, "MS5", { 42.6, -26.5 }, { 60.6, -26 }); - builder.add_polygon_from_box(XY, Type::SHAPE, "MS6", { 60.6, -36.5 }, { 62.1, -16 }); - builder.add_polygon_from_box(XY, Type::SHAPE, "MS7", { 62.1, -26.5 }, { 66.6, -26 }); + builder.add_polygon_from_box(XY, Type::SHAPE, "MS1", RangeZ { 0, 0 }, { 16.1, -26.5 }, { 20.6, -26 }); + builder.add_polygon_from_box(XY, Type::SHAPE, "MS2", RangeZ { 0, 0 }, { 20.6, -36.5 }, { 22.1, -16 }); + builder.add_polygon_from_box(XY, Type::SHAPE, "MS3", RangeZ { 0, 0 }, { 22.1, -26.5 }, { 40.1, -26 }); + builder.add_polygon_from_box(XY, Type::SHAPE, "MS4", RangeZ { 0, 0 }, { 40.1, -36.5 }, { 42.6, -16 }); + builder.add_polygon_from_box(XY, Type::SHAPE, "MS5", RangeZ { 0, 0 }, { 42.6, -26.5 }, { 60.6, -26 }); + builder.add_polygon_from_box(XY, Type::SHAPE, "MS6", RangeZ { 0, 0 }, { 60.6, -36.5 }, { 62.1, -16 }); + builder.add_polygon_from_box(XY, Type::SHAPE, "MS7", RangeZ { 0, 0 }, { 62.1, -26.5 }, { 66.6, -26 }); return builder.build(); } diff --git a/test/unit/infra/serializers/stub.hpp b/test/unit/infra/serializers/stub.hpp index 05486c55..5e4a6e79 100644 --- a/test/unit/infra/serializers/stub.hpp +++ b/test/unit/infra/serializers/stub.hpp @@ -10,48 +10,49 @@ std::shared_ptr create_stub() { using namespace domain; using Type = Polygon::Type; + using RangeZ = Polygon::RangeZ; Board::Builder builder; - builder.add_polygon_from_box(XY, Type::SHAPE, "MS1", { 31.1, -44.8024 }, { 51.3539, -42.0164 }); - builder.add_polygon_from_box(XY, Type::SHAPE, "MS2", { 120.029, -44.8024 }, { 140.283, -42.0164 }); - builder.add_polygon_from_box(XY, Type::SHAPE, "MS3", { 51.6077, -42.0164 }, { 51.3539, -31 }); - builder.add_polygon_from_box(XY, Type::SHAPE, "MS4", { 120.024, -42.0164 }, { 119.78, -31 }); - builder.add_polygon_from_box(XY, Type::SHAPE, "MS5", { 109.208, -43.9276 }, { 119.775, -42.8913 }); - builder.add_polygon_from_box(XY, Type::SHAPE, "MS6", { 51.6077, -43.9276 }, { 62.1753, -42.8913 }); - builder.add_polygon_from_box(XY, Type::SHAPE, "MS7", { 70.3673, -42.8674 }, { 62.1753, -33.2952 }); - builder.add_polygon_from_box(XY, Type::SHAPE, "MS8", { 109.208, -42.8674 }, { 101.016, -33.2952 }); - builder.add_polygon_from_box(XY, Type::SHAPE, "MS9", { 90.96, -42.8674 }, { 80.4229, -33.1334 }); - builder.add_polygon_from_box(XY, Type::SHAPE, "MS10", { 70.3673, -43.9514 }, { 80.4229, -42.8674 }); - builder.add_polygon_from_box(XY, Type::SHAPE, "MS11", { 90.96, -43.9514 }, { 101.016, -42.8674 }); - builder.add_polygon(XY, Type::SHAPE, "MS12", { + builder.add_polygon_from_box(XY, Type::SHAPE, "MS1", RangeZ { 0, 0 }, { 31.1, -44.8024 }, { 51.3539, -42.0164 }); + builder.add_polygon_from_box(XY, Type::SHAPE, "MS2", RangeZ { 0, 0 }, { 120.029, -44.8024 }, { 140.283, -42.0164 }); + builder.add_polygon_from_box(XY, Type::SHAPE, "MS3", RangeZ { 0, 0 }, { 51.6077, -42.0164 }, { 51.3539, -31 }); + builder.add_polygon_from_box(XY, Type::SHAPE, "MS4", RangeZ { 0, 0 }, { 120.024, -42.0164 }, { 119.78, -31 }); + builder.add_polygon_from_box(XY, Type::SHAPE, "MS5", RangeZ { 0, 0 }, { 109.208, -43.9276 }, { 119.775, -42.8913 }); + builder.add_polygon_from_box(XY, Type::SHAPE, "MS6", RangeZ { 0, 0 }, { 51.6077, -43.9276 }, { 62.1753, -42.8913 }); + builder.add_polygon_from_box(XY, Type::SHAPE, "MS7", RangeZ { 0, 0 }, { 70.3673, -42.8674 }, { 62.1753, -33.2952 }); + builder.add_polygon_from_box(XY, Type::SHAPE, "MS8", RangeZ { 0, 0 }, { 109.208, -42.8674 }, { 101.016, -33.2952 }); + builder.add_polygon_from_box(XY, Type::SHAPE, "MS9", RangeZ { 0, 0 }, { 90.96, -42.8674 }, { 80.4229, -33.1334 }); + builder.add_polygon_from_box(XY, Type::SHAPE, "MS10", RangeZ { 0, 0 }, { 70.3673, -43.9514 }, { 80.4229, -42.8674 }); + builder.add_polygon_from_box(XY, Type::SHAPE, "MS11", RangeZ { 0, 0 }, { 90.96, -43.9514 }, { 101.016, -42.8674 }); + builder.add_polygon(XY, Type::SHAPE, "MS12", RangeZ { 0, 0 }, { { 51.6077, -42.0164 }, { 51.3539, -42.0164 }, { 51.3539, -44.8024 }, { 51.4808, -44.8024 }, { 51.4808, -43.9276 }, { 51.6077, -43.9276 }}); - builder.add_polygon(XY, Type::SHAPE, "MS13", { + builder.add_polygon(XY, Type::SHAPE, "MS13", RangeZ { 0, 0 }, { { 70.3673, -42.8674 }, { 62.1753, -42.8674 }, { 62.1753, -43.9276 }, { 66.2713, -43.9276 }, { 66.2713, -43.9514 }, { 70.3673, -43.9514 }}); - builder.add_polygon(XY, Type::SHAPE, "MS14", { + builder.add_polygon(XY, Type::SHAPE, "MS14", RangeZ { 0, 0 }, { { 90.96, -42.8674 }, { 80.4229, -42.8674 }, { 80.4229, -43.9514 }, { 85.6915, -43.9514 }, { 85.6915, -43.9514 }, { 90.96, -43.9514 }}); - builder.add_polygon(XY, Type::SHAPE, "MS15", { + builder.add_polygon(XY, Type::SHAPE, "MS15", RangeZ { 0, 0 }, { { 109.208, -42.8674 }, { 101.016, -42.8674 }, { 101.016, -43.9514 }, { 105.112, -43.9514 }, { 105.112, -43.9276 }, { 109.208, -43.9276 }}); - builder.add_polygon(XY, Type::SHAPE, "MS16", { + builder.add_polygon(XY, Type::SHAPE, "MS16", RangeZ { 0, 0 }, { { 120.029, -42.0164 }, { 119.775, -42.0164 }, { 119.775, -43.9276 }, From a121e1ed8f3c7b034e73667f76ba64f487699a3f Mon Sep 17 00:00:00 2001 From: "tlepoix@localhost" Date: Thu, 25 Sep 2025 09:51:48 +0200 Subject: [PATCH 02/14] add Polygon::priority --- src/domain/board.cpp | 16 +- src/domain/board.hpp | 6 +- src/infra/parsers/parser_from_csx.cpp | 32 ++- test/unit/domain/geometrics/test_polygon.cpp | 26 +- test/unit/domain/test_board.cpp | 237 ++++++++++++++++--- test/unit/domain/test_conflict_manager.cpp | 4 +- test/unit/infra/serializers/lpf.hpp | 14 +- test/unit/infra/serializers/stub.hpp | 32 +-- 8 files changed, 270 insertions(+), 97 deletions(-) diff --git a/src/domain/board.cpp b/src/domain/board.cpp index 859531ca..727e8aa9 100644 --- a/src/domain/board.cpp +++ b/src/domain/board.cpp @@ -88,24 +88,24 @@ void Board::Builder::add_fixed_meshline_policy(Axis const axis, Coord const coor } //****************************************************************************** -void Board::Builder::add_polygon(Plane plane, Polygon::Type type, string const& name, Polygon::RangeZ const& z_placement, initializer_list points) { - polygons[plane].push_back(make_shared(plane, type, name, z_placement, from_init_list(points), Caretaker::singleton().get_history_root())); +void Board::Builder::add_polygon(Plane plane, Polygon::Type type, string const& name, size_t priority, Polygon::RangeZ const& z_placement, initializer_list points) { + polygons[plane].push_back(make_shared(plane, type, name, priority, z_placement, from_init_list(points), Caretaker::singleton().get_history_root())); } //****************************************************************************** -void Board::Builder::add_polygon(Plane plane, Polygon::Type type, string const& name, Polygon::RangeZ const& z_placement, vector>&& points) { - polygons[plane].push_back(make_shared(plane, type, name, z_placement, std::move(points), Caretaker::singleton().get_history_root())); +void Board::Builder::add_polygon(Plane plane, Polygon::Type type, string const& name, size_t priority, Polygon::RangeZ const& z_placement, vector>&& points) { + polygons[plane].push_back(make_shared(plane, type, name, priority, z_placement, std::move(points), Caretaker::singleton().get_history_root())); } //****************************************************************************** -void Board::Builder::add_polygon_from_box(Plane plane, Polygon::Type type, string const& name, Polygon::RangeZ const& z_placement, Point const p1, Point const p3) { +void Board::Builder::add_polygon_from_box(Plane plane, Polygon::Type type, string const& name, size_t priority, Polygon::RangeZ const& z_placement, Point const p1, Point const p3) { vector> points(4); points[0] = make_unique(p1.x, p1.y); points[1] = make_unique(p1.x, p3.y); points[2] = make_unique(p3.x, p3.y); points[3] = make_unique(p3.x, p1.y); - polygons[plane].push_back(make_shared(plane, type, name, z_placement, std::move(points), Caretaker::singleton().get_history_root())); + polygons[plane].push_back(make_shared(plane, type, name, priority, z_placement, std::move(points), Caretaker::singleton().get_history_root())); } //****************************************************************************** @@ -169,6 +169,10 @@ void Board::detect_edges_in_polygons(Plane const plane) { if(poly_b == poly_a) continue; + // Same priority : no reason to dismiss one. + if(poly_a->priority > poly_b->priority) + continue; + if(!does_overlap(poly_b->z_placement, poly_a->z_placement)) continue; diff --git a/src/domain/board.hpp b/src/domain/board.hpp index 4e29ca7d..7796b03a 100644 --- a/src/domain/board.hpp +++ b/src/domain/board.hpp @@ -56,9 +56,9 @@ class Board public: void add_fixed_meshline_policy(Axis axis, Coord coord); - void add_polygon(Plane plane, Polygon::Type type, std::string const& name, std::initializer_list points); - void add_polygon(Plane plane, Polygon::Type type, std::string const& name, std::vector>&& points); - void add_polygon_from_box(Plane plane, Polygon::Type type, std::string const& name, Point const p1, Point const p3); + void add_polygon(Plane plane, Polygon::Type type, std::string const& name, std::size_t priority, Polygon::RangeZ const& z_placement, std::initializer_list points); + void add_polygon(Plane plane, Polygon::Type type, std::string const& name, std::size_t priority, Polygon::RangeZ const& z_placement, std::vector>&& points); + void add_polygon_from_box(Plane plane, Polygon::Type type, std::string const& name, std::size_t priority, Polygon::RangeZ const& z_placement, Point const p1, Point const p3); [[nodiscard]] std::shared_ptr build(Params&& params = Params()); diff --git a/src/infra/parsers/parser_from_csx.cpp b/src/infra/parsers/parser_from_csx.cpp index a3c9f6a0..5647b8fd 100644 --- a/src/infra/parsers/parser_from_csx.cpp +++ b/src/infra/parsers/parser_from_csx.cpp @@ -154,6 +154,7 @@ void ParserFromCsx::Pimpl::parse_primitive_box(pugi::xml_node const& node, strin if(!type.has_value() || type.value() == Polygon::Type::SUBSTRATE) // TODO return; + size_t priority = node.attribute("Priority").as_uint(); pugi::xml_node node_p1 = node.child("P1"); pugi::xml_node node_p2 = node.child("P2"); Point3D p1( @@ -165,11 +166,11 @@ void ParserFromCsx::Pimpl::parse_primitive_box(pugi::xml_node const& node, strin node_p2.attribute("Y").as_double(), node_p2.attribute("Z").as_double()); if(params.with_yz) - board.add_polygon_from_box(YZ, type.value(), name, { p1.x, p2.x }, { p1.y, p1.z }, { p2.y, p2.z }); + board.add_polygon_from_box(YZ, type.value(), name, priority, { p1.x, p2.x }, { p1.y, p1.z }, { p2.y, p2.z }); if(params.with_zx) - board.add_polygon_from_box(ZX, type.value(), name, { p1.y, p2.y }, { p1.z, p1.x }, { p2.z, p2.x }); + board.add_polygon_from_box(ZX, type.value(), name, priority, { p1.y, p2.y }, { p1.z, p1.x }, { p2.z, p2.x }); if(params.with_xy) - board.add_polygon_from_box(XY, type.value(), name, { p1.z, p2.z }, { p1.x, p1.y }, { p2.x, p2.y }); + board.add_polygon_from_box(XY, type.value(), name, priority, { p1.z, p2.z }, { p1.x, p1.y }, { p2.x, p2.y }); // TODO if property == ConductingSheet : add_fixed_meshline_policy() } @@ -180,6 +181,7 @@ void ParserFromCsx::Pimpl::parse_primitive_linpoly(pugi::xml_node const& node, s if(!type.has_value() || type.value() == Polygon::Type::SUBSTRATE) // TODO return; + size_t priority = node.attribute("Priority").as_uint(); double elevation = node.attribute("Elevation").as_double(); // offset in normdir double length = node.attribute("Length").as_double(); // height in normdir size_t normdir = node.attribute("NormDir").as_uint(); // (0->x, 1->y, 2->z) @@ -196,9 +198,9 @@ void ParserFromCsx::Pimpl::parse_primitive_linpoly(pugi::xml_node const& node, s Bounding2D bounding(detect_bounding(points)); - board.add_polygon(plane.value(), type.value(), name, { elevation, elevation + length }, std::move(points)); + board.add_polygon(plane.value(), type.value(), name, priority, { elevation, elevation + length }, std::move(points)); if(length == 0) { - board.add_fixed_meshline_policy(normal.value(), elevation); +// board.add_fixed_meshline_policy(normal.value(), elevation); // switch(plane.value()) { // case YZ: // board.add_fixed_meshline_policy(Y, elevation); @@ -216,42 +218,46 @@ void ParserFromCsx::Pimpl::parse_primitive_linpoly(pugi::xml_node const& node, s // unreachable(); // } } else { -/* switch(plane.value()) { case YZ: if(params.with_zx) - board.add_polygon_from_box(ZX, name, + board.add_polygon_from_box(ZX, type.value(), name, priority, + { bounding[XMIN], bounding[XMAX] }, { bounding[YMIN], elevation }, { bounding[YMAX], elevation + length }); if(params.with_xy) - board.add_polygon_from_box(XY, name, + board.add_polygon_from_box(XY, type.value(), name, priority, + { bounding[YMIN], bounding[YMAX] }, { elevation, bounding[XMIN] }, { elevation + length, bounding[XMAX] }); break; case ZX: if(params.with_xy) - board.add_polygon_from_box(XY, name, + board.add_polygon_from_box(XY, type.value(), name, priority, + { bounding[XMIN], bounding[XMAX] }, { bounding[YMIN], elevation }, { bounding[YMAX], elevation + length }); if(params.with_yz) - board.add_polygon_from_box(YZ, name, + board.add_polygon_from_box(YZ, type.value(), name, priority, + { bounding[YMIN], bounding[YMAX] }, { elevation, bounding[XMIN] }, { elevation + length, bounding[XMAX] }); break; case XY: if(params.with_yz) - board.add_polygon_from_box(YZ, name, + board.add_polygon_from_box(YZ, type.value(), name, priority, + { bounding[XMIN], bounding[XMAX] }, { bounding[YMIN], elevation }, { bounding[YMAX], elevation + length }); if(params.with_zx) - board.add_polygon_from_box(ZX, name, + board.add_polygon_from_box(ZX, type.value(), name, priority, + { bounding[YMIN], bounding[YMAX] }, { elevation, bounding[XMIN] }, { elevation + length, bounding[XMAX] }); break; default: unreachable(); } -*/ } } diff --git a/test/unit/domain/geometrics/test_polygon.cpp b/test/unit/domain/geometrics/test_polygon.cpp index fe2e4c8c..b49548e8 100644 --- a/test/unit/domain/geometrics/test_polygon.cpp +++ b/test/unit/domain/geometrics/test_polygon.cpp @@ -64,7 +64,7 @@ SCENARIO("template Polygon::Rotation detect_rotation(T& points) noexcep Timepoint t; GIVEN("A polygon or a bunch of points") { WHEN("Points order is oriented clockwise") { - Polygon a(XY, Polygon::Type::SHAPE, "", { 0, 0 }, from_init_list({{ 1, 2 }, { 1, 4 }, { 4, 4 }}), &t); + Polygon a(XY, Polygon::Type::SHAPE, "", 0 , { 0, 0 }, from_init_list({{ 1, 2 }, { 1, 4 }, { 4, 4 }}), &t); std::vector b({a.points[0].get(), a.points[1].get(), a.points[2].get()}); THEN("Should be detected as CW") { REQUIRE(detect_rotation(a.points) == Polygon::Rotation::CW); @@ -73,7 +73,7 @@ SCENARIO("template Polygon::Rotation detect_rotation(T& points) noexcep } WHEN("Points order is oriented counter clockwise") { - Polygon a(XY, Polygon::Type::SHAPE, "", { 0, 0 }, from_init_list({{ 1, 2 }, { 4, 4 }, { 1, 4 }}), &t); + Polygon a(XY, Polygon::Type::SHAPE, "", 0 , { 0, 0 }, from_init_list({{ 1, 2 }, { 4, 4 }, { 1, 4 }}), &t); std::vector b({a.points[0].get(), a.points[1].get(), a.points[2].get()}); THEN("Should be detected as CCW") { REQUIRE(detect_rotation(a.points) == Polygon::Rotation::CCW); @@ -82,8 +82,8 @@ SCENARIO("template Polygon::Rotation detect_rotation(T& points) noexcep } WHEN("Points are all aligned in an axis") { - Polygon a(XY, Polygon::Type::SHAPE, "", { 0, 0 }, from_init_list({{ 1, 2 }, { 1, 4 }, { 1, 1 }}), &t); - Polygon b(XY, Polygon::Type::SHAPE, "", { 0, 0 }, from_init_list({{ 51.3539, -44.8024 }, { 120.0290, -44.8024 }, { 140.2830, -44.8024 }}), &t); + Polygon a(XY, Polygon::Type::SHAPE, "", 0 , { 0, 0 }, from_init_list({{ 1, 2 }, { 1, 4 }, { 1, 1 }}), &t); + Polygon b(XY, Polygon::Type::SHAPE, "", 0 , { 0, 0 }, from_init_list({{ 51.3539, -44.8024 }, { 120.0290, -44.8024 }, { 140.2830, -44.8024 }}), &t); std::vector c({a.points[0].get(), a.points[1].get(), a.points[2].get()}); std::vector d({b.points[0].get(), b.points[1].get(), b.points[2].get()}); THEN("Should be detected as COLINEAR") { @@ -95,7 +95,7 @@ SCENARIO("template Polygon::Rotation detect_rotation(T& points) noexcep } WHEN("Points are all aligned in diagonal") { - Polygon a(XY, Polygon::Type::SHAPE, "", { 0, 0 }, from_init_list({{ 1, 2 }, { 4, 4 }, { 2.5, 3 }}), &t); + Polygon a(XY, Polygon::Type::SHAPE, "", 0 , { 0, 0 }, from_init_list({{ 1, 2 }, { 4, 4 }, { 2.5, 3 }}), &t); std::vector b({a.points[0].get(), a.points[1].get(), a.points[2].get()}); THEN("Should be detected as COLINEAR") { REQUIRE(detect_rotation(a.points) == Polygon::Rotation::COLINEAR); @@ -104,7 +104,7 @@ SCENARIO("template Polygon::Rotation detect_rotation(T& points) noexcep } WHEN("Two points of a triangle are at the same place") { - Polygon a(XY, Polygon::Type::SHAPE, "", { 0, 0 }, from_init_list({{ 1, 2 }, { 4, 4 }, { 1, 2 }}), &t); + Polygon a(XY, Polygon::Type::SHAPE, "", 0 , { 0, 0 }, from_init_list({{ 1, 2 }, { 4, 4 }, { 1, 2 }}), &t); std::vector b({a.points[0].get(), a.points[1].get(), a.points[2].get()}); THEN("Should be detected as COLINEAR") { REQUIRE(detect_rotation(a.points) == Polygon::Rotation::COLINEAR); @@ -119,7 +119,7 @@ SCENARIO("void Polygon::detect_edge_normal() noexcept", "[polygon]") { Timepoint t; GIVEN("An octogon : 2 horizontal edges, 2 verticals, 4 diagonals") { WHEN("Points order is oriented clockwise") { - Polygon a(XY, Polygon::Type::SHAPE, "", { 0, 0 }, from_init_list({ + Polygon a(XY, Polygon::Type::SHAPE, "", 0 , { 0, 0 }, from_init_list({ { 2, 1 }, { 1, 2 }, { 1, 3 }, { 2, 4 }, { 3, 4 }, { 4, 3 }, { 4, 2 }, { 3, 1 }}), &t); THEN("For edges going down to the X axis, the normal should go down to the Y") { @@ -151,7 +151,7 @@ SCENARIO("void Polygon::detect_edge_normal() noexcept", "[polygon]") { } WHEN("Points order is oriented counter clockwise") { - Polygon a(XY, Polygon::Type::SHAPE, "", { 0, 0 }, from_init_list({ + Polygon a(XY, Polygon::Type::SHAPE, "", 0 , { 0, 0 }, from_init_list({ { 2, 1 }, { 3, 1 }, { 4, 2 }, { 4, 3 }, { 3, 4 }, { 2, 4 }, { 1, 3 }, { 1, 2 }}), &t); THEN("For edges going down to the X axis, the normal should go up to the Y") { @@ -183,7 +183,7 @@ SCENARIO("void Polygon::detect_edge_normal() noexcept", "[polygon]") { } WHEN("Points are all aligned or at the same position") { - Polygon a(XY, Polygon::Type::SHAPE, "", { 0, 0 }, from_init_list({{ 1, 2 }, { 1, 4 }, { 1, 1 }, { 1, 1 }}), &t); + Polygon a(XY, Polygon::Type::SHAPE, "", 0 , { 0, 0 }, from_init_list({{ 1, 2 }, { 1, 4 }, { 1, 1 }, { 1, 1 }}), &t); THEN("There should not be any normal") { REQUIRE(a.rotation == Polygon::Rotation::COLINEAR); REQUIRE(a.edges[0]->normal == Normal::NONE); @@ -199,7 +199,7 @@ SCENARIO("void Polygon::detect_edge_normal() noexcept", "[polygon]") { SCENARIO("relation::PolygonPoint Polygon::relation_to(Point const* point) const noexcept", "[polygon]") { Timepoint t; GIVEN("A simple polygon") { - Polygon poly(XY, Polygon::Type::SHAPE, "", { 0, 0 }, from_init_list({{ 1, 1 }, { 1, 3 }, { 3, 3 }, { 3, 1 }}), &t); + Polygon poly(XY, Polygon::Type::SHAPE, "", 0 , { 0, 0 }, from_init_list({{ 1, 1 }, { 1, 3 }, { 3, 3 }, { 3, 1 }}), &t); WHEN("A point is inside the polygon") { Point p(2, 2); THEN("Should be detected as IN") { @@ -256,7 +256,7 @@ SCENARIO("relation::PolygonPoint Polygon::relation_to(Point const* point) const GIVEN("A polygon with vertices on the firsts rays") { WHEN("The polygon have 4 edge colinear to the 4 first rays") { - Polygon poly(XY, Polygon::Type::SHAPE, "", { 0, 0 }, from_init_list({ + Polygon poly(XY, Polygon::Type::SHAPE, "", 0 , { 0, 0 }, from_init_list({ { 3, 1 }, { 3, 2 }, { 4, 3 }, { 5, 3 }, { 3, 5 }, { 3, 4 }, { 2, 3 }, { 1, 3 }}), &t); Point p(3, 3); @@ -266,7 +266,7 @@ SCENARIO("relation::PolygonPoint Polygon::relation_to(Point const* point) const } WHEN("The polygon have 4 angles on the 4 first rays") { - Polygon poly(XY, Polygon::Type::SHAPE, "", { 0, 0 }, from_init_list({{ 2, 1 }, { 3, 2 }, { 2, 3 }, { 1, 2 }}), &t); + Polygon poly(XY, Polygon::Type::SHAPE, "", 0 , { 0, 0 }, from_init_list({{ 2, 1 }, { 3, 2 }, { 2, 3 }, { 1, 2 }}), &t); Point p(2, 2); THEN("Should be detected as IN") { REQUIRE(poly.relation_to(p) == relation::PolygonPoint::IN); @@ -276,7 +276,7 @@ SCENARIO("relation::PolygonPoint Polygon::relation_to(Point const* point) const GIVEN("A simple polygon that flirt with floating points calculus imprecision") { WHEN("A point is outside the polygon, but colinear to an edge") { - Polygon poly(XY, Polygon::Type::SHAPE, "", { 0, 0 }, from_init_list({ + Polygon poly(XY, Polygon::Type::SHAPE, "", 0 , { 0, 0 }, from_init_list({ { 120.0290, -44.8024 }, { 120.0290, -42.0164 }, { 140.2830, -42.0164 }, diff --git a/test/unit/domain/test_board.cpp b/test/unit/domain/test_board.cpp index bf5755c4..38a5ad60 100644 --- a/test/unit/domain/test_board.cpp +++ b/test/unit/domain/test_board.cpp @@ -141,7 +141,7 @@ SCENARIO("void Board::Builder::add_polygon(Plane plane, std::string const& name, Board::Builder b; REQUIRE(b.polygons[XY].empty()); WHEN("Adding a polygon as an initializer_list of Points") { - b.add_polygon(XY, Polygon::Type::SHAPE, "MS13", { 0, 0 }, { + b.add_polygon(XY, Polygon::Type::SHAPE, "MS13", 0, { 0, 0 }, { { 70.3673, -42.8674 }, { 62.1753, -42.8674 }, { 62.1753, -43.9276 }, @@ -175,8 +175,8 @@ SCENARIO("void Board::Builder::add_polygon(Plane plane, std::string const& name, { 66.2713, -43.9276 }, { 66.2713, -43.9514 }, { 70.3673, -43.9514 }})); - b.add_polygon(XY, Polygon::Type::SHAPE, "MS13", { 0, 0 }, std::move(points)); - b.add_polygon(XY, Polygon::Type::SHAPE, "MS15", { 0, 0 }, from_init_list({ + b.add_polygon(XY, Polygon::Type::SHAPE, "MS13", 0, { 0, 0 }, std::move(points)); + b.add_polygon(XY, Polygon::Type::SHAPE, "MS15", 0, { 0, 0 }, from_init_list({ { 70.3673, -42.8674 }, { 62.1753, -42.8674 }, { 62.1753, -43.9276 }, @@ -210,7 +210,7 @@ SCENARIO("void Board::Builder::add_polygon_from_box(Plane plane, std::string con Board::Builder b; REQUIRE(b.polygons[XY].empty()); WHEN("Adding a rectangle polygon as a box of opposite Points") { - b.add_polygon_from_box(XY, Polygon::Type::SHAPE, "MS1", { 0, 0 }, { 16.1, -26.5 }, { 20.6, -26 }); + b.add_polygon_from_box(XY, Polygon::Type::SHAPE, "MS1", 0, { 0, 0 }, { 16.1, -26.5 }, { 20.6, -26 }); THEN("Should add a Polygon in the inner vector") { REQUIRE(b.polygons[XY].size() == 1); REQUIRE(b.polygons[XY][0]->name == "MS1"); @@ -228,15 +228,15 @@ SCENARIO("std::unique_ptr Board::Builder::build()", "[board]") { GIVEN("A Board Builder previously fed of polygons") { Board::Builder b; REQUIRE(b.polygons[XY].empty()); - b.add_polygon_from_box(XY, Polygon::Type::SHAPE, "MS1", { 0, 0 }, { 16.1, -26.5 }, { 20.6, -26 }); - b.add_polygon(XY, Polygon::Type::SHAPE, "MS15", { 0, 0 }, from_init_list({ + b.add_polygon_from_box(XY, Polygon::Type::SHAPE, "MS1", 0, { 0, 0 }, { 16.1, -26.5 }, { 20.6, -26 }); + b.add_polygon(XY, Polygon::Type::SHAPE, "MS15", 0, { 0, 0 }, from_init_list({ { 70.3673, -42.8674 }, { 62.1753, -42.8674 }, { 62.1753, -43.9276 }, { 66.2713, -43.9276 }, { 66.2713, -43.9514 }, { 70.3673, -43.9514 }})); - b.add_polygon(XY, Polygon::Type::SHAPE, "MS13", { 0, 0 }, { + b.add_polygon(XY, Polygon::Type::SHAPE, "MS13", 0, { 0, 0 }, { { 70.3673, -42.8674 }, { 62.1753, -42.8674 }, { 62.1753, -43.9276 }, @@ -284,8 +284,8 @@ SCENARIO("void Board::detect_edges_in_polygons()", "[board]") { std::unique_ptr b; { PlaneSpace>> tmp; - tmp[XY].push_back(std::make_shared(XY, Polygon::Type::SHAPE, "", Polygon::RangeZ { 0, 0 }, from_init_list({{ 1, 1 }, { 4, 1 }, { 4, 4 }, { 1, 4 }}), t)); - tmp[XY].push_back(std::make_shared(XY, Polygon::Type::SHAPE, "", Polygon::RangeZ { 0, 0 }, from_init_list({{ 2, 2 }, { 2, 3 }, { 3, 3 }, { 3, 2 }}), t)); + tmp[XY].push_back(std::make_shared(XY, Polygon::Type::SHAPE, "", 0, Polygon::RangeZ { 0, 0 }, from_init_list({{ 1, 1 }, { 4, 1 }, { 4, 4 }, { 1, 4 }}), t)); + tmp[XY].push_back(std::make_shared(XY, Polygon::Type::SHAPE, "", 0, Polygon::RangeZ { 0, 0 }, from_init_list({{ 2, 2 }, { 2, 3 }, { 3, 3 }, { 3, 2 }}), t)); b = std::make_unique(std::move(tmp), Params(), t); } b->detect_edges_in_polygons(); @@ -361,8 +361,8 @@ SCENARIO("void Board::detect_edges_in_polygons()", "[board]") { std::unique_ptr b; { PlaneSpace>> tmp; - tmp[XY].push_back(std::make_shared(XY, Polygon::Type::SHAPE, "", Polygon::RangeZ { 0, 0 }, from_init_list({{ 1, 2 }, { 3, 2 }, { 3, 4 }, { 1, 4 }}), t)); - tmp[XY].push_back(std::make_shared(XY, Polygon::Type::SHAPE, "", Polygon::RangeZ { 0, 0 }, from_init_list({{ 2, 1 }, { 4, 1 }, { 4, 3 }, { 2, 3 }}), t)); + tmp[XY].push_back(std::make_shared(XY, Polygon::Type::SHAPE, "", 0, Polygon::RangeZ { 0, 0 }, from_init_list({{ 1, 2 }, { 3, 2 }, { 3, 4 }, { 1, 4 }}), t)); + tmp[XY].push_back(std::make_shared(XY, Polygon::Type::SHAPE, "", 0, Polygon::RangeZ { 0, 0 }, from_init_list({{ 2, 1 }, { 4, 1 }, { 4, 3 }, { 2, 3 }}), t)); b = std::make_unique(std::move(tmp), Params(), t); } b->detect_edges_in_polygons(); @@ -439,8 +439,8 @@ SCENARIO("void Board::detect_edges_in_polygons()", "[board]") { std::unique_ptr b; { PlaneSpace>> tmp; - tmp[XY].push_back(std::make_shared(XY, Polygon::Type::SHAPE, "", Polygon::RangeZ { 0, 0 }, from_init_list({{ 1, 2 }, { 4, 2 }, { 4, 4 }, { 1, 4 }}), t)); - tmp[XY].push_back(std::make_shared(XY, Polygon::Type::SHAPE, "", Polygon::RangeZ { 0, 0 }, from_init_list({{ 2, 1 }, { 3, 1 }, { 3, 3 }, { 2, 3 }}), t)); + tmp[XY].push_back(std::make_shared(XY, Polygon::Type::SHAPE, "", 0, Polygon::RangeZ { 0, 0 }, from_init_list({{ 1, 2 }, { 4, 2 }, { 4, 4 }, { 1, 4 }}), t)); + tmp[XY].push_back(std::make_shared(XY, Polygon::Type::SHAPE, "", 0, Polygon::RangeZ { 0, 0 }, from_init_list({{ 2, 1 }, { 3, 1 }, { 3, 3 }, { 2, 3 }}), t)); b = std::make_unique(std::move(tmp), Params(), t); } b->detect_edges_in_polygons(); @@ -517,8 +517,8 @@ SCENARIO("void Board::detect_edges_in_polygons()", "[board]") { std::unique_ptr b; { PlaneSpace>> tmp; - tmp[XY].push_back(std::make_shared(XY, Polygon::Type::SHAPE, "", Polygon::RangeZ { 0, 0 }, from_init_list({{ 1, 1 }, { 4, 1 }, { 4, 4 }, { 1, 4 }}), t)); - tmp[XY].push_back(std::make_shared(XY, Polygon::Type::SHAPE, "", Polygon::RangeZ { 0, 0 }, from_init_list({{ 2, 3 }, { 3, 2 }, { 5, 4 }, { 4, 5 }}), t)); + tmp[XY].push_back(std::make_shared(XY, Polygon::Type::SHAPE, "", 0, Polygon::RangeZ { 0, 0 }, from_init_list({{ 1, 1 }, { 4, 1 }, { 4, 4 }, { 1, 4 }}), t)); + tmp[XY].push_back(std::make_shared(XY, Polygon::Type::SHAPE, "", 0, Polygon::RangeZ { 0, 0 }, from_init_list({{ 2, 3 }, { 3, 2 }, { 5, 4 }, { 4, 5 }}), t)); b = std::make_unique(std::move(tmp), Params(), t); } b->detect_edges_in_polygons(); @@ -608,8 +608,8 @@ SCENARIO("void Board::detect_edges_in_polygons()", "[board]") { std::unique_ptr b; { PlaneSpace>> tmp; - tmp[XY].push_back(std::make_shared(XY, Polygon::Type::SHAPE, "", Polygon::RangeZ { 0, 0 }, from_init_list({{ 1, 2 }, { 4, 2 }, { 4, 4 }, { 1, 4 }}), t)); - tmp[XY].push_back(std::make_shared(XY, Polygon::Type::SHAPE, "", Polygon::RangeZ { 0, 0 }, from_init_list({{ 2, 1 }, { 3, 1 }, { 3, 2 }, { 2, 2 }}), t)); + tmp[XY].push_back(std::make_shared(XY, Polygon::Type::SHAPE, "", 0, Polygon::RangeZ { 0, 0 }, from_init_list({{ 1, 2 }, { 4, 2 }, { 4, 4 }, { 1, 4 }}), t)); + tmp[XY].push_back(std::make_shared(XY, Polygon::Type::SHAPE, "", 0, Polygon::RangeZ { 0, 0 }, from_init_list({{ 2, 1 }, { 3, 1 }, { 3, 2 }, { 2, 2 }}), t)); b = std::make_unique(std::move(tmp), Params(), t); } b->detect_edges_in_polygons(); @@ -661,8 +661,8 @@ SCENARIO("void Board::detect_edges_in_polygons()", "[board]") { std::unique_ptr b; { PlaneSpace>> tmp; - tmp[XY].push_back(std::make_shared(XY, Polygon::Type::SHAPE, "", Polygon::RangeZ { 0, 0 }, from_init_list({{ 1, 2 }, { 2, 2 }, { 2, 3 }, { 1, 3 }}), t)); - tmp[XY].push_back(std::make_shared(XY, Polygon::Type::SHAPE, "", Polygon::RangeZ { 0, 0 }, from_init_list({{ 2, 1 }, { 3, 1 }, { 3, 2 }, { 2, 2 }}), t)); + tmp[XY].push_back(std::make_shared(XY, Polygon::Type::SHAPE, "", 0, Polygon::RangeZ { 0, 0 }, from_init_list({{ 1, 2 }, { 2, 2 }, { 2, 3 }, { 1, 3 }}), t)); + tmp[XY].push_back(std::make_shared(XY, Polygon::Type::SHAPE, "", 0, Polygon::RangeZ { 0, 0 }, from_init_list({{ 2, 1 }, { 3, 1 }, { 3, 2 }, { 2, 2 }}), t)); b = std::make_unique(std::move(tmp), Params(), t); } b->detect_edges_in_polygons(); @@ -675,8 +675,8 @@ SCENARIO("void Board::detect_edges_in_polygons()", "[board]") { std::unique_ptr b; { PlaneSpace>> tmp; - tmp[XY].push_back(std::make_shared(XY, Polygon::Type::SHAPE, "", Polygon::RangeZ { 0, 0 }, from_init_list({{ 1, 1 }, { 2, 1 }, { 2, 2 }, { 2, 1 }}), t)); - tmp[XY].push_back(std::make_shared(XY, Polygon::Type::SHAPE, "", Polygon::RangeZ { 0, 0 }, from_init_list({{ 3, 3 }, { 3, 4 }, { 4, 4 }, { 4, 3 }}), t)); + tmp[XY].push_back(std::make_shared(XY, Polygon::Type::SHAPE, "", 0, Polygon::RangeZ { 0, 0 }, from_init_list({{ 1, 1 }, { 2, 1 }, { 2, 2 }, { 2, 1 }}), t)); + tmp[XY].push_back(std::make_shared(XY, Polygon::Type::SHAPE, "", 0, Polygon::RangeZ { 0, 0 }, from_init_list({{ 3, 3 }, { 3, 4 }, { 4, 4 }, { 4, 3 }}), t)); b = std::make_unique(std::move(tmp), Params(), t); } b->detect_edges_in_polygons(); @@ -691,9 +691,9 @@ SCENARIO("void Board::detect_edges_in_polygons()", "[board]") { std::unique_ptr b; { PlaneSpace>> tmp; - tmp[XY].push_back(std::make_shared(XY, Polygon::Type::SHAPE, "", Polygon::RangeZ { 0, 1 }, from_init_list({ + tmp[XY].push_back(std::make_shared(XY, Polygon::Type::SHAPE, "", 0, Polygon::RangeZ { 0, 1 }, from_init_list({ { 1, 1 }, { 10, 1 }, { 10, 10 }, { 1, 10 }}), t)); - tmp[XY].push_back(std::make_shared(XY, Polygon::Type::SHAPE, "", Polygon::RangeZ { 2, 3 }, from_init_list({ + tmp[XY].push_back(std::make_shared(XY, Polygon::Type::SHAPE, "", 0, Polygon::RangeZ { 2, 3 }, from_init_list({ { 11, 4 }, { 9, 3 }, { 13, 2 }, { 5, 2 }, { 5, 11 }, { 4, 11.3 }, { 3, 10 }, { 2, 10 }, { 2.3, 12 }, { 6, 11.3 }, { 6, 9 }, { 10, 10 }, @@ -706,13 +706,176 @@ SCENARIO("void Board::detect_edges_in_polygons()", "[board]") { } } - WHEN("Polygons overlap by many segments and by Z placement") { + WHEN("Polygons overlap by many segments, by Z placement and are of different priority") { + THEN("In one case") { + std::unique_ptr b; + { + PlaneSpace>> tmp; + tmp[XY].push_back(std::make_shared(XY, Polygon::Type::SHAPE, "", 1, Polygon::RangeZ { 0, 0 }, from_init_list({ + { 1, 1 }, { 10, 1 }, { 10, 10 }, { 1, 10 }}), t)); + tmp[XY].push_back(std::make_shared(XY, Polygon::Type::SHAPE, "", 2, Polygon::RangeZ { 0, 0 }, from_init_list({ + { 11, 4 }, { 9, 3 }, { 13, 2 }, { 5, 2 }, + { 5, 11 }, { 4, 11.3 }, { 3, 10 }, { 2, 10 }, + { 2.3, 12 }, { 6, 11.3 }, { 6, 9 }, { 10, 10 }, + { 11, 9 }, { 9, 7 }, { 10, 6.3 }, { 10, 5 }}), t)); + b = std::make_unique(std::move(tmp), Params(), t); + } + b->detect_edges_in_polygons(); + THEN("2 EDGE_IN_POLYGON conflicts should be registered") { + REQUIRE(b->conflict_manager->get_current_state().all_edge_in_polygons[XY].size() == 2); + for(std::shared_ptr const& c : b->conflict_manager->get_current_state().all_edge_in_polygons[XY]) + REQUIRE(c->kind == Conflict::Kind::EDGE_IN_POLYGON); + AND_THEN("The registered conflicts should be between the right edges and polygons") { + std::array are_conflicts_registered; + are_conflicts_registered.fill(false); + for(std::shared_ptr const& c : b->conflict_manager->get_current_state().all_edge_in_polygons[XY]) { + if(c->edge == b->get_current_state().polygons[XY][0]->edges[2].get()) { + are_conflicts_registered[0] = true; + REQUIRE(c->get_current_state().overlaps.size() == 4); + std::array are_overlaps_registered; + are_overlaps_registered.fill(false); + for(auto const& overlap : c->get_current_state().overlaps) { + if(std::get(overlap) == b->get_current_state().polygons[XY][1].get() + && std::get(overlap) == Range({ 10, 2 }, { 10, 2.75 }) + && std::get(overlap) == std::nullopt) + are_overlaps_registered[0] = true; + else if(std::get(overlap) == b->get_current_state().polygons[XY][1].get() + && std::get(overlap) == Range({ 10, 3.5 }, { 10, 5 }) + && std::get(overlap) == std::nullopt) + are_overlaps_registered[1] = true; + else if(std::get(overlap) == b->get_current_state().polygons[XY][1].get() + && std::get(overlap) == Range({ 10, 5 }, { 10, 6.3 }) + && std::get(overlap) == b->get_current_state().polygons[XY][1]->edges[15].get()) + are_overlaps_registered[2] = true; + else if(std::get(overlap) == b->get_current_state().polygons[XY][1].get() + && std::get(overlap) == Range({ 10, 8 }, { 10, 10 }) + && std::get(overlap) == std::nullopt) + are_overlaps_registered[3] = true; + } + for(bool is_overlap_registered : are_overlaps_registered) + REQUIRE(is_overlap_registered); + } else if(c->edge == b->get_current_state().polygons[XY][0]->edges[3].get()) { + are_conflicts_registered[1] = true; + REQUIRE(c->get_current_state().overlaps.size() == 2); + std::array are_overlaps_registered; + are_overlaps_registered.fill(false); + for(auto const& overlap : c->get_current_state().overlaps) { + if(std::get(overlap) == b->get_current_state().polygons[XY][1].get() + && std::get(overlap) == Range({ 5, 10 }, { 6, 10 }) + && std::get(overlap) == std::nullopt) + are_overlaps_registered[0] = true; + else if(std::get(overlap) == b->get_current_state().polygons[XY][1].get() + && std::get(overlap) == Range({ 3, 10 }, { 2, 10 }) + && std::get(overlap) == b->get_current_state().polygons[XY][1]->edges[7].get()) + are_overlaps_registered[1] = true; + } + for(bool is_overlap_registered : are_overlaps_registered) + REQUIRE(is_overlap_registered); + } + } + for(bool is_conflict_registered : are_conflicts_registered) + REQUIRE(is_conflict_registered); + } + } + } + THEN("In the other case") { + std::unique_ptr b; + { + PlaneSpace>> tmp; + tmp[XY].push_back(std::make_shared(XY, Polygon::Type::SHAPE, "", 2, Polygon::RangeZ { 0, 0 }, from_init_list({ + { 1, 1 }, { 10, 1 }, { 10, 10 }, { 1, 10 }}), t)); + tmp[XY].push_back(std::make_shared(XY, Polygon::Type::SHAPE, "", 1, Polygon::RangeZ { 0, 0 }, from_init_list({ + { 11, 4 }, { 9, 3 }, { 13, 2 }, { 5, 2 }, + { 5, 11 }, { 4, 11.3 }, { 3, 10 }, { 2, 10 }, + { 2.3, 12 }, { 6, 11.3 }, { 6, 9 }, { 10, 10 }, + { 11, 9 }, { 9, 7 }, { 10, 6.3 }, { 10, 5 }}), t)); + b = std::make_unique(std::move(tmp), Params(), t); + } + b->detect_edges_in_polygons(); + THEN("10 EDGE_IN_POLYGON conflicts should be registered") { + REQUIRE(b->conflict_manager->get_current_state().all_edge_in_polygons[XY].size() == 10); + for(std::shared_ptr const& c : b->conflict_manager->get_current_state().all_edge_in_polygons[XY]) + REQUIRE(c->kind == Conflict::Kind::EDGE_IN_POLYGON); + AND_THEN("The registered conflicts should be between the right edges and polygons") { + std::array are_conflicts_registered; + are_conflicts_registered.fill(false); + for(std::shared_ptr const& c : b->conflict_manager->get_current_state().all_edge_in_polygons[XY]) { + if(c->edge == b->get_current_state().polygons[XY][1]->edges[1].get()) { + are_conflicts_registered[0] = true; + REQUIRE(c->get_current_state().overlaps.size() == 1); + REQUIRE(std::get(c->get_current_state().overlaps[0]) == b->get_current_state().polygons[XY][0].get()); + REQUIRE(std::get(c->get_current_state().overlaps[0]) == Range({ 10, 3.5 }, { 9, 3 })); + REQUIRE(std::get(c->get_current_state().overlaps[0]) == std::nullopt); + } else if(c->edge == b->get_current_state().polygons[XY][1]->edges[2].get()) { + are_conflicts_registered[1] = true; + REQUIRE(c->get_current_state().overlaps.size() == 1); + REQUIRE(std::get(c->get_current_state().overlaps[0]) == b->get_current_state().polygons[XY][0].get()); + REQUIRE(std::get(c->get_current_state().overlaps[0]) == Range({ 9, 3 }, { 10, 2.75 })); + REQUIRE(std::get(c->get_current_state().overlaps[0]) == std::nullopt); + } else if(c->edge == b->get_current_state().polygons[XY][1]->edges[3].get()) { + are_conflicts_registered[2] = true; + REQUIRE(c->get_current_state().overlaps.size() == 1); + REQUIRE(std::get(c->get_current_state().overlaps[0]) == b->get_current_state().polygons[XY][0].get()); + REQUIRE(std::get(c->get_current_state().overlaps[0]) == Range({ 10, 2 }, { 5, 2 })); + REQUIRE(std::get(c->get_current_state().overlaps[0]) == std::nullopt); + } else if(c->edge == b->get_current_state().polygons[XY][1]->edges[4].get()) { + are_conflicts_registered[3] = true; + REQUIRE(c->get_current_state().overlaps.size() == 1); + REQUIRE(std::get(c->get_current_state().overlaps[0]) == b->get_current_state().polygons[XY][0].get()); + REQUIRE(std::get(c->get_current_state().overlaps[0]) == Range({ 5, 2 }, { 5, 10 })); + REQUIRE(std::get(c->get_current_state().overlaps[0]) == std::nullopt); + } else if(c->edge == b->get_current_state().polygons[XY][1]->edges[7].get()) { + are_conflicts_registered[4] = true; + REQUIRE(c->get_current_state().overlaps.size() == 1); + REQUIRE(std::get(c->get_current_state().overlaps[0]) == b->get_current_state().polygons[XY][0].get()); + REQUIRE(std::get(c->get_current_state().overlaps[0]) == Range({ 3, 10 }, { 2, 10 })); + REQUIRE(std::get(c->get_current_state().overlaps[0]) == b->get_current_state().polygons[XY][0]->edges[3].get()); + } else if(c->edge == b->get_current_state().polygons[XY][1]->edges[10].get()) { + are_conflicts_registered[5] = true; + REQUIRE(c->get_current_state().overlaps.size() == 1); + REQUIRE(std::get(c->get_current_state().overlaps[0]) == b->get_current_state().polygons[XY][0].get()); + REQUIRE(std::get(c->get_current_state().overlaps[0]) == Range({ 6, 10 }, { 6, 9 })); + REQUIRE(std::get(c->get_current_state().overlaps[0]) == std::nullopt); + } else if(c->edge == b->get_current_state().polygons[XY][1]->edges[11].get()) { + are_conflicts_registered[6] = true; + REQUIRE(c->get_current_state().overlaps.size() == 1); + REQUIRE(std::get(c->get_current_state().overlaps[0]) == b->get_current_state().polygons[XY][0].get()); + REQUIRE(std::get(c->get_current_state().overlaps[0]) == Range({ 6, 9 }, { 10, 10 })); + REQUIRE(std::get(c->get_current_state().overlaps[0]) == std::nullopt); + } else if(c->edge == b->get_current_state().polygons[XY][1]->edges[13].get()) { + are_conflicts_registered[7] = true; + REQUIRE(c->get_current_state().overlaps.size() == 1); + REQUIRE(std::get(c->get_current_state().overlaps[0]) == b->get_current_state().polygons[XY][0].get()); + REQUIRE(std::get(c->get_current_state().overlaps[0]) == Range({ 10, 8 }, { 9, 7 })); + REQUIRE(std::get(c->get_current_state().overlaps[0]) == std::nullopt); + } else if(c->edge == b->get_current_state().polygons[XY][1]->edges[14].get()) { + are_conflicts_registered[8] = true; + REQUIRE(c->get_current_state().overlaps.size() == 1); + REQUIRE(std::get(c->get_current_state().overlaps[0]) == b->get_current_state().polygons[XY][0].get()); + REQUIRE(std::get(c->get_current_state().overlaps[0]) == Range({ 9, 7 }, { 10, 6.3 })); + REQUIRE(std::get(c->get_current_state().overlaps[0]) == std::nullopt); + } else if(c->edge == b->get_current_state().polygons[XY][1]->edges[15].get()) { + are_conflicts_registered[9] = true; + REQUIRE(c->get_current_state().overlaps.size() == 1); + REQUIRE(std::get(c->get_current_state().overlaps[0]) == b->get_current_state().polygons[XY][0].get()); + REQUIRE(std::get(c->get_current_state().overlaps[0]) == Range({ 10, 6.3 }, { 10, 5 })); + REQUIRE(std::get(c->get_current_state().overlaps[0]) == b->get_current_state().polygons[XY][0]->edges[2].get()); + } + } + for(bool is_conflict_registered : are_conflicts_registered) + REQUIRE(is_conflict_registered); + } + } + } + } + + WHEN("Polygons overlap by many segments, by Z placement and are of same priority") { std::unique_ptr b; { PlaneSpace>> tmp; - tmp[XY].push_back(std::make_shared(XY, Polygon::Type::SHAPE, "", Polygon::RangeZ { 0, 0 }, from_init_list({ + tmp[XY].push_back(std::make_shared(XY, Polygon::Type::SHAPE, "", 0, Polygon::RangeZ { 0, 0 }, from_init_list({ { 1, 1 }, { 10, 1 }, { 10, 10 }, { 1, 10 }}), t)); - tmp[XY].push_back(std::make_shared(XY, Polygon::Type::SHAPE, "", Polygon::RangeZ { 0, 0 }, from_init_list({ + tmp[XY].push_back(std::make_shared(XY, Polygon::Type::SHAPE, "", 0, Polygon::RangeZ { 0, 0 }, from_init_list({ { 11, 4 }, { 9, 3 }, { 13, 2 }, { 5, 2 }, { 5, 11 }, { 4, 11.3 }, { 3, 10 }, { 2, 10 }, { 2.3, 12 }, { 6, 11.3 }, { 6, 9 }, { 10, 10 }, @@ -848,9 +1011,9 @@ SCENARIO("void Board::detect_colinear_edges()", "[board]") { std::unique_ptr b; { PlaneSpace>> tmp; - tmp[XY].push_back(std::make_shared(XY, Polygon::Type::SHAPE, "", Polygon::RangeZ { 0, 0 }, from_init_list({{ 1, 1 }, { 2, 1 }, { 2, 2 }, { 1, 2 }}), t)); - tmp[XY].push_back(std::make_shared(XY, Polygon::Type::SHAPE, "", Polygon::RangeZ { 0, 0 }, from_init_list({{ 0.5, 3 }, { 2, 3 }, { 2, 4 }, { 0.5, 4 }}), t)); - tmp[XY].push_back(std::make_shared(XY, Polygon::Type::SHAPE, "", Polygon::RangeZ { 0, 0 }, from_init_list({{ 3, 5 }, { 2, 5 }, { 2, 6 }, { 3, 6 }}), t)); + tmp[XY].push_back(std::make_shared(XY, Polygon::Type::SHAPE, "", 0, Polygon::RangeZ { 0, 0 }, from_init_list({{ 1, 1 }, { 2, 1 }, { 2, 2 }, { 1, 2 }}), t)); + tmp[XY].push_back(std::make_shared(XY, Polygon::Type::SHAPE, "", 0, Polygon::RangeZ { 0, 0 }, from_init_list({{ 0.5, 3 }, { 2, 3 }, { 2, 4 }, { 0.5, 4 }}), t)); + tmp[XY].push_back(std::make_shared(XY, Polygon::Type::SHAPE, "", 0, Polygon::RangeZ { 0, 0 }, from_init_list({{ 3, 5 }, { 2, 5 }, { 2, 6 }, { 3, 6 }}), t)); b = std::make_unique(std::move(tmp), Params(), t); } b->detect_colinear_edges(); @@ -891,9 +1054,9 @@ SCENARIO("void Board::detect_colinear_edges()", "[board]") { std::unique_ptr b; { PlaneSpace>> tmp; - tmp[XY].push_back(std::make_shared(XY, Polygon::Type::SHAPE, "", Polygon::RangeZ { 0, 0 }, from_init_list({{ 1, 1 }, { 2, 1 }, { 2, 2 }, { 1, 2 }}), t)); - tmp[XY].push_back(std::make_shared(XY, Polygon::Type::SHAPE, "", Polygon::RangeZ { 0, 0 }, from_init_list({{ 3, 0.5 }, { 3, 2 }, { 4, 2 }, { 4, 0.5 }}), t)); - tmp[XY].push_back(std::make_shared(XY, Polygon::Type::SHAPE, "", Polygon::RangeZ { 0, 0 }, from_init_list({{ 5, 3 }, { 5, 2 }, { 6, 2 }, { 6, 3 }}), t)); + tmp[XY].push_back(std::make_shared(XY, Polygon::Type::SHAPE, "", 0, Polygon::RangeZ { 0, 0 }, from_init_list({{ 1, 1 }, { 2, 1 }, { 2, 2 }, { 1, 2 }}), t)); + tmp[XY].push_back(std::make_shared(XY, Polygon::Type::SHAPE, "", 0, Polygon::RangeZ { 0, 0 }, from_init_list({{ 3, 0.5 }, { 3, 2 }, { 4, 2 }, { 4, 0.5 }}), t)); + tmp[XY].push_back(std::make_shared(XY, Polygon::Type::SHAPE, "", 0, Polygon::RangeZ { 0, 0 }, from_init_list({{ 5, 3 }, { 5, 2 }, { 6, 2 }, { 6, 3 }}), t)); b = std::make_unique(std::move(tmp), Params(), t); } b->detect_colinear_edges(); @@ -934,9 +1097,9 @@ SCENARIO("void Board::detect_colinear_edges()", "[board]") { std::unique_ptr b; { PlaneSpace>> tmp; - tmp[XY].push_back(std::make_shared(XY, Polygon::Type::SHAPE, "", Polygon::RangeZ { 0, 0 }, from_init_list({{ 1, 1 }, { 1, 2 }, { 2, 2 }}), t)); - tmp[XY].push_back(std::make_shared(XY, Polygon::Type::SHAPE, "", Polygon::RangeZ { 0, 0 }, from_init_list({{ 3, 3 }, { 3, 4 }, { 4, 4 }}), t)); - tmp[XY].push_back(std::make_shared(XY, Polygon::Type::SHAPE, "", Polygon::RangeZ { 0, 0 }, from_init_list({{ 5, 5 }, { 5, 6 }, { 6, 6 }}), t)); + tmp[XY].push_back(std::make_shared(XY, Polygon::Type::SHAPE, "", 0, Polygon::RangeZ { 0, 0 }, from_init_list({{ 1, 1 }, { 1, 2 }, { 2, 2 }}), t)); + tmp[XY].push_back(std::make_shared(XY, Polygon::Type::SHAPE, "", 0, Polygon::RangeZ { 0, 0 }, from_init_list({{ 3, 3 }, { 3, 4 }, { 4, 4 }}), t)); + tmp[XY].push_back(std::make_shared(XY, Polygon::Type::SHAPE, "", 0, Polygon::RangeZ { 0, 0 }, from_init_list({{ 5, 5 }, { 5, 6 }, { 6, 6 }}), t)); b = std::make_unique(std::move(tmp), Params(), t); } b->detect_colinear_edges(); @@ -956,8 +1119,8 @@ SCENARIO("void Board::detect_non_conflicting_edges()", "[board]") { std::unique_ptr b; { PlaneSpace>> tmp; - tmp[XY].push_back(std::make_shared(XY, Polygon::Type::SHAPE, "", Polygon::RangeZ { 0, 0 }, from_init_list({{ 1, 1 }, { 1, 2 }, { 2, 2 }}), t)); - tmp[XY].push_back(std::make_shared(XY, Polygon::Type::SHAPE, "", Polygon::RangeZ { 0, 0 }, from_init_list({{ 3, 3 }, { 3, 4 }, { 4, 4 }}), t)); + tmp[XY].push_back(std::make_shared(XY, Polygon::Type::SHAPE, "", 0, Polygon::RangeZ { 0, 0 }, from_init_list({{ 1, 1 }, { 1, 2 }, { 2, 2 }}), t)); + tmp[XY].push_back(std::make_shared(XY, Polygon::Type::SHAPE, "", 0, Polygon::RangeZ { 0, 0 }, from_init_list({{ 3, 3 }, { 3, 4 }, { 4, 4 }}), t)); b = std::make_unique(std::move(tmp), Params(), t); } REQUIRE(b->get_current_state().edges[XY].size() == 6); diff --git a/test/unit/domain/test_conflict_manager.cpp b/test/unit/domain/test_conflict_manager.cpp index 6eb741a8..611fc996 100644 --- a/test/unit/domain/test_conflict_manager.cpp +++ b/test/unit/domain/test_conflict_manager.cpp @@ -257,10 +257,10 @@ SCENARIO("void ConflictManager::add_edge_in_polygon(Edge* a, Polygon* polygon, R Timepoint* t = Caretaker::singleton().get_history_root(); GIVEN("A conflict manager, an edge and some polygons") { ConflictManager cm(t); - Polygon p(XY, Polygon::Type::SHAPE, "", from_init_list({ + Polygon p(XY, Polygon::Type::SHAPE, "", 0, { 0, 0 }, from_init_list({ { 3, 1 }, { 6, 1 }, { 6, 6 }, { 1, 6 }, { 1, 3 }, { 2, 3 }, { 2, 5 }, { 5, 5 }, { 5, 2 }, { 3, 2 }}), t); - Polygon q(XY, Polygon::Type::SHAPE, "", from_init_list({{ 0, 0 }, { 0, 8 }, { 8, 8 }, { 8, 0 }}), t); + Polygon q(XY, Polygon::Type::SHAPE, "", 0, { 0, 0 }, from_init_list({{ 0, 0 }, { 0, 8 }, { 8, 8 }, { 8, 0 }}), t); WHEN("A vertical edge that is in a polygon is reported as partially in this polygon") { Point a0(4, 1), a1(4, 7); Edge a(XY, &a0, &a1, t); diff --git a/test/unit/infra/serializers/lpf.hpp b/test/unit/infra/serializers/lpf.hpp index c9c0fbea..705c7284 100644 --- a/test/unit/infra/serializers/lpf.hpp +++ b/test/unit/infra/serializers/lpf.hpp @@ -15,13 +15,13 @@ std::shared_ptr create_lpf() { using RangeZ = Polygon::RangeZ; Board::Builder builder; - builder.add_polygon_from_box(XY, Type::SHAPE, "MS1", RangeZ { 0, 0 }, { 16.1, -26.5 }, { 20.6, -26 }); - builder.add_polygon_from_box(XY, Type::SHAPE, "MS2", RangeZ { 0, 0 }, { 20.6, -36.5 }, { 22.1, -16 }); - builder.add_polygon_from_box(XY, Type::SHAPE, "MS3", RangeZ { 0, 0 }, { 22.1, -26.5 }, { 40.1, -26 }); - builder.add_polygon_from_box(XY, Type::SHAPE, "MS4", RangeZ { 0, 0 }, { 40.1, -36.5 }, { 42.6, -16 }); - builder.add_polygon_from_box(XY, Type::SHAPE, "MS5", RangeZ { 0, 0 }, { 42.6, -26.5 }, { 60.6, -26 }); - builder.add_polygon_from_box(XY, Type::SHAPE, "MS6", RangeZ { 0, 0 }, { 60.6, -36.5 }, { 62.1, -16 }); - builder.add_polygon_from_box(XY, Type::SHAPE, "MS7", RangeZ { 0, 0 }, { 62.1, -26.5 }, { 66.6, -26 }); + builder.add_polygon_from_box(XY, Type::SHAPE, "MS1", 0, RangeZ { 0, 0 }, { 16.1, -26.5 }, { 20.6, -26 }); + builder.add_polygon_from_box(XY, Type::SHAPE, "MS2", 0, RangeZ { 0, 0 }, { 20.6, -36.5 }, { 22.1, -16 }); + builder.add_polygon_from_box(XY, Type::SHAPE, "MS3", 0, RangeZ { 0, 0 }, { 22.1, -26.5 }, { 40.1, -26 }); + builder.add_polygon_from_box(XY, Type::SHAPE, "MS4", 0, RangeZ { 0, 0 }, { 40.1, -36.5 }, { 42.6, -16 }); + builder.add_polygon_from_box(XY, Type::SHAPE, "MS5", 0, RangeZ { 0, 0 }, { 42.6, -26.5 }, { 60.6, -26 }); + builder.add_polygon_from_box(XY, Type::SHAPE, "MS6", 0, RangeZ { 0, 0 }, { 60.6, -36.5 }, { 62.1, -16 }); + builder.add_polygon_from_box(XY, Type::SHAPE, "MS7", 0, RangeZ { 0, 0 }, { 62.1, -26.5 }, { 66.6, -26 }); return builder.build(); } diff --git a/test/unit/infra/serializers/stub.hpp b/test/unit/infra/serializers/stub.hpp index 5e4a6e79..ccaf3af0 100644 --- a/test/unit/infra/serializers/stub.hpp +++ b/test/unit/infra/serializers/stub.hpp @@ -13,46 +13,46 @@ std::shared_ptr create_stub() { using RangeZ = Polygon::RangeZ; Board::Builder builder; - builder.add_polygon_from_box(XY, Type::SHAPE, "MS1", RangeZ { 0, 0 }, { 31.1, -44.8024 }, { 51.3539, -42.0164 }); - builder.add_polygon_from_box(XY, Type::SHAPE, "MS2", RangeZ { 0, 0 }, { 120.029, -44.8024 }, { 140.283, -42.0164 }); - builder.add_polygon_from_box(XY, Type::SHAPE, "MS3", RangeZ { 0, 0 }, { 51.6077, -42.0164 }, { 51.3539, -31 }); - builder.add_polygon_from_box(XY, Type::SHAPE, "MS4", RangeZ { 0, 0 }, { 120.024, -42.0164 }, { 119.78, -31 }); - builder.add_polygon_from_box(XY, Type::SHAPE, "MS5", RangeZ { 0, 0 }, { 109.208, -43.9276 }, { 119.775, -42.8913 }); - builder.add_polygon_from_box(XY, Type::SHAPE, "MS6", RangeZ { 0, 0 }, { 51.6077, -43.9276 }, { 62.1753, -42.8913 }); - builder.add_polygon_from_box(XY, Type::SHAPE, "MS7", RangeZ { 0, 0 }, { 70.3673, -42.8674 }, { 62.1753, -33.2952 }); - builder.add_polygon_from_box(XY, Type::SHAPE, "MS8", RangeZ { 0, 0 }, { 109.208, -42.8674 }, { 101.016, -33.2952 }); - builder.add_polygon_from_box(XY, Type::SHAPE, "MS9", RangeZ { 0, 0 }, { 90.96, -42.8674 }, { 80.4229, -33.1334 }); - builder.add_polygon_from_box(XY, Type::SHAPE, "MS10", RangeZ { 0, 0 }, { 70.3673, -43.9514 }, { 80.4229, -42.8674 }); - builder.add_polygon_from_box(XY, Type::SHAPE, "MS11", RangeZ { 0, 0 }, { 90.96, -43.9514 }, { 101.016, -42.8674 }); - builder.add_polygon(XY, Type::SHAPE, "MS12", RangeZ { 0, 0 }, { + builder.add_polygon_from_box(XY, Type::SHAPE, "MS1", 0, RangeZ { 0, 0 }, { 31.1, -44.8024 }, { 51.3539, -42.0164 }); + builder.add_polygon_from_box(XY, Type::SHAPE, "MS2", 0, RangeZ { 0, 0 }, { 120.029, -44.8024 }, { 140.283, -42.0164 }); + builder.add_polygon_from_box(XY, Type::SHAPE, "MS3", 0, RangeZ { 0, 0 }, { 51.6077, -42.0164 }, { 51.3539, -31 }); + builder.add_polygon_from_box(XY, Type::SHAPE, "MS4", 0, RangeZ { 0, 0 }, { 120.024, -42.0164 }, { 119.78, -31 }); + builder.add_polygon_from_box(XY, Type::SHAPE, "MS5", 0, RangeZ { 0, 0 }, { 109.208, -43.9276 }, { 119.775, -42.8913 }); + builder.add_polygon_from_box(XY, Type::SHAPE, "MS6", 0, RangeZ { 0, 0 }, { 51.6077, -43.9276 }, { 62.1753, -42.8913 }); + builder.add_polygon_from_box(XY, Type::SHAPE, "MS7", 0, RangeZ { 0, 0 }, { 70.3673, -42.8674 }, { 62.1753, -33.2952 }); + builder.add_polygon_from_box(XY, Type::SHAPE, "MS8", 0, RangeZ { 0, 0 }, { 109.208, -42.8674 }, { 101.016, -33.2952 }); + builder.add_polygon_from_box(XY, Type::SHAPE, "MS9", 0, RangeZ { 0, 0 }, { 90.96, -42.8674 }, { 80.4229, -33.1334 }); + builder.add_polygon_from_box(XY, Type::SHAPE, "MS10", 0, RangeZ { 0, 0 }, { 70.3673, -43.9514 }, { 80.4229, -42.8674 }); + builder.add_polygon_from_box(XY, Type::SHAPE, "MS11", 0, RangeZ { 0, 0 }, { 90.96, -43.9514 }, { 101.016, -42.8674 }); + builder.add_polygon(XY, Type::SHAPE, "MS12", 0, RangeZ { 0, 0 }, { { 51.6077, -42.0164 }, { 51.3539, -42.0164 }, { 51.3539, -44.8024 }, { 51.4808, -44.8024 }, { 51.4808, -43.9276 }, { 51.6077, -43.9276 }}); - builder.add_polygon(XY, Type::SHAPE, "MS13", RangeZ { 0, 0 }, { + builder.add_polygon(XY, Type::SHAPE, "MS13", 0, RangeZ { 0, 0 }, { { 70.3673, -42.8674 }, { 62.1753, -42.8674 }, { 62.1753, -43.9276 }, { 66.2713, -43.9276 }, { 66.2713, -43.9514 }, { 70.3673, -43.9514 }}); - builder.add_polygon(XY, Type::SHAPE, "MS14", RangeZ { 0, 0 }, { + builder.add_polygon(XY, Type::SHAPE, "MS14", 0, RangeZ { 0, 0 }, { { 90.96, -42.8674 }, { 80.4229, -42.8674 }, { 80.4229, -43.9514 }, { 85.6915, -43.9514 }, { 85.6915, -43.9514 }, { 90.96, -43.9514 }}); - builder.add_polygon(XY, Type::SHAPE, "MS15", RangeZ { 0, 0 }, { + builder.add_polygon(XY, Type::SHAPE, "MS15", 0, RangeZ { 0, 0 }, { { 109.208, -42.8674 }, { 101.016, -42.8674 }, { 101.016, -43.9514 }, { 105.112, -43.9514 }, { 105.112, -43.9276 }, { 109.208, -43.9276 }}); - builder.add_polygon(XY, Type::SHAPE, "MS16", RangeZ { 0, 0 }, { + builder.add_polygon(XY, Type::SHAPE, "MS16", 0, RangeZ { 0, 0 }, { { 120.029, -42.0164 }, { 119.775, -42.0164 }, { 119.775, -43.9276 }, From b26d925d910ba8ff081d9a191ba7bb49f1eca15f Mon Sep 17 00:00:00 2001 From: "tlepoix@localhost" Date: Thu, 2 Oct 2025 03:52:25 +0200 Subject: [PATCH 03/14] add Material --- src/CMakeLists.txt | 2 + src/app/openemsh.cpp | 7 +- src/app/steps.hpp | 1 + src/domain/board.cpp | 83 +++++++++-- src/domain/board.hpp | 11 +- .../conflicts/conflict_colinear_edges.cpp | 6 +- src/domain/geometrics/edge.hpp | 1 + src/domain/geometrics/normal.cpp | 27 ++++ src/domain/geometrics/normal.hpp | 3 + src/domain/geometrics/polygon.cpp | 11 +- src/domain/geometrics/polygon.hpp | 13 +- src/domain/material.cpp | 58 ++++++++ src/domain/material.hpp | 46 ++++++ src/infra/parsers/parser_from_csx.cpp | 135 +++++++----------- src/ui/qt/main_window.cpp | 6 + src/ui/qt/main_window.hpp | 3 +- src/ui/qt/processing_view/processing_edge.cpp | 10 ++ src/ui/qt/structure_view/structure_scene.cpp | 56 ++++---- test/unit/CMakeLists.txt | 1 + test/unit/app/test_openemsh.cpp | 23 +++ test/unit/domain/geometrics/test_polygon.cpp | 39 +++-- test/unit/domain/test_board.cpp | 88 ++++++------ test/unit/domain/test_conflict_manager.cpp | 5 +- test/unit/domain/test_material.cpp | 124 ++++++++++++++++ test/unit/infra/serializers/lpf.hpp | 16 +-- test/unit/infra/serializers/stub.hpp | 34 ++--- 26 files changed, 599 insertions(+), 210 deletions(-) create mode 100644 src/domain/geometrics/normal.cpp create mode 100644 src/domain/material.cpp create mode 100644 src/domain/material.hpp create mode 100644 test/unit/domain/test_material.cpp diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index c7659224..0d168d11 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -16,6 +16,7 @@ target_sources( openemsh "${CMAKE_CURRENT_SOURCE_DIR}/domain/geometrics/relation.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/domain/geometrics/bounding.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/domain/geometrics/coord.cpp" + "${CMAKE_CURRENT_SOURCE_DIR}/domain/geometrics/normal.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/domain/geometrics/point.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/domain/geometrics/segment.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/domain/geometrics/edge.cpp" @@ -28,6 +29,7 @@ target_sources( openemsh "${CMAKE_CURRENT_SOURCE_DIR}/domain/mesh/interval.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/domain/mesh/meshline.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/domain/mesh/meshline_policy.cpp" + "${CMAKE_CURRENT_SOURCE_DIR}/domain/material.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/domain/meshline_policy_manager.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/domain/conflict_manager.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/domain/board.cpp" diff --git a/src/app/openemsh.cpp b/src/app/openemsh.cpp index a4f84257..b1bb1dd0 100644 --- a/src/app/openemsh.cpp +++ b/src/app/openemsh.cpp @@ -21,6 +21,8 @@ using namespace std; //****************************************************************************** optional next(Step step) { switch(step) { + case Step::ADJUST_EDGE_TO_MATERIAL: + return Step::DETECT_CONFLICT_EIP; case Step::DETECT_CONFLICT_EIP: return Step::DETECT_CONFLICT_CE; case Step::DETECT_CONFLICT_CE: @@ -50,6 +52,7 @@ set that_and_after(Step step) { using enum Step; switch(step) { + case ADJUST_EDGE_TO_MATERIAL: out.emplace(ADJUST_EDGE_TO_MATERIAL); [[fallthrough]]; case DETECT_CONFLICT_EIP: out.emplace(DETECT_CONFLICT_EIP); [[fallthrough]]; case DETECT_CONFLICT_CE: out.emplace(DETECT_CONFLICT_CE); [[fallthrough]]; case DETECT_NON_CONFLICTING_EDGES: out.emplace(DETECT_NON_CONFLICTING_EDGES); [[fallthrough]]; @@ -131,6 +134,7 @@ void OpenEMSH::run(std::set const& steps) const { }; using enum Step; + handle(ADJUST_EDGE_TO_MATERIAL, [&] { board->adjust_edges_to_materials(); }); handle(DETECT_CONFLICT_EIP, [&] { board->detect_edges_in_polygons(); }); handle(DETECT_CONFLICT_CE, [&] { board->detect_colinear_edges(); }); handle(DETECT_NON_CONFLICTING_EDGES, [&] { board->detect_non_conflicting_edges(); }); @@ -147,6 +151,7 @@ void OpenEMSH::run(std::set const& steps) const { //****************************************************************************** void OpenEMSH::run_all_steps() const { run({ + Step::ADJUST_EDGE_TO_MATERIAL, Step::DETECT_CONFLICT_EIP, Step::DETECT_CONFLICT_CE, Step::DETECT_NON_CONFLICTING_EDGES, @@ -168,7 +173,7 @@ void OpenEMSH::run_next_step() const { ; step) run({ step.value() }); } else { - run({ Step::DETECT_CONFLICT_EIP }); + run({ Step::ADJUST_EDGE_TO_MATERIAL }); } } diff --git a/src/app/steps.hpp b/src/app/steps.hpp index 02043206..6b9a10c4 100644 --- a/src/app/steps.hpp +++ b/src/app/steps.hpp @@ -10,6 +10,7 @@ namespace app { //****************************************************************************** enum class Step { + ADJUST_EDGE_TO_MATERIAL, DETECT_CONFLICT_EIP, DETECT_CONFLICT_CE, DETECT_NON_CONFLICTING_EDGES, diff --git a/src/domain/board.cpp b/src/domain/board.cpp index 727e8aa9..3543f86b 100644 --- a/src/domain/board.cpp +++ b/src/domain/board.cpp @@ -88,24 +88,24 @@ void Board::Builder::add_fixed_meshline_policy(Axis const axis, Coord const coor } //****************************************************************************** -void Board::Builder::add_polygon(Plane plane, Polygon::Type type, string const& name, size_t priority, Polygon::RangeZ const& z_placement, initializer_list points) { - polygons[plane].push_back(make_shared(plane, type, name, priority, z_placement, from_init_list(points), Caretaker::singleton().get_history_root())); +void Board::Builder::add_polygon(Plane plane, shared_ptr const& material, string const& name, size_t priority, Polygon::RangeZ const& z_placement, initializer_list points) { + polygons[plane].push_back(make_shared(plane, material, name, priority, z_placement, from_init_list(points), Caretaker::singleton().get_history_root())); } //****************************************************************************** -void Board::Builder::add_polygon(Plane plane, Polygon::Type type, string const& name, size_t priority, Polygon::RangeZ const& z_placement, vector>&& points) { - polygons[plane].push_back(make_shared(plane, type, name, priority, z_placement, std::move(points), Caretaker::singleton().get_history_root())); +void Board::Builder::add_polygon(Plane plane, shared_ptr const& material, string const& name, size_t priority, Polygon::RangeZ const& z_placement, vector>&& points) { + polygons[plane].push_back(make_shared(plane, material, name, priority, z_placement, std::move(points), Caretaker::singleton().get_history_root())); } //****************************************************************************** -void Board::Builder::add_polygon_from_box(Plane plane, Polygon::Type type, string const& name, size_t priority, Polygon::RangeZ const& z_placement, Point const p1, Point const p3) { +void Board::Builder::add_polygon_from_box(Plane plane, shared_ptr const& material, string const& name, size_t priority, Polygon::RangeZ const& z_placement, Point const p1, Point const p3) { vector> points(4); points[0] = make_unique(p1.x, p1.y); points[1] = make_unique(p1.x, p3.y); points[2] = make_unique(p3.x, p3.y); points[3] = make_unique(p3.x, p1.y); - polygons[plane].push_back(make_shared(plane, type, name, priority, z_placement, std::move(points), Caretaker::singleton().get_history_root())); + polygons[plane].push_back(make_shared(plane, material, name, priority, z_placement, std::move(points), Caretaker::singleton().get_history_root())); } //****************************************************************************** @@ -160,6 +160,66 @@ Board::Board( get_caretaker().take_care_of(polygon); } +/// Check among all Polygons that match segment and current_polygon->z_placement. +/// Choose Material following this rule: CONDUCTOR>DIELECTRIC>AIR +///***************************************************************************** +shared_ptr Board::find_ambient_material(Plane plane, shared_ptr const& current_polygon, Segment const& segment) const { + Bounding2D const segment_bounding = bounding(segment); + + vector> materials; + for(shared_ptr const& polygon : get_current_state().polygons[plane]) { + if(polygon->material + && polygon != current_polygon + && does_overlap(polygon->z_placement, current_polygon->z_placement) + && does_overlap(polygon->bounding, segment_bounding)) + materials.push_back(shared_ptr(polygon->material)); + } + + ranges::sort(materials, [](auto const& a, auto const& b) { + return *a < *b; + }); + + if(!materials.empty()) + return materials.back(); + else + // TODO if no material return Board::background_material + return {}; +} + +//****************************************************************************** +void Board::adjust_edges_to_materials(Plane const plane) { + for(shared_ptr const& polygon : get_current_state().polygons[plane]) { + for(shared_ptr const& edge : polygon->edges) { + auto const& inner_material = polygon->material; + auto const& immediate_ambient_outer_material = [&]() -> shared_ptr { + Point const translate_x(2 * equality_tolerance, 0); + Point const translate_y(0, 2 * equality_tolerance); + switch(edge->normal) { + case Normal::NONE: + return {}; + case Normal::XMIN: + return find_ambient_material(plane, polygon, Range(edge->p0() - translate_x, edge->p1() - translate_x)); + case Normal::XMAX: + return find_ambient_material(plane, polygon, Range(edge->p0() + translate_x, edge->p1() + translate_x)); + case Normal::YMIN: + return find_ambient_material(plane, polygon, Range(edge->p0() - translate_y, edge->p1() - translate_y)); + case Normal::YMAX: + return find_ambient_material(plane, polygon, Range(edge->p0() + translate_y, edge->p1() + translate_y)); + default: + ::unreachable(); + } + } (); + + if(immediate_ambient_outer_material + && *immediate_ambient_outer_material > *inner_material) { + auto state = edge->get_current_state(); + state.to_reverse = true; + edge->set_next_state(state); + } + } + } +} + /// Detect all EDGE_IN_POLYGON. Will also detect some COLINEAR_EDGES. /// Overlapping edges should be EDGE_IN_POLYGON and not COLINEAR_EDGES. ///***************************************************************************** @@ -318,14 +378,13 @@ void Board::detect_non_conflicting_edges(Plane const plane) { for(Edge* edge : get_current_state().edges[plane]) { optional const coord = domain::coord(edge->p0(), edge->axis); optional const axis = transpose(plane, edge->axis); - optional const normal = cast(edge->normal); - if(coord && axis && normal && edge->get_current_state().conflicts.empty()) { + if(coord && axis && edge->get_current_state().conflicts.empty()) { auto [t, state_e] = edge->make_next_state(); state_e.meshline_policy = line_policy_manager->add_meshline_policy( { edge }, axis.value(), MeshlinePolicy::Policy::THIRDS, - normal.value(), + cast(edge->normal), coord.value(), state_e.to_mesh, t); @@ -341,6 +400,12 @@ void Board::add_fixed_meshline_policies(Axis axis) { create_meshline_policy(this, t); } +//****************************************************************************** +void Board::adjust_edges_to_materials() { + for(auto const& plane : AllPlane) + adjust_edges_to_materials(plane); +} + //****************************************************************************** void Board::detect_edges_in_polygons() { for(auto const& plane : AllPlane) diff --git a/src/domain/board.hpp b/src/domain/board.hpp index 7796b03a..a6b0362e 100644 --- a/src/domain/board.hpp +++ b/src/domain/board.hpp @@ -56,9 +56,9 @@ class Board public: void add_fixed_meshline_policy(Axis axis, Coord coord); - void add_polygon(Plane plane, Polygon::Type type, std::string const& name, std::size_t priority, Polygon::RangeZ const& z_placement, std::initializer_list points); - void add_polygon(Plane plane, Polygon::Type type, std::string const& name, std::size_t priority, Polygon::RangeZ const& z_placement, std::vector>&& points); - void add_polygon_from_box(Plane plane, Polygon::Type type, std::string const& name, std::size_t priority, Polygon::RangeZ const& z_placement, Point const p1, Point const p3); + void add_polygon(Plane plane, std::shared_ptr const& material, std::string const& name, std::size_t priority, Polygon::RangeZ const& z_placement, std::initializer_list points); + void add_polygon(Plane plane, std::shared_ptr const& material, std::string const& name, std::size_t priority, Polygon::RangeZ const& z_placement, std::vector>&& points); + void add_polygon_from_box(Plane plane, std::shared_ptr const& material, std::string const& name, std::size_t priority, Polygon::RangeZ const& z_placement, Point const p1, Point const p3); [[nodiscard]] std::shared_ptr build(Params&& params = Params()); @@ -78,11 +78,13 @@ class Board /// Mesh resolution independant detection tasks ///************************************************************************* + void adjust_edges_to_materials(Plane const plane); void detect_edges_in_polygons(Plane const plane); void detect_colinear_edges(Plane plane); void detect_non_conflicting_edges(Plane const plane); void add_fixed_meshline_policies(Axis axis); + void adjust_edges_to_materials(); void detect_edges_in_polygons(); void detect_colinear_edges(); void detect_non_conflicting_edges(); @@ -104,6 +106,9 @@ class Board std::vector> const& get_conflicts_edge_in_polygons(Plane const plane) const; std::vector> const& get_conflicts_colinear_edges(Axis const axis) const; std::vector> const& get_conflicts_too_close_meshline_policies(Axis const axis) const; + +private: + std::shared_ptr find_ambient_material(Plane plane, std::shared_ptr const& current_polygon, Segment const& segment) const; }; #ifdef UNITTEST diff --git a/src/domain/conflicts/conflict_colinear_edges.cpp b/src/domain/conflicts/conflict_colinear_edges.cpp index dbff1cba..b76d2067 100644 --- a/src/domain/conflicts/conflict_colinear_edges.cpp +++ b/src/domain/conflicts/conflict_colinear_edges.cpp @@ -40,7 +40,11 @@ void ConflictColinearEdges::auto_solve(MeshlinePolicyManager& line_policy_manage if(!edge->get_current_state().to_mesh) continue; - switch(edge->normal) { + Normal const normal = edge->get_current_state().to_reverse + ? reverse(edge->normal) + : edge->normal; + + switch(normal) { case Normal::XMIN: case Normal::YMIN: case Normal::ZMIN: diff --git a/src/domain/geometrics/edge.hpp b/src/domain/geometrics/edge.hpp index b5980d4c..03adb328 100644 --- a/src/domain/geometrics/edge.hpp +++ b/src/domain/geometrics/edge.hpp @@ -42,6 +42,7 @@ struct EdgeState final , public IConflictSolutionState , public IMeshLineOriginState { bool to_mesh = true; + bool to_reverse = false; }; //****************************************************************************** diff --git a/src/domain/geometrics/normal.cpp b/src/domain/geometrics/normal.cpp new file mode 100644 index 00000000..f58329a9 --- /dev/null +++ b/src/domain/geometrics/normal.cpp @@ -0,0 +1,27 @@ +///***************************************************************************** +/// @date Feb 2021 +/// @copyright GPL-3.0-or-later +/// @author Thomas Lepoix +///***************************************************************************** + +#include "utils/unreachable.hpp" + +#include "normal.hpp" + +namespace domain { + +//****************************************************************************** +Normal reverse(Normal normal) noexcept { + switch(normal) { + case Normal::XMIN: return Normal::XMAX; + case Normal::XMAX: return Normal::XMIN; + case Normal::YMIN: return Normal::YMAX; + case Normal::YMAX: return Normal::YMIN; + case Normal::ZMIN: return Normal::ZMAX; + case Normal::ZMAX: return Normal::ZMIN; + case Normal::NONE: return Normal::NONE; + default: ::unreachable(); + } +} + +} // namespace domain diff --git a/src/domain/geometrics/normal.hpp b/src/domain/geometrics/normal.hpp index d26433aa..cee6f4b5 100644 --- a/src/domain/geometrics/normal.hpp +++ b/src/domain/geometrics/normal.hpp @@ -21,4 +21,7 @@ enum class Normal { NONE }; +//****************************************************************************** +Normal reverse(Normal normal) noexcept; + } // namespace domain diff --git a/src/domain/geometrics/polygon.cpp b/src/domain/geometrics/polygon.cpp index 7a846680..606cd9a7 100644 --- a/src/domain/geometrics/polygon.cpp +++ b/src/domain/geometrics/polygon.cpp @@ -15,11 +15,18 @@ namespace domain { using namespace std; //****************************************************************************** -Polygon::Polygon(Plane const plane, Type const type, string const& name, RangeZ const& z_placement, vector>&& points, Timepoint* t) +Polygon::RangeZ::RangeZ(Coord const& a, Coord const& b) +: min(a < b ? a : b) +, max(a > b ? a : b) +{} + +//****************************************************************************** +Polygon::Polygon(Plane const plane, shared_ptr const& material, string const& name, size_t priority, RangeZ const& z_placement, vector>&& points, Timepoint* t) : Originator(t) , rotation(detect_rotation(points)) -, type(type) , z_placement(z_placement) +, priority(priority) +, material(material) , plane(plane) , bounding(detect_bounding(points)) , name(name) diff --git a/src/domain/geometrics/polygon.hpp b/src/domain/geometrics/polygon.hpp index 5ec70b46..f1c6296a 100644 --- a/src/domain/geometrics/polygon.hpp +++ b/src/domain/geometrics/polygon.hpp @@ -14,6 +14,7 @@ #include "domain/conflicts/i_conflict_origin.hpp" #include "domain/mesh/i_meshline_origin.hpp" #include "domain/utils/entity_visitor.hpp" +#include "domain/material.hpp" #include "utils/entity.hpp" #include "utils/state_management.hpp" #include "bounding.hpp" @@ -48,18 +49,14 @@ class Polygon COLINEAR } const rotation; - enum class Type { - SHAPE, - PORT, - GROUND, - SUBSTRATE - } const type; - struct RangeZ { Coord min; Coord max; + RangeZ(Coord const& a, Coord const& b); } const z_placement; + std::size_t const priority; /// At 3D overlap, the higher is selected. + std::shared_ptr material; Plane const plane; Bounding2D const bounding; std::string const name; @@ -71,7 +68,7 @@ class Polygon ///************************************************************************* std::vector> const edges; - Polygon(Plane plane, Type type, std::string const& name, RangeZ const& z_placement, std::vector>&& points, Timepoint* t); + Polygon(Plane plane, std::shared_ptr const& material, std::string const& name, std::size_t priority, RangeZ const& z_placement, std::vector>&& points, Timepoint* t); ~Polygon() override; // relation::PolygonEdge relation_to(Edge const* edge); diff --git a/src/domain/material.cpp b/src/domain/material.cpp new file mode 100644 index 00000000..112221f2 --- /dev/null +++ b/src/domain/material.cpp @@ -0,0 +1,58 @@ +///***************************************************************************** +/// @date Feb 2021 +/// @copyright GPL-3.0-or-later +/// @author Thomas Lepoix +///***************************************************************************** + +#include "utils/unreachable.hpp" + +#include "material.hpp" + +using namespace std; + +namespace domain { + +/// Simplified deduction. +///***************************************************************************** +Material::Type Material::deduce_type(double epsilon, double mue, double kappa) { + if(epsilon == default_epsilon && mue == default_mue && kappa == default_kappa) return Material::Type::AIR; + else if(epsilon > default_epsilon && mue >= default_mue && kappa == default_kappa) return Material::Type::DIELECTRIC; + else if(epsilon == default_epsilon && mue == default_mue && kappa > default_kappa) return Material::Type::CONDUCTOR; + else return Material::Type::DIELECTRIC; +} + +//****************************************************************************** +Material::Material(Type type, string const& name) +: type(type) +, name(name) +{} + +//****************************************************************************** +strong_ordering Material::operator<=>(Material const& other) const noexcept { + switch(type) { + case Type::CONDUCTOR: + switch(other.type) { + case Type::CONDUCTOR: return strong_ordering::equivalent; + case Type::DIELECTRIC: return strong_ordering::greater; + case Type::AIR: return strong_ordering::greater; + default: unreachable(); + } + case Type::DIELECTRIC: + switch(other.type) { + case Type::CONDUCTOR: return strong_ordering::less; + case Type::DIELECTRIC: return strong_ordering::equivalent; + case Type::AIR: return strong_ordering::greater; + default: unreachable(); + } + case Type::AIR: + switch(other.type) { + case Type::CONDUCTOR: return strong_ordering::less; + case Type::DIELECTRIC: return strong_ordering::less; + case Type::AIR: return strong_ordering::equivalent; + default: unreachable(); + } + default: unreachable(); + } +} + +} // namespace domain diff --git a/src/domain/material.hpp b/src/domain/material.hpp new file mode 100644 index 00000000..76012654 --- /dev/null +++ b/src/domain/material.hpp @@ -0,0 +1,46 @@ +///***************************************************************************** +/// @date Feb 2021 +/// @copyright GPL-3.0-or-later +/// @author Thomas Lepoix +///***************************************************************************** + +#pragma once + +#include +#include + +namespace domain { + +//****************************************************************************** +class Material { +public: + + enum class Type { +// DUMP, +// PEC, + CONDUCTOR, + DIELECTRIC, + AIR + } const type; + + std::strong_ordering operator<=>(Material const& other) const noexcept; + + Material(Type type, std::string const& name); + + // https://wiki.openems.de/index.php/Material_Property.html + // Epsilon: relative electric permittivity (must be >=1) + // Mue: relative magnetic permeability (must be >=1) + // Kappa: electric conductivity (must be >=0) + // Sigma: magnetic conductivity (non-physical property, must be >=0) + // Values from CSXCAD. + static double constexpr default_epsilon = 1; + static double constexpr default_mue = 1; + static double constexpr default_kappa = 0; + static double constexpr default_sigma = 0; + + static Type deduce_type(double epsilon, double mue, double kappa); + + std::string const name; +}; + +} // namespace domain diff --git a/src/infra/parsers/parser_from_csx.cpp b/src/infra/parsers/parser_from_csx.cpp index 5647b8fd..bc1ef21c 100644 --- a/src/infra/parsers/parser_from_csx.cpp +++ b/src/infra/parsers/parser_from_csx.cpp @@ -5,10 +5,12 @@ ///***************************************************************************** #include +#include #include #include +#include "domain/material.hpp" #include "domain/geometrics/bounding.hpp" #include "domain/geometrics/polygon.hpp" #include "domain/geometrics/space.hpp" @@ -51,14 +53,13 @@ class ParserFromCsx::Pimpl { Pimpl(ParserFromCsx::Params const& params); - void parse_property(pugi::xml_node const& node); + shared_ptr parse_property(pugi::xml_node const& node); - void parse_primitive(pugi::xml_node const& node); - void parse_primitive_box(pugi::xml_node const& node, std::string name); - void parse_primitive_linpoly(pugi::xml_node const& node, std::string name); + bool parse_primitive(pugi::xml_node const& node, shared_ptr const& material); + void parse_primitive_box(pugi::xml_node const& node, shared_ptr const& material, std::string name); + void parse_primitive_linpoly(pugi::xml_node const& node, shared_ptr const& material, std::string name); private: - optional which_material_is(pugi::xml_node const& primitive_node); }; //****************************************************************************** @@ -67,22 +68,26 @@ ParserFromCsx::Pimpl::Pimpl(ParserFromCsx::Params const& params) {} //****************************************************************************** -void ParserFromCsx::Pimpl::parse_property(pugi::xml_node const& node) { - cerr << node.name() << endl; - - // TODO try to guess kind TRACK GROUND SUBSTRATE to disable EIP detection +shared_ptr ParserFromCsx::Pimpl::parse_property(pugi::xml_node const& node) { string name(node.attribute("Name").as_string()); if(node.name() == "Material"s) { + // https://github.com/thliebig/openEMS-Project/discussions/347 + // Currently do not take care of Isotropy=false + // as_double() selects the first term and ditch the part after + bool isotropy = node.attribute("Isotropy").as_bool(); pugi::xml_node property = node.child("Property"); - double epsilon = node.attribute("Epsilon").as_double(); // TODO optional - double mue = node.attribute("Mue").as_double(); // TODO optional - double kappa = node.attribute("Kappa").as_double(); // TODO optional - double sigma = node.attribute("Sigma").as_double(); // TODO optional + double epsilon = property.attribute("Epsilon").as_double(Material::default_epsilon); + double mue = property.attribute("Mue").as_double(Material::default_mue); + double kappa = property.attribute("Kappa").as_double(Material::default_kappa); + double sigma = property.attribute("Sigma").as_double(Material::default_sigma); + return make_shared(Material::deduce_type(epsilon, mue, kappa), name); } else if(node.name() == "Metal"s) { + return make_shared(Material::Type::CONDUCTOR, name); } else if(node.name() == "ConductingSheet"s) { double conductivity = node.attribute("Conductivity").as_double(); double thickness = node.attribute("Thickness").as_double(); + return make_shared(Material::Type::CONDUCTOR, name); } else if(node.name() == "LumpedElement"s) { } else if(node.name() == "Excitation"s) { } else if(node.name() == "ProbeBox"s) { @@ -93,67 +98,38 @@ void ParserFromCsx::Pimpl::parse_property(pugi::xml_node const& node) { } else if(node.name() == "Unknown"s) { } else if(node.name() == "DiscMaterial"s) { } + + return shared_ptr(); } //****************************************************************************** -void ParserFromCsx::Pimpl::parse_primitive(pugi::xml_node const& node) { - cerr << node.name() << endl; +bool ParserFromCsx::Pimpl::parse_primitive(pugi::xml_node const& node, shared_ptr const& material) { string property_name(node.parent().parent().attribute("Name").as_string()); string name(property_name + "::" + to_string(primitives_ids.at(node))); using pugi::char_t; - if(node.name() == "Box"s) - parse_primitive_box(node, name); - else if(node.name() == "LinPoly"s) - parse_primitive_linpoly(node, name); - else if(node.name() == "Polyhedron"s) {} - else if(node.name() == "Polygon"s) {} - else if(node.name() == "RotPoly"s) {} - else if(node.name() == "Sphere"s) {} - else if(node.name() == "Cylinder"s) {} - else if(node.name() == "Wire"s) {} - else if(node.name() == "CylindricalShell"s) {} - else if(node.name() == "User-Defined"s) {} - else if(node.name() == "Curve"s) {} - -} - -//****************************************************************************** -optional ParserFromCsx::Pimpl::which_material_is(pugi::xml_node const& primitive_node) { - string property(primitive_node.parent().parent().name()); - string property_name(primitive_node.parent().parent().attribute("Name").as_string()); - - if(contains(params.grounds, property_name)) { - return Polygon::Type::GROUND; - } else { - if(property == "Material") { - return Polygon::Type::SUBSTRATE; - } else if(property == "Metal" - || property == "ConductingSheet") { - return Polygon::Type::SHAPE; - } else if(property == "LumpedElement") { - } else if(property == "Excitation") { - } else if(property == "ProbeBox") { - } else if(property == "DumpBox") { - } else if(property == "DebyeMaterial") { - } else if(property == "LorentzMaterial") { - } else if(property == "ResBox") { - } else if(property == "Unknown") { - } else if(property == "DiscMaterial") { - } + if(node.name() == "Box"s) { + parse_primitive_box(node, material, name); + return true; + } else if(node.name() == "LinPoly"s) { + parse_primitive_linpoly(node, material, name); + return true; + } else if(node.name() == "Polyhedron"s) { + } else if(node.name() == "Polygon"s) { + } else if(node.name() == "RotPoly"s) { + } else if(node.name() == "Sphere"s) { + } else if(node.name() == "Cylinder"s) { + } else if(node.name() == "Wire"s) { + } else if(node.name() == "CylindricalShell"s) { + } else if(node.name() == "User-Defined"s) { + } else if(node.name() == "Curve"s) { } - - return nullopt; + return false; } //****************************************************************************** -void ParserFromCsx::Pimpl::parse_primitive_box(pugi::xml_node const& node, string name) { - auto const type = which_material_is(node); -// if(!type.has_value() || type.value() != Polygon::Type::SHAPE) // TODO - if(!type.has_value() || type.value() == Polygon::Type::SUBSTRATE) // TODO - return; - +void ParserFromCsx::Pimpl::parse_primitive_box(pugi::xml_node const& node, shared_ptr const& material, string name) { size_t priority = node.attribute("Priority").as_uint(); pugi::xml_node node_p1 = node.child("P1"); pugi::xml_node node_p2 = node.child("P2"); @@ -166,21 +142,16 @@ void ParserFromCsx::Pimpl::parse_primitive_box(pugi::xml_node const& node, strin node_p2.attribute("Y").as_double(), node_p2.attribute("Z").as_double()); if(params.with_yz) - board.add_polygon_from_box(YZ, type.value(), name, priority, { p1.x, p2.x }, { p1.y, p1.z }, { p2.y, p2.z }); + board.add_polygon_from_box(YZ, material, name, priority, { p1.x, p2.x }, { p1.y, p1.z }, { p2.y, p2.z }); if(params.with_zx) - board.add_polygon_from_box(ZX, type.value(), name, priority, { p1.y, p2.y }, { p1.z, p1.x }, { p2.z, p2.x }); + board.add_polygon_from_box(ZX, material, name, priority, { p1.y, p2.y }, { p1.z, p1.x }, { p2.z, p2.x }); if(params.with_xy) - board.add_polygon_from_box(XY, type.value(), name, priority, { p1.z, p2.z }, { p1.x, p1.y }, { p2.x, p2.y }); + board.add_polygon_from_box(XY, material, name, priority, { p1.z, p2.z }, { p1.x, p1.y }, { p2.x, p2.y }); // TODO if property == ConductingSheet : add_fixed_meshline_policy() } //****************************************************************************** -void ParserFromCsx::Pimpl::parse_primitive_linpoly(pugi::xml_node const& node, string name) { - auto const type = which_material_is(node); -// if(!type.has_value() || type.value() != Polygon::Type::SHAPE) // TODO - if(!type.has_value() || type.value() == Polygon::Type::SUBSTRATE) // TODO - return; - +void ParserFromCsx::Pimpl::parse_primitive_linpoly(pugi::xml_node const& node, shared_ptr const& material, string name) { size_t priority = node.attribute("Priority").as_uint(); double elevation = node.attribute("Elevation").as_double(); // offset in normdir double length = node.attribute("Length").as_double(); // height in normdir @@ -198,7 +169,7 @@ void ParserFromCsx::Pimpl::parse_primitive_linpoly(pugi::xml_node const& node, s Bounding2D bounding(detect_bounding(points)); - board.add_polygon(plane.value(), type.value(), name, priority, { elevation, elevation + length }, std::move(points)); + board.add_polygon(plane.value(), material, name, priority, { elevation, elevation + length }, std::move(points)); if(length == 0) { // board.add_fixed_meshline_policy(normal.value(), elevation); // switch(plane.value()) { @@ -221,36 +192,36 @@ void ParserFromCsx::Pimpl::parse_primitive_linpoly(pugi::xml_node const& node, s switch(plane.value()) { case YZ: if(params.with_zx) - board.add_polygon_from_box(ZX, type.value(), name, priority, + board.add_polygon_from_box(ZX, material, name, priority, { bounding[XMIN], bounding[XMAX] }, { bounding[YMIN], elevation }, { bounding[YMAX], elevation + length }); if(params.with_xy) - board.add_polygon_from_box(XY, type.value(), name, priority, + board.add_polygon_from_box(XY, material, name, priority, { bounding[YMIN], bounding[YMAX] }, { elevation, bounding[XMIN] }, { elevation + length, bounding[XMAX] }); break; case ZX: if(params.with_xy) - board.add_polygon_from_box(XY, type.value(), name, priority, + board.add_polygon_from_box(XY, material, name, priority, { bounding[XMIN], bounding[XMAX] }, { bounding[YMIN], elevation }, { bounding[YMAX], elevation + length }); if(params.with_yz) - board.add_polygon_from_box(YZ, type.value(), name, priority, + board.add_polygon_from_box(YZ, material, name, priority, { bounding[YMIN], bounding[YMAX] }, { elevation, bounding[XMIN] }, { elevation + length, bounding[XMAX] }); break; case XY: if(params.with_yz) - board.add_polygon_from_box(YZ, type.value(), name, priority, + board.add_polygon_from_box(YZ, material, name, priority, { bounding[XMIN], bounding[XMAX] }, { bounding[YMIN], elevation }, { bounding[YMAX], elevation + length }); if(params.with_zx) - board.add_polygon_from_box(ZX, type.value(), name, priority, + board.add_polygon_from_box(ZX, material, name, priority, { bounding[YMIN], bounding[YMAX] }, { elevation, bounding[XMIN] }, { elevation + length, bounding[XMAX] }); @@ -322,11 +293,13 @@ void ParserFromCsx::parse() { pugi::xpath_node properties = doc.select_node("/openEMS/ContinuousStructure/Properties"); for(auto const& node : properties.node().children()) { - pimpl->parse_property(node); + auto material = pimpl->parse_property(node); pugi::xml_node primitives = node.child("Primitives"); - for(auto const& node : primitives.children()) - pimpl->parse_primitive(node); + for(auto const& node : primitives.children()) { + if(material) + pimpl->parse_primitive(node, material); + } } } diff --git a/src/ui/qt/main_window.cpp b/src/ui/qt/main_window.cpp index f57157e6..2b75eaa0 100644 --- a/src/ui/qt/main_window.cpp +++ b/src/ui/qt/main_window.cpp @@ -423,6 +423,12 @@ void MainWindow::run(app::Step from) { make_current_state_view(); } +//****************************************************************************** +void MainWindow::run() { + oemsh.run_all_steps(); + make_current_state_view(); +} + //****************************************************************************** void MainWindow::handle_edition_from(app::Step from, std::function const& edit) { oemsh.go_before(from); diff --git a/src/ui/qt/main_window.hpp b/src/ui/qt/main_window.hpp index adec0955..664ee66d 100644 --- a/src/ui/qt/main_window.hpp +++ b/src/ui/qt/main_window.hpp @@ -39,7 +39,8 @@ class MainWindow : public QMainWindow { void go_to_current_state(); void make_current_state_view(); void go_to_or_make_current_state(); - void run(app::Step from = app::Step::DETECT_CONFLICT_EIP); + void run(app::Step from); + void run(); private slots: void on_a_about_triggered(); diff --git a/src/ui/qt/processing_view/processing_edge.cpp b/src/ui/qt/processing_view/processing_edge.cpp index 1d974695..0c443a1a 100644 --- a/src/ui/qt/processing_view/processing_edge.cpp +++ b/src/ui/qt/processing_view/processing_edge.cpp @@ -53,9 +53,11 @@ ProcessingEdge::ProcessingEdge(domain::Edge const* edge, QGraphicsItem* parent) QString normal("Normal: "); QString to_mesh("To mesh: "); + QString to_reverse("To reverse: "); if(edge) { normal += QString::fromStdString(to_string(edge->normal)); to_mesh += (edge->get_current_state().to_mesh ? "true" : "false"); + to_reverse += (edge->get_current_state().to_reverse ? "true" : "false"); } auto* text_normal = new nodegraph::Text(normal, this); @@ -65,6 +67,13 @@ ProcessingEdge::ProcessingEdge(domain::Edge const* edge, QGraphicsItem* parent) return locate_processing_edge_params().main; }; + auto* text_to_reverse = new nodegraph::Text(to_reverse, this); + text_to_reverse->setFlag(QGraphicsItem::ItemIsSelectable); + text_to_reverse->setAcceptedMouseButtons(Qt::NoButton); + text_to_reverse->locate_text_params = [this]() -> auto& { + return locate_processing_edge_params().main; + }; + auto* text_to_mesh = new nodegraph::Text(to_mesh, this); text_to_mesh->setFlag(QGraphicsItem::ItemIsSelectable); text_to_mesh->setAcceptedMouseButtons(Qt::NoButton); @@ -96,6 +105,7 @@ ProcessingEdge::ProcessingEdge(domain::Edge const* edge, QGraphicsItem* parent) v_box1->addStretch(); v_box2->addItem(text_normal); v_box2->addItem(text_to_mesh); + v_box2->addItem(text_to_reverse); v_box3->addStretch(); v_box3->addItem(output_port); v_box3->addStretch(); diff --git a/src/ui/qt/structure_view/structure_scene.cpp b/src/ui/qt/structure_view/structure_scene.cpp index d3522541..e6a58dd5 100644 --- a/src/ui/qt/structure_view/structure_scene.cpp +++ b/src/ui/qt/structure_view/structure_scene.cpp @@ -116,30 +116,38 @@ StructureEdge* StructureScene::add(domain::Edge const* edge) { StructurePolygon* StructureScene::add(domain::Polygon const* polygon) { auto* item = new StructurePolygon(polygon, polygons); index[polygon] = item; - switch(polygon->type) { - case domain::Polygon::Type::SHAPE: - item->locate_structure_polygon_params = [this]() -> auto& { - return style_selector.get_polygon_shape(); - }; - break; - case domain::Polygon::Type::PORT: - item->locate_structure_polygon_params = [this]() -> auto& { - return style_selector.get_polygon_port(); - }; - break; - case domain::Polygon::Type::GROUND: - item->locate_structure_polygon_params = [this]() -> auto& { - return style_selector.get_polygon_ground(); - }; - break; - case domain::Polygon::Type::SUBSTRATE: - item->locate_structure_polygon_params = [this]() -> auto& { - return style_selector.get_polygon_substrate(); - }; - break; - default: - unreachable(); - } +// switch(polygon->material->type) { +// case domain::Material::Type::CONDUCTOR: +// item->locate_structure_polygon_params = [this]() -> auto& { +// return style_selector.get_polygon_shape(); +// }; +// break; +// case domain::Material::Type::PORT: +// item->locate_structure_polygon_params = [this]() -> auto& { +// return style_selector.get_polygon_port(); +// }; +// break; +// case domain::Material::Type::GROUND: +// item->locate_structure_polygon_params = [this]() -> auto& { +// return style_selector.get_polygon_ground(); +// }; +// break; +// case domain::Material::Type::DIELECTRIC: +// item->locate_structure_polygon_params = [this]() -> auto& { +// return style_selector.get_polygon_substrate(); +// }; +// break; +// case domain::Material::Type::AIR: +// item->locate_structure_polygon_params = [this]() -> auto& { +// return style_selector.get_polygon_substrate(); +// }; +// break; +// default: +// unreachable(); +// } + item->locate_structure_polygon_params = [this]() -> auto& { + return style_selector.get_polygon_shape(); + }; return item; } diff --git a/test/unit/CMakeLists.txt b/test/unit/CMakeLists.txt index b80cc68a..e7b49ca2 100644 --- a/test/unit/CMakeLists.txt +++ b/test/unit/CMakeLists.txt @@ -23,6 +23,7 @@ if( Catch2_FOUND ) "${CMAKE_CURRENT_SOURCE_DIR}/domain/mesh/test_meshline_policy.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/domain/test_conflict_manager.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/domain/test_meshline_policy_manager.cpp" + "${CMAKE_CURRENT_SOURCE_DIR}/domain/test_material.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/domain/test_board.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/infra/serializers/test_serializer_to_plantuml.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/infra/utils/test_to_string.cpp" diff --git a/test/unit/app/test_openemsh.cpp b/test/unit/app/test_openemsh.cpp index 49a0bca6..b4c5c938 100644 --- a/test/unit/app/test_openemsh.cpp +++ b/test/unit/app/test_openemsh.cpp @@ -16,6 +16,13 @@ using namespace app; //****************************************************************************** SCENARIO("optional next(Step step)", "[app][openemsh]") { + WHEN("Running for ADJUST_EDGE_TO_MATERIAL") { + THEN("Should return DETECT_CONFLICT_EIP") { + std::optional a = next(Step::ADJUST_EDGE_TO_MATERIAL); + REQUIRE(a.has_value()); + REQUIRE(a.value() == Step::DETECT_CONFLICT_EIP); + } + } WHEN("Running for DETECT_CONFLICT_EIP") { THEN("Should return DETECT_CONFLICT_CE") { std::optional a = next(Step::DETECT_CONFLICT_EIP); @@ -82,6 +89,22 @@ SCENARIO("optional next(Step step)", "[app][openemsh]") { //****************************************************************************** SCENARIO("set that_and_after(Step step)", "[app][openemsh]") { + WHEN("Running for ADJUST_EDGE_TO_MATERIAL") { + THEN("Should return all Steps except those coming before ADJUST_EDGE_TO_MATERIAL") { + REQUIRE(that_and_after(Step::ADJUST_EDGE_TO_MATERIAL) == std::set { + Step::ADJUST_EDGE_TO_MATERIAL, + Step::DETECT_CONFLICT_EIP, + Step::DETECT_CONFLICT_CE, + Step::DETECT_NON_CONFLICTING_EDGES, + Step::ADD_FIXED_MLP, + Step::SOLVE_ALL_EIP, + Step::SOLVE_ALL_CE, + Step::DETECT_AND_SOLVE_TCMLP, + Step::DETECT_INTERVALS, + Step::MESH + }); + } + } WHEN("Running for DETECT_CONFLICT_EIP") { THEN("Should return all Steps except those coming before DETECT_CONFLICT_EIP") { REQUIRE(that_and_after(Step::DETECT_CONFLICT_EIP) == std::set { diff --git a/test/unit/domain/geometrics/test_polygon.cpp b/test/unit/domain/geometrics/test_polygon.cpp index b49548e8..263c1a02 100644 --- a/test/unit/domain/geometrics/test_polygon.cpp +++ b/test/unit/domain/geometrics/test_polygon.cpp @@ -64,7 +64,7 @@ SCENARIO("template Polygon::Rotation detect_rotation(T& points) noexcep Timepoint t; GIVEN("A polygon or a bunch of points") { WHEN("Points order is oriented clockwise") { - Polygon a(XY, Polygon::Type::SHAPE, "", 0 , { 0, 0 }, from_init_list({{ 1, 2 }, { 1, 4 }, { 4, 4 }}), &t); + Polygon a(XY, {}, "", 0 , { 0, 0 }, from_init_list({{ 1, 2 }, { 1, 4 }, { 4, 4 }}), &t); std::vector b({a.points[0].get(), a.points[1].get(), a.points[2].get()}); THEN("Should be detected as CW") { REQUIRE(detect_rotation(a.points) == Polygon::Rotation::CW); @@ -73,7 +73,7 @@ SCENARIO("template Polygon::Rotation detect_rotation(T& points) noexcep } WHEN("Points order is oriented counter clockwise") { - Polygon a(XY, Polygon::Type::SHAPE, "", 0 , { 0, 0 }, from_init_list({{ 1, 2 }, { 4, 4 }, { 1, 4 }}), &t); + Polygon a(XY, {}, "", 0 , { 0, 0 }, from_init_list({{ 1, 2 }, { 4, 4 }, { 1, 4 }}), &t); std::vector b({a.points[0].get(), a.points[1].get(), a.points[2].get()}); THEN("Should be detected as CCW") { REQUIRE(detect_rotation(a.points) == Polygon::Rotation::CCW); @@ -82,8 +82,8 @@ SCENARIO("template Polygon::Rotation detect_rotation(T& points) noexcep } WHEN("Points are all aligned in an axis") { - Polygon a(XY, Polygon::Type::SHAPE, "", 0 , { 0, 0 }, from_init_list({{ 1, 2 }, { 1, 4 }, { 1, 1 }}), &t); - Polygon b(XY, Polygon::Type::SHAPE, "", 0 , { 0, 0 }, from_init_list({{ 51.3539, -44.8024 }, { 120.0290, -44.8024 }, { 140.2830, -44.8024 }}), &t); + Polygon a(XY, {}, "", 0 , { 0, 0 }, from_init_list({{ 1, 2 }, { 1, 4 }, { 1, 1 }}), &t); + Polygon b(XY, {}, "", 0 , { 0, 0 }, from_init_list({{ 51.3539, -44.8024 }, { 120.0290, -44.8024 }, { 140.2830, -44.8024 }}), &t); std::vector c({a.points[0].get(), a.points[1].get(), a.points[2].get()}); std::vector d({b.points[0].get(), b.points[1].get(), b.points[2].get()}); THEN("Should be detected as COLINEAR") { @@ -95,7 +95,7 @@ SCENARIO("template Polygon::Rotation detect_rotation(T& points) noexcep } WHEN("Points are all aligned in diagonal") { - Polygon a(XY, Polygon::Type::SHAPE, "", 0 , { 0, 0 }, from_init_list({{ 1, 2 }, { 4, 4 }, { 2.5, 3 }}), &t); + Polygon a(XY, {}, "", 0 , { 0, 0 }, from_init_list({{ 1, 2 }, { 4, 4 }, { 2.5, 3 }}), &t); std::vector b({a.points[0].get(), a.points[1].get(), a.points[2].get()}); THEN("Should be detected as COLINEAR") { REQUIRE(detect_rotation(a.points) == Polygon::Rotation::COLINEAR); @@ -104,7 +104,7 @@ SCENARIO("template Polygon::Rotation detect_rotation(T& points) noexcep } WHEN("Two points of a triangle are at the same place") { - Polygon a(XY, Polygon::Type::SHAPE, "", 0 , { 0, 0 }, from_init_list({{ 1, 2 }, { 4, 4 }, { 1, 2 }}), &t); + Polygon a(XY, {}, "", 0 , { 0, 0 }, from_init_list({{ 1, 2 }, { 4, 4 }, { 1, 2 }}), &t); std::vector b({a.points[0].get(), a.points[1].get(), a.points[2].get()}); THEN("Should be detected as COLINEAR") { REQUIRE(detect_rotation(a.points) == Polygon::Rotation::COLINEAR); @@ -119,7 +119,7 @@ SCENARIO("void Polygon::detect_edge_normal() noexcept", "[polygon]") { Timepoint t; GIVEN("An octogon : 2 horizontal edges, 2 verticals, 4 diagonals") { WHEN("Points order is oriented clockwise") { - Polygon a(XY, Polygon::Type::SHAPE, "", 0 , { 0, 0 }, from_init_list({ + Polygon a(XY, {}, "", 0 , { 0, 0 }, from_init_list({ { 2, 1 }, { 1, 2 }, { 1, 3 }, { 2, 4 }, { 3, 4 }, { 4, 3 }, { 4, 2 }, { 3, 1 }}), &t); THEN("For edges going down to the X axis, the normal should go down to the Y") { @@ -151,7 +151,7 @@ SCENARIO("void Polygon::detect_edge_normal() noexcept", "[polygon]") { } WHEN("Points order is oriented counter clockwise") { - Polygon a(XY, Polygon::Type::SHAPE, "", 0 , { 0, 0 }, from_init_list({ + Polygon a(XY, {}, "", 0 , { 0, 0 }, from_init_list({ { 2, 1 }, { 3, 1 }, { 4, 2 }, { 4, 3 }, { 3, 4 }, { 2, 4 }, { 1, 3 }, { 1, 2 }}), &t); THEN("For edges going down to the X axis, the normal should go up to the Y") { @@ -183,7 +183,7 @@ SCENARIO("void Polygon::detect_edge_normal() noexcept", "[polygon]") { } WHEN("Points are all aligned or at the same position") { - Polygon a(XY, Polygon::Type::SHAPE, "", 0 , { 0, 0 }, from_init_list({{ 1, 2 }, { 1, 4 }, { 1, 1 }, { 1, 1 }}), &t); + Polygon a(XY, {}, "", 0 , { 0, 0 }, from_init_list({{ 1, 2 }, { 1, 4 }, { 1, 1 }, { 1, 1 }}), &t); THEN("There should not be any normal") { REQUIRE(a.rotation == Polygon::Rotation::COLINEAR); REQUIRE(a.edges[0]->normal == Normal::NONE); @@ -199,7 +199,7 @@ SCENARIO("void Polygon::detect_edge_normal() noexcept", "[polygon]") { SCENARIO("relation::PolygonPoint Polygon::relation_to(Point const* point) const noexcept", "[polygon]") { Timepoint t; GIVEN("A simple polygon") { - Polygon poly(XY, Polygon::Type::SHAPE, "", 0 , { 0, 0 }, from_init_list({{ 1, 1 }, { 1, 3 }, { 3, 3 }, { 3, 1 }}), &t); + Polygon poly(XY, {}, "", 0 , { 0, 0 }, from_init_list({{ 1, 1 }, { 1, 3 }, { 3, 3 }, { 3, 1 }}), &t); WHEN("A point is inside the polygon") { Point p(2, 2); THEN("Should be detected as IN") { @@ -256,7 +256,7 @@ SCENARIO("relation::PolygonPoint Polygon::relation_to(Point const* point) const GIVEN("A polygon with vertices on the firsts rays") { WHEN("The polygon have 4 edge colinear to the 4 first rays") { - Polygon poly(XY, Polygon::Type::SHAPE, "", 0 , { 0, 0 }, from_init_list({ + Polygon poly(XY, {}, "", 0 , { 0, 0 }, from_init_list({ { 3, 1 }, { 3, 2 }, { 4, 3 }, { 5, 3 }, { 3, 5 }, { 3, 4 }, { 2, 3 }, { 1, 3 }}), &t); Point p(3, 3); @@ -266,7 +266,7 @@ SCENARIO("relation::PolygonPoint Polygon::relation_to(Point const* point) const } WHEN("The polygon have 4 angles on the 4 first rays") { - Polygon poly(XY, Polygon::Type::SHAPE, "", 0 , { 0, 0 }, from_init_list({{ 2, 1 }, { 3, 2 }, { 2, 3 }, { 1, 2 }}), &t); + Polygon poly(XY, {}, "", 0 , { 0, 0 }, from_init_list({{ 2, 1 }, { 3, 2 }, { 2, 3 }, { 1, 2 }}), &t); Point p(2, 2); THEN("Should be detected as IN") { REQUIRE(poly.relation_to(p) == relation::PolygonPoint::IN); @@ -276,7 +276,7 @@ SCENARIO("relation::PolygonPoint Polygon::relation_to(Point const* point) const GIVEN("A simple polygon that flirt with floating points calculus imprecision") { WHEN("A point is outside the polygon, but colinear to an edge") { - Polygon poly(XY, Polygon::Type::SHAPE, "", 0 , { 0, 0 }, from_init_list({ + Polygon poly(XY, {}, "", 0 , { 0, 0 }, from_init_list({ { 120.0290, -44.8024 }, { 120.0290, -42.0164 }, { 140.2830, -42.0164 }, @@ -328,4 +328,17 @@ SCENARIO("bool does_overlap(Polygon::RangeZ const& a, Polygon::RangeZ const& b) REQUIRE(does_overlap(b, a)); } } + + GIVEN("Two coincident Z ranges") { + Polygon::RangeZ a { 1, 4 }; + Polygon::RangeZ b { 4, 1 }; + Polygon::RangeZ c { 1, -1 }; + THEN("Should be detected as overlapping") { + REQUIRE(does_overlap(a, a)); + REQUIRE(does_overlap(a, a)); + REQUIRE(does_overlap(a, b)); + REQUIRE(does_overlap(b, a)); + REQUIRE(does_overlap(c, c)); + } + } } diff --git a/test/unit/domain/test_board.cpp b/test/unit/domain/test_board.cpp index 38a5ad60..45bcf023 100644 --- a/test/unit/domain/test_board.cpp +++ b/test/unit/domain/test_board.cpp @@ -11,6 +11,7 @@ #include "domain/conflicts/conflict_colinear_edges.hpp" #include "domain/conflicts/conflict_edge_in_polygon.hpp" +#include "domain/material.hpp" #include "utils/vector_utils.hpp" #include "domain/board.hpp" @@ -139,9 +140,10 @@ SCENARIO("void sort_points_by_vector_orientation(std::vector& points, Poi SCENARIO("void Board::Builder::add_polygon(Plane plane, std::string const& name, Polygon::RangeZ const& z_placement, std::initializer_list points)", "[board]") { GIVEN("A Board Builder") { Board::Builder b; + auto material = std::make_shared(Material::Type::CONDUCTOR, ""); REQUIRE(b.polygons[XY].empty()); WHEN("Adding a polygon as an initializer_list of Points") { - b.add_polygon(XY, Polygon::Type::SHAPE, "MS13", 0, { 0, 0 }, { + b.add_polygon(XY, material, "MS13", 0, { 0, 0 }, { { 70.3673, -42.8674 }, { 62.1753, -42.8674 }, { 62.1753, -43.9276 }, @@ -166,6 +168,7 @@ SCENARIO("void Board::Builder::add_polygon(Plane plane, std::string const& name, SCENARIO("void Board::Builder::add_polygon(Plane plane, std::string const& name, Polygon::RangeZ const& z_placement, std::vector>&& points)", "[board]") { GIVEN("A Board Builder") { Board::Builder b; + auto material = std::make_shared(Material::Type::CONDUCTOR, ""); REQUIRE(b.polygons[XY].empty()); WHEN("Adding a polygon as a vector of Points") { std::vector> points(from_init_list({ @@ -175,8 +178,8 @@ SCENARIO("void Board::Builder::add_polygon(Plane plane, std::string const& name, { 66.2713, -43.9276 }, { 66.2713, -43.9514 }, { 70.3673, -43.9514 }})); - b.add_polygon(XY, Polygon::Type::SHAPE, "MS13", 0, { 0, 0 }, std::move(points)); - b.add_polygon(XY, Polygon::Type::SHAPE, "MS15", 0, { 0, 0 }, from_init_list({ + b.add_polygon(XY, material, "MS13", 0, { 0, 0 }, std::move(points)); + b.add_polygon(XY, material, "MS15", 0, { 0, 0 }, from_init_list({ { 70.3673, -42.8674 }, { 62.1753, -42.8674 }, { 62.1753, -43.9276 }, @@ -208,9 +211,10 @@ SCENARIO("void Board::Builder::add_polygon(Plane plane, std::string const& name, SCENARIO("void Board::Builder::add_polygon_from_box(Plane plane, std::string const& name, Polygon::RangeZ const& z_placement, Point const p1, Point const p3)", "[board]") { GIVEN("A Board Builder") { Board::Builder b; + auto material = std::make_shared(Material::Type::CONDUCTOR, ""); REQUIRE(b.polygons[XY].empty()); WHEN("Adding a rectangle polygon as a box of opposite Points") { - b.add_polygon_from_box(XY, Polygon::Type::SHAPE, "MS1", 0, { 0, 0 }, { 16.1, -26.5 }, { 20.6, -26 }); + b.add_polygon_from_box(XY, material, "MS1", 0, { 0, 0 }, { 16.1, -26.5 }, { 20.6, -26 }); THEN("Should add a Polygon in the inner vector") { REQUIRE(b.polygons[XY].size() == 1); REQUIRE(b.polygons[XY][0]->name == "MS1"); @@ -227,16 +231,17 @@ SCENARIO("void Board::Builder::add_polygon_from_box(Plane plane, std::string con SCENARIO("std::unique_ptr Board::Builder::build()", "[board]") { GIVEN("A Board Builder previously fed of polygons") { Board::Builder b; + auto material = std::make_shared(Material::Type::CONDUCTOR, ""); REQUIRE(b.polygons[XY].empty()); - b.add_polygon_from_box(XY, Polygon::Type::SHAPE, "MS1", 0, { 0, 0 }, { 16.1, -26.5 }, { 20.6, -26 }); - b.add_polygon(XY, Polygon::Type::SHAPE, "MS15", 0, { 0, 0 }, from_init_list({ + b.add_polygon_from_box(XY, material, "MS1", 0, { 0, 0 }, { 16.1, -26.5 }, { 20.6, -26 }); + b.add_polygon(XY, material, "MS15", 0, { 0, 0 }, from_init_list({ { 70.3673, -42.8674 }, { 62.1753, -42.8674 }, { 62.1753, -43.9276 }, { 66.2713, -43.9276 }, { 66.2713, -43.9514 }, { 70.3673, -43.9514 }})); - b.add_polygon(XY, Polygon::Type::SHAPE, "MS13", 0, { 0, 0 }, { + b.add_polygon(XY, material, "MS13", 0, { 0, 0 }, { { 70.3673, -42.8674 }, { 62.1753, -42.8674 }, { 62.1753, -43.9276 }, @@ -279,13 +284,14 @@ SCENARIO("std::unique_ptr Board::Builder::build()", "[board]") { //****************************************************************************** SCENARIO("void Board::detect_edges_in_polygons()", "[board]") { Timepoint* t = Caretaker::singleton().get_history_root(); + auto material = std::make_shared(Material::Type::CONDUCTOR, ""); GIVEN("A board holding two simple polygons (orthogonal squares)") { WHEN("A polygon is totally inside the other") { std::unique_ptr b; { PlaneSpace>> tmp; - tmp[XY].push_back(std::make_shared(XY, Polygon::Type::SHAPE, "", 0, Polygon::RangeZ { 0, 0 }, from_init_list({{ 1, 1 }, { 4, 1 }, { 4, 4 }, { 1, 4 }}), t)); - tmp[XY].push_back(std::make_shared(XY, Polygon::Type::SHAPE, "", 0, Polygon::RangeZ { 0, 0 }, from_init_list({{ 2, 2 }, { 2, 3 }, { 3, 3 }, { 3, 2 }}), t)); + tmp[XY].push_back(std::make_shared(XY, material, "", 0, Polygon::RangeZ { 0, 0 }, from_init_list({{ 1, 1 }, { 4, 1 }, { 4, 4 }, { 1, 4 }}), t)); + tmp[XY].push_back(std::make_shared(XY, material, "", 0, Polygon::RangeZ { 0, 0 }, from_init_list({{ 2, 2 }, { 2, 3 }, { 3, 3 }, { 3, 2 }}), t)); b = std::make_unique(std::move(tmp), Params(), t); } b->detect_edges_in_polygons(); @@ -361,8 +367,8 @@ SCENARIO("void Board::detect_edges_in_polygons()", "[board]") { std::unique_ptr b; { PlaneSpace>> tmp; - tmp[XY].push_back(std::make_shared(XY, Polygon::Type::SHAPE, "", 0, Polygon::RangeZ { 0, 0 }, from_init_list({{ 1, 2 }, { 3, 2 }, { 3, 4 }, { 1, 4 }}), t)); - tmp[XY].push_back(std::make_shared(XY, Polygon::Type::SHAPE, "", 0, Polygon::RangeZ { 0, 0 }, from_init_list({{ 2, 1 }, { 4, 1 }, { 4, 3 }, { 2, 3 }}), t)); + tmp[XY].push_back(std::make_shared(XY, material, "", 0, Polygon::RangeZ { 0, 0 }, from_init_list({{ 1, 2 }, { 3, 2 }, { 3, 4 }, { 1, 4 }}), t)); + tmp[XY].push_back(std::make_shared(XY, material, "", 0, Polygon::RangeZ { 0, 0 }, from_init_list({{ 2, 1 }, { 4, 1 }, { 4, 3 }, { 2, 3 }}), t)); b = std::make_unique(std::move(tmp), Params(), t); } b->detect_edges_in_polygons(); @@ -439,8 +445,8 @@ SCENARIO("void Board::detect_edges_in_polygons()", "[board]") { std::unique_ptr b; { PlaneSpace>> tmp; - tmp[XY].push_back(std::make_shared(XY, Polygon::Type::SHAPE, "", 0, Polygon::RangeZ { 0, 0 }, from_init_list({{ 1, 2 }, { 4, 2 }, { 4, 4 }, { 1, 4 }}), t)); - tmp[XY].push_back(std::make_shared(XY, Polygon::Type::SHAPE, "", 0, Polygon::RangeZ { 0, 0 }, from_init_list({{ 2, 1 }, { 3, 1 }, { 3, 3 }, { 2, 3 }}), t)); + tmp[XY].push_back(std::make_shared(XY, material, "", 0, Polygon::RangeZ { 0, 0 }, from_init_list({{ 1, 2 }, { 4, 2 }, { 4, 4 }, { 1, 4 }}), t)); + tmp[XY].push_back(std::make_shared(XY, material, "", 0, Polygon::RangeZ { 0, 0 }, from_init_list({{ 2, 1 }, { 3, 1 }, { 3, 3 }, { 2, 3 }}), t)); b = std::make_unique(std::move(tmp), Params(), t); } b->detect_edges_in_polygons(); @@ -517,8 +523,8 @@ SCENARIO("void Board::detect_edges_in_polygons()", "[board]") { std::unique_ptr b; { PlaneSpace>> tmp; - tmp[XY].push_back(std::make_shared(XY, Polygon::Type::SHAPE, "", 0, Polygon::RangeZ { 0, 0 }, from_init_list({{ 1, 1 }, { 4, 1 }, { 4, 4 }, { 1, 4 }}), t)); - tmp[XY].push_back(std::make_shared(XY, Polygon::Type::SHAPE, "", 0, Polygon::RangeZ { 0, 0 }, from_init_list({{ 2, 3 }, { 3, 2 }, { 5, 4 }, { 4, 5 }}), t)); + tmp[XY].push_back(std::make_shared(XY, material, "", 0, Polygon::RangeZ { 0, 0 }, from_init_list({{ 1, 1 }, { 4, 1 }, { 4, 4 }, { 1, 4 }}), t)); + tmp[XY].push_back(std::make_shared(XY, material, "", 0, Polygon::RangeZ { 0, 0 }, from_init_list({{ 2, 3 }, { 3, 2 }, { 5, 4 }, { 4, 5 }}), t)); b = std::make_unique(std::move(tmp), Params(), t); } b->detect_edges_in_polygons(); @@ -608,8 +614,8 @@ SCENARIO("void Board::detect_edges_in_polygons()", "[board]") { std::unique_ptr b; { PlaneSpace>> tmp; - tmp[XY].push_back(std::make_shared(XY, Polygon::Type::SHAPE, "", 0, Polygon::RangeZ { 0, 0 }, from_init_list({{ 1, 2 }, { 4, 2 }, { 4, 4 }, { 1, 4 }}), t)); - tmp[XY].push_back(std::make_shared(XY, Polygon::Type::SHAPE, "", 0, Polygon::RangeZ { 0, 0 }, from_init_list({{ 2, 1 }, { 3, 1 }, { 3, 2 }, { 2, 2 }}), t)); + tmp[XY].push_back(std::make_shared(XY, material, "", 0, Polygon::RangeZ { 0, 0 }, from_init_list({{ 1, 2 }, { 4, 2 }, { 4, 4 }, { 1, 4 }}), t)); + tmp[XY].push_back(std::make_shared(XY, material, "", 0, Polygon::RangeZ { 0, 0 }, from_init_list({{ 2, 1 }, { 3, 1 }, { 3, 2 }, { 2, 2 }}), t)); b = std::make_unique(std::move(tmp), Params(), t); } b->detect_edges_in_polygons(); @@ -661,8 +667,8 @@ SCENARIO("void Board::detect_edges_in_polygons()", "[board]") { std::unique_ptr b; { PlaneSpace>> tmp; - tmp[XY].push_back(std::make_shared(XY, Polygon::Type::SHAPE, "", 0, Polygon::RangeZ { 0, 0 }, from_init_list({{ 1, 2 }, { 2, 2 }, { 2, 3 }, { 1, 3 }}), t)); - tmp[XY].push_back(std::make_shared(XY, Polygon::Type::SHAPE, "", 0, Polygon::RangeZ { 0, 0 }, from_init_list({{ 2, 1 }, { 3, 1 }, { 3, 2 }, { 2, 2 }}), t)); + tmp[XY].push_back(std::make_shared(XY, material, "", 0, Polygon::RangeZ { 0, 0 }, from_init_list({{ 1, 2 }, { 2, 2 }, { 2, 3 }, { 1, 3 }}), t)); + tmp[XY].push_back(std::make_shared(XY, material, "", 0, Polygon::RangeZ { 0, 0 }, from_init_list({{ 2, 1 }, { 3, 1 }, { 3, 2 }, { 2, 2 }}), t)); b = std::make_unique(std::move(tmp), Params(), t); } b->detect_edges_in_polygons(); @@ -675,8 +681,8 @@ SCENARIO("void Board::detect_edges_in_polygons()", "[board]") { std::unique_ptr b; { PlaneSpace>> tmp; - tmp[XY].push_back(std::make_shared(XY, Polygon::Type::SHAPE, "", 0, Polygon::RangeZ { 0, 0 }, from_init_list({{ 1, 1 }, { 2, 1 }, { 2, 2 }, { 2, 1 }}), t)); - tmp[XY].push_back(std::make_shared(XY, Polygon::Type::SHAPE, "", 0, Polygon::RangeZ { 0, 0 }, from_init_list({{ 3, 3 }, { 3, 4 }, { 4, 4 }, { 4, 3 }}), t)); + tmp[XY].push_back(std::make_shared(XY, material, "", 0, Polygon::RangeZ { 0, 0 }, from_init_list({{ 1, 1 }, { 2, 1 }, { 2, 2 }, { 2, 1 }}), t)); + tmp[XY].push_back(std::make_shared(XY, material, "", 0, Polygon::RangeZ { 0, 0 }, from_init_list({{ 3, 3 }, { 3, 4 }, { 4, 4 }, { 4, 3 }}), t)); b = std::make_unique(std::move(tmp), Params(), t); } b->detect_edges_in_polygons(); @@ -691,9 +697,9 @@ SCENARIO("void Board::detect_edges_in_polygons()", "[board]") { std::unique_ptr b; { PlaneSpace>> tmp; - tmp[XY].push_back(std::make_shared(XY, Polygon::Type::SHAPE, "", 0, Polygon::RangeZ { 0, 1 }, from_init_list({ + tmp[XY].push_back(std::make_shared(XY, material, "", 0, Polygon::RangeZ { 0, 1 }, from_init_list({ { 1, 1 }, { 10, 1 }, { 10, 10 }, { 1, 10 }}), t)); - tmp[XY].push_back(std::make_shared(XY, Polygon::Type::SHAPE, "", 0, Polygon::RangeZ { 2, 3 }, from_init_list({ + tmp[XY].push_back(std::make_shared(XY, material, "", 0, Polygon::RangeZ { 2, 3 }, from_init_list({ { 11, 4 }, { 9, 3 }, { 13, 2 }, { 5, 2 }, { 5, 11 }, { 4, 11.3 }, { 3, 10 }, { 2, 10 }, { 2.3, 12 }, { 6, 11.3 }, { 6, 9 }, { 10, 10 }, @@ -711,9 +717,9 @@ SCENARIO("void Board::detect_edges_in_polygons()", "[board]") { std::unique_ptr b; { PlaneSpace>> tmp; - tmp[XY].push_back(std::make_shared(XY, Polygon::Type::SHAPE, "", 1, Polygon::RangeZ { 0, 0 }, from_init_list({ + tmp[XY].push_back(std::make_shared(XY, material, "", 1, Polygon::RangeZ { 0, 0 }, from_init_list({ { 1, 1 }, { 10, 1 }, { 10, 10 }, { 1, 10 }}), t)); - tmp[XY].push_back(std::make_shared(XY, Polygon::Type::SHAPE, "", 2, Polygon::RangeZ { 0, 0 }, from_init_list({ + tmp[XY].push_back(std::make_shared(XY, material, "", 2, Polygon::RangeZ { 0, 0 }, from_init_list({ { 11, 4 }, { 9, 3 }, { 13, 2 }, { 5, 2 }, { 5, 11 }, { 4, 11.3 }, { 3, 10 }, { 2, 10 }, { 2.3, 12 }, { 6, 11.3 }, { 6, 9 }, { 10, 10 }, @@ -782,9 +788,9 @@ SCENARIO("void Board::detect_edges_in_polygons()", "[board]") { std::unique_ptr b; { PlaneSpace>> tmp; - tmp[XY].push_back(std::make_shared(XY, Polygon::Type::SHAPE, "", 2, Polygon::RangeZ { 0, 0 }, from_init_list({ + tmp[XY].push_back(std::make_shared(XY, material, "", 2, Polygon::RangeZ { 0, 0 }, from_init_list({ { 1, 1 }, { 10, 1 }, { 10, 10 }, { 1, 10 }}), t)); - tmp[XY].push_back(std::make_shared(XY, Polygon::Type::SHAPE, "", 1, Polygon::RangeZ { 0, 0 }, from_init_list({ + tmp[XY].push_back(std::make_shared(XY, material, "", 1, Polygon::RangeZ { 0, 0 }, from_init_list({ { 11, 4 }, { 9, 3 }, { 13, 2 }, { 5, 2 }, { 5, 11 }, { 4, 11.3 }, { 3, 10 }, { 2, 10 }, { 2.3, 12 }, { 6, 11.3 }, { 6, 9 }, { 10, 10 }, @@ -873,9 +879,9 @@ SCENARIO("void Board::detect_edges_in_polygons()", "[board]") { std::unique_ptr b; { PlaneSpace>> tmp; - tmp[XY].push_back(std::make_shared(XY, Polygon::Type::SHAPE, "", 0, Polygon::RangeZ { 0, 0 }, from_init_list({ + tmp[XY].push_back(std::make_shared(XY, material, "", 0, Polygon::RangeZ { 0, 0 }, from_init_list({ { 1, 1 }, { 10, 1 }, { 10, 10 }, { 1, 10 }}), t)); - tmp[XY].push_back(std::make_shared(XY, Polygon::Type::SHAPE, "", 0, Polygon::RangeZ { 0, 0 }, from_init_list({ + tmp[XY].push_back(std::make_shared(XY, material, "", 0, Polygon::RangeZ { 0, 0 }, from_init_list({ { 11, 4 }, { 9, 3 }, { 13, 2 }, { 5, 2 }, { 5, 11 }, { 4, 11.3 }, { 3, 10 }, { 2, 10 }, { 2.3, 12 }, { 6, 11.3 }, { 6, 9 }, { 10, 10 }, @@ -1006,14 +1012,15 @@ SCENARIO("void Board::detect_edges_in_polygons()", "[board]") { //****************************************************************************** SCENARIO("void Board::detect_colinear_edges()", "[board]") { Timepoint* t = Caretaker::singleton().get_history_root(); + auto material = std::make_shared(Material::Type::CONDUCTOR, ""); GIVEN("A board holding three polygons") { WHEN("Three polygons share a colinear vertical edge") { std::unique_ptr b; { PlaneSpace>> tmp; - tmp[XY].push_back(std::make_shared(XY, Polygon::Type::SHAPE, "", 0, Polygon::RangeZ { 0, 0 }, from_init_list({{ 1, 1 }, { 2, 1 }, { 2, 2 }, { 1, 2 }}), t)); - tmp[XY].push_back(std::make_shared(XY, Polygon::Type::SHAPE, "", 0, Polygon::RangeZ { 0, 0 }, from_init_list({{ 0.5, 3 }, { 2, 3 }, { 2, 4 }, { 0.5, 4 }}), t)); - tmp[XY].push_back(std::make_shared(XY, Polygon::Type::SHAPE, "", 0, Polygon::RangeZ { 0, 0 }, from_init_list({{ 3, 5 }, { 2, 5 }, { 2, 6 }, { 3, 6 }}), t)); + tmp[XY].push_back(std::make_shared(XY, material, "", 0, Polygon::RangeZ { 0, 0 }, from_init_list({{ 1, 1 }, { 2, 1 }, { 2, 2 }, { 1, 2 }}), t)); + tmp[XY].push_back(std::make_shared(XY, material, "", 0, Polygon::RangeZ { 0, 0 }, from_init_list({{ 0.5, 3 }, { 2, 3 }, { 2, 4 }, { 0.5, 4 }}), t)); + tmp[XY].push_back(std::make_shared(XY, material, "", 0, Polygon::RangeZ { 0, 0 }, from_init_list({{ 3, 5 }, { 2, 5 }, { 2, 6 }, { 3, 6 }}), t)); b = std::make_unique(std::move(tmp), Params(), t); } b->detect_colinear_edges(); @@ -1054,9 +1061,9 @@ SCENARIO("void Board::detect_colinear_edges()", "[board]") { std::unique_ptr b; { PlaneSpace>> tmp; - tmp[XY].push_back(std::make_shared(XY, Polygon::Type::SHAPE, "", 0, Polygon::RangeZ { 0, 0 }, from_init_list({{ 1, 1 }, { 2, 1 }, { 2, 2 }, { 1, 2 }}), t)); - tmp[XY].push_back(std::make_shared(XY, Polygon::Type::SHAPE, "", 0, Polygon::RangeZ { 0, 0 }, from_init_list({{ 3, 0.5 }, { 3, 2 }, { 4, 2 }, { 4, 0.5 }}), t)); - tmp[XY].push_back(std::make_shared(XY, Polygon::Type::SHAPE, "", 0, Polygon::RangeZ { 0, 0 }, from_init_list({{ 5, 3 }, { 5, 2 }, { 6, 2 }, { 6, 3 }}), t)); + tmp[XY].push_back(std::make_shared(XY, material, "", 0, Polygon::RangeZ { 0, 0 }, from_init_list({{ 1, 1 }, { 2, 1 }, { 2, 2 }, { 1, 2 }}), t)); + tmp[XY].push_back(std::make_shared(XY, material, "", 0, Polygon::RangeZ { 0, 0 }, from_init_list({{ 3, 0.5 }, { 3, 2 }, { 4, 2 }, { 4, 0.5 }}), t)); + tmp[XY].push_back(std::make_shared(XY, material, "", 0, Polygon::RangeZ { 0, 0 }, from_init_list({{ 5, 3 }, { 5, 2 }, { 6, 2 }, { 6, 3 }}), t)); b = std::make_unique(std::move(tmp), Params(), t); } b->detect_colinear_edges(); @@ -1097,9 +1104,9 @@ SCENARIO("void Board::detect_colinear_edges()", "[board]") { std::unique_ptr b; { PlaneSpace>> tmp; - tmp[XY].push_back(std::make_shared(XY, Polygon::Type::SHAPE, "", 0, Polygon::RangeZ { 0, 0 }, from_init_list({{ 1, 1 }, { 1, 2 }, { 2, 2 }}), t)); - tmp[XY].push_back(std::make_shared(XY, Polygon::Type::SHAPE, "", 0, Polygon::RangeZ { 0, 0 }, from_init_list({{ 3, 3 }, { 3, 4 }, { 4, 4 }}), t)); - tmp[XY].push_back(std::make_shared(XY, Polygon::Type::SHAPE, "", 0, Polygon::RangeZ { 0, 0 }, from_init_list({{ 5, 5 }, { 5, 6 }, { 6, 6 }}), t)); + tmp[XY].push_back(std::make_shared(XY, material, "", 0, Polygon::RangeZ { 0, 0 }, from_init_list({{ 1, 1 }, { 1, 2 }, { 2, 2 }}), t)); + tmp[XY].push_back(std::make_shared(XY, material, "", 0, Polygon::RangeZ { 0, 0 }, from_init_list({{ 3, 3 }, { 3, 4 }, { 4, 4 }}), t)); + tmp[XY].push_back(std::make_shared(XY, material, "", 0, Polygon::RangeZ { 0, 0 }, from_init_list({{ 5, 5 }, { 5, 6 }, { 6, 6 }}), t)); b = std::make_unique(std::move(tmp), Params(), t); } b->detect_colinear_edges(); @@ -1115,12 +1122,13 @@ SCENARIO("void Board::detect_colinear_edges()", "[board]") { //****************************************************************************** SCENARIO("void Board::detect_non_conflicting_edges()", "[board]") { Timepoint* t = Caretaker::singleton().get_history_root(); + auto material = std::make_shared(Material::Type::CONDUCTOR, ""); GIVEN("Some conflicting edges and some non conflicting edges") { std::unique_ptr b; { PlaneSpace>> tmp; - tmp[XY].push_back(std::make_shared(XY, Polygon::Type::SHAPE, "", 0, Polygon::RangeZ { 0, 0 }, from_init_list({{ 1, 1 }, { 1, 2 }, { 2, 2 }}), t)); - tmp[XY].push_back(std::make_shared(XY, Polygon::Type::SHAPE, "", 0, Polygon::RangeZ { 0, 0 }, from_init_list({{ 3, 3 }, { 3, 4 }, { 4, 4 }}), t)); + tmp[XY].push_back(std::make_shared(XY, material, "", 0, Polygon::RangeZ { 0, 0 }, from_init_list({{ 1, 1 }, { 1, 2 }, { 2, 2 }}), t)); + tmp[XY].push_back(std::make_shared(XY, material, "", 0, Polygon::RangeZ { 0, 0 }, from_init_list({{ 3, 3 }, { 3, 4 }, { 4, 4 }}), t)); b = std::make_unique(std::move(tmp), Params(), t); } REQUIRE(b->get_current_state().edges[XY].size() == 6); diff --git a/test/unit/domain/test_conflict_manager.cpp b/test/unit/domain/test_conflict_manager.cpp index 611fc996..ee39dfc7 100644 --- a/test/unit/domain/test_conflict_manager.cpp +++ b/test/unit/domain/test_conflict_manager.cpp @@ -255,12 +255,13 @@ SCENARIO("void ConflictManager::add_colinear_edges(Edge* a, Edge* b)", "[conflic //****************************************************************************** SCENARIO("void ConflictManager::add_edge_in_polygon(Edge* a, Polygon* polygon, Range const range, std::optional b)", "[conflict_manager]") { Timepoint* t = Caretaker::singleton().get_history_root(); + auto material = std::make_shared(Material::Type::CONDUCTOR, ""); GIVEN("A conflict manager, an edge and some polygons") { ConflictManager cm(t); - Polygon p(XY, Polygon::Type::SHAPE, "", 0, { 0, 0 }, from_init_list({ + Polygon p(XY, material, "", 0, { 0, 0 }, from_init_list({ { 3, 1 }, { 6, 1 }, { 6, 6 }, { 1, 6 }, { 1, 3 }, { 2, 3 }, { 2, 5 }, { 5, 5 }, { 5, 2 }, { 3, 2 }}), t); - Polygon q(XY, Polygon::Type::SHAPE, "", 0, { 0, 0 }, from_init_list({{ 0, 0 }, { 0, 8 }, { 8, 8 }, { 8, 0 }}), t); + Polygon q(XY, material, "", 0, { 0, 0 }, from_init_list({{ 0, 0 }, { 0, 8 }, { 8, 8 }, { 8, 0 }}), t); WHEN("A vertical edge that is in a polygon is reported as partially in this polygon") { Point a0(4, 1), a1(4, 7); Edge a(XY, &a0, &a1, t); diff --git a/test/unit/domain/test_material.cpp b/test/unit/domain/test_material.cpp new file mode 100644 index 00000000..43e3d549 --- /dev/null +++ b/test/unit/domain/test_material.cpp @@ -0,0 +1,124 @@ +///***************************************************************************** +/// @date Feb 2021 +/// @copyright GPL-3.0-or-later +/// @author Thomas Lepoix +///***************************************************************************** + +#include + +#include "domain/material.hpp" + +/// @test Material::Type Material::deduce_type(double epsilon, double mue, double kappa) +///***************************************************************************** + +using namespace domain; + +// Use materials from +// https://github.com/VolkerMuehlhaus/openems_ihp_sg13g2/blob/820044c/workflow/output/run_dual_dipole_data/sub-1/run_dual_dipole.xml +//****************************************************************************** +SCENARIO("Material::Type Material::deduce_type(double epsilon, double mue, double kappa)", "[domain][material]") { + WHEN("Deducing Type of default values") { + double epsilon = 1; + double mue = 1; + double kappa = 0; + THEN("Should return AIR") { + REQUIRE(Material::deduce_type(epsilon, mue, kappa) == Material::Type::AIR); + } + } + WHEN("Deducing Type of Metal1") { + double epsilon = 1.0; + double mue = 1.0; + double kappa = 2.164000e+07; + THEN("Should return CONDUCTOR") { + REQUIRE(Material::deduce_type(epsilon, mue, kappa) == Material::Type::CONDUCTOR); + } + } + WHEN("Deducing Type of Metal2") { + double epsilon = 1.0; + double mue = 1.0; + double kappa = 2.319000e+07; + THEN("Should return CONDUCTOR") { + REQUIRE(Material::deduce_type(epsilon, mue, kappa) == Material::Type::CONDUCTOR); + } + } + WHEN("Deducing Type of TopMetal1") { + double epsilon = 1.0; + double mue = 1.0; + double kappa = 2.780000e+07; + THEN("Should return CONDUCTOR") { + REQUIRE(Material::deduce_type(epsilon, mue, kappa) == Material::Type::CONDUCTOR); + } + } + WHEN("Deducing Type of TopMetal2") { + double epsilon = 1.0; + double mue = 1.0; + double kappa = 3.030000e+07; + THEN("Should return CONDUCTOR") { + REQUIRE(Material::deduce_type(epsilon, mue, kappa) == Material::Type::CONDUCTOR); + } + } + WHEN("Deducing Type of TopVia1") { + double epsilon = 1.0; + double mue = 1.0; + double kappa = 2.191000e+06; + THEN("Should return CONDUCTOR") { + REQUIRE(Material::deduce_type(epsilon, mue, kappa) == Material::Type::CONDUCTOR); + } + } + WHEN("Deducing Type of TopVia2") { + double epsilon = 1.0; + double mue = 1.0; + double kappa = 3.143000e+06; + THEN("Should return CONDUCTOR") { + REQUIRE(Material::deduce_type(epsilon, mue, kappa) == Material::Type::CONDUCTOR); + } + } + WHEN("Deducing Type of Via1") { + double epsilon = 1.0; + double mue = 1.0; + double kappa = 1.660000e+06; + THEN("Should return CONDUCTOR") { + REQUIRE(Material::deduce_type(epsilon, mue, kappa) == Material::Type::CONDUCTOR); + } + } + WHEN("Deducing Type of AIR") { + double epsilon = 1.0; + double mue = 1.0; + double kappa = 0.0; + THEN("Should return AIR") { + REQUIRE(Material::deduce_type(epsilon, mue, kappa) == Material::Type::AIR); + } + } + WHEN("Deducing Type of Passive") { + double epsilon = 6.600000e+00; + double mue = 1.0; + double kappa = 0.0; + THEN("Should return DIELECTRIC") { + REQUIRE(Material::deduce_type(epsilon, mue, kappa) == Material::Type::DIELECTRIC); + } + } + WHEN("Deducing Type of SiO2") { + double epsilon = 4.100000e+00; + double mue = 1.0; + double kappa = 0.0; + THEN("Should return DIELECTRIC") { + REQUIRE(Material::deduce_type(epsilon, mue, kappa) == Material::Type::DIELECTRIC); + } + } + WHEN("Deducing Type of EPI") { + double epsilon = 1.190000e+01; + double mue = 1.0; + double kappa = 5.000000e+00; + THEN("Should return DIELECTRIC") { + REQUIRE(Material::deduce_type(epsilon, mue, kappa) == Material::Type::DIELECTRIC); + } + } + WHEN("Deducing Type of Substrate") { + double epsilon = 1.190000e+01; + double mue = 1.0; + double kappa = 2.000000e+00; + THEN("Should return DIELECTRIC") { + REQUIRE(Material::deduce_type(epsilon, mue, kappa) == Material::Type::DIELECTRIC); + } + } +} diff --git a/test/unit/infra/serializers/lpf.hpp b/test/unit/infra/serializers/lpf.hpp index 705c7284..9bbaa6c7 100644 --- a/test/unit/infra/serializers/lpf.hpp +++ b/test/unit/infra/serializers/lpf.hpp @@ -11,17 +11,17 @@ //****************************************************************************** std::shared_ptr create_lpf() { using namespace domain; - using Type = Polygon::Type; using RangeZ = Polygon::RangeZ; + auto material = std::make_shared(Material::Type::CONDUCTOR, ""); Board::Builder builder; - builder.add_polygon_from_box(XY, Type::SHAPE, "MS1", 0, RangeZ { 0, 0 }, { 16.1, -26.5 }, { 20.6, -26 }); - builder.add_polygon_from_box(XY, Type::SHAPE, "MS2", 0, RangeZ { 0, 0 }, { 20.6, -36.5 }, { 22.1, -16 }); - builder.add_polygon_from_box(XY, Type::SHAPE, "MS3", 0, RangeZ { 0, 0 }, { 22.1, -26.5 }, { 40.1, -26 }); - builder.add_polygon_from_box(XY, Type::SHAPE, "MS4", 0, RangeZ { 0, 0 }, { 40.1, -36.5 }, { 42.6, -16 }); - builder.add_polygon_from_box(XY, Type::SHAPE, "MS5", 0, RangeZ { 0, 0 }, { 42.6, -26.5 }, { 60.6, -26 }); - builder.add_polygon_from_box(XY, Type::SHAPE, "MS6", 0, RangeZ { 0, 0 }, { 60.6, -36.5 }, { 62.1, -16 }); - builder.add_polygon_from_box(XY, Type::SHAPE, "MS7", 0, RangeZ { 0, 0 }, { 62.1, -26.5 }, { 66.6, -26 }); + builder.add_polygon_from_box(XY, material, "MS1", 0, RangeZ { 0, 0 }, { 16.1, -26.5 }, { 20.6, -26 }); + builder.add_polygon_from_box(XY, material, "MS2", 0, RangeZ { 0, 0 }, { 20.6, -36.5 }, { 22.1, -16 }); + builder.add_polygon_from_box(XY, material, "MS3", 0, RangeZ { 0, 0 }, { 22.1, -26.5 }, { 40.1, -26 }); + builder.add_polygon_from_box(XY, material, "MS4", 0, RangeZ { 0, 0 }, { 40.1, -36.5 }, { 42.6, -16 }); + builder.add_polygon_from_box(XY, material, "MS5", 0, RangeZ { 0, 0 }, { 42.6, -26.5 }, { 60.6, -26 }); + builder.add_polygon_from_box(XY, material, "MS6", 0, RangeZ { 0, 0 }, { 60.6, -36.5 }, { 62.1, -16 }); + builder.add_polygon_from_box(XY, material, "MS7", 0, RangeZ { 0, 0 }, { 62.1, -26.5 }, { 66.6, -26 }); return builder.build(); } diff --git a/test/unit/infra/serializers/stub.hpp b/test/unit/infra/serializers/stub.hpp index ccaf3af0..6bee8af2 100644 --- a/test/unit/infra/serializers/stub.hpp +++ b/test/unit/infra/serializers/stub.hpp @@ -9,50 +9,50 @@ //****************************************************************************** std::shared_ptr create_stub() { using namespace domain; - using Type = Polygon::Type; using RangeZ = Polygon::RangeZ; + auto material = std::make_shared(Material::Type::CONDUCTOR, ""); Board::Builder builder; - builder.add_polygon_from_box(XY, Type::SHAPE, "MS1", 0, RangeZ { 0, 0 }, { 31.1, -44.8024 }, { 51.3539, -42.0164 }); - builder.add_polygon_from_box(XY, Type::SHAPE, "MS2", 0, RangeZ { 0, 0 }, { 120.029, -44.8024 }, { 140.283, -42.0164 }); - builder.add_polygon_from_box(XY, Type::SHAPE, "MS3", 0, RangeZ { 0, 0 }, { 51.6077, -42.0164 }, { 51.3539, -31 }); - builder.add_polygon_from_box(XY, Type::SHAPE, "MS4", 0, RangeZ { 0, 0 }, { 120.024, -42.0164 }, { 119.78, -31 }); - builder.add_polygon_from_box(XY, Type::SHAPE, "MS5", 0, RangeZ { 0, 0 }, { 109.208, -43.9276 }, { 119.775, -42.8913 }); - builder.add_polygon_from_box(XY, Type::SHAPE, "MS6", 0, RangeZ { 0, 0 }, { 51.6077, -43.9276 }, { 62.1753, -42.8913 }); - builder.add_polygon_from_box(XY, Type::SHAPE, "MS7", 0, RangeZ { 0, 0 }, { 70.3673, -42.8674 }, { 62.1753, -33.2952 }); - builder.add_polygon_from_box(XY, Type::SHAPE, "MS8", 0, RangeZ { 0, 0 }, { 109.208, -42.8674 }, { 101.016, -33.2952 }); - builder.add_polygon_from_box(XY, Type::SHAPE, "MS9", 0, RangeZ { 0, 0 }, { 90.96, -42.8674 }, { 80.4229, -33.1334 }); - builder.add_polygon_from_box(XY, Type::SHAPE, "MS10", 0, RangeZ { 0, 0 }, { 70.3673, -43.9514 }, { 80.4229, -42.8674 }); - builder.add_polygon_from_box(XY, Type::SHAPE, "MS11", 0, RangeZ { 0, 0 }, { 90.96, -43.9514 }, { 101.016, -42.8674 }); - builder.add_polygon(XY, Type::SHAPE, "MS12", 0, RangeZ { 0, 0 }, { + builder.add_polygon_from_box(XY, material, "MS1", 0, RangeZ { 0, 0 }, { 31.1, -44.8024 }, { 51.3539, -42.0164 }); + builder.add_polygon_from_box(XY, material, "MS2", 0, RangeZ { 0, 0 }, { 120.029, -44.8024 }, { 140.283, -42.0164 }); + builder.add_polygon_from_box(XY, material, "MS3", 0, RangeZ { 0, 0 }, { 51.6077, -42.0164 }, { 51.3539, -31 }); + builder.add_polygon_from_box(XY, material, "MS4", 0, RangeZ { 0, 0 }, { 120.024, -42.0164 }, { 119.78, -31 }); + builder.add_polygon_from_box(XY, material, "MS5", 0, RangeZ { 0, 0 }, { 109.208, -43.9276 }, { 119.775, -42.8913 }); + builder.add_polygon_from_box(XY, material, "MS6", 0, RangeZ { 0, 0 }, { 51.6077, -43.9276 }, { 62.1753, -42.8913 }); + builder.add_polygon_from_box(XY, material, "MS7", 0, RangeZ { 0, 0 }, { 70.3673, -42.8674 }, { 62.1753, -33.2952 }); + builder.add_polygon_from_box(XY, material, "MS8", 0, RangeZ { 0, 0 }, { 109.208, -42.8674 }, { 101.016, -33.2952 }); + builder.add_polygon_from_box(XY, material, "MS9", 0, RangeZ { 0, 0 }, { 90.96, -42.8674 }, { 80.4229, -33.1334 }); + builder.add_polygon_from_box(XY, material, "MS10", 0, RangeZ { 0, 0 }, { 70.3673, -43.9514 }, { 80.4229, -42.8674 }); + builder.add_polygon_from_box(XY, material, "MS11", 0, RangeZ { 0, 0 }, { 90.96, -43.9514 }, { 101.016, -42.8674 }); + builder.add_polygon(XY, material, "MS12", 0, RangeZ { 0, 0 }, { { 51.6077, -42.0164 }, { 51.3539, -42.0164 }, { 51.3539, -44.8024 }, { 51.4808, -44.8024 }, { 51.4808, -43.9276 }, { 51.6077, -43.9276 }}); - builder.add_polygon(XY, Type::SHAPE, "MS13", 0, RangeZ { 0, 0 }, { + builder.add_polygon(XY, material, "MS13", 0, RangeZ { 0, 0 }, { { 70.3673, -42.8674 }, { 62.1753, -42.8674 }, { 62.1753, -43.9276 }, { 66.2713, -43.9276 }, { 66.2713, -43.9514 }, { 70.3673, -43.9514 }}); - builder.add_polygon(XY, Type::SHAPE, "MS14", 0, RangeZ { 0, 0 }, { + builder.add_polygon(XY, material, "MS14", 0, RangeZ { 0, 0 }, { { 90.96, -42.8674 }, { 80.4229, -42.8674 }, { 80.4229, -43.9514 }, { 85.6915, -43.9514 }, { 85.6915, -43.9514 }, { 90.96, -43.9514 }}); - builder.add_polygon(XY, Type::SHAPE, "MS15", 0, RangeZ { 0, 0 }, { + builder.add_polygon(XY, material, "MS15", 0, RangeZ { 0, 0 }, { { 109.208, -42.8674 }, { 101.016, -42.8674 }, { 101.016, -43.9514 }, { 105.112, -43.9514 }, { 105.112, -43.9276 }, { 109.208, -43.9276 }}); - builder.add_polygon(XY, Type::SHAPE, "MS16", 0, RangeZ { 0, 0 }, { + builder.add_polygon(XY, material, "MS16", 0, RangeZ { 0, 0 }, { { 120.029, -42.0164 }, { 119.775, -42.0164 }, { 119.775, -43.9276 }, From edecb5cde7ecb069f6c0dd895c0344cbde43a54a Mon Sep 17 00:00:00 2001 From: "tlepoix@localhost" Date: Fri, 3 Oct 2025 22:14:36 +0200 Subject: [PATCH 04/14] GUI : show all edges disregarding polygons stack order --- src/ui/qt/style.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/ui/qt/style.cpp b/src/ui/qt/style.cpp index 04991063..5b3f1b74 100644 --- a/src/ui/qt/style.cpp +++ b/src/ui/qt/style.cpp @@ -116,7 +116,8 @@ std::vector