KiCad PCB EDA Suite
Loading...
Searching...
No Matches
test_odbpp_netlist.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 3
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/gpl-3.0.html
19 * or you may search the http://www.gnu.org website for the version 3 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
31
32#include <boost/test/unit_test.hpp>
33
34#include <board.h>
36#include <footprint.h>
37#include <pad.h>
38#include <pcb_track.h>
39#include <base_units.h>
40#include <core/utf8.h>
41
43
44#include <wx/dir.h>
45#include <wx/ffile.h>
46#include <wx/filename.h>
47#include <wx/regex.h>
48
49#include "odb_test_utils.h"
50
51
52namespace
53{
54
55wxString ReadFile( const wxFileName& aPath )
56{
57 wxFFile stream( aPath.GetFullPath(), wxT( "rb" ) );
58 wxString contents;
59 BOOST_REQUIRE( stream.ReadAll( &contents ) );
60 stream.Close();
61 return contents;
62}
63
64} // anonymous namespace
65
66
67BOOST_AUTO_TEST_CASE( ODBNetlistCoordinatesMatchFeatures )
68{
69 KI_TEST::SCOPED_TEMP_DIR tempDir( wxT( "odb-netlist" ) );
70
71 BOARD board;
72 board.SetCopperLayerCount( 2 );
73
74 // Set a non-zero aux origin to trigger the bug
75 VECTOR2I auxOrigin( pcbIUScale.mmToIU( 50.0 ), pcbIUScale.mmToIU( 30.0 ) );
76 board.GetDesignSettings().SetAuxOrigin( auxOrigin );
77
78 // Add a footprint with a pad at a known position
79 FOOTPRINT* fp = new FOOTPRINT( &board );
80 fp->SetPosition( VECTOR2I( pcbIUScale.mmToIU( 100.0 ), pcbIUScale.mmToIU( 80.0 ) ) );
81 fp->SetReference( wxT( "U1" ) );
82
83 PAD* pad = new PAD( fp );
84 pad->SetPadstackMode( PADSTACK::MODE::NORMAL );
85 pad->SetAttribute( PAD_ATTRIB::SMD );
87 pad->SetSize( PADSTACK::ALL_LAYERS, VECTOR2I( pcbIUScale.mmToIU( 1.0 ), pcbIUScale.mmToIU( 0.5 ) ) );
88 pad->SetPosition( VECTOR2I( pcbIUScale.mmToIU( 100.0 ), pcbIUScale.mmToIU( 80.0 ) ) );
89 pad->SetLayerSet( LSET( { F_Cu, F_Mask, F_Paste } ) );
90 pad->SetNumber( wxT( "1" ) );
91
92 NETINFO_ITEM* net1 = new NETINFO_ITEM( &board, wxT( "TestNet" ), 1 );
93 board.Add( net1 );
94 pad->SetNet( net1 );
95
96 fp->Add( pad );
97 board.Add( fp );
98
99 // Add a via at a known position
100 PCB_VIA* via = new PCB_VIA( &board );
101 via->SetPadstackMode( PADSTACK::MODE::NORMAL );
102 via->SetPosition( VECTOR2I( pcbIUScale.mmToIU( 120.0 ), pcbIUScale.mmToIU( 60.0 ) ) );
103 via->SetLayerPair( F_Cu, B_Cu );
104 via->SetDrill( pcbIUScale.mmToIU( 0.3 ) );
105 via->SetWidth( PADSTACK::ALL_LAYERS, pcbIUScale.mmToIU( 0.6 ) );
106 via->SetNet( net1 );
107 board.Add( via );
108
109 // Export ODB++
110 wxFileName odbRoot( tempDir.PathStr(), wxEmptyString );
111 odbRoot.AppendDir( wxT( "odb_out" ) );
112 BOOST_REQUIRE( odbRoot.Mkdir( wxS_DIR_DEFAULT, wxPATH_MKDIR_FULL ) );
113
114 PCB_IO_ODBPP odbExporter;
115 std::map<std::string, UTF8> props;
116 props["units"] = "mm";
117 props["sigfig"] = "6";
118 BOOST_REQUIRE_NO_THROW( odbExporter.SaveBoard( odbRoot.GetFullPath(), board, &props ) );
119
120 // Read the netlist file
121 wxFileName netlistFile( odbRoot.GetFullPath(), wxEmptyString );
122 netlistFile.AppendDir( wxT( "steps" ) );
123 netlistFile.AppendDir( wxT( "pcb" ) );
124 netlistFile.AppendDir( wxT( "netlists" ) );
125 netlistFile.AppendDir( wxT( "cadnet" ) );
126 netlistFile.SetFullName( wxT( "netlist" ) );
127 BOOST_REQUIRE( netlistFile.FileExists() );
128
129 wxString netlistContent = ReadFile( netlistFile );
130
131 // Read a features file that has the toeprint/component position to compare
132 wxFileName compFile( odbRoot.GetFullPath(), wxEmptyString );
133 compFile.AppendDir( wxT( "steps" ) );
134 compFile.AppendDir( wxT( "pcb" ) );
135 compFile.AppendDir( wxT( "layers" ) );
136 compFile.AppendDir( wxT( "comp_+_top" ) );
137 compFile.SetFullName( wxT( "components" ) );
138 BOOST_REQUIRE( compFile.FileExists() );
139
140 wxString compContent = ReadFile( compFile );
141
142 // The pad is at board position (100, 80) mm.
143 // ODB::AddXY applies m_scale and negates Y, giving (100.0, -80.0) in mm.
144 // The toeprint (TOP record) should have x=100.0, y=-80.0 if in mm.
145 // The netlist net-point should have the same coordinates.
146
147 // Verify the toeprint has the pad position (component file uses ODB::AddXY)
148 BOOST_CHECK_MESSAGE( compContent.Contains( wxT( "100" ) ),
149 "Component file should contain the pad X coordinate" );
150
151 // The critical check: the netlist should NOT be offset by the aux origin.
152 // With the bug, x would be (100 - 50) = 50 and y would be (30 - 80) = -50 in mm.
153 // With the fix, x should be 100 and y should be -80 in mm.
154 // We look for "100" and "-80" appearing in the netlist net-point data.
155 BOOST_CHECK_MESSAGE( !netlistContent.Contains( wxT( "50.0" ) ),
156 "Netlist should not contain aux-origin-shifted X coordinate 50.0" );
157 BOOST_CHECK_MESSAGE( netlistContent.Contains( wxT( "100.0" ) ),
158 "Netlist should contain the raw pad X coordinate 100.0" );
159}
constexpr EDA_IU_SCALE pcbIUScale
Definition base_units.h:128
void SetAuxOrigin(const VECTOR2I &aOrigin)
Information pertinent to a Pcbnew printed circuit board.
Definition board.h:411
void Add(BOARD_ITEM *aItem, ADD_MODE aMode=ADD_MODE::INSERT, bool aSkipConnectivity=false) override
Removes an item from the container.
Definition board.cpp:1520
void SetCopperLayerCount(int aCount)
Definition board.cpp:1133
BOARD_DESIGN_SETTINGS & GetDesignSettings()
Definition board.cpp:1290
void SetPosition(const VECTOR2I &aPos) override
void SetReference(const wxString &aReference)
Definition footprint.h:799
void Add(BOARD_ITEM *aItem, ADD_MODE aMode=ADD_MODE::INSERT, bool aSkipConnectivity=false) override
Adds an item to the container.
wxString PathStr() const
Get the path to the temporary directory as a wxString.
Definition file_utils.h:64
LSET is a set of PCB_LAYER_IDs.
Definition lset.h:37
Handle the data for a net.
Definition netinfo.h:50
@ NORMAL
Shape is the same on all layers.
Definition padstack.h:170
static constexpr PCB_LAYER_ID ALL_LAYERS
! The layer identifier to use for the single defintion on normal padstacks
Definition padstack.h:179
Definition pad.h:61
void SaveBoard(const wxString &aFileName, BOARD &aBoard, const std::map< std::string, UTF8 > *aProperties=nullptr) override
Write aBoard to a storage file in a format that this PCB_IO implementation knows about or it can be u...
@ F_Paste
Definition layer_ids.h:100
@ B_Cu
Definition layer_ids.h:61
@ F_Mask
Definition layer_ids.h:93
@ F_Cu
Definition layer_ids.h:60
@ SMD
Smd pad, appears on the solder paste layer (default)
Definition padstack.h:98
@ RECTANGLE
Definition padstack.h:53
BOOST_REQUIRE(intersection.has_value()==c.ExpectedIntersection.has_value())
BOOST_AUTO_TEST_CASE(ODBNetlistCoordinatesMatchFeatures)
VECTOR2< int32_t > VECTOR2I
Definition vector2d.h:708