-
-
Notifications
You must be signed in to change notification settings - Fork 620
Expand file tree
/
Copy pathfootprint_utils.cpp
More file actions
106 lines (85 loc) · 3.71 KB
/
footprint_utils.cpp
File metadata and controls
106 lines (85 loc) · 3.71 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright The KiCad Developers, see AUTHORS.txt for contributors.
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation, either version 3 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "footprint_utils.h"
#include <trigo.h>
#include <footprint.h>
#include <item_realignment.h>
#include <pad.h>
bool ComputeFootprintShift( const FOOTPRINT& aExisting, const FOOTPRINT& aNew, VECTOR2I& aShift,
EDA_ANGLE& aAngleShift )
{
// First, we will collect a list of "useful" corresponding points in the two footprints.
// To be useful, a point from a pad must have a unique pad number, as in the general case, we
// won't know which of multiple same-named pads in one footprint correspond to which in the
// other.
//
// Theoretically, we could use graphics items and other hints like pad shape matching
// but these would be hard to unambiguously match in the general case and pad numbers should
// cover 99% of cases.
const auto getUniquelyNumberedPads = []( const FOOTPRINT& fp ) -> std::unordered_map<wxString, VECTOR2I>
{
std::unordered_map<wxString, VECTOR2I> result;
std::unordered_set<wxString> seenDuplicate;
for( PAD* pad : fp.Pads() )
{
const wxString& number = pad->GetNumber();
// Already seen a pad with this number, so not unique
// (and it won't be found in result)
if( seenDuplicate.find( number ) != seenDuplicate.end() )
continue;
// Already have a pad with this number, so not unique.
// Remove the previous entry from the result and mark this number as seen.
if( result.find( number ) != result.end() )
{
result.erase( number );
seenDuplicate.insert( number );
continue;
}
result[number] = pad->GetFPRelativePosition();
}
return result;
};
std::unordered_map<wxString, VECTOR2I> existingPads = getUniquelyNumberedPads( aExisting );
std::unordered_map<wxString, VECTOR2I> newPads = getUniquelyNumberedPads( aNew );
std::vector<VECTOR2I> existingPoints;
std::vector<VECTOR2I> newPoints;
// The matching points are the ones with the same unique pad number in both footprints
// If a pad is missing in the new footprint, it won't be included.
for( const auto& [number, pos] : existingPads )
{
auto it = newPads.find( number );
if( it == newPads.end() )
continue;
existingPoints.push_back( pos );
newPoints.push_back( it->second );
}
ORTHO_ITEM_REALIGNER aligner;
std::optional<ITEM_REALIGNER_BASE::TRANSFORM> transform =
aligner.GetTransform( existingPoints, newPoints );
if( !transform.has_value() )
{
// Failed to compute a transform - perhaps there were no useful pads
aShift = VECTOR2I( 0, 0 );
aAngleShift = ANGLE_0;
return false;
}
aShift = GetRotated( transform->m_Translation, aExisting.GetOrientation() );
aAngleShift = transform->m_Rotation;
return true;
}