KiCad PCB EDA Suite
Loading...
Searching...
No Matches
footprint_utils.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 modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation, either version 3 of the License, or (at your
9 * option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License along
17 * with this program. If not, see <http://www.gnu.org/licenses/>.
18 */
19
20#include "footprint_utils.h"
21
22#include <trigo.h>
23
24#include <footprint.h>
25#include <item_realignment.h>
26#include <pad.h>
27
28
29bool ComputeFootprintShift( const FOOTPRINT& aExisting, const FOOTPRINT& aNew, VECTOR2I& aShift,
30 EDA_ANGLE& aAngleShift )
31{
32 // First, we will collect a list of "useful" corresponding points in the two footprints.
33 // To be useful, a point from a pad must have a unique pad number, as in the general case, we
34 // won't know which of multiple same-named pads in one footprint correspond to which in the
35 // other.
36 //
37 // Theoretically, we could use graphics items and other hints like pad shape matching
38 // but these would be hard to unambiguously match in the general case and pad numbers should
39 // cover 99% of cases.
40
41 const auto getUniquelyNumberedPads = []( const FOOTPRINT& fp ) -> std::unordered_map<wxString, VECTOR2I>
42 {
43 std::unordered_map<wxString, VECTOR2I> result;
44 std::unordered_set<wxString> seenDuplicate;
45
46 for( PAD* pad : fp.Pads() )
47 {
48 const wxString& number = pad->GetNumber();
49
50 // Already seen a pad with this number, so not unique
51 // (and it won't be found in result)
52 if( seenDuplicate.find( number ) != seenDuplicate.end() )
53 continue;
54
55 // Already have a pad with this number, so not unique.
56 // Remove the previous entry from the result and mark this number as seen.
57 if( result.find( number ) != result.end() )
58 {
59 result.erase( number );
60 seenDuplicate.insert( number );
61 continue;
62 }
63
64 result[number] = pad->GetFPRelativePosition();
65 }
66
67 return result;
68 };
69
70 std::unordered_map<wxString, VECTOR2I> existingPads = getUniquelyNumberedPads( aExisting );
71 std::unordered_map<wxString, VECTOR2I> newPads = getUniquelyNumberedPads( aNew );
72
73 std::vector<VECTOR2I> existingPoints;
74 std::vector<VECTOR2I> newPoints;
75
76 // The matching points are the ones with the same unique pad number in both footprints
77 // If a pad is missing in the new footprint, it won't be included.
78 for( const auto& [number, pos] : existingPads )
79 {
80 auto it = newPads.find( number );
81
82 if( it == newPads.end() )
83 continue;
84
85 existingPoints.push_back( pos );
86 newPoints.push_back( it->second );
87 }
88
90
91 std::optional<ITEM_REALIGNER_BASE::TRANSFORM> transform =
92 aligner.GetTransform( existingPoints, newPoints );
93
94 if( !transform.has_value() )
95 {
96 // Failed to compute a transform - perhaps there were no useful pads
97 aShift = VECTOR2I( 0, 0 );
98 aAngleShift = ANGLE_0;
99 return false;
100 }
101
102 aShift = GetRotated( transform->m_Translation, aExisting.GetOrientation() );
103 aAngleShift = transform->m_Rotation;
104
105 return true;
106}
EDA_ANGLE GetOrientation() const
Definition footprint.h:350
This is a relatively straight-forward implementation of the ITEM_REALIGNER_BASE that should handle mo...
std::optional< TRANSFORM > GetTransform(const std::vector< VECTOR2I > &aPtsA, const std::vector< VECTOR2I > &aPtsB) const override
Compute the best fit transform to align the two sets of points.
Definition pad.h:55
static constexpr EDA_ANGLE ANGLE_0
Definition eda_angle.h:411
bool ComputeFootprintShift(const FOOTPRINT &aExisting, const FOOTPRINT &aNew, VECTOR2I &aShift, EDA_ANGLE &aAngleShift)
Compute position and angle shift between two footprints.
Collection of reusable/testable functions for footprint manipulation.
wxString result
Test unit parsing edge cases and error handling.
VECTOR2I GetRotated(const VECTOR2I &aVector, const EDA_ANGLE &aAngle)
Return a new VECTOR2I that is the result of rotating aVector by aAngle.
Definition trigo.h:77
VECTOR2< int32_t > VECTOR2I
Definition vector2d.h:687