KiCad PCB EDA Suite
Loading...
Searching...
No Matches
test_step_model_color_transfer.cpp
Go to the documentation of this file.
1/*
2 * This program source code file is part of KiCad, a free EDA CAD application.
3 *
4 * Copyright The KiCad Developers, see AUTHORS.txt for contributors.
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 2
9 * of the License, or (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, you may find one here:
18 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
19 * or you may search the http://www.gnu.org website for the version 2 license,
20 * or you may write to the Free Software Foundation, Inc.,
21 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
22 */
23
24/*
25 * Regression test for https://gitlab.com/kicad/code/kicad/-/issues/24026
26 *
27 * Some default KiCad STEP models (e.g. SOT-89-3, TO-252-2, TO-263-2, TO-263-5_TabPin6)
28 * lost their colors when exported to STEP or 3D PDF because the XDE label tree was
29 * transferred via TDocStd_XLinkTool::Copy, which only copies a single label closure.
30 * These models store their colored "_part" labels as siblings of the assembly root
31 * (under the "Shapes" folder) rather than as descendants, so the closure did not
32 * include them and the downstream color-transfer pass found no matching shape.
33 *
34 * The fix routes transferModel() through XCAFDoc_Editor::Extract(), which rebuilds
35 * the XDE label tree by walking the component reference graph and automatically
36 * clones color/name metadata along with the shapes.
37 */
38
39#include <filesystem>
40#include <fstream>
41#include <sstream>
42
44#include <boost/test/unit_test.hpp>
45
47#include <reporter.h>
50#include <layer_ids.h>
51#include <footprint.h>
52
54
55#include <wx/filename.h>
56
57
58namespace
59{
60
61// Count occurrences of a substring in a text file. Used to verify that colors
62// survived the round trip into the exported STEP file.
63static int countEntities( const std::filesystem::path& aFile, const std::string& aToken )
64{
65 std::ifstream in( aFile );
66 BOOST_REQUIRE_MESSAGE( in.good(), "Cannot open exported STEP file for inspection" );
67
68 std::stringstream buf;
69 buf << in.rdbuf();
70 const std::string contents = buf.str();
71
72 int count = 0;
73 size_t pos = 0;
74
75 while( ( pos = contents.find( aToken, pos ) ) != std::string::npos )
76 {
77 ++count;
78 pos += aToken.size();
79 }
80
81 return count;
82}
83
84} // namespace
85
86
87BOOST_AUTO_TEST_SUITE( StepModelColorTransfer )
88
89
90
98BOOST_AUTO_TEST_CASE( TO252_2_ColorsPreserved )
99{
100 const std::filesystem::path sourceModel =
101 std::filesystem::path( KI_TEST::GetPcbnewTestDataDir() )
102 / "step_model_colors" / "TO-252-2.step";
103
104 BOOST_REQUIRE_MESSAGE( std::filesystem::exists( sourceModel ),
105 "Missing test model " << sourceModel.string() );
106
107 const std::filesystem::path outputFile =
108 std::filesystem::temp_directory_path() / "kicad_step_model_color_test.step";
109
110 if( std::filesystem::exists( outputFile ) )
111 std::filesystem::remove( outputFile );
112
113 NULL_REPORTER reporter;
114
115 STEP_PCB_MODEL model( wxT( "test" ), &reporter );
116 model.SpecializeVariant( OUTPUT_FORMAT::FMT_OUT_STEP );
117 model.SetCopperColor( 0.75, 0.61, 0.23 );
118 model.SetPadColor( 0.9, 0.9, 0.9 );
119
120 // Emit a trivial board outline so CreatePCB has something to extrude.
121 SHAPE_POLY_SET outline;
122 outline.NewOutline();
123 outline.Append( VECTOR2I( 0, 0 ) );
124 outline.Append( VECTOR2I( 10'000'000, 0 ) );
125 outline.Append( VECTOR2I( 10'000'000, 10'000'000 ) );
126 outline.Append( VECTOR2I( 0, 10'000'000 ) );
127
128 BOOST_REQUIRE( model.CreatePCB( outline, VECTOR2D( 0, 0 ), true ) );
129
130 const wxString modelPath = wxString::FromUTF8( sourceModel.string().c_str() );
131
132 const bool added = model.AddComponent( wxT( "TO-252-2" ), modelPath, {}, wxT( "U1" ), false,
133 VECTOR2D( 5.0, 5.0 ), 0.0, VECTOR3D( 0.0, 0.0, 0.0 ),
134 VECTOR3D( 0.0, 0.0, 0.0 ), VECTOR3D( 1.0, 1.0, 1.0 ),
135 false );
136
137 BOOST_REQUIRE_MESSAGE( added, "AddComponent failed for TO-252-2.step" );
138
139 const wxString outputPath = wxString::FromUTF8( outputFile.string().c_str() );
140
141 BOOST_REQUIRE_MESSAGE( model.WriteSTEP( outputPath, false, false ),
142 "WriteSTEP returned failure" );
143
144 BOOST_REQUIRE( std::filesystem::exists( outputFile ) );
145
146 const int styled = countEntities( outputFile, "STYLED_ITEM" );
147 const int colors = countEntities( outputFile, "COLOUR_RGB" );
148
149 BOOST_TEST_MESSAGE( "Exported STEP: " << styled << " STYLED_ITEM, " << colors
150 << " COLOUR_RGB entities" );
151
152 // The component model carries two distinct colors; the board body adds more. A healthy
153 // export must retain at least the component's colors (> 2 COLOUR_RGB); without the fix
154 // the component contribution is zero so COLOUR_RGB drops to whatever the board body emits.
156 styled > 0,
157 "Exported STEP has no STYLED_ITEM entities; component colors were dropped" );
159 colors > 2,
160 "Expected > 2 COLOUR_RGB entities (component + board); got " << colors
161 << ". Component model colors were not transferred." );
162
163 // Keep the file around for inspection when the test fails.
164 if( styled > 0 && colors > 2 && std::filesystem::exists( outputFile ) )
165 std::filesystem::remove( outputFile );
166}
167
168
General utilities for PCB file IO for QA programs.
A singleton reporter that reports to nowhere.
Definition reporter.h:218
Represent a set of closed polygons.
int Append(int x, int y, int aOutline=-1, int aHole=-1, bool aAllowDuplication=false)
Appends a vertex at the end of the given outline/hole (default: the last outline)
int NewOutline()
Creates a new empty polygon in the set and returns its index.
std::string GetPcbnewTestDataDir()
Utility which returns a path to the data directory where the test board files are stored.
BOOST_AUTO_TEST_CASE(HorizontalAlignment)
BOOST_AUTO_TEST_SUITE(CadstarPartParser)
BOOST_REQUIRE(intersection.has_value()==c.ExpectedIntersection.has_value())
BOOST_AUTO_TEST_SUITE_END()
KIBIS_MODEL * model
BOOST_CHECK_MESSAGE(totalMismatches==0, std::to_string(totalMismatches)+" board(s) with strategy disagreements")
BOOST_TEST_MESSAGE("\n=== Real-World Polygon PIP Benchmark ===\n"<< formatTable(table))
VECTOR2< int32_t > VECTOR2I
Definition vector2d.h:687
VECTOR2< double > VECTOR2D
Definition vector2d.h:686
VECTOR3< double > VECTOR3D
Definition vector3.h:230