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 if( m_layerSet.count() == 1 )
251 return m_layerSet.UIOrder()[0];
252 else
253 return UNDEFINED_LAYER;
254}
255
256
258{
259 if( m_layerSet.count() )
260 return m_layerSet.UIOrder()[0];
261 else
262 return UNDEFINED_LAYER;
263}
264
265
267{
268 return ( m_layerSet & LSET::AllCuMask() ).count() > 0;
269}
270
271
273{
274 SetLayerSet( LSET( aLayer ) );
275}
276
277
278void ZONE::SetLayerSet( LSET aLayerSet )
279{
280 if( aLayerSet.count() == 0 )
281 return;
282
283 if( m_layerSet != aLayerSet )
284 {
285 SetNeedRefill( true );
286
287 UnFill();
288
289 m_FilledPolysList.clear();
290 m_filledPolysHash.clear();
291 m_insulatedIslands.clear();
292
293 for( PCB_LAYER_ID layer : aLayerSet.Seq() )
294 {
295 m_FilledPolysList[layer] = std::make_shared<SHAPE_POLY_SET>();
296 m_filledPolysHash[layer] = {};
297 m_insulatedIslands[layer] = {};
298 }
299 }
300
301 m_layerSet = aLayerSet;
302}
303
304
305void ZONE::ViewGetLayers( int aLayers[], int& aCount ) const
306{
307 aCount = 0;
308 LSEQ layers = m_layerSet.Seq();
309
310 for( PCB_LAYER_ID layer : m_layerSet.Seq() )
311 {
312 aLayers[ aCount++ ] = layer; // For outline (always full opacity)
313 aLayers[ aCount++ ] = layer + LAYER_ZONE_START; // For fill (obeys global zone opacity)
314 }
315
316 if( IsConflicting() )
317 aLayers[ aCount++ ] = LAYER_CONFLICTS_SHADOW;
318}
319
320
321double ZONE::ViewGetLOD( int aLayer, KIGFX::VIEW* aView ) const
322{
323 constexpr double HIDE = std::numeric_limits<double>::max();
324
325 if( !aView )
326 return 0;
327
328 if( !aView->IsLayerVisible( LAYER_ZONES ) )
329 return HIDE;
330
331 if( FOOTPRINT* parentFP = GetParentFootprint() )
332 {
333 bool flipped = parentFP->GetLayer() == B_Cu;
334
335 // Handle Render tab switches
336 if( !flipped && !aView->IsLayerVisible( LAYER_FOOTPRINTS_FR ) )
337 return HIDE;
338
339 if( flipped && !aView->IsLayerVisible( LAYER_FOOTPRINTS_BK ) )
340 return HIDE;
341 }
342
343 // Other layers are shown without any conditions
344 return 0.0;
345}
346
347
348bool ZONE::IsOnLayer( PCB_LAYER_ID aLayer ) const
349{
350 return m_layerSet.test( aLayer );
351}
352
353
355{
356 if( const BOARD* board = GetBoard() )
357 {
358 std::unordered_map<const ZONE*, BOX2I>& cache = board->m_ZoneBBoxCache;
359 auto cacheIter = cache.find( this );
360
361 if( cacheIter != cache.end() )
362 return cacheIter->second;
363
364 BOX2I bbox = m_Poly->BBox();
365
366 std::unique_lock<std::mutex> cacheLock( const_cast<BOARD*>( board )->m_CachesMutex );
367 cache[ this ] = bbox;
368
369 return bbox;
370 }
371
372 return m_Poly->BBox();
373}
374
375
377{
378 BOARD* board = GetBoard();
379 std::unordered_map<const ZONE*, BOX2I>& cache = board->m_ZoneBBoxCache;
380
381 auto cacheIter = cache.find( this );
382
383 if( cacheIter == cache.end() )
384 {
385 std::unique_lock<std::mutex> cacheLock( board->m_CachesMutex );
386 cache[ this ] = m_Poly->BBox();
387 }
388}
389
390
391int ZONE::GetThermalReliefGap( PAD* aPad, wxString* aSource ) const
392{
393 if( aPad->GetLocalThermalGapOverride() == 0 )
394 {
395 if( aSource )
396 *aSource = _( "zone" );
397
398 return m_thermalReliefGap;
399 }
400
401 return aPad->GetLocalThermalGapOverride( aSource );
402
403}
404
405
406void ZONE::SetCornerRadius( unsigned int aRadius )
407{
408 if( m_cornerRadius != aRadius )
409 SetNeedRefill( true );
410
411 m_cornerRadius = aRadius;
412}
413
414
416
417
419{
420 if( !m_filledPolysHash.count( aLayer ) )
421 return g_nullPoly.GetHash();
422 else
423 return m_filledPolysHash.at( aLayer );
424}
425
426
428{
429 if( !m_FilledPolysList.count( aLayer ) )
431 else
432 m_filledPolysHash[aLayer] = m_FilledPolysList.at( aLayer )->GetHash();
433}
434
435
436bool ZONE::HitTest( const VECTOR2I& aPosition, int aAccuracy ) const
437{
438 // When looking for an "exact" hit aAccuracy will be 0 which works poorly for very thin
439 // lines. Give it a floor.
440 int accuracy = std::max( aAccuracy, pcbIUScale.mmToIU( 0.1 ) );
441
442 return HitTestForCorner( aPosition, accuracy * 2 ) || HitTestForEdge( aPosition, accuracy );
443}
444
445
446bool ZONE::HitTestForCorner( const VECTOR2I& refPos, int aAccuracy,
447 SHAPE_POLY_SET::VERTEX_INDEX* aCornerHit ) const
448{
449 return m_Poly->CollideVertex( VECTOR2I( refPos ), aCornerHit, aAccuracy );
450}
451
452
453bool ZONE::HitTestForEdge( const VECTOR2I& refPos, int aAccuracy,
454 SHAPE_POLY_SET::VERTEX_INDEX* aCornerHit ) const
455{
456 return m_Poly->CollideEdge( VECTOR2I( refPos ), aCornerHit, aAccuracy );
457}
458
459
460bool ZONE::HitTest( const BOX2I& aRect, bool aContained, int aAccuracy ) const
461{
462 // Calculate bounding box for zone
463 BOX2I bbox = GetBoundingBox();
464 bbox.Normalize();
465
466 BOX2I arect = aRect;
467 arect.Normalize();
468 arect.Inflate( aAccuracy );
469
470 if( aContained )
471 {
472 return arect.Contains( bbox );
473 }
474 else
475 {
476 // Fast test: if aBox is outside the polygon bounding box, rectangles cannot intersect
477 if( !arect.Intersects( bbox ) )
478 return false;
479
480 int count = m_Poly->TotalVertices();
481
482 for( int ii = 0; ii < count; ii++ )
483 {
484 VECTOR2I vertex = m_Poly->CVertex( ii );
485 VECTOR2I vertexNext = m_Poly->CVertex( ( ii + 1 ) % count );
486
487 // Test if the point is within the rect
488 if( arect.Contains( vertex ) )
489 return true;
490
491 // Test if this edge intersects the rect
492 if( arect.Intersects( vertex, vertexNext ) )
493 return true;
494 }
495
496 return false;
497 }
498}
499
500
501int ZONE::GetLocalClearance( wxString* aSource ) const
502{
503 if( m_isRuleArea )
504 return 0;
505
506 if( aSource )
507 *aSource = _( "zone" );
508
509 return m_ZoneClearance;
510}
511
512
513bool ZONE::HitTestFilledArea( PCB_LAYER_ID aLayer, const VECTOR2I& aRefPos, int aAccuracy ) const
514{
515 // Rule areas have no filled area, but it's generally nice to treat their interior as if it were
516 // filled so that people don't have to select them by their outline (which is min-width)
517 if( GetIsRuleArea() )
518 return m_Poly->Contains( aRefPos, -1, aAccuracy );
519
520 if( !m_FilledPolysList.count( aLayer ) )
521 return false;
522
523 return m_FilledPolysList.at( aLayer )->Contains( aRefPos, -1, aAccuracy );
524}
525
526
527bool ZONE::HitTestCutout( const VECTOR2I& aRefPos, int* aOutlineIdx, int* aHoleIdx ) const
528{
529 // Iterate over each outline polygon in the zone and then iterate over
530 // each hole it has to see if the point is in it.
531 for( int i = 0; i < m_Poly->OutlineCount(); i++ )
532 {
533 for( int j = 0; j < m_Poly->HoleCount( i ); j++ )
534 {
535 if( m_Poly->Hole( i, j ).PointInside( aRefPos ) )
536 {
537 if( aOutlineIdx )
538 *aOutlineIdx = i;
539
540 if( aHoleIdx )
541 *aHoleIdx = j;
542
543 return true;
544 }
545 }
546 }
547
548 return false;
549}
550
551
552void ZONE::GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_ITEM>& aList )
553{
554 wxString msg = GetFriendlyName();
555
556 // Display Cutout instead of Outline for holes inside a zone (i.e. when num contour !=0).
557 // Check whether the selected corner is in a hole; i.e., in any contour but the first one.
558 if( m_CornerSelection != nullptr && m_CornerSelection->m_contour > 0 )
559 msg << wxT( " " ) << _( "Cutout" );
560
561 aList.emplace_back( _( "Type" ), msg );
562
563 if( GetIsRuleArea() )
564 {
565 msg.Empty();
566
567 if( GetDoNotAllowVias() )
568 AccumulateDescription( msg, _( "No vias" ) );
569
570 if( GetDoNotAllowTracks() )
571 AccumulateDescription( msg, _( "No tracks" ) );
572
573 if( GetDoNotAllowPads() )
574 AccumulateDescription( msg, _( "No pads" ) );
575
577 AccumulateDescription( msg, _( "No copper zones" ) );
578
580 AccumulateDescription( msg, _( "No footprints" ) );
581
582 if( !msg.IsEmpty() )
583 aList.emplace_back( _( "Restrictions" ), msg );
584 }
585 else if( IsOnCopperLayer() )
586 {
587 if( aFrame->GetName() == PCB_EDIT_FRAME_NAME )
588 {
589 aList.emplace_back( _( "Net" ), UnescapeString( GetNetname() ) );
590
591 aList.emplace_back( _( "Resolved Netclass" ),
592 UnescapeString( GetEffectiveNetClass()->GetName() ) );
593 }
594
595 // Display priority level
596 aList.emplace_back( _( "Priority" ),
597 wxString::Format( wxT( "%d" ), GetAssignedPriority() ) );
598 }
599
600 if( aFrame->GetName() == PCB_EDIT_FRAME_NAME )
601 {
602 if( IsLocked() )
603 aList.emplace_back( _( "Status" ), _( "Locked" ) );
604 }
605
606 LSEQ layers = m_layerSet.Seq();
607 wxString layerDesc;
608
609 if( layers.size() == 1 )
610 {
611 layerDesc.Printf( _( "%s" ), GetBoard()->GetLayerName( layers[0] ) );
612 }
613 else if (layers.size() == 2 )
614 {
615 layerDesc.Printf( _( "%s and %s" ),
616 GetBoard()->GetLayerName( layers[0] ),
617 GetBoard()->GetLayerName( layers[1] ) );
618 }
619 else if (layers.size() == 3 )
620 {
621 layerDesc.Printf( _( "%s, %s and %s" ),
622 GetBoard()->GetLayerName( layers[0] ),
623 GetBoard()->GetLayerName( layers[1] ),
624 GetBoard()->GetLayerName( layers[2] ) );
625 }
626 else if( layers.size() > 3 )
627 {
628 layerDesc.Printf( _( "%s, %s and %d more" ),
629 GetBoard()->GetLayerName( layers[0] ),
630 GetBoard()->GetLayerName( layers[1] ),
631 static_cast<int>( layers.size() - 2 ) );
632 }
633
634 aList.emplace_back( _( "Layer" ), layerDesc );
635
636 if( !m_zoneName.empty() )
637 aList.emplace_back( _( "Name" ), m_zoneName );
638
639 switch( m_fillMode )
640 {
641 case ZONE_FILL_MODE::POLYGONS: msg = _( "Solid" ); break;
642 case ZONE_FILL_MODE::HATCH_PATTERN: msg = _( "Hatched" ); break;
643 default: msg = _( "Unknown" ); break;
644 }
645
646 aList.emplace_back( _( "Fill Mode" ), msg );
647
648 aList.emplace_back( _( "Filled Area" ),
649 aFrame->MessageTextFromValue( m_area, true, EDA_DATA_TYPE::AREA ) );
650
651 wxString source;
652 int clearance = GetOwnClearance( UNDEFINED_LAYER, &source );
653
654 if( !source.IsEmpty() )
655 {
656 aList.emplace_back( wxString::Format( _( "Min Clearance: %s" ),
657 aFrame->MessageTextFromValue( clearance ) ),
658 wxString::Format( _( "(from %s)" ),
659 source ) );
660 }
661
662 if( !m_FilledPolysList.empty() )
663 {
664 int count = 0;
665
666 for( std::pair<const PCB_LAYER_ID, std::shared_ptr<SHAPE_POLY_SET>>& ii: m_FilledPolysList )
667 count += ii.second->TotalVertices();
668
669 aList.emplace_back( _( "Corner Count" ), wxString::Format( wxT( "%d" ), count ) );
670 }
671}
672
673
674void ZONE::Move( const VECTOR2I& offset )
675{
676 /* move outlines */
677 m_Poly->Move( offset );
678
679 HatchBorder();
680
681 /* move fills */
682 for( std::pair<const PCB_LAYER_ID, std::shared_ptr<SHAPE_POLY_SET>>& pair : m_FilledPolysList )
683 pair.second->Move( offset );
684
685 /*
686 * move boundingbox cache
687 *
688 * While the cache will get nuked at the conclusion of the operation, we use it for some
689 * things (such as drawing the parent group) during the move.
690 */
691 if( GetBoard() )
692 {
693 auto it = GetBoard()->m_ZoneBBoxCache.find( this );
694
695 if( it != GetBoard()->m_ZoneBBoxCache.end() )
696 it->second.Move( offset );
697 }
698}
699
700
701wxString ZONE::GetFriendlyName() const
702{
703 if( GetIsRuleArea() )
704 return _( "Rule Area" );
705 else if( IsTeardropArea() )
706 return _( "Teardrop Area" );
707 else if( IsOnCopperLayer() )
708 return _( "Copper Zone" );
709 else
710 return _( "Non-copper Zone" );
711}
712
713
714void ZONE::MoveEdge( const VECTOR2I& offset, int aEdge )
715{
716 int next_corner;
717
718 if( m_Poly->GetNeighbourIndexes( aEdge, nullptr, &next_corner ) )
719 {
720 m_Poly->SetVertex( aEdge, m_Poly->CVertex( aEdge ) + VECTOR2I( offset ) );
721 m_Poly->SetVertex( next_corner, m_Poly->CVertex( next_corner ) + VECTOR2I( offset ) );
722 HatchBorder();
723
724 SetNeedRefill( true );
725 }
726}
727
728
729void ZONE::Rotate( const VECTOR2I& aCentre, const EDA_ANGLE& aAngle )
730{
731 m_Poly->Rotate( aAngle, aCentre );
732 HatchBorder();
733
734 /* rotate filled areas: */
735 for( std::pair<const PCB_LAYER_ID, std::shared_ptr<SHAPE_POLY_SET>>& pair : m_FilledPolysList )
736 pair.second->Rotate( aAngle, aCentre );
737}
738
739
740void ZONE::Flip( const VECTOR2I& aCentre, bool aFlipLeftRight )
741{
742 Mirror( aCentre, aFlipLeftRight );
743
744 SetLayerSet( FlipLayerMask( GetLayerSet(), GetBoard()->GetCopperLayerCount() ) );
745}
746
747
748void ZONE::Mirror( const VECTOR2I& aMirrorRef, bool aMirrorLeftRight )
749{
750 m_Poly->Mirror( aMirrorLeftRight, !aMirrorLeftRight, aMirrorRef );
751
752 HatchBorder();
753
754 for( std::pair<const PCB_LAYER_ID, std::shared_ptr<SHAPE_POLY_SET>>& pair : m_FilledPolysList )
755 pair.second->Mirror( aMirrorLeftRight, !aMirrorLeftRight, aMirrorRef );
756}
757
758
759void ZONE::RemoveCutout( int aOutlineIdx, int aHoleIdx )
760{
761 // Ensure the requested cutout is valid
762 if( m_Poly->OutlineCount() < aOutlineIdx || m_Poly->HoleCount( aOutlineIdx ) < aHoleIdx )
763 return;
764
765 SHAPE_POLY_SET cutPoly( m_Poly->Hole( aOutlineIdx, aHoleIdx ) );
766
767 // Add the cutout back to the zone
769
770 SetNeedRefill( true );
771}
772
773
774void ZONE::AddPolygon( const SHAPE_LINE_CHAIN& aPolygon )
775{
776 wxASSERT( aPolygon.IsClosed() );
777
778 // Add the outline as a new polygon in the polygon set
779 if( m_Poly->OutlineCount() == 0 )
780 m_Poly->AddOutline( aPolygon );
781 else
782 m_Poly->AddHole( aPolygon );
783
784 SetNeedRefill( true );
785}
786
787
788void ZONE::AddPolygon( std::vector<VECTOR2I>& aPolygon )
789{
790 if( aPolygon.empty() )
791 return;
792
793 SHAPE_LINE_CHAIN outline;
794
795 // Create an outline and populate it with the points of aPolygon
796 for( const VECTOR2I& pt : aPolygon )
797 outline.Append( pt );
798
799 outline.SetClosed( true );
800
801 AddPolygon( outline );
802}
803
804
805bool ZONE::AppendCorner( VECTOR2I aPosition, int aHoleIdx, bool aAllowDuplication )
806{
807 // Ensure the main outline exists:
808 if( m_Poly->OutlineCount() == 0 )
810
811 // If aHoleIdx >= 0, the corner musty be added to the hole, index aHoleIdx.
812 // (remember: the index of the first hole is 0)
813 // Return error if it does not exist.
814 if( aHoleIdx >= m_Poly->HoleCount( 0 ) )
815 return false;
816
817 m_Poly->Append( aPosition.x, aPosition.y, -1, aHoleIdx, aAllowDuplication );
818
819 SetNeedRefill( true );
820
821 return true;
822}
823
824
825wxString ZONE::GetItemDescription( UNITS_PROVIDER* aUnitsProvider ) const
826{
827 LSEQ layers = m_layerSet.Seq();
828 wxString layerDesc;
829
830 if( layers.size() == 1 )
831 {
832 layerDesc.Printf( _( "on %s" ), GetBoard()->GetLayerName( layers[0] ) );
833 }
834 else if (layers.size() == 2 )
835 {
836 layerDesc.Printf( _( "on %s and %s" ),
837 GetBoard()->GetLayerName( layers[0] ),
838 GetBoard()->GetLayerName( layers[1] ) );
839 }
840 else if (layers.size() == 3 )
841 {
842 layerDesc.Printf( _( "on %s, %s and %s" ),
843 GetBoard()->GetLayerName( layers[0] ),
844 GetBoard()->GetLayerName( layers[1] ),
845 GetBoard()->GetLayerName( layers[2] ) );
846 }
847 else if( layers.size() > 3 )
848 {
849 layerDesc.Printf( _( "on %s, %s and %zu more" ),
850 GetBoard()->GetLayerName( layers[0] ),
851 GetBoard()->GetLayerName( layers[1] ),
852 layers.size() - 2 );
853 }
854
855 // Check whether the selected contour is a hole (contour index > 0)
856 if( m_CornerSelection != nullptr && m_CornerSelection->m_contour > 0 )
857 {
858 if( GetIsRuleArea() )
859 return wxString::Format( _( "Rule Area Cutout %s" ), layerDesc );
860 else
861 return wxString::Format( _( "Zone Cutout %s" ), layerDesc );
862 }
863 else
864 {
865 if( GetIsRuleArea() )
866 return wxString::Format( _( "Rule Area %s" ), layerDesc );
867 else
868 return wxString::Format( _( "Zone %s %s" ), GetNetnameMsg(), layerDesc );
869 }
870}
871
872
874{
875 return m_borderHatchPitch;
876}
877
878
880 int aBorderHatchPitch, bool aRebuildBorderHatch )
881{
882 aBorderHatchPitch = std::max( aBorderHatchPitch,
884 aBorderHatchPitch = std::min( aBorderHatchPitch,
886 SetBorderHatchPitch( aBorderHatchPitch );
887 m_borderStyle = aBorderHatchStyle;
888
889 if( aRebuildBorderHatch )
890 HatchBorder();
891}
892
893
895{
896 m_borderHatchPitch = aPitch;
897}
898
899
901{
902 m_borderHatchLines.clear();
903}
904
905
906// Creates hatch lines inside the outline of the complex polygon
907// sort function used in ::HatchBorder to sort points by descending VECTOR2I.x values
908bool sortEndsByDescendingX( const VECTOR2I& ref, const VECTOR2I& tst )
909{
910 return tst.x < ref.x;
911}
912
913
915{
917
918 if( m_borderStyle == ZONE_BORDER_DISPLAY_STYLE::NO_HATCH
919 || m_borderHatchPitch == 0
920 || m_Poly->IsEmpty() )
921 {
922 return;
923 }
924
925 // define range for hatch lines
926 int min_x = m_Poly->CVertex( 0 ).x;
927 int max_x = m_Poly->CVertex( 0 ).x;
928 int min_y = m_Poly->CVertex( 0 ).y;
929 int max_y = m_Poly->CVertex( 0 ).y;
930
931 for( auto iterator = m_Poly->IterateWithHoles(); iterator; iterator++ )
932 {
933 if( iterator->x < min_x )
934 min_x = iterator->x;
935
936 if( iterator->x > max_x )
937 max_x = iterator->x;
938
939 if( iterator->y < min_y )
940 min_y = iterator->y;
941
942 if( iterator->y > max_y )
943 max_y = iterator->y;
944 }
945
946 // Calculate spacing between 2 hatch lines
947 int spacing;
948
949 if( m_borderStyle == ZONE_BORDER_DISPLAY_STYLE::DIAGONAL_EDGE )
950 spacing = m_borderHatchPitch;
951 else
952 spacing = m_borderHatchPitch * 2;
953
954 // set the "length" of hatch lines (the length on horizontal axis)
955 int hatch_line_len = m_borderHatchPitch;
956
957 // To have a better look, give a slope depending on the layer
958 int layer = GetFirstLayer();
959 std::vector<int> slope_flags;
960
961 if( IsTeardropArea() )
962 slope_flags = { 1, -1 };
963 else if( layer & 1 )
964 slope_flags = { 1 };
965 else
966 slope_flags = { -1 };
967
968 for( int slope_flag : slope_flags )
969 {
970 double slope = 0.707106 * slope_flag; // 45 degrees slope
971 int64_t max_a, min_a;
972
973 if( slope_flag == 1 )
974 {
975 max_a = KiROUND( max_y - slope * min_x );
976 min_a = KiROUND( min_y - slope * max_x );
977 }
978 else
979 {
980 max_a = KiROUND( max_y - slope * max_x );
981 min_a = KiROUND( min_y - slope * min_x );
982 }
983
984 min_a = (min_a / spacing) * spacing;
985
986 // calculate an offset depending on layer number,
987 // for a better look of hatches on a multilayer board
988 int offset = (layer * 7) / 8;
989 min_a += offset;
990
991 // loop through hatch lines
992 std::vector<VECTOR2I> pointbuffer;
993 pointbuffer.reserve( 256 );
994
995 for( int64_t a = min_a; a < max_a; a += spacing )
996 {
997 pointbuffer.clear();
998
999 // Iterate through all vertices
1000 for( auto iterator = m_Poly->IterateSegmentsWithHoles(); iterator; iterator++ )
1001 {
1002 const SEG seg = *iterator;
1003 double x, y;
1004
1005 if( FindLineSegmentIntersection( a, slope, seg.A.x, seg.A.y, seg.B.x, seg.B.y, x, y ) )
1006 pointbuffer.emplace_back( KiROUND( x ), KiROUND( y ) );
1007 }
1008
1009 // sort points in order of descending x (if more than 2) to
1010 // ensure the starting point and the ending point of the same segment
1011 // are stored one just after the other.
1012 if( pointbuffer.size() > 2 )
1013 sort( pointbuffer.begin(), pointbuffer.end(), sortEndsByDescendingX );
1014
1015 // creates lines or short segments inside the complex polygon
1016 for( size_t ip = 0; ip + 1 < pointbuffer.size(); ip += 2 )
1017 {
1018 int dx = pointbuffer[ip + 1].x - pointbuffer[ip].x;
1019
1020 // Push only one line for diagonal hatch,
1021 // or for small lines < twice the line length
1022 // else push 2 small lines
1023 if( m_borderStyle == ZONE_BORDER_DISPLAY_STYLE::DIAGONAL_FULL
1024 || std::abs( dx ) < 2 * hatch_line_len )
1025 {
1026 m_borderHatchLines.emplace_back( SEG( pointbuffer[ip], pointbuffer[ ip + 1] ) );
1027 }
1028 else
1029 {
1030 double dy = pointbuffer[ip + 1].y - pointbuffer[ip].y;
1031 slope = dy / dx;
1032
1033 if( dx > 0 )
1034 dx = hatch_line_len;
1035 else
1036 dx = -hatch_line_len;
1037
1038 int x1 = KiROUND( pointbuffer[ip].x + dx );
1039 int x2 = KiROUND( pointbuffer[ip + 1].x - dx );
1040 int y1 = KiROUND( pointbuffer[ip].y + dx * slope );
1041 int y2 = KiROUND( pointbuffer[ip + 1].y - dx * slope );
1042
1043 m_borderHatchLines.emplace_back( SEG( pointbuffer[ip].x, pointbuffer[ip].y,
1044 x1, y1 ) );
1045
1046 m_borderHatchLines.emplace_back( SEG( pointbuffer[ip+1].x, pointbuffer[ip+1].y,
1047 x2, y2 ) );
1048 }
1049 }
1050 }
1051 }
1052}
1053
1054
1056{
1058}
1059
1060
1062{
1063 return BITMAPS::add_zone;
1064}
1065
1066
1068{
1069 assert( aImage->Type() == PCB_ZONE_T );
1070
1071 std::swap( *static_cast<ZONE*>( this ), *static_cast<ZONE*>( aImage) );
1072}
1073
1074
1076{
1077 if( aLayer == UNDEFINED_LAYER )
1078 {
1079 for( auto& [ layer, poly ] : m_FilledPolysList )
1080 poly->CacheTriangulation();
1081
1082 m_Poly->CacheTriangulation( false );
1083 }
1084 else
1085 {
1086 if( m_FilledPolysList.count( aLayer ) )
1087 m_FilledPolysList[ aLayer ]->CacheTriangulation();
1088 }
1089}
1090
1091
1092bool ZONE::IsIsland( PCB_LAYER_ID aLayer, int aPolyIdx ) const
1093{
1094 if( GetNetCode() < 1 )
1095 return true;
1096
1097 if( !m_insulatedIslands.count( aLayer ) )
1098 return false;
1099
1100 return m_insulatedIslands.at( aLayer ).count( aPolyIdx );
1101}
1102
1103
1104void ZONE::GetInteractingZones( PCB_LAYER_ID aLayer, std::vector<ZONE*>* aSameNetCollidingZones,
1105 std::vector<ZONE*>* aOtherNetIntersectingZones ) const
1106{
1107 int epsilon = pcbIUScale.mmToIU( 0.001 );
1108 BOX2I bbox = GetBoundingBox();
1109
1110 bbox.Inflate( epsilon );
1111
1112 for( ZONE* candidate : GetBoard()->Zones() )
1113 {
1114 if( candidate == this )
1115 continue;
1116
1117 if( !candidate->GetLayerSet().test( aLayer ) )
1118 continue;
1119
1120 if( candidate->GetIsRuleArea() || candidate->IsTeardropArea() )
1121 continue;
1122
1123 if( !candidate->GetBoundingBox().Intersects( bbox ) )
1124 continue;
1125
1126 if( candidate->GetNetCode() == GetNetCode() )
1127 {
1128 if( m_Poly->Collide( candidate->m_Poly ) )
1129 aSameNetCollidingZones->push_back( candidate );
1130 }
1131 else
1132 {
1133 aOtherNetIntersectingZones->push_back( candidate );
1134 }
1135 }
1136}
1137
1138
1140 SHAPE_POLY_SET* aBoardOutline,
1141 SHAPE_POLY_SET* aSmoothedPolyWithApron ) const
1142{
1143 if( GetNumCorners() <= 2 ) // malformed zone. polygon calculations will not like it ...
1144 return false;
1145
1146 // Processing of arc shapes in zones is not yet supported because Clipper can't do boolean
1147 // operations on them. The poly outline must be converted to segments first.
1149 flattened.ClearArcs();
1150
1151 if( GetIsRuleArea() )
1152 {
1153 // We like keepouts just the way they are....
1154 aSmoothedPoly = flattened;
1155 return true;
1156 }
1157
1158 const BOARD* board = GetBoard();
1159 int maxError = ARC_HIGH_DEF;
1160 bool keepExternalFillets = false;
1163
1164 if( IsTeardropArea() )
1165 {
1166 // We use teardrop shapes with no smoothing; these shapes are already optimized
1167 smooth_requested = false;
1168 }
1169
1170 if( board )
1171 {
1173
1174 maxError = bds.m_MaxError;
1175 keepExternalFillets = bds.m_ZoneKeepExternalFillets;
1176 }
1177
1178 auto smooth = [&]( SHAPE_POLY_SET& aPoly )
1179 {
1180 if( !smooth_requested )
1181 return;
1182
1183 switch( m_cornerSmoothingType )
1184 {
1186 aPoly = aPoly.Chamfer( (int) m_cornerRadius );
1187 break;
1188
1190 {
1191 aPoly = aPoly.Fillet( (int) m_cornerRadius, maxError );
1192 break;
1193 }
1194
1195 default:
1196 break;
1197 }
1198 };
1199
1200 SHAPE_POLY_SET* maxExtents = &flattened;
1201 SHAPE_POLY_SET withFillets;
1202
1203 aSmoothedPoly = flattened;
1204
1205 // Should external fillets (that is, those applied to concave corners) be kept? While it
1206 // seems safer to never have copper extend outside the zone outline, 5.1.x and prior did
1207 // indeed fill them so we leave the mode available.
1208 if( keepExternalFillets && smooth_requested )
1209 {
1210 withFillets = flattened;
1211 smooth( withFillets );
1212 withFillets.BooleanAdd( flattened, SHAPE_POLY_SET::PM_FAST );
1213 maxExtents = &withFillets;
1214 }
1215
1216 // We now add in the areas of any same-net, intersecting zones. This keeps us from smoothing
1217 // corners at an intersection (which often produces undesired divots between the intersecting
1218 // zones -- see #2752).
1219 //
1220 // After smoothing, we'll subtract back out everything outside of our zone.
1221 std::vector<ZONE*> sameNetCollidingZones;
1222 std::vector<ZONE*> otherNetIntersectingZones;
1223 GetInteractingZones( aLayer, &sameNetCollidingZones, &otherNetIntersectingZones );
1224
1225 for( ZONE* sameNetZone : sameNetCollidingZones )
1226 {
1227 BOX2I sameNetBoundingBox = sameNetZone->GetBoundingBox();
1228 SHAPE_POLY_SET sameNetPoly = sameNetZone->Outline()->CloneDropTriangulation();
1229
1230 SHAPE_POLY_SET diffNetPoly;
1232
1233 sameNetPoly.ClearArcs();
1234
1235 // Of course there's always a wrinkle. The same-net intersecting zone *might* get knocked
1236 // out along the border by a higher-priority, different-net zone. #12797
1237 for( ZONE* otherNetZone : otherNetIntersectingZones )
1238 {
1239 if( otherNetZone->HigherPriority( sameNetZone )
1240 && otherNetZone->GetBoundingBox().Intersects( sameNetBoundingBox ) )
1241 {
1242 diffNetPoly.BooleanAdd( *otherNetZone->Outline(), SHAPE_POLY_SET::PM_FAST );
1243 }
1244 }
1245
1246 // Second wrinkle. After unioning the higher priority, different net zones together,
1247 // we need to check to see if they completely enclose our zone. If they do, then
1248 // we need to treat the enclosed zone as isolated, not connected to the outer zone
1249 // #13915
1250 if( diffNetPoly.OutlineCount() )
1251 sumPoly.BooleanSubtract( diffNetPoly, SHAPE_POLY_SET::PM_FAST );
1252
1253 if( sumPoly.OutlineCount() )
1254 aSmoothedPoly.BooleanAdd( sameNetPoly, SHAPE_POLY_SET::PM_FAST );
1255 }
1256
1257 if( aBoardOutline )
1258 aSmoothedPoly.BooleanIntersection( *aBoardOutline, SHAPE_POLY_SET::PM_STRICTLY_SIMPLE );
1259
1260 smooth( aSmoothedPoly );
1261
1262 if( aSmoothedPolyWithApron )
1263 {
1264 SHAPE_POLY_SET poly = maxExtents->CloneDropTriangulation();
1266 *aSmoothedPolyWithApron = aSmoothedPoly;
1267 aSmoothedPolyWithApron->BooleanIntersection( poly, SHAPE_POLY_SET::PM_FAST );
1268 }
1269
1270 aSmoothedPoly.BooleanIntersection( *maxExtents, SHAPE_POLY_SET::PM_FAST );
1271
1272 return true;
1273}
1274
1275
1277{
1278 m_area = 0.0;
1279
1280 // Iterate over each outline polygon in the zone and then iterate over
1281 // each hole it has to compute the total area.
1282 for( std::pair<const PCB_LAYER_ID, std::shared_ptr<SHAPE_POLY_SET>>& pair : m_FilledPolysList )
1283 {
1284 std::shared_ptr<SHAPE_POLY_SET>& poly = pair.second;
1285
1286 for( int i = 0; i < poly->OutlineCount(); i++ )
1287 {
1288 m_area += poly->Outline( i ).Area();
1289
1290 for( int j = 0; j < poly->HoleCount( i ); j++ )
1291 m_area -= poly->Hole( i, j ).Area();
1292 }
1293 }
1294
1295 return m_area;
1296}
1297
1298
1300{
1302 return m_outlinearea;
1303}
1304
1305
1307 int aMaxError, ERROR_LOC aErrorLoc,
1308 SHAPE_POLY_SET* aBoardOutline ) const
1309{
1310 // Creates the zone outline polygon (with holes if any)
1311 SHAPE_POLY_SET polybuffer;
1312
1313 // TODO: using GetFirstLayer() means it only works for single-layer zones....
1314 BuildSmoothedPoly( polybuffer, GetFirstLayer(), aBoardOutline );
1315
1316 // Calculate the polygon with clearance
1317 // holes are linked to the main outline, so only one polygon is created.
1318 if( aClearance )
1319 {
1320 const BOARD* board = GetBoard();
1321 int maxError = ARC_HIGH_DEF;
1322
1323 if( board )
1324 maxError = board->GetDesignSettings().m_MaxError;
1325
1326 if( aErrorLoc == ERROR_OUTSIDE )
1327 aClearance += maxError;
1328
1329 polybuffer.Inflate( aClearance, SHAPE_POLY_SET::ROUND_ALL_CORNERS, maxError );
1330 }
1331
1332 polybuffer.Fracture( SHAPE_POLY_SET::PM_FAST );
1333 aBuffer.Append( polybuffer );
1334}
1335
1336
1337std::shared_ptr<SHAPE> ZONE::GetEffectiveShape( PCB_LAYER_ID aLayer, FLASHING aFlash ) const
1338{
1339 if( m_FilledPolysList.find( aLayer ) == m_FilledPolysList.end() )
1340 return std::make_shared<SHAPE_NULL>();
1341 else
1342 return m_FilledPolysList.at( aLayer );
1343}
1344
1345
1346void ZONE::TransformShapeToPolygon( SHAPE_POLY_SET& aBuffer, PCB_LAYER_ID aLayer, int aClearance,
1347 int aError, ERROR_LOC aErrorLoc, bool aIgnoreLineWidth ) const
1348{
1349 wxASSERT_MSG( !aIgnoreLineWidth, wxT( "IgnoreLineWidth has no meaning for zones." ) );
1350
1351 if( !m_FilledPolysList.count( aLayer ) )
1352 return;
1353
1354 if( !aClearance )
1355 {
1356 aBuffer.Append( *m_FilledPolysList.at( aLayer ) );
1357 return;
1358 }
1359
1360 SHAPE_POLY_SET temp_buf = m_FilledPolysList.at( aLayer )->CloneDropTriangulation();
1361
1362 // Rebuild filled areas only if clearance is not 0
1363 if( aClearance > 0 || aErrorLoc == ERROR_OUTSIDE )
1364 {
1365 if( aErrorLoc == ERROR_OUTSIDE )
1366 aClearance += aError;
1367
1368 temp_buf.InflateWithLinkedHoles( aClearance, SHAPE_POLY_SET::ROUND_ALL_CORNERS, aError,
1370 }
1371
1372 aBuffer.Append( temp_buf );
1373}
1374
1375
1377{
1378 if( m_FilledPolysList.count( aLayer ) && !m_FilledPolysList.at( aLayer )->IsEmpty() )
1379 aBuffer.Append( *m_FilledPolysList.at( aLayer ) );
1380}
1381
1382
1383static struct ZONE_DESC
1384{
1386 {
1388
1389 if( layerEnum.Choices().GetCount() == 0 )
1390 {
1391 layerEnum.Undefined( UNDEFINED_LAYER );
1392
1393 for( LSEQ seq = LSET::AllLayersMask().Seq(); seq; ++seq )
1394 layerEnum.Map( *seq, LSET::Name( *seq ) );
1395 }
1396
1398
1399 if( zcMap.Choices().GetCount() == 0 )
1400 {
1401 zcMap.Undefined( ZONE_CONNECTION::INHERITED );
1402 zcMap.Map( ZONE_CONNECTION::INHERITED, _HKI( "Inherited" ) )
1403 .Map( ZONE_CONNECTION::NONE, _HKI( "None" ) )
1404 .Map( ZONE_CONNECTION::THERMAL, _HKI( "Thermal reliefs" ) )
1405 .Map( ZONE_CONNECTION::FULL, _HKI( "Solid" ) )
1406 .Map( ZONE_CONNECTION::THT_THERMAL, _HKI( "Thermal reliefs for PTH" ) );
1407 }
1408
1410
1411 if( zfmMap.Choices().GetCount() == 0 )
1412 {
1413 zfmMap.Undefined( ZONE_FILL_MODE::POLYGONS );
1414 zfmMap.Map( ZONE_FILL_MODE::POLYGONS, _HKI( "Solid fill" ) )
1415 .Map( ZONE_FILL_MODE::HATCH_PATTERN, _HKI( "Hatch pattern" ) );
1416 }
1417
1421
1422 // Mask layer and position properties; they aren't useful in current form
1423 auto posX = new PROPERTY<ZONE, int>( _HKI( "Position X" ), NO_SETTER( ZONE, int ),
1424 static_cast<int ( ZONE::* )() const>( &ZONE::GetX ),
1425 PROPERTY_DISPLAY::PT_COORD,
1427 posX->SetIsHiddenFromPropertiesManager();
1428
1429 auto posY = new PROPERTY<ZONE, int>( _HKI( "Position Y" ), NO_SETTER( ZONE, int ),
1430 static_cast<int ( ZONE::* )() const>( &ZONE::GetY ),
1431 PROPERTY_DISPLAY::PT_COORD,
1433 posY->SetIsHiddenFromPropertiesManager();
1434
1435 propMgr.ReplaceProperty( TYPE_HASH( BOARD_ITEM ), _HKI( "Position X" ), posX );
1436 propMgr.ReplaceProperty( TYPE_HASH( BOARD_ITEM ), _HKI( "Position Y" ), posY );
1437
1438 auto isCopperZone =
1439 []( INSPECTABLE* aItem ) -> bool
1440 {
1441 if( ZONE* zone = dynamic_cast<ZONE*>( aItem ) )
1442 return !zone->GetIsRuleArea() && IsCopperLayer( zone->GetFirstLayer() );
1443
1444 return false;
1445 };
1446
1447 auto isHatchedFill =
1448 []( INSPECTABLE* aItem ) -> bool
1449 {
1450 if( ZONE* zone = dynamic_cast<ZONE*>( aItem ) )
1451 return zone->GetFillMode() == ZONE_FILL_MODE::HATCH_PATTERN;
1452
1453 return false;
1454 };
1455
1456 // Layer property is hidden because it only holds a single layer and zones actually use
1457 // a layer set
1458 propMgr.ReplaceProperty( TYPE_HASH( BOARD_CONNECTED_ITEM ), _HKI( "Layer" ),
1461 &ZONE::GetLayer ) )
1462 .SetIsHiddenFromPropertiesManager();
1463
1465 _HKI( "Net" ), isCopperZone );
1467 _HKI( "Net Class" ), isCopperZone );
1468
1469 propMgr.AddProperty( new PROPERTY<ZONE, unsigned>( _HKI( "Priority" ),
1472 .SetAvailableFunc( isCopperZone );
1473
1474 propMgr.AddProperty( new PROPERTY<ZONE, wxString>( _HKI( "Name" ),
1476
1477 const wxString groupFill = _HKI( "Fill Style" );
1478
1479 propMgr.AddProperty( new PROPERTY_ENUM<ZONE, ZONE_FILL_MODE>( _HKI( "Fill Mode" ),
1482 groupFill );
1483
1484 propMgr.AddProperty( new PROPERTY<ZONE, EDA_ANGLE>( _HKI( "Orientation" ),
1487 PROPERTY_DISPLAY::PT_DEGREE ),
1488 groupFill )
1489 .SetWriteableFunc( isHatchedFill );
1490
1491 // TODO: Switch to translated
1492 auto atLeastMinWidthValidator =
1493 []( const wxAny&& aValue, EDA_ITEM* aZone ) -> VALIDATOR_RESULT
1494 {
1495 int val = aValue.As<int>();
1496 ZONE* zone = dynamic_cast<ZONE*>( aZone );
1497 wxCHECK( zone, std::nullopt );
1498
1499 if( val < zone->GetMinThickness() )
1500 {
1501 return std::make_unique<VALIDATION_ERROR_MSG>(
1502 wxT( "Cannot be less than zone minimum width" ) );
1503 }
1504
1505 return std::nullopt;
1506 };
1507
1508 // TODO: Switch to translated
1509 propMgr.AddProperty( new PROPERTY<ZONE, int>( wxT( "Hatch Width" ),
1512 PROPERTY_DISPLAY::PT_SIZE ),
1513 groupFill )
1514 .SetWriteableFunc( isHatchedFill )
1515 .SetValidator( atLeastMinWidthValidator );
1516
1517 // TODO: Switch to translated
1518 propMgr.AddProperty( new PROPERTY<ZONE, int>( wxT( "Hatch Gap" ), &ZONE::SetHatchGap,
1520 PROPERTY_DISPLAY::PT_SIZE ),
1521 groupFill )
1522 .SetWriteableFunc( isHatchedFill )
1523 .SetValidator( atLeastMinWidthValidator );
1524
1525 // TODO: Smoothing effort needs to change to enum (in dialog too)
1526 // TODO: Smoothing amount (double)
1527 // Unexposed properties (HatchHoleMinArea / HatchBorderAlgorithm)?
1528
1529 const wxString groupOverrides = _HKI( "Overrides" );
1530
1531 auto clearanceOverride = new PROPERTY<ZONE, int>( _HKI( "Clearance Override" ),
1533 PROPERTY_DISPLAY::PT_SIZE );
1534 clearanceOverride->SetAvailableFunc( isCopperZone );
1535 constexpr int maxClearance = pcbIUScale.mmToIU( ZONE_CLEARANCE_MAX_VALUE_MM );
1536 clearanceOverride->SetValidator( PROPERTY_VALIDATORS::RangeIntValidator<0, maxClearance> );
1537
1538 auto minWidth = new PROPERTY<ZONE, int>( _HKI( "Minimum Width" ),
1540 PROPERTY_DISPLAY::PT_SIZE );
1541 minWidth->SetAvailableFunc( isCopperZone );
1542 constexpr int minMinWidth = pcbIUScale.mmToIU( ZONE_THICKNESS_MIN_VALUE_MM );
1543 clearanceOverride->SetValidator( PROPERTY_VALIDATORS::RangeIntValidator<minMinWidth,
1544 INT_MAX> );
1545
1546 auto padConnections = new PROPERTY_ENUM<ZONE, ZONE_CONNECTION>( _HKI( "Pad Connections" ),
1548 padConnections->SetAvailableFunc( isCopperZone );
1549
1550 auto thermalGap = new PROPERTY<ZONE, int>( _HKI( "Thermal Relief Gap" ),
1552 PROPERTY_DISPLAY::PT_SIZE );
1553 thermalGap->SetAvailableFunc( isCopperZone );
1554 thermalGap->SetValidator( PROPERTY_VALIDATORS::PositiveIntValidator );
1555
1556 auto thermalSpokeWidth = new PROPERTY<ZONE, int>( _HKI( "Thermal Relief Spoke Width" ),
1558 PROPERTY_DISPLAY::PT_SIZE );
1559 thermalSpokeWidth->SetAvailableFunc( isCopperZone );
1560 thermalSpokeWidth->SetValidator( atLeastMinWidthValidator );
1561
1562 propMgr.AddProperty( clearanceOverride, groupOverrides );
1563 propMgr.AddProperty( minWidth, groupOverrides );
1564 propMgr.AddProperty( padConnections, groupOverrides );
1565 propMgr.AddProperty( thermalGap, groupOverrides );
1566 propMgr.AddProperty( thermalSpokeWidth, groupOverrides );
1567 }
1569
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:77
int GetY() const
Definition: board_item.h:101
int GetX() const
Definition: board_item.h:95
virtual const BOARD * GetBoard() const
Return the BOARD in which this BOARD_ITEM resides, or NULL if none.
Definition: board_item.cpp:45
FOOTPRINT * GetParentFootprint() const
Definition: board_item.cpp:247
virtual bool IsLocked() const
Definition: board_item.cpp:73
wxString GetLayerName() const
Return the name of the PCB layer on which the item resides.
Definition: board_item.cpp:102
Information pertinent to a Pcbnew printed circuit board.
Definition: board.h:271
std::unordered_map< const ZONE *, BOX2I > m_ZoneBBoxCache
Definition: board.h:1200
BOARD_DESIGN_SETTINGS & GetDesignSettings() const
Definition: board.cpp:731
std::mutex m_CachesMutex
Definition: board.h:1191
BOX2< Vec > & Normalize()
Ensure that the height and width are positive.
Definition: box2.h:120
bool Intersects(const BOX2< Vec > &aRect) const
Definition: box2.h:270
bool Contains(const Vec &aPoint) const
Definition: box2.h:142
BOX2< Vec > & Inflate(coord_type dx, coord_type dy)
Inflates the rectangle horizontally by dx and vertically by dy.
Definition: box2.h:507
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:258
const KIID m_Uuid
Definition: eda_item.h:482
bool m_forceVisible
Definition: eda_item.h:486
KICAD_T Type() const
Returns the type of object.
Definition: eda_item.h:97
EDA_ITEM_FLAGS m_flags
Definition: eda_item.h:487
bool HasFlag(EDA_ITEM_FLAGS aFlag) const
Definition: eda_item.h:127
ENUM_MAP & Map(T aValue, const wxString &aName)
Definition: property.h:646
static ENUM_MAP< T > & Instance()
Definition: property.h:640
ENUM_MAP & Undefined(T aValue)
Definition: property.h:653
wxPGChoices & Choices()
Definition: property.h:689
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:68
bool IsLayerVisible(int aLayer) const
Return information about visibility of a particular layer.
Definition: view.h:409
LSEQ is a sequence (and therefore also a set) of PCB_LAYER_IDs.
Definition: layer_ids.h:513
LSET is a set of PCB_LAYER_IDs.
Definition: layer_ids.h:552
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:58
int GetLocalThermalGapOverride(wxString *aSource=nullptr) const
Definition: pad.cpp:958
PROPERTY_BASE & SetWriteableFunc(std::function< bool(INSPECTABLE *)> aFunc)
Definition: property.h:260
PROPERTY_BASE & SetValidator(PROPERTY_VALIDATOR_FN &&aValidator)
Definition: property.h:315
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 override
Check if point aP lies inside a closed shape.
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)
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)
bool GetNeighbourIndexes(int aGlobalIndex, int *aPrevious, int *aNext) const
Return the global indexes of the previous and the next corner of the aGlobalIndex-th corner of a cont...
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:436
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:825
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:748
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:1376
void SetCornerRadius(unsigned int aRadius)
Definition: zone.cpp:406
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:305
void AddPolygon(std::vector< VECTOR2I > &aPolygon)
Add a polygon to the zone outline.
Definition: zone.cpp:788
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:1306
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:527
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:1075
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:914
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:879
MD5_HASH GetHashValue(PCB_LAYER_ID aLayer)
Definition: zone.cpp:418
bool GetDoNotAllowPads() const
Definition: zone.h:714
const BOX2I GetBoundingBox() const override
Definition: zone.cpp:354
void SetMinThickness(int aMinThickness)
Definition: zone.h:259
double m_outlinearea
Definition: zone.h:912
wxString GetFriendlyName() const override
Definition: zone.cpp:701
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:740
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:446
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:272
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:674
bool IsIsland(PCB_LAYER_ID aLayer, int aPolyIdx) const
Check if a given filled polygon is an insulated island.
Definition: zone.cpp:1092
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
const 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:376
int GetMinThickness() const
Definition: zone.h:258
virtual void swapData(BOARD_ITEM *aImage) override
Definition: zone.cpp:1067
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:453
void RemoveCutout(int aOutlineIdx, int aHoleIdx)
Remove a cutout from the zone.
Definition: zone.cpp:759
void Rotate(const VECTOR2I &aCentre, const EDA_ANGLE &aAngle) override
Rotate the outlines.
Definition: zone.cpp:729
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:513
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:1061
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:552
virtual bool IsOnLayer(PCB_LAYER_ID) const override
Test to see if this object is on the given layer.
Definition: zone.cpp:348
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:873
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:427
void SetThermalReliefGap(int aThermalReliefGap)
Definition: zone.h:183
EDA_ANGLE GetHatchOrientation() const
Definition: zone.h:279
void SetLayerSet(LSET aLayerSet) override
Definition: zone.cpp:278
bool BuildSmoothedPoly(SHAPE_POLY_SET &aSmoothedPoly, PCB_LAYER_ID aLayer, SHAPE_POLY_SET *aBoardOutline, SHAPE_POLY_SET *aSmoothedPolyWithApron=nullptr) const
Definition: zone.cpp:1139
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:894
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:1104
int GetHatchGap() const
Definition: zone.h:276
double CalculateOutlineArea()
Compute the area of the zone outline (not the filled area).
Definition: zone.cpp:1299
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:805
void MoveEdge(const VECTOR2I &offset, int aEdge)
Move the outline Edge.
Definition: zone.cpp:714
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:321
bool IsOnCopperLayer() const override
Definition: zone.cpp:266
double CalculateFilledArea()
Compute the area currently occupied by the zone fill.
Definition: zone.cpp:1276
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:1346
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:900
PCB_LAYER_ID GetFirstLayer() const
Definition: zone.cpp:257
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:1055
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:1337
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:148
bool IsCopperLayer(int aLayerId)
Tests whether a layer is a copper layer.
Definition: layer_ids.h:847
@ LAYER_CONFLICTS_SHADOW
shadow layer for items flagged conficting
Definition: layer_ids.h:242
@ LAYER_FOOTPRINTS_FR
show footprints on front
Definition: layer_ids.h:209
@ LAYER_ZONES
Control for copper zone opacity/visibility (color ignored)
Definition: layer_ids.h:232
@ LAYER_ZONE_START
Virtual layers for stacking zones and tracks on a given copper layer.
Definition: layer_ids.h:254
@ LAYER_FOOTPRINTS_BK
show footprints on back
Definition: layer_ids.h:210
PCB_LAYER_ID
A quick note on layer IDs:
Definition: layer_ids.h:60
@ B_Cu
Definition: layer_ids.h:96
@ UNDEFINED_LAYER
Definition: layer_ids.h:61
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:426
#define TYPE_HASH(x)
Definition: property.h:64
#define IMPLEMENT_ENUM_TO_WXANY(type)
Definition: property.h:740
#define NO_SETTER(owner, type)
Definition: property.h:751
#define REGISTER_TYPE(x)
Definition: property_mgr.h:356
std::optional< std::unique_ptr< VALIDATION_ERROR > > VALIDATOR_RESULT
Null optional means validation succeeded.
const double epsilon
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:1385
@ PCB_ZONE_T
class ZONE, a copper pour area
Definition: typeinfo.h:104
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:415
bool sortEndsByDescendingX(const VECTOR2I &ref, const VECTOR2I &tst)
Definition: zone.cpp:908
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