39#include <boost/test/unit_test.hpp>
61std::map<int, std::vector<VECTOR2D>> ReadBoardOutlineLoops(
const std::filesystem::path& aEmnPath )
63 std::ifstream in( aEmnPath );
64 BOOST_REQUIRE_MESSAGE( in,
"Cannot open exported .emn: " << aEmnPath.string() );
66 std::map<int, std::vector<VECTOR2D>> loops;
68 bool inSection =
false;
70 while( std::getline( in, line ) )
72 if( line.find(
".BOARD_OUTLINE" ) != std::string::npos )
78 if( line.find(
".END_BOARD_OUTLINE" ) != std::string::npos )
84 std::istringstream ss( line );
85 std::vector<std::string> tokens;
87 for( std::string tok; ss >> tok; )
88 tokens.push_back( tok );
92 if( tokens.size() < 4 )
95 const std::string& first = tokens.front();
96 const bool isLoopIndex =
97 std::all_of( first.begin(), first.end(), [](
unsigned char c ) { return std::isdigit( c ); } );
101 loops[std::stoi( first )].emplace_back( std::stod( tokens[1] ),
102 std::stod( tokens[2] ) );
113void CheckLoopContainsPoints(
const std::vector<VECTOR2D>& aLoopPoints,
114 const std::vector<VECTOR2I>& aExpectedIU )
121 const bool found = std::any_of( aLoopPoints.begin(), aLoopPoints.end(),
124 return std::abs( pt.x - expX ) < 1e-3
125 && std::abs( pt.y - expY ) < 1e-3;
128 BOOST_CHECK_MESSAGE( found,
"Cutout corner (" << expX <<
", " << expY
129 <<
") missing from exported loop" );
145 cutout =
static_cast<PCB_SHAPE*
>( item );
161 BOOST_REQUIRE_MESSAGE( std::filesystem::exists( sourceBoard ),
"Missing test board " << sourceBoard );
167 const std::filesystem::path emnPath = outDir.
Path() /
"cutout.emn";
176 const bool ok = exporter.
Export( wxString::FromUTF8( emnPath.string().c_str() ) );
178 BOOST_REQUIRE_MESSAGE( ok,
"IDF export failed: " <<
reporter.GetMessages() );
181 const std::map<int, std::vector<VECTOR2D>> loops = ReadBoardOutlineLoops( emnPath );
184 BOOST_CHECK_MESSAGE( loops.count( 0 ) == 1,
"Board outline (loop 0) missing from .emn" );
185 BOOST_REQUIRE_MESSAGE( loops.count( 1 ) == 1,
"Footprint cutout (loop 1) missing from .emn" );
189 PCB_SHAPE* cutout = GetCutoutShape( board->Footprints().front() );
195 CheckLoopContainsPoints( loops.at( 1 ),
196 { start, VECTOR2I( end.x, start.y ), end,
197 VECTOR2I( start.x, end.y ) } );
206 BOOST_REQUIRE_MESSAGE( std::filesystem::exists( sourceBoard ),
"Missing test board " << sourceBoard );
211 FOOTPRINT* footprint = board->Footprints().front();
216 const std::filesystem::path emnPath = outDir.
Path() /
"poly_cutout.emn";
225 const bool ok = exporter.
Export( wxString::FromUTF8( emnPath.string().c_str() ) );
227 BOOST_REQUIRE_MESSAGE( ok,
"IDF export failed: " <<
reporter.GetMessages() );
230 const std::map<int, std::vector<VECTOR2D>> loops = ReadBoardOutlineLoops( emnPath );
232 BOOST_CHECK_MESSAGE( loops.count( 0 ) == 1,
"Board outline (loop 0) missing from .emn" );
233 BOOST_REQUIRE_MESSAGE( loops.count( 1 ) == 1,
234 "Rotated polygon cutout (loop 1) missing from .emn" );
237 PCB_SHAPE* cutout = GetCutoutShape( footprint );
240 std::vector<VECTOR2I> corners;
243 for(
int ii = 0; ii <
chain.PointCount(); ++ii )
244 corners.push_back(
chain.CPoint( ii ) );
246 CheckLoopContainsPoints( loops.at( 1 ), corners );
constexpr EDA_IU_SCALE pcbIUScale
General utilities for PCB file IO for QA programs.
A base class for any item which can be embedded within the BOARD container class, and therefore insta...
SHAPE_POLY_SET & GetPolyShape()
const VECTOR2I & GetEnd() const
Return the ending point of the graphic.
const VECTOR2I & GetStart() const
Return the starting point of the graphic.
Provide an extensible class to resolve 3D model paths.
bool Export(const wxString &aFullFileName) const
Generate IDFv3 compliant board (*.emn) and library (*.emp) files for aPcb.
IDF_SETTINGS::COORD_ORIGIN m_originMode
const std::filesystem::path & Path() const
Get the path to the temporary directory as a std::filesystem::path.
Represent a polyline containing arcs as well as line segments: A chain of connected line and/or arc s...
const SHAPE_LINE_CHAIN & COutline(int aIndex) const
A wrapper for reporting to a wxString object.
@ RECTANGLE
Use RECTANGLE instead of RECT to avoid collision in a Windows header.
std::string GetPcbnewTestDataDir()
Utility which returns a path to the data directory where the test board files are stored.
std::unique_ptr< BOARD > RequireBoardFromPcbnewQAData(const std::filesystem::path &aFilename)
Require a board from the path relative to the pcbnew QA data directory.
BOOST_AUTO_TEST_CASE(HorizontalAlignment)
BOOST_AUTO_TEST_SUITE(CadstarPartParser)
BOOST_REQUIRE(intersection.has_value()==c.ExpectedIntersection.has_value())
BOOST_AUTO_TEST_SUITE_END()
BOOST_AUTO_TEST_CASE(FootprintCutoutIsExported)
IbisParser parser & reporter
VECTOR3I expected(15, 30, 45)
const SHAPE_LINE_CHAIN chain
@ PCB_SHAPE_T
class PCB_SHAPE, a segment not on copper layers
VECTOR2< int32_t > VECTOR2I
VECTOR2< double > VECTOR2D