147 std::vector<SCH_PIN*> pins;
149 for(
SCH_ITEM& item : symbol->GetDrawItems() )
152 pins.push_back(
static_cast<SCH_PIN*
>( &item ) );
155 BOOST_REQUIRE_GE( pins.size(), 2 );
158 std::vector<TRANSFORM> rotations = {
163 std::vector<wxString> rotationNames = { wxT(
"0°" ), wxT(
"90°" ) };
165 for(
size_t r = 0; r < rotations.size(); r++ )
167 const TRANSFORM& transform = rotations[r];
168 const wxString& rotName = rotationNames[r];
184 std::vector<PinTextBoxes> pinBoxes;
189 boxes.pinNumber =
pin->GetNumber();
190 boxes.hasName =
false;
191 boxes.hasNumber =
false;
196 std::optional<PIN_LAYOUT_CACHE::TEXT_INFO> nameInfo = cache.
GetPinNameInfo( 0 );
198 if( nameInfo.has_value() && !nameInfo->m_Text.IsEmpty() )
201 boxes.hasName =
true;
205 std::optional<PIN_LAYOUT_CACHE::TEXT_INFO> numberInfo = cache.
GetPinNumberInfo( 0 );
207 if( numberInfo.has_value() && !numberInfo->m_Text.IsEmpty() )
210 boxes.hasNumber =
true;
213 pinBoxes.push_back( boxes );
217 for(
size_t i = 0; i < pinBoxes.size(); i++ )
219 for(
size_t j = i + 1; j < pinBoxes.size(); j++ )
221 const PinTextBoxes& pinA = pinBoxes[i];
222 const PinTextBoxes& pinB = pinBoxes[j];
225 if( pinA.hasName && pinB.hasName )
227 bool namesOverlap = pinA.nameBBox.Intersects( pinB.nameBBox );
230 "At " << rotName <<
": Pin " << pinA.pinNumber <<
" name overlaps with pin "
231 << pinB.pinNumber <<
" name. "
232 <<
"BBoxA=(" << pinA.nameBBox.GetLeft() <<
","
233 << pinA.nameBBox.GetTop() <<
")-(" << pinA.nameBBox.GetRight()
234 <<
"," << pinA.nameBBox.GetBottom() <<
") "
235 <<
"BBoxB=(" << pinB.nameBBox.GetLeft() <<
","
236 << pinB.nameBBox.GetTop() <<
")-(" << pinB.nameBBox.GetRight()
237 <<
"," << pinB.nameBBox.GetBottom() <<
")" );
241 if( pinA.hasNumber && pinB.hasNumber )
243 bool numbersOverlap = pinA.numberBBox.Intersects( pinB.numberBBox );
246 "At " << rotName <<
": Pin " << pinA.pinNumber
247 <<
" number overlaps with pin " << pinB.pinNumber <<
" number. "
248 <<
"BBoxA=(" << pinA.numberBBox.GetLeft() <<
","
249 << pinA.numberBBox.GetTop() <<
")-("
250 << pinA.numberBBox.GetRight() <<
","
251 << pinA.numberBBox.GetBottom() <<
") "
252 <<
"BBoxB=(" << pinB.numberBBox.GetLeft() <<
","
253 << pinB.numberBBox.GetTop() <<
")-("
254 << pinB.numberBBox.GetRight() <<
","
255 << pinB.numberBBox.GetBottom() <<
")" );
259 if( pinA.hasName && pinB.hasNumber )
261 bool overlap = pinA.nameBBox.Intersects( pinB.numberBBox );
264 "At " << rotName <<
": Pin " << pinA.pinNumber
265 <<
" name overlaps with pin " << pinB.pinNumber <<
" number." );
268 if( pinA.hasNumber && pinB.hasName )
270 bool overlap = pinA.numberBBox.Intersects( pinB.nameBBox );
273 "At " << rotName <<
": Pin " << pinA.pinNumber
274 <<
" number overlaps with pin " << pinB.pinNumber <<
" name." );
300 for(
SCH_ITEM& item : symbol->GetDrawItems() )
304 testPin =
static_cast<SCH_PIN*
>( &item );
320 std::optional<PIN_LAYOUT_CACHE::TEXT_INFO> nameInfo0 = cache0.
GetPinNameInfo( 0 );
321 std::optional<PIN_LAYOUT_CACHE::TEXT_INFO> numberInfo0 = cache0.
GetPinNumberInfo( 0 );
323 int nameDistance0 = 0;
324 int numberDistance0 = 0;
326 if( nameInfo0.has_value() )
329 if( numberInfo0.has_value() )
336 std::optional<PIN_LAYOUT_CACHE::TEXT_INFO> nameInfo90 = cache90.
GetPinNameInfo( 0 );
337 std::optional<PIN_LAYOUT_CACHE::TEXT_INFO> numberInfo90 = cache90.
GetPinNumberInfo( 0 );
339 int nameDistance90 = 0;
340 int numberDistance90 = 0;
342 if( nameInfo90.has_value() )
345 if( numberInfo90.has_value() )
352 const int tolerance =
schIUScale.MilsToIU( 5 );
355 if( nameInfo0.has_value() && nameInfo90.has_value() )
357 int nameDiff =
std::abs( nameDistance0 - nameDistance90 );
359 nameDiff <= tolerance,
360 "Pin name perpendicular distance changed across rotation. "
361 <<
"At 0°: " << nameDistance0 <<
", at 90°: " << nameDistance90
362 <<
", difference: " << nameDiff <<
" (tolerance: " << tolerance <<
")" );
366 if( numberInfo0.has_value() && numberInfo90.has_value() )
368 int numberDiff =
std::abs( numberDistance0 - numberDistance90 );
370 numberDiff <= tolerance,
371 "Pin number perpendicular distance changed across rotation. "
372 <<
"At 0°: " << numberDistance0 <<
", at 90°: " << numberDistance90
373 <<
", difference: " << numberDiff <<
" (tolerance: " << tolerance <<
")" );
393 for(
SCH_ITEM& item : symbol->GetDrawItems() )
397 testPin =
static_cast<SCH_PIN*
>( &item );
405 std::vector<TRANSFORM> rotations = {
TRANSFORM( 1, 0, 0, 1 ),
TRANSFORM( 0, -1, 1, 0 ) };
406 std::vector<wxString> rotationNames = { wxT(
"0°" ), wxT(
"90°" ) };
408 for(
size_t r = 0; r < rotations.size(); r++ )
410 const TRANSFORM& transform = rotations[r];
411 const wxString& rotName = rotationNames[r];
417 std::optional<PIN_LAYOUT_CACHE::TEXT_INFO> nameInfo = cache.
GetPinNameInfo( 0 );
418 std::optional<PIN_LAYOUT_CACHE::TEXT_INFO> numberInfo = cache.
GetPinNumberInfo( 0 );
420 BOOST_REQUIRE_MESSAGE( nameInfo.has_value(),
"Pin should have name at " << rotName );
421 BOOST_REQUIRE_MESSAGE( numberInfo.has_value(),
"Pin should have number at " << rotName );
429 bool nameAbove = nameInfo->m_TextPosition.y < pinPos.
y;
430 bool numberAbove = numberInfo->m_TextPosition.y < pinPos.
y;
433 nameAbove != numberAbove,
434 "At " << rotName <<
" (horizontal pin): name and number should be on opposite "
435 <<
"Y sides of pin. Name Y=" << nameInfo->m_TextPosition.y
436 <<
", Number Y=" << numberInfo->m_TextPosition.y
437 <<
", Pin Y=" << pinPos.
y );
442 bool nameLeft = nameInfo->m_TextPosition.x < pinPos.
x;
443 bool numberLeft = numberInfo->m_TextPosition.x < pinPos.
x;
446 nameLeft != numberLeft,
447 "At " << rotName <<
" (vertical pin): name and number should be on opposite "
448 <<
"X sides of pin. Name X=" << nameInfo->m_TextPosition.x
449 <<
", Number X=" << numberInfo->m_TextPosition.x
450 <<
", Pin X=" << pinPos.
x );
PIN_ORIENTATION PinDrawOrient(const TRANSFORM &aTransform) const
Return the pin real orientation (PIN_UP, PIN_DOWN, PIN_RIGHT, PIN_LEFT), according to its orientation...
static BOX2I getTextBoundingBox(const PIN_LAYOUT_CACHE::TEXT_INFO &textInfo)
Get the bounding box of pin text (name or number) for a given pin.
static std::unique_ptr< LIB_SYMBOL > createAdjacentPinsSymbol()
Create a test symbol with adjacent pins for testing overlap.
static int getPerpendicularDistance(const SCH_PIN *pin, const VECTOR2I &textPos, const TRANSFORM &transform)
Calculate perpendicular distance from pin line to text center.
BOOST_AUTO_TEST_CASE(AdjacentPinTextNoOverlap)
Test that pin names and numbers don't overlap with adjacent pins at 0° and 90°.