KiCad PCB EDA Suite
Loading...
Searching...
No Matches
zone.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) 2017 Jean-Pierre Charras, jp.charras at wanadoo.fr
5 * Copyright (C) 2012 SoftPLC Corporation, Dick Hollenbeck <[email protected]>
6 * Copyright (C) 1992-2023 KiCad Developers, see AUTHORS.txt for contributors.
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License
10 * as published by the Free Software Foundation; either version 2
11 * of the License, or (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, you may find one here:
20 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
21 * or you may search the http://www.gnu.org website for the version 2 license,
22 * or you may write to the Free Software Foundation, Inc.,
23 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
24 */
25
26#include <bitmaps.h>
28#include <geometry/shape_null.h>
29#include <pcb_edit_frame.h>
30#include <pcb_screen.h>
31#include <board.h>
33#include <pad.h>
34#include <zone.h>
35#include <footprint.h>
36#include <string_utils.h>
37#include <math_for_graphics.h>
41#include <trigo.h>
42#include <i18n_utility.h>
43
44
47 m_Poly( nullptr ),
48 m_isFilled( false ),
49 m_CornerSelection( nullptr ),
50 m_area( 0.0 ),
51 m_outlinearea( 0.0 )
52{
53 m_Poly = new SHAPE_POLY_SET(); // Outlines
56 m_teardropType = TEARDROP_TYPE::TD_NONE;
57 m_islandRemovalMode = ISLAND_REMOVAL_MODE::ALWAYS;
58 m_borderStyle = ZONE_BORDER_DISPLAY_STYLE::DIAGONAL_EDGE;
60 m_priority = 0;
61 SetLocalFlags( 0 ); // flags temporary used in zone calculations
62 m_fillVersion = 5; // set the "old" way to build filled polygon areas (< 6.0.x)
63
64 if( GetParentFootprint() )
65 SetIsRuleArea( true ); // Zones living in footprints have the rule area option
66
67 // Technically not necesssary to set this here, but just ensure a safe min value is set
69
70 // Will be overridden by larger defaults from ZONE_SETTINGS
75
76 aParent->GetZoneSettings().ExportSetting( *this );
77
78 m_needRefill = false; // True only after edits.
79}
80
81
82ZONE::ZONE( const ZONE& aZone ) :
83 BOARD_CONNECTED_ITEM( aZone ),
84 m_Poly( nullptr ),
85 m_CornerSelection( nullptr )
86{
88}
89
90
91ZONE& ZONE::operator=( const ZONE& aOther )
92{
94
96
97 return *this;
98}
99
100
102{
103 delete m_Poly;
104 delete m_CornerSelection;
105
106 if( BOARD* board = GetBoard() )
107 board->IncrementTimeStamp();
108}
109
110
112{
113 // members are expected non initialize in this.
114 // InitDataFromSrcInCopyCtor() is expected to be called only from a copy constructor.
115
116 // Copy only useful EDA_ITEM flags:
117 m_flags = aZone.m_flags;
119
120 // Replace the outlines for aZone outlines.
121 delete m_Poly;
122 m_Poly = new SHAPE_POLY_SET( *aZone.m_Poly );
123
126 m_zoneName = aZone.m_zoneName;
127 m_priority = aZone.m_priority;
129 SetLayerSet( aZone.GetLayerSet() );
130
136
138 m_ZoneClearance = aZone.m_ZoneClearance; // clearance value
143
144 m_isFilled = aZone.m_isFilled;
147
150
151 m_fillMode = aZone.m_fillMode; // solid vs. hatched
153 m_hatchGap = aZone.m_hatchGap;
159
160 // For corner moving, corner index to drag, or nullptr if no selection
161 delete m_CornerSelection;
162 m_CornerSelection = nullptr;
163
164 for( PCB_LAYER_ID layer : aZone.GetLayerSet().Seq() )
165 {
166 std::shared_ptr<SHAPE_POLY_SET> fill = aZone.m_FilledPolysList.at( layer );
167
168 if( fill )
169 m_FilledPolysList[layer] = std::make_shared<SHAPE_POLY_SET>( *fill );
170 else
171 m_FilledPolysList[layer] = std::make_shared<SHAPE_POLY_SET>();
172
173 m_filledPolysHash[layer] = aZone.m_filledPolysHash.at( layer );
174 m_insulatedIslands[layer] = aZone.m_insulatedIslands.at( layer );
175 }
176
180
181 SetLocalFlags( aZone.GetLocalFlags() );
182
183 m_netinfo = aZone.m_netinfo;
184 m_area = aZone.m_area;
186}
187
188
190{
191 return new ZONE( *this );
192}
193
194
195bool ZONE::HigherPriority( const ZONE* aOther ) const
196{
197 // Teardrops are always higher priority than regular zones, so if one zone is a teardrop
198 // and the other is not, then return higher priority as the teardrop
199 if( ( m_teardropType == TEARDROP_TYPE::TD_NONE )
200 ^ ( aOther->m_teardropType == TEARDROP_TYPE::TD_NONE ) )
201 {
202 return static_cast<int>( m_teardropType ) > static_cast<int>( aOther->m_teardropType );
203 }
204
205 if( m_priority != aOther->m_priority )
206 return m_priority > aOther->m_priority;
207
208 return m_Uuid > aOther->m_Uuid;
209}
210
211
212bool ZONE::SameNet( const ZONE* aOther ) const
213{
214 return GetNetCode() == aOther->GetNetCode();
215}
216
217
219{
220 bool change = false;
221
222 for( std::pair<const PCB_LAYER_ID, std::shared_ptr<SHAPE_POLY_SET>>& pair : m_FilledPolysList )
223 {
224 change |= !pair.second->IsEmpty();
225 m_insulatedIslands[pair.first].clear();
226 pair.second->RemoveAllContours();
227 }
228
229 m_isFilled = false;
230 m_fillFlags.reset();
231
232 return change;
233}
234
235
237{
238 return HasFlag( COURTYARD_CONFLICT );
239}
240
241
243{
244 return GetCornerPosition( 0 );
245}
246
247
249{
250 return BOARD_ITEM::GetLayer();
251}
252
253
255{
256 if( m_layerSet.size() )
257 return m_layerSet.UIOrder()[0];
258 else
259 return UNDEFINED_LAYER;
260}
261
262
264{
265 return ( m_layerSet & LSET::AllCuMask() ).count() > 0;
266}
267
268
270{
271 SetLayerSet( LSET( aLayer ) );
272}
273
274
275void ZONE::SetLayerSet( LSET aLayerSet )
276{
277 if( aLayerSet.count() == 0 )
278 return;
279
280 if( m_layerSet != aLayerSet )
281 {
282 SetNeedRefill( true );
283
284 UnFill();
285
286 m_FilledPolysList.clear();
287 m_filledPolysHash.clear();
288 m_insulatedIslands.clear();
289
290 for( PCB_LAYER_ID layer : aLayerSet.Seq() )
291 {
292 m_FilledPolysList[layer] = std::make_shared<SHAPE_POLY_SET>();
293 m_filledPolysHash[layer] = {};
294 m_insulatedIslands[layer] = {};
295 }
296 }
297
298 m_layerSet = aLayerSet;
299}
300
301
302void ZONE::ViewGetLayers( int aLayers[], int& aCount ) const
303{
304 aCount = 0;
305 LSEQ layers = m_layerSet.Seq();
306
307 for( PCB_LAYER_ID layer : m_layerSet.Seq() )
308 {
309 aLayers[ aCount++ ] = layer; // For outline (always full opacity)
310 aLayers[ aCount++ ] = layer + LAYER_ZONE_START; // For fill (obeys global zone opacity)
311 }
312
313 if( IsConflicting() )
314 aLayers[ aCount++ ] = LAYER_CONFLICTS_SHADOW;
315}
316
317
318double ZONE::ViewGetLOD( int aLayer, KIGFX::VIEW* aView ) const
319{
320 constexpr double HIDE = std::numeric_limits<double>::max();
321
322 if( !aView )
323 return 0;
324
325 if( !aView->IsLayerVisible( LAYER_ZONES ) )
326 return HIDE;
327
328 if( FOOTPRINT* parentFP = GetParentFootprint() )
329 {
330 bool flipped = parentFP->GetLayer() == B_Cu;
331
332 // Handle Render tab switches
333 if( !flipped && !aView->IsLayerVisible( LAYER_MOD_FR ) )
334 return HIDE;
335
336 if( flipped && !aView->IsLayerVisible( LAYER_MOD_BK ) )
337 return HIDE;
338 }
339
340 // Other layers are shown without any conditions
341 return 0.0;
342}
343
344
345bool ZONE::IsOnLayer( PCB_LAYER_ID aLayer, bool aIncludeCourtyards ) const
346{
347 return m_layerSet.test( aLayer );
348}
349
350
352{
353 if( const BOARD* board = GetBoard() )
354 {
355 std::unordered_map<const ZONE*, BOX2I>& cache = board->m_ZoneBBoxCache;
356 auto cacheIter = cache.find( this );
357
358 if( cacheIter != cache.end() )
359 return cacheIter->second;
360
361 BOX2I bbox = m_Poly->BBox();
362
363 std::unique_lock<std::mutex> cacheLock( const_cast<BOARD*>( board )->m_CachesMutex );
364 cache[ this ] = bbox;
365
366 return bbox;
367 }
368
369 return m_Poly->BBox();
370}
371
372
374{
375 BOARD* board = GetBoard();
376 std::unordered_map<const ZONE*, BOX2I>& cache = board->m_ZoneBBoxCache;
377
378 auto cacheIter = cache.find( this );
379
380 if( cacheIter == cache.end() )
381 {
382 std::unique_lock<std::mutex> cacheLock( board->m_CachesMutex );
383 cache[ this ] = m_Poly->BBox();
384 }
385}
386
387
388int ZONE::GetThermalReliefGap( PAD* aPad, wxString* aSource ) const
389{
390 if( aPad->GetLocalThermalGapOverride() == 0 )
391 {
392 if( aSource )
393 *aSource = _( "zone" );
394
395 return m_thermalReliefGap;
396 }
397
398 return aPad->GetLocalThermalGapOverride( aSource );
399
400}
401
402
403void ZONE::SetCornerRadius( unsigned int aRadius )
404{
405 if( m_cornerRadius != aRadius )
406 SetNeedRefill( true );
407
408 m_cornerRadius = aRadius;
409}
410
411
413
414
416{
417 if( !m_filledPolysHash.count( aLayer ) )
418 return g_nullPoly.GetHash();
419 else
420 return m_filledPolysHash.at( aLayer );
421}
422
423
425{
426 if( !m_FilledPolysList.count( aLayer ) )
428 else
429 m_filledPolysHash[aLayer] = m_FilledPolysList.at( aLayer )->GetHash();
430}
431
432
433bool ZONE::HitTest( const VECTOR2I& aPosition, int aAccuracy ) const
434{
435 // When looking for an "exact" hit aAccuracy will be 0 which works poorly for very thin
436 // lines. Give it a floor.
437 int accuracy = std::max( aAccuracy, pcbIUScale.mmToIU( 0.1 ) );
438
439 return HitTestForCorner( aPosition, accuracy * 2 ) || HitTestForEdge( aPosition, accuracy );
440}
441
442
443bool ZONE::HitTestForCorner( const VECTOR2I& refPos, int aAccuracy,
444 SHAPE_POLY_SET::VERTEX_INDEX* aCornerHit ) const
445{
446 return m_Poly->CollideVertex( VECTOR2I( refPos ), aCornerHit, aAccuracy );
447}
448
449
450bool ZONE::HitTestForEdge( const VECTOR2I& refPos, int aAccuracy,
451 SHAPE_POLY_SET::VERTEX_INDEX* aCornerHit ) const
452{
453 return m_Poly->CollideEdge( VECTOR2I( refPos ), aCornerHit, aAccuracy );
454}
455
456
457bool ZONE::HitTest( const BOX2I& aRect, bool aContained, int aAccuracy ) const
458{
459 // Calculate bounding box for zone
460 BOX2I bbox = GetBoundingBox();
461 bbox.Normalize();
462
463 BOX2I arect = aRect;
464 arect.Normalize();
465 arect.Inflate( aAccuracy );
466
467 if( aContained )
468 {
469 return arect.Contains( bbox );
470 }
471 else
472 {
473 // Fast test: if aBox is outside the polygon bounding box, rectangles cannot intersect
474 if( !arect.Intersects( bbox ) )
475 return false;
476
477 int count = m_Poly->TotalVertices();
478
479 for( int ii = 0; ii < count; ii++ )
480 {
481 VECTOR2I vertex = m_Poly->CVertex( ii );
482 VECTOR2I vertexNext = m_Poly->CVertex( ( ii + 1 ) % count );
483
484 // Test if the point is within the rect
485 if( arect.Contains( vertex ) )
486 return true;
487
488 // Test if this edge intersects the rect
489 if( arect.Intersects( vertex, vertexNext ) )
490 return true;
491 }
492
493 return false;
494 }
495}
496
497
498int ZONE::GetLocalClearance( wxString* aSource ) const
499{
500 if( m_isRuleArea )
501 return 0;
502
503 if( aSource )
504 *aSource = _( "zone" );
505
506 return m_ZoneClearance;
507}
508
509
510bool ZONE::HitTestFilledArea( PCB_LAYER_ID aLayer, const VECTOR2I& aRefPos, int aAccuracy ) const
511{
512 // Rule areas have no filled area, but it's generally nice to treat their interior as if it were
513 // filled so that people don't have to select them by their outline (which is min-width)
514 if( GetIsRuleArea() )
515 return m_Poly->Contains( aRefPos, -1, aAccuracy );
516
517 if( !m_FilledPolysList.count( aLayer ) )
518 return false;
519
520 return m_FilledPolysList.at( aLayer )->Contains( aRefPos, -1, aAccuracy );
521}
522
523
524bool ZONE::HitTestCutout( const VECTOR2I& aRefPos, int* aOutlineIdx, int* aHoleIdx ) const
525{
526 // Iterate over each outline polygon in the zone and then iterate over
527 // each hole it has to see if the point is in it.
528 for( int i = 0; i < m_Poly->OutlineCount(); i++ )
529 {
530 for( int j = 0; j < m_Poly->HoleCount( i ); j++ )
531 {
532 if( m_Poly->Hole( i, j ).PointInside( aRefPos ) )
533 {
534 if( aOutlineIdx )
535 *aOutlineIdx = i;
536
537 if( aHoleIdx )
538 *aHoleIdx = j;
539
540 return true;
541 }
542 }
543 }
544
545 return false;
546}
547
548
549void ZONE::GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_ITEM>& aList )
550{
551 wxString msg = GetFriendlyName();
552
553 // Display Cutout instead of Outline for holes inside a zone (i.e. when num contour !=0).
554 // Check whether the selected corner is in a hole; i.e., in any contour but the first one.
555 if( m_CornerSelection != nullptr && m_CornerSelection->m_contour > 0 )
556 msg << wxT( " " ) << _( "Cutout" );
557
558 aList.emplace_back( _( "Type" ), msg );
559
560 if( GetIsRuleArea() )
561 {
562 msg.Empty();
563
564 if( GetDoNotAllowVias() )
565 AccumulateDescription( msg, _( "No vias" ) );
566
567 if( GetDoNotAllowTracks() )
568 AccumulateDescription( msg, _( "No tracks" ) );
569
570 if( GetDoNotAllowPads() )
571 AccumulateDescription( msg, _( "No pads" ) );
572
574 AccumulateDescription( msg, _( "No copper zones" ) );
575
577 AccumulateDescription( msg, _( "No footprints" ) );
578
579 if( !msg.IsEmpty() )
580 aList.emplace_back( _( "Restrictions" ), msg );
581 }
582 else if( IsOnCopperLayer() )
583 {
584 if( aFrame->GetName() == PCB_EDIT_FRAME_NAME )
585 {
586 aList.emplace_back( _( "Net" ), UnescapeString( GetNetname() ) );
587
588 aList.emplace_back( _( "Resolved Netclass" ),
589 UnescapeString( GetEffectiveNetClass()->GetName() ) );
590 }
591
592 // Display priority level
593 aList.emplace_back( _( "Priority" ),
594 wxString::Format( wxT( "%d" ), GetAssignedPriority() ) );
595 }
596
597 if( aFrame->GetName() == PCB_EDIT_FRAME_NAME )
598 {
599 if( IsLocked() )
600 aList.emplace_back( _( "Status" ), _( "Locked" ) );
601 }
602
603 wxString layerDesc;
604 int count = 0;
605
606 for( PCB_LAYER_ID layer : m_layerSet.Seq() )
607 {
608 if( count == 0 )
609 layerDesc = GetBoard()->GetLayerName( layer );
610
611 count++;
612 }
613
614 if( count > 1 )
615 layerDesc.Printf( _( "%s and %d more" ), layerDesc, count - 1 );
616
617 aList.emplace_back( _( "Layer" ), layerDesc );
618
619 if( !m_zoneName.empty() )
620 aList.emplace_back( _( "Name" ), m_zoneName );
621
622 switch( m_fillMode )
623 {
624 case ZONE_FILL_MODE::POLYGONS: msg = _( "Solid" ); break;
625 case ZONE_FILL_MODE::HATCH_PATTERN: msg = _( "Hatched" ); break;
626 default: msg = _( "Unknown" ); break;
627 }
628
629 aList.emplace_back( _( "Fill Mode" ), msg );
630
631 aList.emplace_back( _( "Filled Area" ),
632 aFrame->MessageTextFromValue( m_area, true, EDA_DATA_TYPE::AREA ) );
633
634 wxString source;
635 int clearance = GetOwnClearance( UNDEFINED_LAYER, &source );
636
637 if( !source.IsEmpty() )
638 {
639 aList.emplace_back( wxString::Format( _( "Min Clearance: %s" ),
640 aFrame->MessageTextFromValue( clearance ) ),
641 wxString::Format( _( "(from %s)" ),
642 source ) );
643 }
644
645 if( !m_FilledPolysList.empty() )
646 {
647 count = 0;
648
649 for( std::pair<const PCB_LAYER_ID, std::shared_ptr<SHAPE_POLY_SET>>& ii: m_FilledPolysList )
650 count += ii.second->TotalVertices();
651
652 aList.emplace_back( _( "Corner Count" ), wxString::Format( wxT( "%d" ), count ) );
653 }
654}
655
656
657void ZONE::Move( const VECTOR2I& offset )
658{
659 /* move outlines */
660 m_Poly->Move( offset );
661
662 HatchBorder();
663
664 /* move fills */
665 for( std::pair<const PCB_LAYER_ID, std::shared_ptr<SHAPE_POLY_SET>>& pair : m_FilledPolysList )
666 pair.second->Move( offset );
667
668 /*
669 * move boundingbox cache
670 *
671 * While the cache will get nuked at the conclusion of the operation, we use it for some
672 * things (such as drawing the parent group) during the move.
673 */
674 if( GetBoard() )
675 {
676 auto it = GetBoard()->m_ZoneBBoxCache.find( this );
677
678 if( it != GetBoard()->m_ZoneBBoxCache.end() )
679 it->second.Move( offset );
680 }
681}
682
683
684wxString ZONE::GetFriendlyName() const
685{
686 if( GetIsRuleArea() )
687 return _( "Rule Area" );
688 else if( IsTeardropArea() )
689 return _( "Teardrop Area" );
690 else if( IsOnCopperLayer() )
691 return _( "Copper Zone" );
692 else
693 return _( "Non-copper Zone" );
694}
695
696
697void ZONE::MoveEdge( const VECTOR2I& offset, int aEdge )
698{
699 int next_corner;
700
701 if( m_Poly->GetNeighbourIndexes( aEdge, nullptr, &next_corner ) )
702 {
703 m_Poly->SetVertex( aEdge, m_Poly->CVertex( aEdge ) + VECTOR2I( offset ) );
704 m_Poly->SetVertex( next_corner, m_Poly->CVertex( next_corner ) + VECTOR2I( offset ) );
705 HatchBorder();
706
707 SetNeedRefill( true );
708 }
709}
710
711
712void ZONE::Rotate( const VECTOR2I& aCentre, const EDA_ANGLE& aAngle )
713{
714 m_Poly->Rotate( aAngle, aCentre );
715 HatchBorder();
716
717 /* rotate filled areas: */
718 for( std::pair<const PCB_LAYER_ID, std::shared_ptr<SHAPE_POLY_SET>>& pair : m_FilledPolysList )
719 pair.second->Rotate( aAngle, aCentre );
720}
721
722
723void ZONE::Flip( const VECTOR2I& aCentre, bool aFlipLeftRight )
724{
725 Mirror( aCentre, aFlipLeftRight );
726
727 SetLayerSet( FlipLayerMask( GetLayerSet(), GetBoard()->GetCopperLayerCount() ) );
728}
729
730
731void ZONE::Mirror( const VECTOR2I& aMirrorRef, bool aMirrorLeftRight )
732{
733 m_Poly->Mirror( aMirrorLeftRight, !aMirrorLeftRight, aMirrorRef );
734
735 HatchBorder();
736
737 for( std::pair<const PCB_LAYER_ID, std::shared_ptr<SHAPE_POLY_SET>>& pair : m_FilledPolysList )
738 pair.second->Mirror( aMirrorLeftRight, !aMirrorLeftRight, aMirrorRef );
739}
740
741
742void ZONE::RemoveCutout( int aOutlineIdx, int aHoleIdx )
743{
744 // Ensure the requested cutout is valid
745 if( m_Poly->OutlineCount() < aOutlineIdx || m_Poly->HoleCount( aOutlineIdx ) < aHoleIdx )
746 return;
747
748 SHAPE_POLY_SET cutPoly( m_Poly->Hole( aOutlineIdx, aHoleIdx ) );
749
750 // Add the cutout back to the zone
752
753 SetNeedRefill( true );
754}
755
756
757void ZONE::AddPolygon( const SHAPE_LINE_CHAIN& aPolygon )
758{
759 wxASSERT( aPolygon.IsClosed() );
760
761 // Add the outline as a new polygon in the polygon set
762 if( m_Poly->OutlineCount() == 0 )
763 m_Poly->AddOutline( aPolygon );
764 else
765 m_Poly->AddHole( aPolygon );
766
767 SetNeedRefill( true );
768}
769
770
771void ZONE::AddPolygon( std::vector<VECTOR2I>& aPolygon )
772{
773 if( aPolygon.empty() )
774 return;
775
776 SHAPE_LINE_CHAIN outline;
777
778 // Create an outline and populate it with the points of aPolygon
779 for( const VECTOR2I& pt : aPolygon )
780 outline.Append( pt );
781
782 outline.SetClosed( true );
783
784 AddPolygon( outline );
785}
786
787
788bool ZONE::AppendCorner( VECTOR2I aPosition, int aHoleIdx, bool aAllowDuplication )
789{
790 // Ensure the main outline exists:
791 if( m_Poly->OutlineCount() == 0 )
793
794 // If aHoleIdx >= 0, the corner musty be added to the hole, index aHoleIdx.
795 // (remember: the index of the first hole is 0)
796 // Return error if it does not exist.
797 if( aHoleIdx >= m_Poly->HoleCount( 0 ) )
798 return false;
799
800 m_Poly->Append( aPosition.x, aPosition.y, -1, aHoleIdx, aAllowDuplication );
801
802 SetNeedRefill( true );
803
804 return true;
805}
806
807
808wxString ZONE::GetItemDescription( UNITS_PROVIDER* aUnitsProvider ) const
809{
810 wxString layerDesc;
811 int count = 0;
812
813 for( PCB_LAYER_ID layer : m_layerSet.Seq() )
814 {
815 if( count == 0 )
816 layerDesc = GetBoard()->GetLayerName( layer );
817
818 count++;
819 }
820
821 if( count > 1 )
822 layerDesc.Printf( _( "%s and %d more" ), layerDesc, count - 1 );
823
824 // Check whether the selected contour is a hole (contour index > 0)
825 if( m_CornerSelection != nullptr && m_CornerSelection->m_contour > 0 )
826 {
827 if( GetIsRuleArea() )
828 return wxString::Format( _( "Rule Area Cutout on %s" ), layerDesc );
829 else
830 return wxString::Format( _( "Zone Cutout on %s" ), layerDesc );
831 }
832 else
833 {
834 if( GetIsRuleArea() )
835 return wxString::Format( _( "Rule Area on %s" ), layerDesc );
836 else
837 return wxString::Format( _( "Zone %s on %s" ), GetNetnameMsg(), layerDesc );
838 }
839}
840
841
843{
844 return m_borderHatchPitch;
845}
846
847
849 int aBorderHatchPitch, bool aRebuildBorderHatch )
850{
851 aBorderHatchPitch = std::max( aBorderHatchPitch,
853 aBorderHatchPitch = std::min( aBorderHatchPitch,
855 SetBorderHatchPitch( aBorderHatchPitch );
856 m_borderStyle = aBorderHatchStyle;
857
858 if( aRebuildBorderHatch )
859 HatchBorder();
860}
861
862
864{
865 m_borderHatchPitch = aPitch;
866}
867
868
870{
871 m_borderHatchLines.clear();
872}
873
874
875// Creates hatch lines inside the outline of the complex polygon
876// sort function used in ::HatchBorder to sort points by descending VECTOR2I.x values
877bool sortEndsByDescendingX( const VECTOR2I& ref, const VECTOR2I& tst )
878{
879 return tst.x < ref.x;
880}
881
882
884{
886
887 if( m_borderStyle == ZONE_BORDER_DISPLAY_STYLE::NO_HATCH
888 || m_borderHatchPitch == 0
889 || m_Poly->IsEmpty() )
890 {
891 return;
892 }
893
894 // define range for hatch lines
895 int min_x = m_Poly->CVertex( 0 ).x;
896 int max_x = m_Poly->CVertex( 0 ).x;
897 int min_y = m_Poly->CVertex( 0 ).y;
898 int max_y = m_Poly->CVertex( 0 ).y;
899
900 for( auto iterator = m_Poly->IterateWithHoles(); iterator; iterator++ )
901 {
902 if( iterator->x < min_x )
903 min_x = iterator->x;
904
905 if( iterator->x > max_x )
906 max_x = iterator->x;
907
908 if( iterator->y < min_y )
909 min_y = iterator->y;
910
911 if( iterator->y > max_y )
912 max_y = iterator->y;
913 }
914
915 // Calculate spacing between 2 hatch lines
916 int spacing;
917
918 if( m_borderStyle == ZONE_BORDER_DISPLAY_STYLE::DIAGONAL_EDGE )
919 spacing = m_borderHatchPitch;
920 else
921 spacing = m_borderHatchPitch * 2;
922
923 // set the "length" of hatch lines (the length on horizontal axis)
924 int hatch_line_len = m_borderHatchPitch;
925
926 // To have a better look, give a slope depending on the layer
927 int layer = GetFirstLayer();
928 std::vector<int> slope_flags;
929
930 if( IsTeardropArea() )
931 slope_flags = { 1, -1 };
932 else if( layer & 1 )
933 slope_flags = { 1 };
934 else
935 slope_flags = { -1 };
936
937 for( int slope_flag : slope_flags )
938 {
939 double slope = 0.707106 * slope_flag; // 45 degrees slope
940 int64_t max_a, min_a;
941
942 if( slope_flag == 1 )
943 {
944 max_a = KiROUND( max_y - slope * min_x );
945 min_a = KiROUND( min_y - slope * max_x );
946 }
947 else
948 {
949 max_a = KiROUND( max_y - slope * max_x );
950 min_a = KiROUND( min_y - slope * min_x );
951 }
952
953 min_a = (min_a / spacing) * spacing;
954
955 // calculate an offset depending on layer number,
956 // for a better look of hatches on a multilayer board
957 int offset = (layer * 7) / 8;
958 min_a += offset;
959
960 // loop through hatch lines
961 std::vector<VECTOR2I> pointbuffer;
962 pointbuffer.reserve( 256 );
963
964 for( int64_t a = min_a; a < max_a; a += spacing )
965 {
966 pointbuffer.clear();
967
968 // Iterate through all vertices
969 for( auto iterator = m_Poly->IterateSegmentsWithHoles(); iterator; iterator++ )
970 {
971 const SEG seg = *iterator;
972 double x, y;
973
974 if( FindLineSegmentIntersection( a, slope, seg.A.x, seg.A.y, seg.B.x, seg.B.y, x, y ) )
975 pointbuffer.emplace_back( KiROUND( x ), KiROUND( y ) );
976 }
977
978 // sort points in order of descending x (if more than 2) to
979 // ensure the starting point and the ending point of the same segment
980 // are stored one just after the other.
981 if( pointbuffer.size() > 2 )
982 sort( pointbuffer.begin(), pointbuffer.end(), sortEndsByDescendingX );
983
984 // creates lines or short segments inside the complex polygon
985 for( size_t ip = 0; ip + 1 < pointbuffer.size(); ip += 2 )
986 {
987 int dx = pointbuffer[ip + 1].x - pointbuffer[ip].x;
988
989 // Push only one line for diagonal hatch,
990 // or for small lines < twice the line length
991 // else push 2 small lines
992 if( m_borderStyle == ZONE_BORDER_DISPLAY_STYLE::DIAGONAL_FULL
993 || std::abs( dx ) < 2 * hatch_line_len )
994 {
995 m_borderHatchLines.emplace_back( SEG( pointbuffer[ip], pointbuffer[ ip + 1] ) );
996 }
997 else
998 {
999 double dy = pointbuffer[ip + 1].y - pointbuffer[ip].y;
1000 slope = dy / dx;
1001
1002 if( dx > 0 )
1003 dx = hatch_line_len;
1004 else
1005 dx = -hatch_line_len;
1006
1007 int x1 = KiROUND( pointbuffer[ip].x + dx );
1008 int x2 = KiROUND( pointbuffer[ip + 1].x - dx );
1009 int y1 = KiROUND( pointbuffer[ip].y + dx * slope );
1010 int y2 = KiROUND( pointbuffer[ip + 1].y - dx * slope );
1011
1012 m_borderHatchLines.emplace_back( SEG( pointbuffer[ip].x, pointbuffer[ip].y,
1013 x1, y1 ) );
1014
1015 m_borderHatchLines.emplace_back( SEG( pointbuffer[ip+1].x, pointbuffer[ip+1].y,
1016 x2, y2 ) );
1017 }
1018 }
1019 }
1020 }
1021}
1022
1023
1025{
1027}
1028
1029
1031{
1032 return BITMAPS::add_zone;
1033}
1034
1035
1037{
1038 assert( aImage->Type() == PCB_ZONE_T );
1039
1040 std::swap( *static_cast<ZONE*>( this ), *static_cast<ZONE*>( aImage) );
1041}
1042
1043
1045{
1046 if( aLayer == UNDEFINED_LAYER )
1047 {
1048 for( auto& [ layer, poly ] : m_FilledPolysList )
1049 poly->CacheTriangulation();
1050
1051 m_Poly->CacheTriangulation( false );
1052 }
1053 else
1054 {
1055 if( m_FilledPolysList.count( aLayer ) )
1056 m_FilledPolysList[ aLayer ]->CacheTriangulation();
1057 }
1058}
1059
1060
1061bool ZONE::IsIsland( PCB_LAYER_ID aLayer, int aPolyIdx ) const
1062{
1063 if( GetNetCode() < 1 )
1064 return true;
1065
1066 if( !m_insulatedIslands.count( aLayer ) )
1067 return false;
1068
1069 return m_insulatedIslands.at( aLayer ).count( aPolyIdx );
1070}
1071
1072
1073void ZONE::GetInteractingZones( PCB_LAYER_ID aLayer, std::vector<ZONE*>* aSameNetCollidingZones,
1074 std::vector<ZONE*>* aOtherNetIntersectingZones ) const
1075{
1076 int epsilon = pcbIUScale.mmToIU( 0.001 );
1077 BOX2I bbox = GetBoundingBox();
1078
1079 bbox.Inflate( epsilon );
1080
1081 for( ZONE* candidate : GetBoard()->Zones() )
1082 {
1083 if( candidate == this )
1084 continue;
1085
1086 if( !candidate->GetLayerSet().test( aLayer ) )
1087 continue;
1088
1089 if( candidate->GetIsRuleArea() || candidate->IsTeardropArea() )
1090 continue;
1091
1092 if( !candidate->GetBoundingBox().Intersects( bbox ) )
1093 continue;
1094
1095 if( candidate->GetNetCode() == GetNetCode() )
1096 {
1097 if( m_Poly->Collide( candidate->m_Poly ) )
1098 aSameNetCollidingZones->push_back( candidate );
1099 }
1100 else
1101 {
1102 aOtherNetIntersectingZones->push_back( candidate );
1103 }
1104 }
1105}
1106
1107
1109 SHAPE_POLY_SET* aBoardOutline,
1110 SHAPE_POLY_SET* aSmoothedPolyWithApron ) const
1111{
1112 if( GetNumCorners() <= 2 ) // malformed zone. polygon calculations will not like it ...
1113 return false;
1114
1115 // Processing of arc shapes in zones is not yet supported because Clipper can't do boolean
1116 // operations on them. The poly outline must be converted to segments first.
1118 flattened.ClearArcs();
1119
1120 if( GetIsRuleArea() )
1121 {
1122 // We like keepouts just the way they are....
1123 aSmoothedPoly = flattened;
1124 return true;
1125 }
1126
1127 const BOARD* board = GetBoard();
1128 int maxError = ARC_HIGH_DEF;
1129 bool keepExternalFillets = false;
1132
1133 if( IsTeardropArea() )
1134 {
1135 // We use teardrop shapes with no smoothing; these shapes are already optimized
1136 smooth_requested = false;
1137 }
1138
1139 if( board )
1140 {
1142
1143 maxError = bds.m_MaxError;
1144 keepExternalFillets = bds.m_ZoneKeepExternalFillets;
1145 }
1146
1147 auto smooth = [&]( SHAPE_POLY_SET& aPoly )
1148 {
1149 if( !smooth_requested )
1150 return;
1151
1152 switch( m_cornerSmoothingType )
1153 {
1155 aPoly = aPoly.Chamfer( (int) m_cornerRadius );
1156 break;
1157
1159 {
1160 aPoly = aPoly.Fillet( (int) m_cornerRadius, maxError );
1161 break;
1162 }
1163
1164 default:
1165 break;
1166 }
1167 };
1168
1169 SHAPE_POLY_SET* maxExtents = &flattened;
1170 SHAPE_POLY_SET withFillets;
1171
1172 aSmoothedPoly = flattened;
1173
1174 // Should external fillets (that is, those applied to concave corners) be kept? While it
1175 // seems safer to never have copper extend outside the zone outline, 5.1.x and prior did
1176 // indeed fill them so we leave the mode available.
1177 if( keepExternalFillets && smooth_requested )
1178 {
1179 withFillets = flattened;
1180 smooth( withFillets );
1181 withFillets.BooleanAdd( flattened, SHAPE_POLY_SET::PM_FAST );
1182 maxExtents = &withFillets;
1183 }
1184
1185 // We now add in the areas of any same-net, intersecting zones. This keeps us from smoothing
1186 // corners at an intersection (which often produces undesired divots between the intersecting
1187 // zones -- see #2752).
1188 //
1189 // After smoothing, we'll subtract back out everything outside of our zone.
1190 std::vector<ZONE*> sameNetCollidingZones;
1191 std::vector<ZONE*> otherNetIntersectingZones;
1192 GetInteractingZones( aLayer, &sameNetCollidingZones, &otherNetIntersectingZones );
1193
1194 for( ZONE* sameNetZone : sameNetCollidingZones )
1195 {
1196 BOX2I sameNetBoundingBox = sameNetZone->GetBoundingBox();
1197 SHAPE_POLY_SET sameNetPoly = sameNetZone->Outline()->CloneDropTriangulation();
1198
1199 SHAPE_POLY_SET diffNetPoly;
1201
1202 sameNetPoly.ClearArcs();
1203
1204 // Of course there's always a wrinkle. The same-net intersecting zone *might* get knocked
1205 // out along the border by a higher-priority, different-net zone. #12797
1206 for( ZONE* otherNetZone : otherNetIntersectingZones )
1207 {
1208 if( otherNetZone->HigherPriority( sameNetZone )
1209 && otherNetZone->GetBoundingBox().Intersects( sameNetBoundingBox ) )
1210 {
1211 diffNetPoly.BooleanAdd( *otherNetZone->Outline(), SHAPE_POLY_SET::PM_FAST );
1212 }
1213 }
1214
1215 // Second wrinkle. After unioning the higher priority, different net zones together,
1216 // we need to check to see if they completely enclose our zone. If they do, then
1217 // we need to treat the enclosed zone as isolated, not connected to the outer zone
1218 // #13915
1219 if( diffNetPoly.OutlineCount() )
1220 sumPoly.BooleanSubtract( diffNetPoly, SHAPE_POLY_SET::PM_FAST );
1221
1222 if( sumPoly.OutlineCount() )
1223 aSmoothedPoly.BooleanAdd( sameNetPoly, SHAPE_POLY_SET::PM_FAST );
1224 }
1225
1226 if( aBoardOutline )
1227 aSmoothedPoly.BooleanIntersection( *aBoardOutline, SHAPE_POLY_SET::PM_STRICTLY_SIMPLE );
1228
1229 smooth( aSmoothedPoly );
1230
1231 if( aSmoothedPolyWithApron )
1232 {
1233 SHAPE_POLY_SET poly = maxExtents->CloneDropTriangulation();
1235 *aSmoothedPolyWithApron = aSmoothedPoly;
1236 aSmoothedPolyWithApron->BooleanIntersection( poly, SHAPE_POLY_SET::PM_FAST );
1237 }
1238
1239 aSmoothedPoly.BooleanIntersection( *maxExtents, SHAPE_POLY_SET::PM_FAST );
1240
1241 return true;
1242}
1243
1244
1246{
1247 m_area = 0.0;
1248
1249 // Iterate over each outline polygon in the zone and then iterate over
1250 // each hole it has to compute the total area.
1251 for( std::pair<const PCB_LAYER_ID, std::shared_ptr<SHAPE_POLY_SET>>& pair : m_FilledPolysList )
1252 {
1253 std::shared_ptr<SHAPE_POLY_SET>& poly = pair.second;
1254
1255 for( int i = 0; i < poly->OutlineCount(); i++ )
1256 {
1257 m_area += poly->Outline( i ).Area();
1258
1259 for( int j = 0; j < poly->HoleCount( i ); j++ )
1260 m_area -= poly->Hole( i, j ).Area();
1261 }
1262 }
1263
1264 return m_area;
1265}
1266
1267
1269{
1271 return m_outlinearea;
1272}
1273
1274
1276 int aMaxError, ERROR_LOC aErrorLoc,
1277 SHAPE_POLY_SET* aBoardOutline ) const
1278{
1279 // Creates the zone outline polygon (with holes if any)
1280 SHAPE_POLY_SET polybuffer;
1281
1282 // TODO: using GetFirstLayer() means it only works for single-layer zones....
1283 BuildSmoothedPoly( polybuffer, GetFirstLayer(), aBoardOutline );
1284
1285 // Calculate the polygon with clearance
1286 // holes are linked to the main outline, so only one polygon is created.
1287 if( aClearance )
1288 {
1289 const BOARD* board = GetBoard();
1290 int maxError = ARC_HIGH_DEF;
1291
1292 if( board )
1293 maxError = board->GetDesignSettings().m_MaxError;
1294
1295 if( aErrorLoc == ERROR_OUTSIDE )
1296 aClearance += maxError;
1297
1298 polybuffer.Inflate( aClearance, SHAPE_POLY_SET::ROUND_ALL_CORNERS, maxError );
1299 }
1300
1301 polybuffer.Fracture( SHAPE_POLY_SET::PM_FAST );
1302 aBuffer.Append( polybuffer );
1303}
1304
1305
1306std::shared_ptr<SHAPE> ZONE::GetEffectiveShape( PCB_LAYER_ID aLayer, FLASHING aFlash ) const
1307{
1308 if( m_FilledPolysList.find( aLayer ) == m_FilledPolysList.end() )
1309 return std::make_shared<SHAPE_NULL>();
1310 else
1311 return m_FilledPolysList.at( aLayer );
1312}
1313
1314
1315void ZONE::TransformShapeToPolygon( SHAPE_POLY_SET& aBuffer, PCB_LAYER_ID aLayer, int aClearance,
1316 int aError, ERROR_LOC aErrorLoc, bool aIgnoreLineWidth ) const
1317{
1318 wxASSERT_MSG( !aIgnoreLineWidth, wxT( "IgnoreLineWidth has no meaning for zones." ) );
1319
1320 if( !m_FilledPolysList.count( aLayer ) )
1321 return;
1322
1323 if( !aClearance )
1324 {
1325 aBuffer.Append( *m_FilledPolysList.at( aLayer ) );
1326 return;
1327 }
1328
1329 SHAPE_POLY_SET temp_buf = m_FilledPolysList.at( aLayer )->CloneDropTriangulation();
1330
1331 // Rebuild filled areas only if clearance is not 0
1332 if( aClearance > 0 || aErrorLoc == ERROR_OUTSIDE )
1333 {
1334 if( aErrorLoc == ERROR_OUTSIDE )
1335 aClearance += aError;
1336
1337 temp_buf.InflateWithLinkedHoles( aClearance, SHAPE_POLY_SET::ROUND_ALL_CORNERS, aError,
1339 }
1340
1341 aBuffer.Append( temp_buf );
1342}
1343
1344
1346{
1347 if( m_FilledPolysList.count( aLayer ) && !m_FilledPolysList.at( aLayer )->IsEmpty() )
1348 aBuffer.Append( *m_FilledPolysList.at( aLayer ) );
1349}
1350
1351
1352static struct ZONE_DESC
1353{
1355 {
1357
1358 if( layerEnum.Choices().GetCount() == 0 )
1359 {
1360 layerEnum.Undefined( UNDEFINED_LAYER );
1361
1362 for( LSEQ seq = LSET::AllLayersMask().Seq(); seq; ++seq )
1363 layerEnum.Map( *seq, LSET::Name( *seq ) );
1364 }
1365
1367
1368 if( zcMap.Choices().GetCount() == 0 )
1369 {
1370 zcMap.Undefined( ZONE_CONNECTION::INHERITED );
1371 zcMap.Map( ZONE_CONNECTION::INHERITED, _HKI( "Inherited" ) )
1372 .Map( ZONE_CONNECTION::NONE, _HKI( "None" ) )
1373 .Map( ZONE_CONNECTION::THERMAL, _HKI( "Thermal reliefs" ) )
1374 .Map( ZONE_CONNECTION::FULL, _HKI( "Solid" ) )
1375 .Map( ZONE_CONNECTION::THT_THERMAL, _HKI( "Thermal reliefs for PTH" ) );
1376 }
1377
1379
1380 if( zfmMap.Choices().GetCount() == 0 )
1381 {
1382 zfmMap.Undefined( ZONE_FILL_MODE::POLYGONS );
1383 zfmMap.Map( ZONE_FILL_MODE::POLYGONS, _HKI( "Solid fill" ) )
1384 .Map( ZONE_FILL_MODE::HATCH_PATTERN, _HKI( "Hatch pattern" ) );
1385 }
1386
1390
1391 // Mask layer and position properties; they aren't useful in current form
1392 auto posX = new PROPERTY<ZONE, int>( _HKI( "Position X" ),
1393 NO_SETTER( ZONE, int ),
1394 reinterpret_cast<int (ZONE::*)() const>( &ZONE::GetX ),
1395 PROPERTY_DISPLAY::PT_COORD,
1397 posX->SetIsHiddenFromPropertiesManager();
1398
1399 auto posY = new PROPERTY<ZONE, int>( _HKI( "Position Y" ), NO_SETTER( ZONE, int ),
1400 reinterpret_cast<int (ZONE::*)() const>( &ZONE::GetY ),
1401 PROPERTY_DISPLAY::PT_COORD,
1403 posY->SetIsHiddenFromPropertiesManager();
1404
1405 propMgr.ReplaceProperty( TYPE_HASH( BOARD_ITEM ), _HKI( "Position X" ), posX );
1406 propMgr.ReplaceProperty( TYPE_HASH( BOARD_ITEM ), _HKI( "Position Y" ), posY );
1407
1408 auto isCopperZone =
1409 []( INSPECTABLE* aItem ) -> bool
1410 {
1411 if( ZONE* zone = dynamic_cast<ZONE*>( aItem ) )
1412 return !zone->GetIsRuleArea() && IsCopperLayer( zone->GetFirstLayer() );
1413
1414 return false;
1415 };
1416
1417 auto isHatchedFill =
1418 []( INSPECTABLE* aItem ) -> bool
1419 {
1420 if( ZONE* zone = dynamic_cast<ZONE*>( aItem ) )
1421 return zone->GetFillMode() == ZONE_FILL_MODE::HATCH_PATTERN;
1422
1423 return false;
1424 };
1425
1426 // Layer property is hidden because it only holds a single layer and zones actually use
1427 // a layer set
1428 propMgr.ReplaceProperty( TYPE_HASH( BOARD_CONNECTED_ITEM ), _HKI( "Layer" ),
1431 &ZONE::GetLayer ) )
1432 .SetIsHiddenFromPropertiesManager();
1433
1435 _HKI( "Net" ), isCopperZone );
1437 _HKI( "Net Class" ), isCopperZone );
1438
1439 propMgr.AddProperty( new PROPERTY<ZONE, unsigned>( _HKI( "Priority" ),
1442 .SetAvailableFunc( isCopperZone );
1443
1444 propMgr.AddProperty( new PROPERTY<ZONE, wxString>( _HKI( "Name" ),
1446
1447 const wxString groupFill = _HKI( "Fill Style" );
1448
1449 propMgr.AddProperty( new PROPERTY_ENUM<ZONE, ZONE_FILL_MODE>( _HKI( "Fill Mode" ),
1452 groupFill );
1453
1454 propMgr.AddProperty( new PROPERTY<ZONE, EDA_ANGLE>( _HKI( "Orientation" ),
1457 PROPERTY_DISPLAY::PT_DEGREE ),
1458 groupFill )
1459 .SetWriteableFunc( isHatchedFill );
1460
1461 // TODO: Switch to translated
1462 auto atLeastMinWidthValidator =
1463 []( const wxAny&& aValue, EDA_ITEM* aZone ) -> VALIDATOR_RESULT
1464 {
1465 int val = aValue.As<int>();
1466 ZONE* zone = dynamic_cast<ZONE*>( aZone );
1467 wxCHECK( zone, std::nullopt );
1468
1469 if( val < zone->GetMinThickness() )
1470 {
1471 return std::make_unique<VALIDATION_ERROR_MSG>(
1472 wxT( "Cannot be less than zone minimum width" ) );
1473 }
1474
1475 return std::nullopt;
1476 };
1477
1478 // TODO: Switch to translated
1479 propMgr.AddProperty( new PROPERTY<ZONE, int>( wxT( "Hatch Width" ),
1482 PROPERTY_DISPLAY::PT_SIZE ),
1483 groupFill )
1484 .SetWriteableFunc( isHatchedFill )
1485 .SetValidator( atLeastMinWidthValidator );
1486
1487 // TODO: Switch to translated
1488 propMgr.AddProperty( new PROPERTY<ZONE, int>( wxT( "Hatch Gap" ), &ZONE::SetHatchGap,
1490 PROPERTY_DISPLAY::PT_SIZE ),
1491 groupFill )
1492 .SetWriteableFunc( isHatchedFill )
1493 .SetValidator( atLeastMinWidthValidator );
1494
1495 // TODO: Smoothing effort needs to change to enum (in dialog too)
1496 // TODO: Smoothing amount (double)
1497 // Unexposed properties (HatchHoleMinArea / HatchBorderAlgorithm)?
1498
1499 const wxString groupOverrides = _HKI( "Overrides" );
1500
1501 auto clearanceOverride = new PROPERTY<ZONE, int>( _HKI( "Clearance Override" ),
1503 PROPERTY_DISPLAY::PT_SIZE );
1504 clearanceOverride->SetAvailableFunc( isCopperZone );
1505 constexpr int maxClearance = pcbIUScale.mmToIU( ZONE_CLEARANCE_MAX_VALUE_MM );
1506 clearanceOverride->SetValidator( PROPERTY_VALIDATORS::RangeIntValidator<0, maxClearance> );
1507
1508 auto minWidth = new PROPERTY<ZONE, int>( _HKI( "Minimum Width" ),
1510 PROPERTY_DISPLAY::PT_SIZE );
1511 minWidth->SetAvailableFunc( isCopperZone );
1512 constexpr int minMinWidth = pcbIUScale.mmToIU( ZONE_THICKNESS_MIN_VALUE_MM );
1513 clearanceOverride->SetValidator( PROPERTY_VALIDATORS::RangeIntValidator<minMinWidth,
1514 INT_MAX> );
1515
1516 auto padConnections = new PROPERTY_ENUM<ZONE, ZONE_CONNECTION>( _HKI( "Pad Connections" ),
1518 padConnections->SetAvailableFunc( isCopperZone );
1519
1520 auto thermalGap = new PROPERTY<ZONE, int>( _HKI( "Thermal Relief Gap" ),
1522 PROPERTY_DISPLAY::PT_SIZE );
1523 thermalGap->SetAvailableFunc( isCopperZone );
1524 thermalGap->SetValidator( PROPERTY_VALIDATORS::PositiveIntValidator );
1525
1526 auto thermalSpokeWidth = new PROPERTY<ZONE, int>( _HKI( "Thermal Relief Spoke Width" ),
1528 PROPERTY_DISPLAY::PT_SIZE );
1529 thermalSpokeWidth->SetAvailableFunc( isCopperZone );
1530 thermalSpokeWidth->SetValidator( atLeastMinWidthValidator );
1531
1532 propMgr.AddProperty( clearanceOverride, groupOverrides );
1533 propMgr.AddProperty( minWidth, groupOverrides );
1534 propMgr.AddProperty( padConnections, groupOverrides );
1535 propMgr.AddProperty( thermalGap, groupOverrides );
1536 propMgr.AddProperty( thermalSpokeWidth, groupOverrides );
1537 }
1539
constexpr int ARC_HIGH_DEF
Definition: base_units.h:121
constexpr EDA_IU_SCALE pcbIUScale
Definition: base_units.h:109
BITMAPS
A list of all bitmap identifiers.
Definition: bitmaps_list.h:33
A base class derived from BOARD_ITEM for items that can be connected and have a net,...
wxString GetNetnameMsg() const
virtual NETCLASS * GetEffectiveNetClass() const
Return the NETCLASS for this item.
NETINFO_ITEM * m_netinfo
Store all information about the net that item belongs to.
virtual int GetOwnClearance(PCB_LAYER_ID aLayer, wxString *aSource=nullptr) const
Return an item's "own" clearance in internal units.
Container for design settings for a BOARD object.
Abstract interface for BOARD_ITEMs capable of storing other items inside.
virtual const ZONE_SETTINGS & GetZoneSettings() const
Fetch the zone settings for this container.
A base class for any item which can be embedded within the BOARD container class, and therefore insta...
Definition: board_item.h:71
virtual PCB_LAYER_ID GetLayer() const
Return the primary layer this item is on.
Definition: board_item.h:196
int GetY() const
Definition: board_item.h:95
int GetX() const
Definition: board_item.h:89
virtual const BOARD * GetBoard() const
Return the BOARD in which this BOARD_ITEM resides, or NULL if none.
Definition: board_item.cpp:44
FOOTPRINT * GetParentFootprint() const
Definition: board_item.cpp:240
virtual bool IsLocked() const
Definition: board_item.cpp:72
Information pertinent to a Pcbnew printed circuit board.
Definition: board.h:270
std::unordered_map< const ZONE *, BOX2I > m_ZoneBBoxCache
Definition: board.h:1185
const wxString GetLayerName(PCB_LAYER_ID aLayer) const
Return the name of a aLayer.
Definition: board.cpp:498
BOARD_DESIGN_SETTINGS & GetDesignSettings() const
Definition: board.cpp:728
std::mutex m_CachesMutex
Definition: board.h:1176
BOX2< Vec > & Normalize()
Ensure that the height and width are positive.
Definition: box2.h:119
bool Intersects(const BOX2< Vec > &aRect) const
Definition: box2.h:269
bool Contains(const Vec &aPoint) const
Definition: box2.h:141
BOX2< Vec > & Inflate(coord_type dx, coord_type dy)
Inflates the rectangle horizontally by dx and vertically by dy.
Definition: box2.h:506
The base class for create windows for drawing purpose.
A base class for most all the KiCad significant classes used in schematics and boards.
Definition: eda_item.h:85
EDA_ITEM & operator=(const EDA_ITEM &aItem)
Assign the members of aItem to another object.
Definition: eda_item.cpp:239
const KIID m_Uuid
Definition: eda_item.h:475
bool m_forceVisible
Definition: eda_item.h:479
KICAD_T Type() const
Returns the type of object.
Definition: eda_item.h:97
EDA_ITEM_FLAGS m_flags
Definition: eda_item.h:480
bool HasFlag(EDA_ITEM_FLAGS aFlag) const
Definition: eda_item.h:127
ENUM_MAP & Map(T aValue, const wxString &aName)
Definition: property.h:633
static ENUM_MAP< T > & Instance()
Definition: property.h:627
ENUM_MAP & Undefined(T aValue)
Definition: property.h:640
wxPGChoices & Choices()
Definition: property.h:676
Class that other classes need to inherit from, in order to be inspectable.
Definition: inspectable.h:36
Hold a (potentially large) number of VIEW_ITEMs and renders them on a graphics device provided by the...
Definition: view.h:69
bool IsLayerVisible(int aLayer) const
Return information about visibility of a particular layer.
Definition: view.h:410
LSEQ is a sequence (and therefore also a set) of PCB_LAYER_IDs.
Definition: layer_ids.h:497
LSET is a set of PCB_LAYER_IDs.
Definition: layer_ids.h:536
LSEQ UIOrder() const
Definition: lset.cpp:922
static LSET AllLayersMask()
Definition: lset.cpp:808
LSEQ Seq(const PCB_LAYER_ID *aWishListSequence, unsigned aCount) const
Return an LSEQ from the union of this LSET and a desired sequence.
Definition: lset.cpp:411
static LSET AllCuMask(int aCuLayerCount=MAX_CU_LAYERS)
Return a mask holding the requested number of Cu PCB_LAYER_IDs.
Definition: lset.cpp:773
static const wxChar * Name(PCB_LAYER_ID aLayerId)
Return the fixed name association with aLayerId.
Definition: lset.cpp:82
Definition: pad.h:59
int GetLocalThermalGapOverride(wxString *aSource=nullptr) const
Definition: pad.cpp:957
PROPERTY_BASE & SetWriteableFunc(std::function< bool(INSPECTABLE *)> aFunc)
Definition: property.h:252
PROPERTY_BASE & SetValidator(PROPERTY_VALIDATOR_FN &&aValidator)
Definition: property.h:307
Provide class metadata.Helper macro to map type hashes to names.
Definition: property_mgr.h:74
void InheritsAfter(TYPE_ID aDerived, TYPE_ID aBase)
Declare an inheritance relationship between types.
static PROPERTY_MANAGER & Instance()
Definition: property_mgr.h:76
PROPERTY_BASE & AddProperty(PROPERTY_BASE *aProperty, const wxString &aGroup=wxEmptyString)
Register a property.
void OverrideAvailability(TYPE_ID aDerived, TYPE_ID aBase, const wxString &aName, std::function< bool(INSPECTABLE *)> aFunc)
Sets an override availability functor for a base class property of a given derived class.
PROPERTY_BASE & ReplaceProperty(size_t aBase, const wxString &aName, PROPERTY_BASE *aNew, const wxString &aGroup=wxEmptyString)
Replace an existing property for a specific type.
static VALIDATOR_RESULT PositiveIntValidator(const wxAny &&aValue, EDA_ITEM *aItem)
static VALIDATOR_RESULT RangeIntValidator(const wxAny &&aValue, EDA_ITEM *aItem)
Definition: seg.h:42
VECTOR2I A
Definition: seg.h:49
VECTOR2I B
Definition: seg.h:50
bool PointInside(const VECTOR2I &aPt, int aAccuracy=0, bool aUseBBoxCache=false) const
Check if point aP lies inside a polygon (any type) defined by the line chain.
Represent a polyline containing arcs as well as line segments: A chain of connected line and/or arc s...
bool IsClosed() const override
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.
bool CollideEdge(const VECTOR2I &aPoint, VERTEX_INDEX *aClosestVertex=nullptr, int aClearance=0) const
Check whether aPoint collides with any edge of any of the contours of the polygon.
void BooleanSubtract(const SHAPE_POLY_SET &b, POLYGON_MODE aFastMode)
Perform boolean polyset difference For aFastMode meaning, see function booleanOp.
void InflateWithLinkedHoles(int aFactor, CORNER_STRATEGY aCornerStrategy, int aMaxError, POLYGON_MODE aFastMode)
Perform outline inflation/deflation, using round corners.
ITERATOR IterateWithHoles(int aOutline)
void Fracture(POLYGON_MODE aFastMode)
Convert a set of polygons with holes to a single outline with "slits"/"fractures" connecting the oute...
void ClearArcs()
Removes all arc references from all the outlines and holes in the polyset.
@ ROUND_ALL_CORNERS
All angles are rounded.
int AddOutline(const SHAPE_LINE_CHAIN &aOutline)
Adds a new outline to the set and returns its index.
double Area()
Return the area of this poly set.
void SetVertex(const VERTEX_INDEX &aIndex, const VECTOR2I &aPos)
Accessor function to set the position of a specific point.
bool IsEmpty() const
Return true if the set is empty (no polygons at all)
void BooleanAdd(const SHAPE_POLY_SET &b, POLYGON_MODE aFastMode)
Perform boolean polyset union For aFastMode meaning, see function booleanOp.
void CacheTriangulation(bool aPartition=true, bool aSimplify=false)
Build a polygon triangulation, needed to draw a polygon on OpenGL and in some other calculations.
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,...
int TotalVertices() const
Return total number of vertices stored in the set.
void BooleanIntersection(const SHAPE_POLY_SET &b, POLYGON_MODE aFastMode)
Perform boolean polyset intersection For aFastMode meaning, see function booleanOp.
MD5_HASH GetHash() const
void Inflate(int aAmount, CORNER_STRATEGY aCornerStrategy, int aMaxError, bool aSimplify=false)
Perform outline inflation/deflation.
int HoleCount(int aOutline) const
Returns the number of holes in a given outline.
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)
bool GetNeighbourIndexes(int aGlobalIndex, int *aPrevious, int *aNext)
Return the global indexes of the previous and the next corner of the aGlobalIndex-th corner of a cont...
int AddHole(const SHAPE_LINE_CHAIN &aHole, int aOutline=-1)
Adds a new hole to the given outline (default: last) and returns its index.
void Mirror(bool aX=true, bool aY=false, const VECTOR2I &aRef={ 0, 0 })
Mirror the line points about y or x (or both)
SHAPE_LINE_CHAIN & Outline(int aIndex)
Return the reference to aIndex-th outline in the set.
SHAPE_LINE_CHAIN & Hole(int aOutline, int aHole)
Return the reference to aHole-th hole in the aIndex-th outline.
int NewOutline()
Creates a new empty polygon in the set and returns its index.
bool CollideVertex(const VECTOR2I &aPoint, VERTEX_INDEX *aClosestVertex=nullptr, int aClearance=0) const
Check whether aPoint collides with any vertex of any of the contours of the polygon.
const VECTOR2I & CVertex(int aIndex, int aOutline, int aHole) const
Return the index-th vertex in a given hole outline within a given outline.
int OutlineCount() const
Return the number of outlines in the set.
void Move(const VECTOR2I &aVector) override
bool Contains(const VECTOR2I &aP, int aSubpolyIndex=-1, int aAccuracy=0, bool aUseBBoxCaches=false) const
Return true if a given subpolygon contains the point aP.
SHAPE_POLY_SET CloneDropTriangulation() const
SEGMENT_ITERATOR IterateSegmentsWithHoles()
Returns an iterator object, for all outlines in the set (with holes)
const BOX2I BBox(int aClearance=0) const override
Compute a bounding box of the shape, with a margin of aClearance a collision.
wxString MessageTextFromValue(double aValue, bool aAddUnitLabel=true, EDA_DATA_TYPE aType=EDA_DATA_TYPE::DISTANCE)
A lower-precision version of StringFromValue().
void ExportSetting(ZONE &aTarget, bool aFullExport=true) const
Function ExportSetting copy settings to a given zone.
Handle a list of polygons defining a copper zone.
Definition: zone.h:72
void SetHatchThickness(int aThickness)
Definition: zone.h:274
SHAPE_POLY_SET::VERTEX_INDEX * m_CornerSelection
The index of the corner being moved or nullptr if no corner is selected.
Definition: zone.h:884
void SetNeedRefill(bool aNeedRefill)
Definition: zone.h:253
bool HitTest(const VECTOR2I &aPosition, int aAccuracy=0) const override
Test if a point is near an outline edge or a corner of this zone.
Definition: zone.cpp:433
int m_borderHatchPitch
Definition: zone.h:905
bool m_isRuleArea
Definition: zone.h:820
wxString GetItemDescription(UNITS_PROVIDER *aUnitsProvider) const override
Return a user-visible description string of this item.
Definition: zone.cpp:808
ZONE & operator=(const ZONE &aOther)
Definition: zone.cpp:91
int m_cornerSmoothingType
Definition: zone.h:803
void Mirror(const VECTOR2I &aMirrorRef, bool aMirrorLeftRight)
Mirror the outlines relative to a given horizontal axis the layer is not changed.
Definition: zone.cpp:731
bool GetIsRuleArea() const
Accessors to parameters used in Rule Area zones:
Definition: zone.h:710
bool m_doNotAllowVias
Definition: zone.h:832
bool UnFill()
Removes the zone filling.
Definition: zone.cpp:218
bool GetDoNotAllowVias() const
Definition: zone.h:712
void TransformSolidAreasShapesToPolygon(PCB_LAYER_ID aLayer, SHAPE_POLY_SET &aBuffer) const
Convert solid areas full shapes to polygon set (the full shape is the polygon area with a thick outli...
Definition: zone.cpp:1345
void SetCornerRadius(unsigned int aRadius)
Definition: zone.cpp:403
ZONE_FILL_MODE m_fillMode
How to fill areas:
Definition: zone.h:870
bool m_doNotAllowFootprints
Definition: zone.h:835
int m_ZoneMinThickness
Definition: zone.h:839
virtual void ViewGetLayers(int aLayers[], int &aCount) const override
Return the all the layers within the VIEW the object is painted on.
Definition: zone.cpp:302
virtual bool IsOnLayer(PCB_LAYER_ID, bool aIncludeCourtyards=false) const override
Test to see if this object is on the given layer.
Definition: zone.cpp:345
void AddPolygon(std::vector< VECTOR2I > &aPolygon)
Add a polygon to the zone outline.
Definition: zone.cpp:771
double m_hatchSmoothingValue
Definition: zone.h:878
void SetLocalFlags(int aFlags)
Definition: zone.h:323
void TransformSmoothedOutlineToPolygon(SHAPE_POLY_SET &aBuffer, int aClearance, int aError, ERROR_LOC aErrorLoc, SHAPE_POLY_SET *aBoardOutline) const
Convert the outlines shape to a polygon with no holes inflated (optional) by max( aClearanceValue,...
Definition: zone.cpp:1275
int m_thermalReliefSpokeWidth
Definition: zone.h:861
bool HitTestCutout(const VECTOR2I &aRefPos, int *aOutlineIdx=nullptr, int *aHoleIdx=nullptr) const
Test if the given point is contained within a cutout of the zone.
Definition: zone.cpp:524
EDA_ANGLE m_hatchOrientation
Definition: zone.h:873
void CacheTriangulation(PCB_LAYER_ID aLayer=UNDEFINED_LAYER)
Create a list of triangles that "fill" the solid areas used for instance to draw these solid areas on...
Definition: zone.cpp:1044
std::map< PCB_LAYER_ID, std::set< int > > m_insulatedIslands
For each layer, a set of insulated islands that were not removed.
Definition: zone.h:909
wxString m_zoneName
An optional unique name for this zone, used for identifying it in DRC checking.
Definition: zone.h:807
void HatchBorder()
Compute the hatch lines depending on the hatch parameters and stores it in the zone's attribute m_bor...
Definition: zone.cpp:883
std::map< PCB_LAYER_ID, std::shared_ptr< SHAPE_POLY_SET > > m_FilledPolysList
Definition: zone.h:896
void SetBorderDisplayStyle(ZONE_BORDER_DISPLAY_STYLE aBorderHatchStyle, int aBorderHatchPitch, bool aRebuilBorderdHatch)
Set all hatch parameters for the zone.
Definition: zone.cpp:848
MD5_HASH GetHashValue(PCB_LAYER_ID aLayer)
Definition: zone.cpp:415
bool GetDoNotAllowPads() const
Definition: zone.h:714
const BOX2I GetBoundingBox() const override
Definition: zone.cpp:351
void SetMinThickness(int aMinThickness)
Definition: zone.h:259
double m_outlinearea
Definition: zone.h:912
wxString GetFriendlyName() const override
Definition: zone.cpp:684
bool GetDoNotAllowTracks() const
Definition: zone.h:713
int GetLocalFlags() const
Definition: zone.h:322
EDA_ITEM * Clone() const override
Create a duplicate of this item with linked list members set to NULL.
Definition: zone.cpp:189
void SetHatchOrientation(const EDA_ANGLE &aStep)
Definition: zone.h:280
bool m_doNotAllowCopperPour
Definition: zone.h:831
bool m_needRefill
False when a zone was refilled, true after changes in zone params.
Definition: zone.h:858
virtual void Flip(const VECTOR2I &aCentre, bool aFlipLeftRight) override
Flip this object, i.e.
Definition: zone.cpp:723
bool HitTestForCorner(const VECTOR2I &refPos, int aAccuracy, SHAPE_POLY_SET::VERTEX_INDEX *aCornerHit=nullptr) const
Test if the given VECTOR2I is near a corner.
Definition: zone.cpp:443
bool m_doNotAllowTracks
Definition: zone.h:833
void SetThermalReliefSpokeWidth(int aThermalReliefSpokeWidth)
Definition: zone.h:194
virtual PCB_LAYER_ID GetLayer() const override
Return the primary layer this item is on.
Definition: zone.cpp:248
virtual void SetLayer(PCB_LAYER_ID aLayer) override
Set the layer this item is on.
Definition: zone.cpp:269
LSET m_fillFlags
Temp variables used while filling.
Definition: zone.h:899
SHAPE_POLY_SET * Outline()
Definition: zone.h:325
bool m_doNotAllowPads
Definition: zone.h:834
ZONE(BOARD_ITEM_CONTAINER *parent)
Definition: zone.cpp:45
void Move(const VECTOR2I &offset) override
Move the outlines.
Definition: zone.cpp:657
bool IsIsland(PCB_LAYER_ID aLayer, int aPolyIdx) const
Check if a given filled polygon is an insulated island.
Definition: zone.cpp:1061
SHAPE_POLY_SET * m_Poly
Outline of the zone.
Definition: zone.h:802
TEARDROP_TYPE m_teardropType
Definition: zone.h:826
~ZONE()
Definition: zone.cpp:101
int m_hatchSmoothingLevel
Definition: zone.h:874
int GetLocalClearance() const
Definition: zone.h:159
LSET m_layerSet
Definition: zone.h:809
void SetIsRuleArea(bool aEnable)
Definition: zone.h:717
int m_ZoneClearance
Definition: zone.h:838
wxString GetZoneName() const
Definition: zone.h:131
void CacheBoundingBox()
Used to preload the zone bounding box cache so we don't have to worry about mutex-locking it each tim...
Definition: zone.cpp:373
int GetMinThickness() const
Definition: zone.h:258
virtual void swapData(BOARD_ITEM *aImage) override
Definition: zone.cpp:1036
bool HitTestForEdge(const VECTOR2I &refPos, int aAccuracy, SHAPE_POLY_SET::VERTEX_INDEX *aCornerHit=nullptr) const
Test if the given VECTOR2I is near a segment defined by 2 corners.
Definition: zone.cpp:450
void RemoveCutout(int aOutlineIdx, int aHoleIdx)
Remove a cutout from the zone.
Definition: zone.cpp:742
void Rotate(const VECTOR2I &aCentre, const EDA_ANGLE &aAngle) override
Rotate the outlines.
Definition: zone.cpp:712
bool HigherPriority(const ZONE *aOther) const
Definition: zone.cpp:195
bool HitTestFilledArea(PCB_LAYER_ID aLayer, const VECTOR2I &aRefPos, int aAccuracy=0) const
Test if the given VECTOR2I is within the bounds of a filled area of this zone.
Definition: zone.cpp:510
void SetFillMode(ZONE_FILL_MODE aFillMode)
Definition: zone.h:180
BITMAPS GetMenuImage() const override
Return a pointer to an image to be used in menus.
Definition: zone.cpp:1030
int m_hatchGap
Definition: zone.h:872
ZONE_CONNECTION GetPadConnection() const
Definition: zone.h:255
void InitDataFromSrcInCopyCtor(const ZONE &aZone)
Copy aZone data to me.
Definition: zone.cpp:111
int GetHatchThickness() const
Definition: zone.h:273
void GetMsgPanelInfo(EDA_DRAW_FRAME *aFrame, std::vector< MSG_PANEL_ITEM > &aList) override
Populate aList of MSG_PANEL_ITEM objects with it's internal state for display purposes.
Definition: zone.cpp:549
int m_hatchBorderAlgorithm
Definition: zone.h:880
bool IsTeardropArea() const
Definition: zone.h:694
std::vector< SEG > m_borderHatchLines
Definition: zone.h:906
VECTOR2I GetPosition() const override
Definition: zone.cpp:242
int GetThermalReliefSpokeWidth() const
Definition: zone.h:202
int GetBorderHatchPitch() const
HatchBorder related methods.
Definition: zone.cpp:842
void SetLocalClearance(int aClearance)
Definition: zone.h:160
void BuildHashValue(PCB_LAYER_ID aLayer)
Build the hash value of m_FilledPolysList, and store it internally in m_filledPolysHash.
Definition: zone.cpp:424
void SetThermalReliefGap(int aThermalReliefGap)
Definition: zone.h:183
EDA_ANGLE GetHatchOrientation() const
Definition: zone.h:279
void SetLayerSet(LSET aLayerSet) override
Definition: zone.cpp:275
bool BuildSmoothedPoly(SHAPE_POLY_SET &aSmoothedPoly, PCB_LAYER_ID aLayer, SHAPE_POLY_SET *aBoardOutline, SHAPE_POLY_SET *aSmoothedPolyWithApron=nullptr) const
Definition: zone.cpp:1108
int m_fillVersion
Definition: zone.h:840
const VECTOR2I & GetCornerPosition(int aCornerIndex) const
Definition: zone.h:543
bool GetDoNotAllowFootprints() const
Definition: zone.h:715
ZONE_FILL_MODE GetFillMode() const
Definition: zone.h:181
double m_hatchHoleMinArea
Definition: zone.h:879
virtual LSET GetLayerSet() const override
Return a std::bitset of all layers on which the item physically resides.
Definition: zone.h:129
bool GetDoNotAllowCopperPour() const
Definition: zone.h:711
void SetBorderHatchPitch(int aPitch)
Set the hatch pitch parameter for the zone.
Definition: zone.cpp:863
void GetInteractingZones(PCB_LAYER_ID aLayer, std::vector< ZONE * > *aSameNetCollidingZones, std::vector< ZONE * > *aOtherNetIntersectingZones) const
Some intersecting zones, despite being on the same layer with the same net, cannot be merged due to o...
Definition: zone.cpp:1073
int GetHatchGap() const
Definition: zone.h:276
double CalculateOutlineArea()
Compute the area of the zone outline (not the filled area).
Definition: zone.cpp:1268
unsigned m_priority
Definition: zone.h:815
bool IsConflicting() const
For rule areas which exclude footprints (and therefore participate in courtyard conflicts during move...
Definition: zone.cpp:236
std::map< PCB_LAYER_ID, MD5_HASH > m_filledPolysHash
A hash value used in zone filling calculations to see if the filled areas are up to date.
Definition: zone.h:902
ISLAND_REMOVAL_MODE m_islandRemovalMode
Definition: zone.h:842
bool m_isFilled
True when a zone was filled, false after deleting the filled areas.
Definition: zone.h:851
bool AppendCorner(VECTOR2I aPosition, int aHoleIdx, bool aAllowDuplication=false)
Add a new corner to the zone outline (to the main outline or a hole)
Definition: zone.cpp:788
void MoveEdge(const VECTOR2I &offset, int aEdge)
Move the outline Edge.
Definition: zone.cpp:697
int m_thermalReliefGap
Definition: zone.h:860
double ViewGetLOD(int aLayer, KIGFX::VIEW *aView) const override
Return the level of detail (LOD) of the item.
Definition: zone.cpp:318
bool IsOnCopperLayer() const override
Definition: zone.cpp:263
double CalculateFilledArea()
Compute the area currently occupied by the zone fill.
Definition: zone.cpp:1245
int m_hatchThickness
Definition: zone.h:871
void TransformShapeToPolygon(SHAPE_POLY_SET &aBuffer, PCB_LAYER_ID aLayer, int aClearance, int aError, ERROR_LOC aErrorLoc, bool ignoreLineWidth=false) const override
Convert the zone shape to a closed polygon Used in filling zones calculations Circles and arcs are ap...
Definition: zone.cpp:1315
void SetAssignedPriority(unsigned aPriority)
Definition: zone.h:114
double m_area
Definition: zone.h:911
unsigned int m_cornerRadius
Definition: zone.h:804
void SetPadConnection(ZONE_CONNECTION aPadConnection)
Definition: zone.h:256
void SetZoneName(const wxString &aName)
Definition: zone.h:132
void UnHatchBorder()
Clear the zone's hatch.
Definition: zone.cpp:869
PCB_LAYER_ID GetFirstLayer() const
Definition: zone.cpp:254
ZONE_CONNECTION m_PadConnection
Definition: zone.h:837
int GetThermalReliefGap() const
Definition: zone.h:191
void SetHatchGap(int aStep)
Definition: zone.h:277
static int GetDefaultHatchPitch()
Definition: zone.cpp:1024
unsigned GetAssignedPriority() const
Definition: zone.h:119
int GetNumCorners(void) const
Access to m_Poly parameters.
Definition: zone.h:503
bool SameNet(const ZONE *aOther) const
Definition: zone.cpp:212
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.
Definition: zone.cpp:1306
ZONE_BORDER_DISPLAY_STYLE m_borderStyle
Definition: zone.h:904
long long int m_minIslandArea
When island removal mode is set to AREA, islands below this area will be removed.
Definition: zone.h:848
#define _HKI(x)
#define _(s)
#define PCB_EDIT_FRAME_NAME
#define COURTYARD_CONFLICT
temporary set when moving footprints having courtyard overlapping
a few functions useful in geometry calculations.
ERROR_LOC
When approximating an arc or circle, should the error be placed on the outside or inside of the curve...
@ ERROR_OUTSIDE
Some functions to handle hotkeys in KiCad.
FLASHING
Enum used during connectivity building to ensure we do not query connectivity while building the data...
Definition: layer_ids.h:147
bool IsCopperLayer(int aLayerId)
Tests whether a layer is a copper layer.
Definition: layer_ids.h:831
@ LAYER_CONFLICTS_SHADOW
shadow layer for items flagged conficting
Definition: layer_ids.h:241
@ LAYER_ZONES
Control for copper zone opacity/visibility (color ignored)
Definition: layer_ids.h:231
@ LAYER_MOD_FR
show footprints on front
Definition: layer_ids.h:208
@ LAYER_ZONE_START
Virtual layers for stacking zones and tracks on a given copper layer.
Definition: layer_ids.h:253
@ LAYER_MOD_BK
show footprints on back
Definition: layer_ids.h:209
PCB_LAYER_ID
A quick note on layer IDs:
Definition: layer_ids.h:59
@ B_Cu
Definition: layer_ids.h:95
@ UNDEFINED_LAYER
Definition: layer_ids.h:60
LSET FlipLayerMask(LSET aMask, int aCopperLayersCount)
Calculate the mask layer when flipping a footprint.
Definition: lset.cpp:590
EDA_ANGLE abs(const EDA_ANGLE &aAngle)
Definition: eda_angle.h:418
#define TYPE_HASH(x)
Definition: property.h:63
#define IMPLEMENT_ENUM_TO_WXANY(type)
Definition: property.h:727
#define NO_SETTER(owner, type)
Definition: property.h:738
#define REGISTER_TYPE(x)
Definition: property_mgr.h:328
std::optional< std::unique_ptr< VALIDATION_ERROR > > VALIDATOR_RESULT
Null optional means validation succeeded.
wxString UnescapeString(const wxString &aSource)
void AccumulateDescription(wxString &aDesc, const wxString &aItem)
Utility to build comma separated lists in messages.
Definition: string_utils.h:323
constexpr int mmToIU(double mm) const
Definition: base_units.h:89
Structure to hold the necessary information in order to index a vertex on a SHAPE_POLY_SET object: th...
ZONE_DESC()
Definition: zone.cpp:1354
@ PCB_ZONE_T
class ZONE, a copper pour area
Definition: typeinfo.h:103
constexpr ret_type KiROUND(fp_type v)
Round a floating point number to an integer using "round halfway cases away from zero".
Definition: util.h:85
VECTOR2< int > VECTOR2I
Definition: vector2d.h:588
static SHAPE_POLY_SET g_nullPoly
Definition: zone.cpp:412
bool sortEndsByDescendingX(const VECTOR2I &ref, const VECTOR2I &tst)
Definition: zone.cpp:877
static struct ZONE_DESC _ZONE_DESC
ZONE_FILL_MODE
Definition: zone_settings.h:41
ZONE_BORDER_DISPLAY_STYLE
Zone border styles.
Definition: zone_settings.h:49
#define ZONE_CLEARANCE_MAX_VALUE_MM
Definition: zones.h:38
ZONE_CONNECTION
How pads are covered by copper in zone.
Definition: zones.h:49
#define ZONE_BORDER_HATCH_DIST_MM
Definition: zones.h:39
#define ZONE_BORDER_HATCH_MINDIST_MM
Definition: zones.h:40
#define ZONE_CLEARANCE_MM
Definition: zones.h:37
#define ZONE_THICKNESS_MIN_VALUE_MM
Definition: zones.h:36
#define ZONE_BORDER_HATCH_MAXDIST_MM
Definition: zones.h:41