143 std::vector<SCH_PIN*> pins;
145 for(
SCH_ITEM& item : symbol->GetDrawItems() )
148 pins.push_back(
static_cast<SCH_PIN*
>( &item ) );
151 BOOST_REQUIRE_GE( pins.size(), 2 );
154 std::vector<TRANSFORM> rotations = {
159 std::vector<wxString> rotationNames = { wxT(
"0°" ), wxT(
"90°" ) };
161 for(
size_t r = 0; r < rotations.size(); r++ )
163 const TRANSFORM& transform = rotations[r];
164 const wxString& rotName = rotationNames[r];
180 std::vector<PinTextBoxes> pinBoxes;
185 boxes.pinNumber =
pin->GetNumber();
186 boxes.hasName =
false;
187 boxes.hasNumber =
false;
192 std::optional<PIN_LAYOUT_CACHE::TEXT_INFO> nameInfo = cache.
GetPinNameInfo( 0 );
194 if( nameInfo.has_value() && !nameInfo->m_Text.IsEmpty() )
197 boxes.hasName =
true;
201 std::optional<PIN_LAYOUT_CACHE::TEXT_INFO> numberInfo = cache.
GetPinNumberInfo( 0 );
203 if( numberInfo.has_value() && !numberInfo->m_Text.IsEmpty() )
206 boxes.hasNumber =
true;
209 pinBoxes.push_back( boxes );
213 for(
size_t i = 0; i < pinBoxes.size(); i++ )
215 for(
size_t j = i + 1; j < pinBoxes.size(); j++ )
217 const PinTextBoxes&
pinA = pinBoxes[i];
218 const PinTextBoxes& pinB = pinBoxes[j];
221 if(
pinA.hasName && pinB.hasName )
223 bool namesOverlap =
pinA.nameBBox.Intersects( pinB.nameBBox );
226 "At " << rotName <<
": Pin " <<
pinA.pinNumber <<
" name overlaps with pin "
227 << pinB.pinNumber <<
" name. "
228 <<
"BBoxA=(" <<
pinA.nameBBox.GetLeft() <<
","
229 <<
pinA.nameBBox.GetTop() <<
")-(" <<
pinA.nameBBox.GetRight()
230 <<
"," <<
pinA.nameBBox.GetBottom() <<
") "
231 <<
"BBoxB=(" << pinB.nameBBox.GetLeft() <<
","
232 << pinB.nameBBox.GetTop() <<
")-(" << pinB.nameBBox.GetRight()
233 <<
"," << pinB.nameBBox.GetBottom() <<
")" );
237 if(
pinA.hasNumber && pinB.hasNumber )
239 bool numbersOverlap =
pinA.numberBBox.Intersects( pinB.numberBBox );
242 "At " << rotName <<
": Pin " <<
pinA.pinNumber
243 <<
" number overlaps with pin " << pinB.pinNumber <<
" number. "
244 <<
"BBoxA=(" <<
pinA.numberBBox.GetLeft() <<
","
245 <<
pinA.numberBBox.GetTop() <<
")-("
246 <<
pinA.numberBBox.GetRight() <<
","
247 <<
pinA.numberBBox.GetBottom() <<
") "
248 <<
"BBoxB=(" << pinB.numberBBox.GetLeft() <<
","
249 << pinB.numberBBox.GetTop() <<
")-("
250 << pinB.numberBBox.GetRight() <<
","
251 << pinB.numberBBox.GetBottom() <<
")" );
255 if(
pinA.hasName && pinB.hasNumber )
257 bool overlap =
pinA.nameBBox.Intersects( pinB.numberBBox );
260 "At " << rotName <<
": Pin " <<
pinA.pinNumber
261 <<
" name overlaps with pin " << pinB.pinNumber <<
" number." );
264 if(
pinA.hasNumber && pinB.hasName )
266 bool overlap =
pinA.numberBBox.Intersects( pinB.nameBBox );
269 "At " << rotName <<
": Pin " <<
pinA.pinNumber
270 <<
" number overlaps with pin " << pinB.pinNumber <<
" name." );
296 for(
SCH_ITEM& item : symbol->GetDrawItems() )
300 testPin =
static_cast<SCH_PIN*
>( &item );
316 std::optional<PIN_LAYOUT_CACHE::TEXT_INFO> nameInfo0 = cache0.
GetPinNameInfo( 0 );
317 std::optional<PIN_LAYOUT_CACHE::TEXT_INFO> numberInfo0 = cache0.
GetPinNumberInfo( 0 );
319 int nameDistance0 = 0;
320 int numberDistance0 = 0;
322 if( nameInfo0.has_value() )
325 if( numberInfo0.has_value() )
332 std::optional<PIN_LAYOUT_CACHE::TEXT_INFO> nameInfo90 = cache90.
GetPinNameInfo( 0 );
333 std::optional<PIN_LAYOUT_CACHE::TEXT_INFO> numberInfo90 = cache90.
GetPinNumberInfo( 0 );
335 int nameDistance90 = 0;
336 int numberDistance90 = 0;
338 if( nameInfo90.has_value() )
341 if( numberInfo90.has_value() )
348 const int tolerance =
schIUScale.MilsToIU( 5 );
351 if( nameInfo0.has_value() && nameInfo90.has_value() )
353 int nameDiff =
std::abs( nameDistance0 - nameDistance90 );
355 nameDiff <= tolerance,
356 "Pin name perpendicular distance changed across rotation. "
357 <<
"At 0°: " << nameDistance0 <<
", at 90°: " << nameDistance90
358 <<
", difference: " << nameDiff <<
" (tolerance: " << tolerance <<
")" );
362 if( numberInfo0.has_value() && numberInfo90.has_value() )
364 int numberDiff =
std::abs( numberDistance0 - numberDistance90 );
366 numberDiff <= tolerance,
367 "Pin number perpendicular distance changed across rotation. "
368 <<
"At 0°: " << numberDistance0 <<
", at 90°: " << numberDistance90
369 <<
", difference: " << numberDiff <<
" (tolerance: " << tolerance <<
")" );
389 for(
SCH_ITEM& item : symbol->GetDrawItems() )
393 testPin =
static_cast<SCH_PIN*
>( &item );
401 std::vector<TRANSFORM> rotations = {
TRANSFORM( 1, 0, 0, 1 ),
TRANSFORM( 0, -1, 1, 0 ) };
402 std::vector<wxString> rotationNames = { wxT(
"0°" ), wxT(
"90°" ) };
404 for(
size_t r = 0; r < rotations.size(); r++ )
406 const TRANSFORM& transform = rotations[r];
407 const wxString& rotName = rotationNames[r];
413 std::optional<PIN_LAYOUT_CACHE::TEXT_INFO> nameInfo = cache.
GetPinNameInfo( 0 );
414 std::optional<PIN_LAYOUT_CACHE::TEXT_INFO> numberInfo = cache.
GetPinNumberInfo( 0 );
416 BOOST_REQUIRE_MESSAGE( nameInfo.has_value(),
"Pin should have name at " << rotName );
417 BOOST_REQUIRE_MESSAGE( numberInfo.has_value(),
"Pin should have number at " << rotName );
425 bool nameAbove = nameInfo->m_TextPosition.y < pinPos.
y;
426 bool numberAbove = numberInfo->m_TextPosition.y < pinPos.
y;
429 nameAbove != numberAbove,
430 "At " << rotName <<
" (horizontal pin): name and number should be on opposite "
431 <<
"Y sides of pin. Name Y=" << nameInfo->m_TextPosition.y
432 <<
", Number Y=" << numberInfo->m_TextPosition.y
433 <<
", Pin Y=" << pinPos.
y );
438 bool nameLeft = nameInfo->m_TextPosition.x < pinPos.
x;
439 bool numberLeft = numberInfo->m_TextPosition.x < pinPos.
x;
442 nameLeft != numberLeft,
443 "At " << rotName <<
" (vertical pin): name and number should be on opposite "
444 <<
"X sides of pin. Name X=" << nameInfo->m_TextPosition.x
445 <<
", Number X=" << numberInfo->m_TextPosition.x
446 <<
", 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°.