KiCad PCB EDA Suite
Loading...
Searching...
No Matches
pcb_barcode.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 (C) 2020 Thomas Pointhuber <[email protected]>
5 * Copyright (C) 2020 KiCad Developers, see AUTHORS.txt for contributors.
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2
10 * of the License, or (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program. If not, see <https://www.gnu.org/licenses/>.
19 */
20
21#include <core/type_helpers.h>
22#include <bitmaps.h>
23#include <gr_basic.h>
24#include <macros.h>
25#include <pcb_edit_frame.h>
26#include <richio.h>
27#include <trigo.h>
28
29#include <base_units.h>
30#include <api/api_enums.h>
31#include <api/board/board_types.pb.h>
32#include <pcb_barcode.h>
33#include <board.h>
34#include <footprint.h>
36#include <pcb_text.h>
37#include <view/view.h>
38#include <math/util.h> // for KiROUND
40#include <wx/log.h>
41#include <pgm_base.h>
44#include <scoped_set_reset.h>
45#include <stdexcept>
46#include <utility>
47#include <algorithm>
48#include <api/api_utils.h>
49#include <footprint.h>
50
51#include <backend/zint.h>
53#include <hash.h>
54#include <google/protobuf/any.pb.h>
55#include <properties/property.h>
57
58constexpr int ECI_UTF8 = 26;
59
61 BOARD_ITEM( aParent, PCB_BARCODE_T ),
62 m_width( pcbIUScale.mmToIU( 40 ) ),
63 m_height( pcbIUScale.mmToIU( 40 ) ),
64 m_libPos( 0, 0 ),
65 m_text( this ),
67 m_libAngle( 0 ),
69{
71}
72
73
77
78
80 BOARD_ITEM( aOther ),
81 m_width( aOther.m_width ),
82 m_height( aOther.m_height ),
83 m_libPos( aOther.m_libPos ),
84 m_margin( aOther.m_margin ),
85 m_text( aOther.m_text ),
86 m_kind( aOther.m_kind ),
87 m_libAngle( aOther.m_libAngle ),
89{
90 m_text.SetParent( this );
91}
92
93
95{
96 if( this != &aOther )
97 {
98 BOARD_ITEM::operator=( aOther );
99
100 m_width = aOther.m_width;
101 m_height = aOther.m_height;
102 m_libPos = aOther.m_libPos;
103 m_margin = aOther.m_margin;
104 m_text = aOther.m_text;
105 m_kind = aOther.m_kind;
106 m_libAngle = aOther.m_libAngle;
108
109 m_cache.reset();
110
111 m_text.SetParent( this );
112 }
113
114 return *this;
115}
116
117
119{
120 VECTOR2I delta = aPos - GetPosition();
121 Move( delta );
122}
123
124
126{
127 if( const FOOTPRINT* fp = GetParentFootprint() )
128 return fp->GetTransform().Apply( m_libPos );
129
130 return m_libPos;
131}
132
133
135{
136 if( const FOOTPRINT* fp = GetParentFootprint() )
137 return ( m_libAngle + fp->GetOrientation() ).Normalize();
138
139 return m_libAngle;
140}
141
142
143void PCB_BARCODE::SetText( const wxString& aNewText )
144{
145 m_text.SetText( aNewText );
146}
147
148
149wxString PCB_BARCODE::GetText() const
150{
151 return m_text.GetText();
152}
153
154
156{
157 return m_text.GetShownText( true );
158}
159
160
161void PCB_BARCODE::Serialize( google::protobuf::Any& aContainer ) const
162{
163 using namespace kiapi::board::types;
164
165 Barcode barcode;
166
167 barcode.mutable_id()->set_value( m_Uuid.AsStdString() );
168 barcode.set_text( GetText().ToUTF8() );
169
170 switch( m_kind )
171 {
172 case BARCODE_T::CODE_39: barcode.set_kind( BK_CODE_39 ); break;
173 case BARCODE_T::CODE_128: barcode.set_kind( BK_CODE_128 ); break;
174 case BARCODE_T::DATA_MATRIX: barcode.set_kind( BK_DATA_MATRIX ); break;
175 case BARCODE_T::QR_CODE: barcode.set_kind( BK_QR_CODE ); break;
176 case BARCODE_T::MICRO_QR_CODE: barcode.set_kind( BK_MICRO_QR_CODE ); break;
177 }
178
179 switch( m_errorCorrection )
180 {
181 case BARCODE_ECC_T::L: barcode.set_error_correction( BEC_L ); break;
182 case BARCODE_ECC_T::M: barcode.set_error_correction( BEC_M ); break;
183 case BARCODE_ECC_T::Q: barcode.set_error_correction( BEC_Q ); break;
184 case BARCODE_ECC_T::H: barcode.set_error_correction( BEC_H ); break;
185 }
186
187 kiapi::common::PackVector2( *barcode.mutable_position(), GetPosition() );
188 barcode.mutable_orientation()->set_value_degrees( GetAngle().AsDegrees() );
189 barcode.set_layer( ToProtoEnum<PCB_LAYER_ID, BoardLayer>( GetLayer() ) );
190
191 barcode.mutable_width()->set_value_nm( m_width );
192 barcode.mutable_height()->set_value_nm( m_height );
193
194 barcode.set_show_text( m_text.IsVisible() );
195 barcode.mutable_text_height()->set_value_nm( m_text.GetTextHeight() );
196
197 barcode.set_knockout( IsKnockout() );
198 kiapi::common::PackVector2( *barcode.mutable_knockout_margin(), m_margin );
199
200 barcode.set_locked( IsLocked() ? kiapi::common::types::LockedState::LS_LOCKED
201 : kiapi::common::types::LockedState::LS_UNLOCKED );
202
203 aContainer.PackFrom( barcode );
204}
205
206
207bool PCB_BARCODE::Deserialize( const google::protobuf::Any& aContainer )
208{
209 using namespace kiapi::board::types;
210
211 Barcode barcode;
212
213 if( !aContainer.UnpackTo( &barcode ) )
214 return false;
215
216 SetUuidDirect( KIID( barcode.id().value() ) );
217 SetText( wxString::FromUTF8( barcode.text() ) );
218
219 switch( barcode.kind() )
220 {
221 case BK_CODE_39: SetKind( BARCODE_T::CODE_39 ); break;
222 case BK_CODE_128: SetKind( BARCODE_T::CODE_128 ); break;
223 case BK_DATA_MATRIX: SetKind( BARCODE_T::DATA_MATRIX ); break;
224 case BK_QR_CODE: SetKind( BARCODE_T::QR_CODE ); break;
225 case BK_MICRO_QR_CODE: SetKind( BARCODE_T::MICRO_QR_CODE ); break;
226 default: SetKind( BARCODE_T::QR_CODE ); break;
227 }
228
229 switch( barcode.error_correction() )
230 {
231 case BEC_L: SetErrorCorrection( BARCODE_ECC_T::L ); break;
232 case BEC_M: SetErrorCorrection( BARCODE_ECC_T::M ); break;
233 case BEC_Q: SetErrorCorrection( BARCODE_ECC_T::Q ); break;
234 case BEC_H: SetErrorCorrection( BARCODE_ECC_T::H ); break;
235 default: SetErrorCorrection( BARCODE_ECC_T::L ); break;
236 }
237
238 SetPosition( kiapi::common::UnpackVector2( barcode.position() ) );
239
240 EDA_ANGLE newAngle( barcode.orientation().value_degrees(), DEGREES_T );
241
242 if( const FOOTPRINT* fp = GetParentFootprint() )
243 m_libAngle = newAngle - fp->GetOrientation();
244 else
245 m_libAngle = newAngle;
246
247 m_libAngle.Normalize();
248
250
251 m_width = barcode.width().value_nm();
252 m_height = barcode.height().value_nm();
253
254 m_text.SetLayer( m_layer );
255 m_text.SetVisible( barcode.show_text() );
256
257 if( barcode.has_text_height() )
258 {
259 int textSize = std::max( 1, static_cast<int>( barcode.text_height().value_nm() ) );
260 m_text.SetTextSize( VECTOR2I( textSize, textSize ) );
261 m_text.SetTextThickness( std::max( 1, GetPenSizeForNormal( m_text.GetTextHeight() ) ) );
262 }
263
264 m_margin = kiapi::common::UnpackVector2( barcode.knockout_margin() );
265 BOARD_ITEM::SetIsKnockout( barcode.knockout() );
266 SetLocked( barcode.locked() == kiapi::common::types::LockedState::LS_LOCKED );
267
269
270 return true;
271}
272
273
275{
276 m_layer = aLayer;
277 m_text.SetLayer( aLayer );
279}
280
281
282void PCB_BARCODE::SetTextSize( int aTextSize )
283{
284 m_text.SetTextSize( VECTOR2I( std::max( 1, aTextSize ), std::max( 1, aTextSize ) ) );
285 m_text.SetTextThickness( std::max( 1, GetPenSizeForNormal( m_text.GetTextHeight() ) ) );
287}
288
289
291{
292 return m_text.GetTextHeight();
293}
294
295
296void PCB_BARCODE::Move( const VECTOR2I& offset )
297{
298 if( const FOOTPRINT* fp = GetParentFootprint() )
299 {
300 const TRANSFORM_TRS& xform = fp->GetTransform();
301 VECTOR2I libOffset = xform.InverseApply( offset ) - xform.InverseApply( VECTOR2I( 0, 0 ) );
302 m_libPos += libOffset;
303 }
304 else
305 {
306 m_libPos += offset;
307 }
308
309 // m_text is intentionally not moved, ComputeTextPoly repositions it
310 // under the symbol on the next AssembleBarcode.
311}
312
313
314void PCB_BARCODE::Rotate( const VECTOR2I& aRotCentre, const EDA_ANGLE& aAngle )
315{
316 VECTOR2I boardPos = GetPosition();
317 RotatePoint( boardPos, aRotCentre, aAngle );
318
319 if( const FOOTPRINT* fp = GetParentFootprint() )
320 m_libPos = fp->GetTransform().InverseApply( boardPos );
321 else
322 m_libPos = boardPos;
323
324 m_libAngle += aAngle;
325 m_libAngle.Normalize();
326
328}
329
330
331void PCB_BARCODE::Flip( const VECTOR2I& aCentre, FLIP_DIRECTION aFlipDirection )
332{
333 if( const FOOTPRINT* fp = GetParentFootprint() )
334 {
335 const VECTOR2I libAxis = fp->GetTransform().InverseApply( aCentre );
336
337 if( aFlipDirection == FLIP_DIRECTION::LEFT_RIGHT )
338 m_libPos.x = 2 * libAxis.x - m_libPos.x;
339 else
340 m_libPos.y = 2 * libAxis.y - m_libPos.y;
341
342 // Reflect the library-frame angle (rotation-independent).
343 if( aFlipDirection == FLIP_DIRECTION::TOP_BOTTOM )
345 else
347
348 m_libAngle.Normalize();
349
352 return;
353 }
354
355 VECTOR2I boardPos = GetPosition();
356 MIRROR( boardPos, aCentre, aFlipDirection );
357 m_libPos = boardPos;
358
359 if( aFlipDirection == FLIP_DIRECTION::TOP_BOTTOM )
361 else
363
364 m_libAngle.Normalize();
365
368}
369
370
371void PCB_BARCODE::OnFootprintRescaled( double /* aRatioX */, double /* aRatioY */, double /* aLinearFactor */,
372 const VECTOR2I& /* aAnchor */, const EDA_ANGLE& /* aParentRotate */ )
373{
374 // Board values derive on read, AssembleBarcode rebuilds on next access.
375}
376
377
378void PCB_BARCODE::StyleFromSettings( const BOARD_DESIGN_SETTINGS& settings, bool aCheckSide )
379{
380 SetTextSize( settings.GetTextSize( GetLayer() ).y );
381}
382
383
385{
386 const VECTOR2I pos = GetPosition();
387 const EDA_ANGLE angle = GetAngle();
388
389 return hash_val( GetShownText(), m_width, m_height, pos.x, pos.y, m_margin.x, m_margin.y,
390 static_cast<int>( m_kind ), angle.AsDegrees(), static_cast<int>( m_errorCorrection ),
391 m_text.IsVisible(), m_text.GetTextHeight(), IsKnockout(), static_cast<int>( m_layer ) );
392}
393
394
396{
397 size_t key = computeCacheKey();
398
399 if( m_cache && m_cache->keyHash == key )
400 return;
401
402 if( !m_cache )
403 m_cache = std::make_unique<PCB_BARCODE_CACHE>();
404
406
407 const VECTOR2I pos = GetPosition();
408
409 // Scale the symbol polygon to the desired barcode width/height and center it at pos.
410 rescaleSymbolPoly( pos - VECTOR2I( m_width / 2, m_height / 2 ), pos + VECTOR2I( m_width / 2, m_height / 2 ) );
411
413
414 // Build full m_poly from symbol + optional text, then apply knockout if requested
415 m_cache->poly.RemoveAllContours();
416 m_cache->poly.Append( m_cache->symbolPoly );
417
418 if( m_text.IsVisible() && m_cache->textPoly.OutlineCount() )
419 m_cache->poly.Append( m_cache->textPoly );
420
421 m_cache->poly.Fracture();
422
423 if( IsKnockout() )
424 {
425 // Enforce minimum margin: at least 10% of the smallest side of the barcode, rounded up
426 // to the nearest 0.1 mm. Use this as a lower bound for both axes.
427 int minSide = std::min( m_width, m_height );
428 int tenPercent = ( minSide + 9 ) / 10; // ceil(minSide * 0.1)
429 int step01mm = std::max( 1, pcbIUScale.mmToIU( 0.1 ) );
430 int tenPercentRounded = ( ( tenPercent + step01mm - 1 ) / step01mm ) * step01mm;
431
432 // Build inversion rectangle based on the local bbox of the current combined geometry
433 BOX2I bbox = m_cache->poly.BBox();
434 bbox.Inflate( std::max( m_margin.x, tenPercentRounded ), std::max( m_margin.y, tenPercentRounded ) );
435
436 SHAPE_LINE_CHAIN rect;
437 rect.Append( bbox.GetLeft(), bbox.GetTop() );
438 rect.Append( bbox.GetRight(), bbox.GetTop() );
439 rect.Append( bbox.GetRight(), bbox.GetBottom() );
440 rect.Append( bbox.GetLeft(), bbox.GetBottom() );
441 rect.SetClosed( true );
442
444 ko.AddOutline( rect );
445 ko.BooleanSubtract( m_cache->poly );
446 ko.Fracture();
447 m_cache->poly = std::move( ko );
448 }
449
451 m_cache->poly.Mirror( pos, FLIP_DIRECTION::LEFT_RIGHT );
452
453 const EDA_ANGLE angle = GetAngle();
454
455 if( !angle.IsZero() )
456 m_cache->poly.Rotate( angle, pos );
457
458 m_cache->poly.CacheTriangulation();
459 m_cache->bbox = m_cache->poly.BBox();
460 m_cache->keyHash = key;
461}
462
463
465{
466 m_cache->textPoly.RemoveAllContours();
467
468 if( !m_text.IsVisible() )
469 return;
470
471 SHAPE_POLY_SET textPoly;
472 m_text.TransformTextToPolySet( textPoly, 0, GetMaxError(), ERROR_INSIDE );
473
474 if( textPoly.OutlineCount() == 0 )
475 return;
476
477 // PCB_TEXT::GetDrawRotation now includes the parent FP orientation, so
478 // TransformTextToPolySet rendered the glyphs already rotated by the FP
479 // angle. The final AssembleBarcode rotation (m_cache->poly.Rotate by
480 // GetAngle = lib_angle + FP_orient) would then rotate the glyphs a
481 // second time, producing twice the intended visual rotation. Undo the
482 // m_text-side rotation here so the glyph-orientation contribution is
483 // only the lib_angle, and the final poly rotation applies the FP-orient
484 // part uniformly with the symbol.
485 if( const FOOTPRINT* fp = GetParentFootprint() )
486 {
487 EDA_ANGLE fpOrient = fp->GetOrientation();
488
489 if( !fpOrient.IsZero() )
490 textPoly.Rotate( -fpOrient, m_text.GetTextPos() );
491 }
492
493 if( m_cache->symbolPoly.OutlineCount() == 0 )
494 return;
495
496 BOX2I textBBox = textPoly.BBox();
497 BOX2I symbolBBox = m_cache->symbolPoly.BBox();
498 VECTOR2I textPos;
499 int textOffset = pcbIUScale.mmToIU( 1 );
500 textPos.x = symbolBBox.GetCenter().x - textBBox.GetCenter().x;
501 textPos.y = symbolBBox.GetBottom() - textBBox.GetTop() + textOffset;
502
503 textPoly.Move( textPos );
504
505 m_cache->textPoly = std::move( textPoly );
506 m_cache->textPoly.CacheTriangulation();
507}
508
509
511{
512 m_cache->symbolPoly.RemoveAllContours();
513 m_cache->lastError.clear();
514
515 std::unique_ptr<zint_symbol, decltype( &ZBarcode_Delete )> symbol( ZBarcode_Create(), &ZBarcode_Delete );
516
517 if( !symbol )
518 {
519 wxLogError( wxT( "Zint: failed to allocate symbol" ) );
520 return;
521 }
522
523 symbol->input_mode = UNICODE_MODE;
524 symbol->show_hrt = 0; // do not show HRT
525
526 switch( m_kind )
527 {
529 symbol->symbology = BARCODE_CODE39;
530 break;
532 symbol->symbology = BARCODE_CODE128;
533 break;
535 symbol->symbology = BARCODE_QRCODE;
536 symbol->option_1 = to_underlying( m_errorCorrection );
537 break;
539 symbol->symbology = BARCODE_MICROQR;
540 symbol->option_1 = to_underlying( m_errorCorrection );
541 break;
543 symbol->symbology = BARCODE_DATAMATRIX;
544 break;
545 default:
546 wxLogError( wxT( "Zint: invalid barcode type" ) );
547 return;
548 }
549
550 wxString text = GetShownText();
551 wxScopedCharBuffer utf8Text = text.ToUTF8();
552 size_t length = utf8Text.length();
553 unsigned char* dataPtr = reinterpret_cast<unsigned char*>( utf8Text.data() );
554
555 if( text.empty() )
556 return;
557
558 if( ( m_kind == BARCODE_T::QR_CODE || m_kind == BARCODE_T::DATA_MATRIX ) && !text.IsAscii() )
559 {
560 symbol->eci = ECI_UTF8;
561 }
562
563 if( ZBarcode_Encode( symbol.get(), dataPtr, length ) >= ZINT_ERROR )
564 {
565 if( !text.IsAscii() )
566 {
567 m_cache->lastError = _( "This barcode type does not support international "
568 "characters. Use QR Code or Data Matrix instead." );
569 }
570 else
571 {
572 m_cache->lastError = wxString::FromUTF8( symbol->errtxt );
573 }
574 return;
575 }
576
577 if( ZBarcode_Buffer_Vector( symbol.get(), 0 ) >= ZINT_ERROR )
578 {
579 m_cache->lastError = wxString::FromUTF8( symbol->errtxt );
580 return;
581 }
582
583 for( zint_vector_rect* rect = symbol->vector->rectangles; rect != nullptr; rect = rect->next )
584 {
585 // Round using absolute edges to avoid cumulative rounding drift across modules.
586 int x1 = KiROUND( rect->x * symbol->scale );
587 int x2 = KiROUND( ( rect->x + rect->width ) * symbol->scale );
588 int y1 = KiROUND( rect->y * symbol->scale );
589 int y2 = KiROUND( ( rect->y + rect->height ) * symbol->scale );
590
591 SHAPE_LINE_CHAIN shapeline;
592 shapeline.Append( x1, y1 );
593 shapeline.Append( x2, y1 );
594 shapeline.Append( x2, y2 );
595 shapeline.Append( x1, y2 );
596 shapeline.SetClosed( true );
597
598 m_cache->symbolPoly.AddOutline( shapeline );
599 }
600
601 for( zint_vector_hexagon* hex = symbol->vector->hexagons; hex != nullptr; hex = hex->next )
602 {
603 // Compute vertices from center using minimal-diameter (inscribed circle) radius.
604 double r = hex->diameter / 2.0; // minimal radius
605 double cx = hex->x;
606 double cy = hex->y;
607
608 // Base orientation has apex at top; hex->rotation rotates by 0/90/180/270 degrees.
609 double baseAngles[6] = { 90.0, 30.0, -30.0, -90.0, -150.0, 150.0 };
610 double rot = static_cast<double>( hex->rotation );
611
612 SHAPE_LINE_CHAIN poly;
613
614 for( int k = 0; k < 6; ++k )
615 {
616 double ang = ( baseAngles[k] + rot ) * M_PI / 180.0;
617 int vx = KiROUND( cx + r * cos( ang ) );
618 int vy = KiROUND( cy + r * sin( ang ) );
619 poly.Append( vx, vy );
620 }
621 poly.SetClosed( true );
622
623 m_cache->symbolPoly.AddOutline( poly );
624 }
625
626 // Set the position of the barcode to the center of the symbol polygon
627 if( m_cache->symbolPoly.OutlineCount() > 0 )
628 {
629 VECTOR2I pos = m_cache->symbolPoly.BBox().GetCenter();
630 m_cache->symbolPoly.Move( -pos );
631 }
632
633 m_cache->symbolPoly.CacheTriangulation();
634}
635
636
637void PCB_BARCODE::GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_ITEM>& aList )
638{
639 FOOTPRINT* parentFP = GetParentFootprint();
640
641 if( parentFP && aFrame->GetName() == PCB_EDIT_FRAME_NAME )
642 aList.emplace_back( _( "Footprint" ), parentFP->GetReference() );
643
644 aList.emplace_back( _( "Barcode" ), ENUM_MAP<BARCODE_T>::Instance().ToString( m_kind ) );
645
646 // Don't use GetShownText() here; we want to show the user the variable references
647 aList.emplace_back( _( "Text" ), KIUI::EllipsizeStatusText( aFrame, GetText() ) );
648
649 if( aFrame->GetName() == PCB_EDIT_FRAME_NAME && IsLocked() )
650 aList.emplace_back( _( "Status" ), _( "Locked" ) );
651
652 aList.emplace_back( _( "Layer" ), GetLayerName() );
653
654 aList.emplace_back( _( "Angle" ), wxString::Format( wxT( "%g" ), GetAngle().AsDegrees() ) );
655
656 aList.emplace_back( _( "Text Height" ), aFrame->MessageTextFromValue( m_text.GetTextHeight() ) );
657}
658
659
660bool PCB_BARCODE::HitTest( const VECTOR2I& aPosition, int aAccuracy ) const
661{
663
664 if( !GetBoundingBox().Contains( aPosition ) )
665 return false;
666
667 SHAPE_POLY_SET hulls;
668
670
671 return hulls.Collide( aPosition );
672}
673
674
675bool PCB_BARCODE::HitTest( const BOX2I& aRect, bool aContained, int aAccuracy ) const
676{
677 BOX2I arect = aRect;
678 arect.Inflate( aAccuracy );
679
680 BOX2I rect = GetBoundingBox();
681
682 if( aAccuracy )
683 rect.Inflate( aAccuracy );
684
685 if( aContained )
686 return arect.Contains( rect );
687
688 return arect.Intersects( rect );
689}
690
691
692void PCB_BARCODE::rescaleSymbolPoly( const VECTOR2I& aTopLeft, const VECTOR2I& aBotRight ) const
693{
694 // Rescale only the symbol polygon to the requested rectangle
695 BOX2I bbox = m_cache->symbolPoly.BBox();
696 int oldW = bbox.GetWidth();
697 int oldH = bbox.GetHeight();
698
699 VECTOR2I newPosition = ( aTopLeft + aBotRight ) / 2;
700 int newW = aBotRight.x - aTopLeft.x;
701 int newH = aBotRight.y - aTopLeft.y;
702 // Guard against zero/negative sizes from interactive edits; enforce a tiny minimum
703 int minIU = std::max( 1, pcbIUScale.mmToIU( 0.01 ) );
704 newW = std::max( newW, minIU );
705 newH = std::max( newH, minIU );
706
707 double scaleX = oldW ? static_cast<double>( newW ) / oldW : 1.0;
708 double scaleY = oldH ? static_cast<double>( newH ) / oldH : 1.0;
709
710 VECTOR2I oldCenter = bbox.GetCenter();
711 m_cache->symbolPoly.Scale( scaleX, scaleY, oldCenter );
712
713 // After scaling, move the symbol polygon to be centered at the new position
714 VECTOR2I newCenter = m_cache->symbolPoly.BBox().GetCenter();
715 VECTOR2I delta = newPosition - newCenter;
716
717 if( delta != VECTOR2I( 0, 0 ) )
718 m_cache->symbolPoly.Move( delta );
719}
720
721
723{
725 return m_cache->bbox;
726}
727
728
729wxString PCB_BARCODE::GetItemDescription( UNITS_PROVIDER* aUnitsProvider, bool aFull ) const
730{
731 return wxString::Format( _( "Barcode '%s' on %s" ), GetText(), GetLayerName() );
732}
733
734
739
740
742{
744 return m_cache->bbox;
745}
746
747
748double PCB_BARCODE::ViewGetLOD( int aLayer, const KIGFX::VIEW* aView ) const
749{
750 // Hide the locked shadow when the barcode's own layer is not shown
751 if( aLayer == LAYER_LOCKED_ITEM_SHADOW && !aView->IsLayerVisibleCached( m_layer ) )
752 return LOD_HIDE;
753
754 return LOD_SHOW;
755}
756
757
759 int aClearance, int aMaxError,
760 ERROR_LOC aErrorLoc, bool ignoreLineWidth ) const
761{
762 if( aLayer != m_layer && aLayer != UNDEFINED_LAYER )
763 return;
764
766
767 if( aClearance == 0 )
768 {
769 aBuffer.Append( m_cache->poly );
770 }
771 else
772 {
773 SHAPE_POLY_SET poly = m_cache->poly;
774 poly.Inflate( aClearance, CORNER_STRATEGY::CHAMFER_ACUTE_CORNERS, aMaxError, aErrorLoc );
775 aBuffer.Append( poly );
776 }
777}
778
779
780std::shared_ptr<SHAPE> PCB_BARCODE::GetEffectiveShape( PCB_LAYER_ID aLayer, FLASHING aFlash ) const
781{
782 SHAPE_POLY_SET poly;
783 TransformShapeToPolygon( poly, aLayer, 0, 0, ERROR_INSIDE, true );
784
785 return std::make_shared<SHAPE_POLY_SET>( std::move( poly ) );
786}
787
788
789void PCB_BARCODE::GetBoundingHull( SHAPE_POLY_SET& aBuffer, PCB_LAYER_ID aLayer, int aClearance,
790 int aMaxError, ERROR_LOC aErrorLoc ) const
791{
793
794 auto getBoundingHull =
795 [this]( SHAPE_POLY_SET& aLocBuffer, const SHAPE_POLY_SET& aSource, int aLocClearance )
796 {
797 BOX2I rect = aSource.BBox( aLocClearance );
798 VECTOR2I corners[4];
799
800 corners[0].x = rect.GetOrigin().x;
801 corners[0].y = rect.GetOrigin().y;
802 corners[1].y = corners[0].y;
803 corners[1].x = rect.GetRight();
804 corners[2].x = corners[1].x;
805 corners[2].y = rect.GetBottom();
806 corners[3].y = corners[2].y;
807 corners[3].x = corners[0].x;
808
809 aLocBuffer.NewOutline();
810
811 const VECTOR2I pos = GetPosition();
812 const EDA_ANGLE angle = GetAngle();
813
814 for( VECTOR2I& corner : corners )
815 {
816 RotatePoint( corner, pos, angle );
817 aLocBuffer.Append( corner.x, corner.y );
818 }
819 };
820
821 if( aLayer == m_layer || aLayer == UNDEFINED_LAYER )
822 {
823 getBoundingHull( aBuffer, m_cache->symbolPoly, aClearance );
824 getBoundingHull( aBuffer, m_cache->textPoly, aClearance );
825 }
826}
827
828
830{
831 // Micro QR codes do not support High (H) error correction level
832 if( m_kind == BARCODE_T::MICRO_QR_CODE && aErrorCorrection == BARCODE_ECC_T::H )
834 else
835 m_errorCorrection = aErrorCorrection;
836 // Don't auto-compute here as it may be called during loading
837}
838
839
841{
842 m_kind = aKind;
843
844 // When switching to Micro QR, validate and adjust ECC if needed
847
848 // Don't auto-compute here as it may be called during loading
849}
850
851
853{
854 SetErrorCorrection( aErrorCorrection );
856}
857
858
860{
861 m_width = aWidth;
862
863 if( KeepSquare() )
864 m_height = aWidth;
865
867}
868
869
871{
872 m_height = aHeight;
873
874 if( KeepSquare() )
875 m_width = aHeight;
876
878}
879
880
882{
883 SetKind( aKind );
885}
886
887
889{
890 PCB_BARCODE* item = new PCB_BARCODE( *this );
891 item->CopyFrom( this );
892 return item;
893}
894
895
897{
898 wxCHECK_RET( aImage && aImage->Type() == PCB_BARCODE_T,
899 wxT( "Cannot swap data with non-barcode item." ) );
900
901 PCB_BARCODE* other = static_cast<PCB_BARCODE*>( aImage );
902
903 std::swap( m_layer, other->m_layer );
904 std::swap( m_isKnockout, other->m_isKnockout );
905 std::swap( m_isLocked, other->m_isLocked );
906 std::swap( m_width, other->m_width );
907 std::swap( m_height, other->m_height );
908 std::swap( m_libPos, other->m_libPos );
909 std::swap( m_margin, other->m_margin );
910 std::swap( m_text, other->m_text );
911 std::swap( m_kind, other->m_kind );
912 std::swap( m_libAngle, other->m_libAngle );
913 std::swap( m_errorCorrection, other->m_errorCorrection );
914 std::swap( m_cache, other->m_cache );
915
916 m_text.SetParent( this );
917 other->m_text.SetParent( other );
918}
919
920double PCB_BARCODE::Similarity( const BOARD_ITEM& aItem ) const
921{
922 if( !ClassOf( &aItem ) )
923 return 0.0;
924
925 const PCB_BARCODE* other = static_cast<const PCB_BARCODE*>( &aItem );
926
927 // Compare text, width, height, text height, position, and kind
928 double similarity = 0.0;
929 const double weight = 1.0 / 6.0;
930
931 if( GetText() == other->GetText() )
932 similarity += weight;
933 if( m_width == other->m_width )
934 similarity += weight;
935 if( m_height == other->m_height )
936 similarity += weight;
937 if( GetTextSize() == other->GetTextSize() )
938 similarity += weight;
939 if( GetPosition() == other->GetPosition() )
940 similarity += weight;
941 if( m_kind == other->m_kind )
942 similarity += weight;
943
944 return similarity;
945}
946
947int PCB_BARCODE::Compare( const PCB_BARCODE* aBarcode, const PCB_BARCODE* aOther )
948{
949 int diff;
950
951 if( ( diff = aBarcode->GetPosition().x - aOther->GetPosition().x ) != 0 )
952 return diff;
953
954 if( ( diff = aBarcode->GetPosition().y - aOther->GetPosition().y ) != 0 )
955 return diff;
956
957 if( ( diff = aBarcode->GetText().Cmp( aOther->GetText() ) ) != 0 )
958 return diff;
959
960 if( ( diff = aBarcode->GetWidth() - aOther->GetWidth() ) != 0 )
961 return diff;
962
963 if( ( diff = aBarcode->GetHeight() - aOther->GetHeight() ) != 0 )
964 return diff;
965
966 if( ( diff = aBarcode->GetTextSize() - aOther->GetTextSize() ) != 0 )
967 return diff;
968
969 if( ( diff = (int) aBarcode->GetKind() - (int) aOther->GetKind() ) != 0 )
970 return diff;
971
972 if( ( diff = aBarcode->GetAngle().AsTenthsOfADegree() - aOther->GetAngle().AsTenthsOfADegree() ) != 0 )
973 return diff;
974
975 if( ( diff = (int) aBarcode->GetErrorCorrection() - (int) aOther->GetErrorCorrection() ) != 0 )
976 return diff;
977
978 return 0;
979}
980
981
982bool PCB_BARCODE::operator==( const BOARD_ITEM& aItem ) const
983{
984 if( !ClassOf( &aItem ) )
985 return false;
986
987 const PCB_BARCODE& other = static_cast<const PCB_BARCODE&>( aItem );
988
989 return *this == other;
990}
991
992
993bool PCB_BARCODE::operator==( const PCB_BARCODE& aOther ) const
994{
995 // Compare text, width, height, text height, position, and kind
996 return ( GetText() == aOther.GetText()
997 && m_width == aOther.m_width
998 && m_height == aOther.m_height
999 && GetTextSize() == aOther.GetTextSize()
1000 && GetPosition() == aOther.GetPosition()
1001 && m_kind == aOther.m_kind );
1002}
1003
1004// ---- Property registration ----
1005static struct PCB_BARCODE_DESC
1006{
1008 {
1012
1013 const wxString groupBarcode = _HKI( "Barcode Properties" );
1014
1016 if( kindMap.Choices().GetCount() == 0 )
1017 {
1018 kindMap.Undefined( BARCODE_T::QR_CODE );
1019 kindMap.Map( BARCODE_T::CODE_39, _HKI( "CODE_39" ) )
1020 .Map( BARCODE_T::CODE_128, _HKI( "CODE_128" ) )
1021 .Map( BARCODE_T::DATA_MATRIX, _HKI( "DATA_MATRIX" ) )
1022 .Map( BARCODE_T::QR_CODE, _HKI( "QR_CODE" ) )
1023 .Map( BARCODE_T::MICRO_QR_CODE, _HKI( "MICRO_QR_CODE" ) );
1024 }
1025
1027 if( eccMap.Choices().GetCount() == 0 )
1028 {
1029 eccMap.Undefined( BARCODE_ECC_T::L );
1030 eccMap.Map( BARCODE_ECC_T::L, _HKI( "L (Low)" ) )
1031 .Map( BARCODE_ECC_T::M, _HKI( "M (Medium)" ) )
1032 .Map( BARCODE_ECC_T::Q, _HKI( "Q (Quartile)" ) )
1033 .Map( BARCODE_ECC_T::H, _HKI( "H (High)" ) );
1034 }
1035
1036 auto hasKnockout =
1037 []( INSPECTABLE* aItem ) -> bool
1038 {
1039 if( PCB_BARCODE* bc = dynamic_cast<PCB_BARCODE*>( aItem ) )
1040 return bc->IsKnockout();
1041 return false;
1042 };
1043
1044 propMgr.AddProperty( new PROPERTY<PCB_BARCODE, wxString>( _HKI( "Text" ),
1046
1047 propMgr.AddProperty( new PROPERTY<PCB_BARCODE, bool>( _HKI( "Show Text" ),
1049
1050 propMgr.AddProperty( new PROPERTY<PCB_BARCODE, int>( _HKI( "Text Size" ),
1052 PROPERTY_DISPLAY::PT_COORD ), groupBarcode );
1053
1054 propMgr.AddProperty( new PROPERTY<PCB_BARCODE, int>( _HKI( "Width" ),
1056 PROPERTY_DISPLAY::PT_COORD ), groupBarcode );
1057
1058 propMgr.AddProperty( new PROPERTY<PCB_BARCODE, int>( _HKI( "Height" ),
1060 PROPERTY_DISPLAY::PT_COORD ), groupBarcode );
1061
1062 propMgr.AddProperty( new PROPERTY<PCB_BARCODE, double>( _HKI( "Orientation" ),
1064
1065 propMgr.AddProperty( new PROPERTY_ENUM<PCB_BARCODE, BARCODE_T>( _HKI( "Barcode Type" ),
1067
1068 auto isQRCode =
1069 []( INSPECTABLE* aItem ) -> bool
1070 {
1071 if( PCB_BARCODE* bc = dynamic_cast<PCB_BARCODE*>( aItem ) )
1072 return bc->GetKind() == BARCODE_T::QR_CODE || bc->GetKind() == BARCODE_T::MICRO_QR_CODE;
1073
1074 return false;
1075 };
1076
1077 propMgr.AddProperty( new PROPERTY_ENUM<PCB_BARCODE, BARCODE_ECC_T>( _HKI( "Error Correction" ),
1079 groupBarcode )
1080 .SetAvailableFunc( isQRCode )
1081 .SetChoicesFunc( []( INSPECTABLE* aItem )
1082 {
1083 PCB_BARCODE* barcode = static_cast<PCB_BARCODE*>( aItem );
1084 wxPGChoices choices;
1085
1086 choices.Add( _( "L (Low)" ), static_cast<int>( BARCODE_ECC_T::L ) );
1087 choices.Add( _( "M (Medium)" ), static_cast<int>( BARCODE_ECC_T::M ) );
1088 choices.Add( _( "Q (Quartile)" ), static_cast<int>( BARCODE_ECC_T::Q ) );
1089
1090 // Only QR_CODE has High
1091 if( barcode->GetKind() == BARCODE_T::QR_CODE )
1092 choices.Add( _( "H (High)" ), static_cast<int>( BARCODE_ECC_T::H ) );
1093
1094 return choices;
1095 } );
1096
1097 propMgr.AddProperty( new PROPERTY<PCB_BARCODE, bool>( _HKI( "Knockout" ),
1099
1100 propMgr.AddProperty( new PROPERTY<PCB_BARCODE, int>( _HKI( "Margin X" ),
1102 PROPERTY_DISPLAY::PT_COORD ), groupBarcode ).SetAvailableFunc( hasKnockout );
1103
1104 propMgr.AddProperty( new PROPERTY<PCB_BARCODE, int>( _HKI( "Margin Y" ),
1106 PROPERTY_DISPLAY::PT_COORD ), groupBarcode ).SetAvailableFunc( hasKnockout );
1107 }
1109
types::KiCadObjectType ToProtoEnum(KICAD_T aValue)
KICAD_T FromProtoEnum(types::KiCadObjectType aValue)
Definition api_enums.cpp:47
ERROR_LOC
When approximating an arc or circle, should the error be placed on the outside or inside of the curve...
@ ERROR_OUTSIDE
@ ERROR_INSIDE
constexpr EDA_IU_SCALE pcbIUScale
Definition base_units.h:121
constexpr int ARC_LOW_DEF
Definition base_units.h:136
BITMAPS
A list of all bitmap identifiers.
BOX2< VECTOR2I > BOX2I
Definition box2.h:918
constexpr BOX2I KiROUND(const BOX2D &aBoxD)
Definition box2.h:986
Container for design settings for a BOARD object.
VECTOR2I GetTextSize(PCB_LAYER_ID aLayer) const
Return the default text size from the layer class for the given layer.
A base class for any item which can be embedded within the BOARD container class, and therefore insta...
Definition board_item.h:81
BOARD_ITEM(BOARD_ITEM *aParent, KICAD_T idtype, PCB_LAYER_ID aLayer=F_Cu)
Definition board_item.h:83
virtual PCB_LAYER_ID GetLayer() const
Return the primary layer this item is on.
Definition board_item.h:265
void SetUuidDirect(const KIID &aUuid)
Raw UUID assignment.
void SetLocked(bool aLocked) override
Definition board_item.h:356
bool m_isKnockout
Definition board_item.h:509
PCB_LAYER_ID m_layer
Definition board_item.h:508
bool m_isLocked
Definition board_item.h:510
bool IsLocked() const override
virtual void SetIsKnockout(bool aKnockout)
Definition board_item.h:353
virtual const BOARD * GetBoard() const
Return the BOARD in which this BOARD_ITEM resides, or NULL if none.
FOOTPRINT * GetParentFootprint() const
virtual void CopyFrom(const BOARD_ITEM *aOther)
BOARD_ITEM & operator=(const BOARD_ITEM &aOther)
Definition board_item.h:100
bool IsSideSpecific() const
wxString GetLayerName() const
Return the name of the PCB layer on which the item resides.
int GetMaxError() const
constexpr BOX2< Vec > & Inflate(coord_type dx, coord_type dy)
Inflates the rectangle horizontally by dx and vertically by dy.
Definition box2.h:554
constexpr size_type GetWidth() const
Definition box2.h:210
constexpr const Vec GetCenter() const
Definition box2.h:226
constexpr size_type GetHeight() const
Definition box2.h:211
constexpr coord_type GetLeft() const
Definition box2.h:224
constexpr bool Contains(const Vec &aPoint) const
Definition box2.h:164
constexpr const Vec & GetOrigin() const
Definition box2.h:206
constexpr coord_type GetRight() const
Definition box2.h:213
constexpr coord_type GetTop() const
Definition box2.h:225
constexpr bool Intersects(const BOX2< Vec > &aRect) const
Definition box2.h:307
constexpr coord_type GetBottom() const
Definition box2.h:218
EDA_ANGLE Normalize()
Definition eda_angle.h:229
int AsTenthsOfADegree() const
Definition eda_angle.h:118
double AsDegrees() const
Definition eda_angle.h:116
bool IsZero() const
Definition eda_angle.h:136
The base class for create windows for drawing purpose.
const KIID m_Uuid
Definition eda_item.h:531
KICAD_T Type() const
Returns the type of object.
Definition eda_item.h:108
virtual void SetParent(EDA_ITEM *aParent)
Definition eda_item.cpp:89
EDA_ITEM(EDA_ITEM *parent, KICAD_T idType, bool isSCH_ITEM=false, bool isBOARD_ITEM=false)
Definition eda_item.cpp:37
ENUM_MAP & Map(T aValue, const wxString &aName)
Definition property.h:727
static ENUM_MAP< T > & Instance()
Definition property.h:721
ENUM_MAP & Undefined(T aValue)
Definition property.h:734
wxPGChoices & Choices()
Definition property.h:772
const wxString & GetReference() const
Definition footprint.h:841
Class that other classes need to inherit from, in order to be inspectable.
Definition inspectable.h:38
static constexpr double LOD_HIDE
Return this constant from ViewGetLOD() to hide the item unconditionally.
Definition view_item.h:176
static constexpr double LOD_SHOW
Return this constant from ViewGetLOD() to show the item unconditionally.
Definition view_item.h:181
Hold a (potentially large) number of VIEW_ITEMs and renders them on a graphics device provided by the...
Definition view.h:63
bool IsLayerVisibleCached(int aLayer) const
Definition view.h:437
Definition kiid.h:44
void SetKind(BARCODE_T aKind)
EDA_ANGLE m_libAngle
Angle, FP-relative when in a footprint, board absolute otherwise.
void SetTextSize(int aTextSize)
Change the height of the human-readable text displayed below the barcode.
double GetOrientation() const
std::unique_ptr< PCB_BARCODE_CACHE > m_cache
virtual std::shared_ptr< SHAPE > GetEffectiveShape(PCB_LAYER_ID aLayer=UNDEFINED_LAYER, FLASHING aFlash=FLASHING::DEFAULT) const override
Some pad shapes can be complex (rounded/chamfered rectangle), even without considering custom shapes.
~PCB_BARCODE()
Destructor.
const BOX2I GetBoundingBox() const override
Get the axis-aligned bounding box of the barcode including text.
void SetBarcodeErrorCorrection(BARCODE_ECC_T aErrorCorrection)
virtual const BOX2I ViewBBox() const override
Get the bbox used for drawing/view culling, may include additional view-only extents.
EDA_ITEM * Clone() const override
Create a copy of this item.
void SetErrorCorrection(BARCODE_ECC_T aErrorCorrection)
Set the error correction level used for QR codes.
void SetBarcodeHeight(int aHeight)
void SetShowText(bool aShow)
void SetMarginY(int aY)
void StyleFromSettings(const BOARD_DESIGN_SETTINGS &settings, bool aCheckSide) override
bool KeepSquare() const
void SetBarcodeText(const wxString &aText)
wxString GetItemDescription(UNITS_PROVIDER *aUnitsProvider, bool aFull) const override
Produce a short human-readable description of the item for UI lists.
void AssembleBarcode() const
Assemble the barcode polygon and text polygons into a single polygonal representation.
void SetBarcodeKind(BARCODE_T aKind)
void GetBoundingHull(SHAPE_POLY_SET &aBuffer, PCB_LAYER_ID aLayer, int aClearance, int aMaxError, ERROR_LOC aErrorLoc=ERROR_INSIDE) const
PCB_BARCODE & operator=(const PCB_BARCODE &aOther)
Copy assignment operator.
VECTOR2I GetPosition() const override
Get the position (center) of the barcode in internal units.
void ComputeTextPoly() const
Generate the internal polygon representation for the human-readable text.
wxString GetText() const
void SetPosition(const VECTOR2I &aPos) override
void SetMarginX(int aX)
double ViewGetLOD(int aLayer, const KIGFX::VIEW *aView) const override
Return the level of detail (LOD) of the item.
void SetOrientation(double aDegrees)
double Similarity(const BOARD_ITEM &aItem) const override
Compute a simple similarity score between this barcode and another board item.
int m_height
Barcode height.
PCB_TEXT m_text
void SetLayer(PCB_LAYER_ID aLayer) override
Set the drawing layer for the barcode and its text.
bool operator==(const BOARD_ITEM &aItem) const override
Equality comparison operator for board-level deduplication.
VECTOR2I m_margin
Margin around the barcode (only valid for knockout)
void GetMsgPanelInfo(EDA_DRAW_FRAME *aFrame, std::vector< MSG_PANEL_ITEM > &aList) override
Populate message panel information entries (e.g.
bool Deserialize(const google::protobuf::Any &aContainer) override
Deserializes the given protobuf message into this object.
int GetTextSize() const
void ComputeBarcode() const
Generate the internal polygon representation for the current barcode text, kind and error correction.
void SetBarcodeWidth(int aWidth)
bool IsKnockout() const override
int GetHeight() const
Get the barcode height (in internal units).
BITMAPS GetMenuImage() const override
Icon to show in context menus/toolbars for this item type.
wxString GetShownText() const
size_t computeCacheKey() const
Compute a hash of all cache-key inputs (shown text + geometry parameters + layer).
BARCODE_ECC_T m_errorCorrection
Error correction level for QR codes.
void SetIsKnockout(bool aEnable) override
static bool ClassOf(const EDA_ITEM *aItem)
Type-check helper.
void rescaleSymbolPoly(const VECTOR2I &aTopLeft, const VECTOR2I &aBotRight) const
Scale and translate the symbol polygon to fill the given bounding rectangle.
bool HitTest(const VECTOR2I &aPosition, int aAccuracy) const override
Hit-test a point against the barcode (text and symbol area).
PCB_BARCODE(BOARD_ITEM *aParent)
Construct a PCB_BARCODE.
void OnFootprintRescaled(double aRatioX, double aRatioY, double aLinearFactor, const VECTOR2I &aAnchor, const EDA_ANGLE &aParentRotate) override
Apply a parent footprint scale to this item.
int m_width
Barcode width.
VECTOR2I m_libPos
Position, FP-relative when in a footprint, board absolute otherwise.
int GetMarginY() const
void swapData(BOARD_ITEM *aImage) override
BARCODE_ECC_T GetErrorCorrection() const
bool GetShowText() const
void Rotate(const VECTOR2I &aRotCentre, const EDA_ANGLE &aAngle) override
Rotate the barcode around a given centre by the given angle.
int GetMarginX() const
BARCODE_T m_kind
static int Compare(const PCB_BARCODE *aBarcode, const PCB_BARCODE *aOther)
void TransformShapeToPolygon(SHAPE_POLY_SET &aBuffer, PCB_LAYER_ID aLayer, int aClearance, int aMaxError, ERROR_LOC aErrorLoc=ERROR_INSIDE, bool ignoreLineWidth=false) const override
Convert the barcode (text + symbol shapes) to polygonal geometry suitable for filling/collision tests...
EDA_ANGLE GetAngle() const
void Flip(const VECTOR2I &aCentre, FLIP_DIRECTION aFlipLeftRight) override
Flip the barcode horizontally or vertically around a centre point.
BARCODE_T GetKind() const
Returns the type of the barcode (QR, CODE_39, etc.).
int GetWidth() const
Get the barcode width (in internal units).
void Serialize(google::protobuf::Any &aContainer) const override
Serializes this object to the given Any message.
void SetText(const wxString &aText)
Set the barcode content text to encode.
void Move(const VECTOR2I &offset) override
Function Move.
PROPERTY_BASE & SetChoicesFunc(std::function< wxPGChoices(INSPECTABLE *)> aFunc)
Definition property.h:276
PROPERTY_BASE & SetAvailableFunc(std::function< bool(INSPECTABLE *)> aFunc)
Set a callback function to determine whether an object provides this property.
Definition property.h:262
Provide class metadata.Helper macro to map type hashes to names.
void InheritsAfter(TYPE_ID aDerived, TYPE_ID aBase)
Declare an inheritance relationship between types.
static PROPERTY_MANAGER & Instance()
PROPERTY_BASE & AddProperty(PROPERTY_BASE *aProperty, const wxString &aGroup=wxEmptyString)
Register a property.
Represent a polyline containing arcs as well as line segments: A chain of connected line and/or arc s...
void SetClosed(bool aClosed)
Mark the line chain as closed (i.e.
void Append(int aX, int aY, bool aAllowDuplication=false)
Append a new point at the end of the line chain.
Represent a set of closed polygons.
void Rotate(const EDA_ANGLE &aAngle, const VECTOR2I &aCenter={ 0, 0 }) override
Rotate all vertices by a given angle.
int AddOutline(const SHAPE_LINE_CHAIN &aOutline)
Adds a new outline to the set and returns its index.
bool Collide(const SHAPE *aShape, int aClearance=0, int *aActual=nullptr, VECTOR2I *aLocation=nullptr) const override
Check if the boundary of shape (this) lies closer to the shape aShape than aClearance,...
void Inflate(int aAmount, CORNER_STRATEGY aCornerStrategy, int aMaxError, bool aSimplify=false)
Perform outline inflation/deflation.
int Append(int x, int y, int aOutline=-1, int aHole=-1, bool aAllowDuplication=false)
Appends a vertex at the end of the given outline/hole (default: the last outline)
int NewOutline()
Creates a new empty polygon in the set and returns its index.
int OutlineCount() const
Return the number of outlines in the set.
void Move(const VECTOR2I &aVector) override
void Fracture(bool aSimplify=true)
Convert a set of polygons with holes to a single outline with "slits"/"fractures" connecting the oute...
void BooleanSubtract(const SHAPE_POLY_SET &b)
Perform boolean polyset difference.
const BOX2I BBox(int aClearance=0) const override
Compute a bounding box of the shape, with a margin of aClearance a collision.
VECTOR2I InverseApply(const VECTOR2I &aPoint) const
wxString MessageTextFromValue(double aValue, bool aAddUnitLabel=true, EDA_DATA_TYPE aType=EDA_DATA_TYPE::DISTANCE) const
A lower-precision version of StringFromValue().
@ CHAMFER_ACUTE_CORNERS
Acute angles are chamfered.
#define _(s)
@ DEGREES_T
Definition eda_angle.h:31
static constexpr EDA_ANGLE ANGLE_180
Definition eda_angle.h:415
#define PCB_EDIT_FRAME_NAME
int GetPenSizeForNormal(int aTextSize)
Definition gr_text.cpp:57
static constexpr std::size_t hash_val(const Types &... args)
Definition hash.h:47
PCB_LAYER_ID FlipLayer(PCB_LAYER_ID aLayerId, int aCopperLayersCount)
Definition layer_id.cpp:173
FLASHING
Enum used during connectivity building to ensure we do not query connectivity while building the data...
Definition layer_ids.h:180
bool IsBackLayer(PCB_LAYER_ID aLayerId)
Layer classification: check if it's a back layer.
Definition layer_ids.h:801
@ LAYER_LOCKED_ITEM_SHADOW
Shadow layer for locked items.
Definition layer_ids.h:303
PCB_LAYER_ID
A quick note on layer IDs:
Definition layer_ids.h:56
@ Dwgs_User
Definition layer_ids.h:103
@ UNDEFINED_LAYER
Definition layer_ids.h:57
This file contains miscellaneous commonly used macros and functions.
constexpr void MIRROR(T &aPoint, const T &aMirrorRef)
Updates aPoint with the mirror of aPoint relative to the aMirrorRef.
Definition mirror.h:41
FLIP_DIRECTION
Definition mirror.h:23
@ LEFT_RIGHT
Flip left to right (around the Y axis)
Definition mirror.h:24
@ TOP_BOTTOM
Flip top to bottom (around the X axis)
Definition mirror.h:25
KICOMMON_API wxString EllipsizeStatusText(wxWindow *aWindow, const wxString &aString)
Ellipsize text (at the end) to be no more than 1/3 of the window width.
KICOMMON_API VECTOR2I UnpackVector2(const types::Vector2 &aInput, const EDA_IU_SCALE &aScale)
KICOMMON_API void PackVector2(types::Vector2 &aOutput, const VECTOR2I &aInput, const EDA_IU_SCALE &aScale)
#define _HKI(x)
Definition page_info.cpp:40
static struct PCB_BARCODE_DESC _PCB_BARCODE_DESC
constexpr int ECI_UTF8
BARCODE class definition.
BARCODE_ECC_T
Definition pcb_barcode.h:49
BARCODE_T
Definition pcb_barcode.h:40
see class PGM_BASE
#define TYPE_HASH(x)
Definition property.h:74
#define IMPLEMENT_ENUM_TO_WXANY(type)
Definition property.h:826
@ PT_COORD
Coordinate expressed in distance units (mm/inch)
Definition property.h:65
#define REGISTER_TYPE(x)
int delta
#define M_PI
void RotatePoint(int *pX, int *pY, const EDA_ANGLE &aAngle)
Calculate the new point of coord coord pX, pY, for a rotation center 0, 0.
Definition trigo.cpp:225
constexpr auto to_underlying(E e) noexcept
@ PCB_BARCODE_T
class PCB_BARCODE, a barcode (graphic item)
Definition typeinfo.h:94
VECTOR2< int32_t > VECTOR2I
Definition vector2d.h:683