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 The 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 <advanced_config.h>
27#include <bitmaps.h>
29#include <geometry/shape_null.h>
30#include <pcb_edit_frame.h>
31#include <pcb_screen.h>
32#include <board.h>
34#include <lset.h>
35#include <pad.h>
36#include <zone.h>
37#include <footprint.h>
38#include <string_utils.h>
40#include <properties/property.h>
44#include <trigo.h>
45#include <i18n_utility.h>
46#include <mutex>
47#include <magic_enum.hpp>
48
49#include <google/protobuf/any.pb.h>
50#include <api/api_enums.h>
51#include <api/api_utils.h>
52#include <api/api_pcb_utils.h>
53#include <api/board/board_types.pb.h>
54
55
58 m_Poly( nullptr ),
59 m_cornerRadius( 0 ),
60 m_priority( 0 ),
61 m_isRuleArea( false ),
66 m_ZoneClearance( 0 ),
69 m_isFilled( false ),
74 m_hatchGap( 0 ),
78 m_area( 0.0 ),
79 m_outlinearea( 0.0 )
80{
81 m_Poly = new SHAPE_POLY_SET(); // Outlines
82 SetLocalFlags( 0 ); // flags temporary used in zone calculations
83 m_fillVersion = 5; // set the "old" way to build filled polygon areas (< 6.0.x)
84
85 if( GetParentFootprint() )
86 SetIsRuleArea( true ); // Zones living in footprints have the rule area option
87
88 if( aParent->GetBoard() )
89 aParent->GetBoard()->GetDesignSettings().GetDefaultZoneSettings().ExportSetting( *this, false );
90 else
91 ZONE_SETTINGS().ExportSetting( *this, false );
92
93 m_needRefill = false; // True only after edits.
94}
95
96
97ZONE::ZONE( const ZONE& aZone ) :
98 BOARD_CONNECTED_ITEM( aZone ),
99 m_Poly( nullptr )
100{
102}
103
104
105ZONE& ZONE::operator=( const ZONE& aOther )
106{
108
110
111 return *this;
112}
113
114
115void ZONE::CopyFrom( const BOARD_ITEM* aOther )
116{
117 wxCHECK( aOther && aOther->Type() == PCB_ZONE_T, /* void */ );
118 *this = *static_cast<const ZONE*>( aOther );
119}
120
121
123{
124 delete m_Poly;
125
126 if( BOARD* board = GetBoard() )
127 board->IncrementTimeStamp();
128}
129
130
132{
133 // members are expected non initialize in this.
134 // InitDataFromSrcInCopyCtor() is expected to be called only from a copy constructor.
135
136 // Copy only useful EDA_ITEM flags:
137 m_flags = aZone.m_flags;
139
140 // Replace the outlines for aZone outlines.
141 delete m_Poly;
142 m_Poly = new SHAPE_POLY_SET( *aZone.m_Poly );
143
146 m_zoneName = aZone.m_zoneName;
147 m_priority = aZone.m_priority;
152
153 if( aLayer == UNDEFINED_LAYER )
154 SetLayerSet( aZone.GetLayerSet() );
155 else
156 SetLayerSet( { aLayer } );
157
163
165 m_ZoneClearance = aZone.m_ZoneClearance; // clearance value
170
171 m_isFilled = aZone.m_isFilled;
172 m_needRefill = aZone.m_needRefill.load();
174
177
178 m_fillMode = aZone.m_fillMode; // solid vs. hatched
180 m_hatchGap = aZone.m_hatchGap;
186
187 aZone.GetLayerSet().RunOnLayers(
188 [&]( PCB_LAYER_ID layer )
189 {
190 if( aLayer != UNDEFINED_LAYER && aLayer != layer )
191 return;
192
193 std::shared_ptr<SHAPE_POLY_SET> fill = aZone.m_FilledPolysList.at( layer );
194
195 if( fill )
196 m_FilledPolysList[layer] = std::make_shared<SHAPE_POLY_SET>( *fill );
197 else
198 m_FilledPolysList[layer] = std::make_shared<SHAPE_POLY_SET>();
199
200 m_filledPolysHash[layer] = aZone.m_filledPolysHash.at( layer );
201 m_insulatedIslands[layer] = aZone.m_insulatedIslands.at( layer );
202 } );
203
205
209
210 SetLocalFlags( aZone.GetLocalFlags() );
211
212 m_netinfo = aZone.m_netinfo;
213 m_area = aZone.m_area;
215}
216
217
219{
220 return new ZONE( *this );
221}
222
223
225{
226 ZONE* clone = new ZONE( BOARD_ITEM::GetParent() );
227 clone->InitDataFromSrcInCopyCtor( *this, aLayer );
228 return clone;
229}
230
231
232void ZONE::Serialize( google::protobuf::Any& aContainer ) const
233{
234 using namespace kiapi::board;
235 types::Zone zone;
237
238 zone.mutable_id()->set_value( m_Uuid.AsStdString() );
239 PackLayerSet( *zone.mutable_layers(), GetLayerSet() );
240
241 if( m_isRuleArea )
242 zone.set_type( types::ZT_RULE_AREA );
244 zone.set_type( types::ZT_TEARDROP );
245 else if( IsOnCopperLayer() )
246 zone.set_type( types::ZT_COPPER );
247 else
248 zone.set_type( types::ZT_GRAPHICAL );
249
250 kiapi::common::PackPolySet( *zone.mutable_outline(), *m_Poly );
251
252 zone.set_name( m_zoneName.ToUTF8() );
253 zone.set_priority( m_priority );
254 zone.set_filled( m_isFilled );
255
256 if( m_isRuleArea )
257 {
258 types::RuleAreaSettings* ra = zone.mutable_rule_area_settings();
259 ra->set_keepout_copper( m_doNotAllowZoneFills );
260 ra->set_keepout_footprints( m_doNotAllowFootprints );
261 ra->set_keepout_pads( m_doNotAllowPads );
262 ra->set_keepout_tracks( m_doNotAllowTracks );
263 ra->set_keepout_vias( m_doNotAllowVias );
264
265 ra->set_placement_enabled( m_placementAreaEnabled );
266 ra->set_placement_source( m_placementAreaSource.ToUTF8() );
267 ra->set_placement_source_type( ToProtoEnum<PLACEMENT_SOURCE_T,
268 types::PlacementRuleSourceType>( m_placementAreaSourceType ) );
269 }
270 else
271 {
272 types::CopperZoneSettings* cu = zone.mutable_copper_settings();
273 cu->mutable_connection()->set_zone_connection(
275
276 types::ThermalSpokeSettings* thermals = cu->mutable_connection()->mutable_thermal_spokes();
277 thermals->mutable_width()->set_value_nm( m_thermalReliefSpokeWidth );
278 thermals->mutable_gap()->set_value_nm( m_thermalReliefGap );
279 // n.b. zones don't currently have an overall thermal angle override
280
281 cu->mutable_clearance()->set_value_nm( m_ZoneClearance );
282 cu->mutable_min_thickness()->set_value_nm( m_ZoneMinThickness );
283 cu->set_island_mode(
285 cu->set_min_island_area( m_minIslandArea );
287
288 types::HatchFillSettings* hatch = cu->mutable_hatch_settings();
289 hatch->mutable_thickness()->set_value_nm( m_hatchThickness );
290 hatch->mutable_gap()->set_value_nm( m_hatchGap );
291 hatch->mutable_orientation()->set_value_degrees( m_hatchOrientation.AsDegrees() );
292 hatch->set_hatch_smoothing_ratio( m_hatchSmoothingValue );
293 hatch->set_hatch_hole_min_area_ratio( m_hatchHoleMinArea );
294
295 switch( m_hatchBorderAlgorithm )
296 {
297 default:
298 case 0: hatch->set_border_mode( types::ZHFBM_USE_MIN_ZONE_THICKNESS ); break;
299 case 1: hatch->set_border_mode( types::ZHFBM_USE_HATCH_THICKNESS ); break;
300 }
301
302 PackNet( cu->mutable_net() );
303 cu->mutable_teardrop()->set_type(
305 }
306
307 for( const auto& [layer, shape] : m_FilledPolysList )
308 {
309 types::ZoneFilledPolygons* filledLayer = zone.add_filled_polygons();
310 filledLayer->set_layer( ToProtoEnum<PCB_LAYER_ID, types::BoardLayer>( layer ) );
311 kiapi::common::PackPolySet( *filledLayer->mutable_shapes(), *shape );
312 }
313
314 for( const auto& [layer, properties] : m_layerProperties )
315 {
316 types::ZoneLayerProperties* layerProperties = zone.add_layer_properties();
317 layerProperties->set_layer( ToProtoEnum<PCB_LAYER_ID, types::BoardLayer>( layer ) );
318
319 if( properties.hatching_offset.has_value() )
320 {
321 PackVector2( *layerProperties->mutable_hatching_offset(),
322 properties.hatching_offset.value() );
323 }
324 }
325
326 zone.mutable_border()->set_style(
328 zone.mutable_border()->mutable_pitch()->set_value_nm( m_borderHatchPitch );
329
330 aContainer.PackFrom( zone );
331}
332
333
334bool ZONE::Deserialize( const google::protobuf::Any& aContainer )
335{
336 using namespace kiapi::board;
337 types::Zone zone;
339
340 if( !aContainer.UnpackTo( &zone ) )
341 return false;
342
343 SetUuidDirect( KIID( zone.id().value() ) );
344 SetLayerSet( UnpackLayerSet( zone.layers() ) );
345 SetAssignedPriority( zone.priority() );
346 SetZoneName( wxString::FromUTF8( zone.name() ) );
347
348 if( zone.type() == types::ZoneType::ZT_RULE_AREA )
349 m_isRuleArea = true;
350
351 if( !m_Poly )
353
354 *m_Poly = kiapi::common::UnpackPolySet( zone.outline() );
355
356 if( m_Poly->OutlineCount() == 0 )
357 return false;
358
359 if( m_isRuleArea )
360 {
361 const types::RuleAreaSettings& ra = zone.rule_area_settings();
362 m_doNotAllowZoneFills = ra.keepout_copper();
363 m_doNotAllowFootprints = ra.keepout_footprints();
364 m_doNotAllowPads = ra.keepout_pads();
365 m_doNotAllowTracks = ra.keepout_tracks();
366 m_doNotAllowVias = ra.keepout_vias();
367
368 m_placementAreaEnabled = ra.placement_enabled();
369 m_placementAreaSource = wxString::FromUTF8( ra.placement_source() );
370 m_placementAreaSourceType = FromProtoEnum<PLACEMENT_SOURCE_T>( ra.placement_source_type() );
371 }
372 else
373 {
374 const types::CopperZoneSettings& cu = zone.copper_settings();
375 m_PadConnection = FromProtoEnum<ZONE_CONNECTION>( cu.connection().zone_connection() );
376 m_thermalReliefSpokeWidth = cu.connection().thermal_spokes().width().value_nm();
377 m_thermalReliefGap = cu.connection().thermal_spokes().gap().value_nm();
378 m_ZoneClearance = cu.clearance().value_nm();
379 m_ZoneMinThickness = cu.min_thickness().value_nm();
381 m_minIslandArea = cu.min_island_area();
382 m_fillMode = FromProtoEnum<ZONE_FILL_MODE>( cu.fill_mode() );
383
384 m_hatchThickness = cu.hatch_settings().thickness().value_nm();
385 m_hatchGap = cu.hatch_settings().gap().value_nm();
386 m_hatchOrientation = EDA_ANGLE( cu.hatch_settings().orientation().value_degrees(), DEGREES_T );
387 m_hatchSmoothingValue = cu.hatch_settings().hatch_smoothing_ratio();
388 m_hatchHoleMinArea = cu.hatch_settings().hatch_hole_min_area_ratio();
389
390 switch( cu.hatch_settings().border_mode() )
391 {
392 default:
393 case types::ZHFBM_USE_MIN_ZONE_THICKNESS: m_hatchBorderAlgorithm = 0; break;
394 case types::ZHFBM_USE_HATCH_THICKNESS: m_hatchBorderAlgorithm = 1; break;
395 }
396
397 UnpackNet( cu.net() );
398 m_teardropType = FromProtoEnum<TEARDROP_TYPE>( cu.teardrop().type() );
399
400 for( const auto& properties : zone.layer_properties() )
401 {
402 PCB_LAYER_ID layer = FromProtoEnum<PCB_LAYER_ID>( properties.layer() );
403
404 ZONE_LAYER_PROPERTIES layerProperties;
405
406 if( properties.has_hatching_offset() )
407 layerProperties.hatching_offset = UnpackVector2( properties.hatching_offset() );
408
409 m_layerProperties[layer] = layerProperties;
410 }
411 }
412
414 m_borderHatchPitch = zone.border().pitch().value_nm();
415
416 if( zone.filled() )
417 {
418 // TODO(JE) check what else has to happen here
419 SetIsFilled( true );
420 SetNeedRefill( false );
421
422 for( const types::ZoneFilledPolygons& fillLayer : zone.filled_polygons() )
423 {
424 PCB_LAYER_ID layer = FromProtoEnum<PCB_LAYER_ID>( fillLayer.layer() );
425 SHAPE_POLY_SET shape = kiapi::common::UnpackPolySet( fillLayer.shapes() );
426 m_FilledPolysList[layer] = std::make_shared<SHAPE_POLY_SET>( shape );
427 }
428 }
429
430 HatchBorder();
431
432 return true;
433}
434
435
436bool ZONE::HigherPriority( const ZONE* aOther ) const
437{
438 // Teardrops are always higher priority than regular zones, so if one zone is a teardrop
439 // and the other is not, then return higher priority as the teardrop
441 return static_cast<int>( m_teardropType ) > static_cast<int>( aOther->m_teardropType );
442
443 if( m_priority != aOther->m_priority )
444 return m_priority > aOther->m_priority;
445
446 return m_Uuid > aOther->m_Uuid;
447}
448
449
450bool ZONE::SameNet( const ZONE* aOther ) const
451{
452 return GetNetCode() == aOther->GetNetCode();
453}
454
455
457{
458 std::lock_guard<std::mutex> lock( m_filledPolysListMutex );
459
460 return unFillLocked();
461}
462
463
465{
466 bool change = false;
467
468 for( std::pair<const PCB_LAYER_ID, std::shared_ptr<SHAPE_POLY_SET>>& pair : m_FilledPolysList )
469 {
470 change |= !pair.second->IsEmpty();
471 m_insulatedIslands[pair.first].clear();
472
473 // Replace the shared_ptr with a new empty object rather than clearing the existing one.
474 // This ensures that any CN_ZONE_LAYERs holding shared_ptr copies still have valid data
475 // (the old, now orphaned SHAPE_POLY_SET) while we get a fresh container.
476 pair.second = std::make_shared<SHAPE_POLY_SET>();
477 }
478
479 m_isFilled = false;
480 m_fillFlags.reset();
481
482 return change;
483}
484
485
487{
488 return HasFlag( COURTYARD_CONFLICT );
489}
490
491
493{
494 if( m_Poly->OutlineCount() == 0 || m_Poly->TotalVertices() == 0 )
495 return VECTOR2I( 0, 0 );
496
497 return GetCornerPosition( 0 );
498}
499
500
502{
503 std::lock_guard<std::mutex> lock( m_layerSetMutex );
504
505 if( m_layerSet.count() == 1 )
506 {
507 // GetFirstLayer would try to acquire the mutex again, so inline its logic here
508 if( m_layerSet.count() == 0 )
509 return UNDEFINED_LAYER;
510
511 const LSEQ uiLayers = m_layerSet.UIOrder();
512
513 if( uiLayers.size() )
514 return uiLayers[0];
515
516 return m_layerSet.Seq()[0];
517 }
518
519 return UNDEFINED_LAYER;
520}
521
522
524{
525 std::lock_guard<std::mutex> lock( m_layerSetMutex );
526
527 if( m_layerSet.count() == 0 )
528 return UNDEFINED_LAYER;
529
530 const LSEQ uiLayers = m_layerSet.UIOrder();
531
532 // This can't use m_layerSet.count() because it's possible to have a zone on
533 // a rescue layer that is not in the UI order.
534 if( uiLayers.size() )
535 return uiLayers[0];
536
537 // If it's not in the UI set at all, just return the first layer in the set.
538 // (we know the count > 0)
539 return m_layerSet.Seq()[0];
540}
541
542
544{
545 std::lock_guard<std::mutex> lock( m_layerSetMutex );
546 return ( m_layerSet & LSET::AllCuMask() ).count() > 0;
547}
548
549
551{
552 SetLayerSet( LSET( { aLayer } ) );
553}
554
555
556void ZONE::SetLayerSet( const LSET& aLayerSet )
557{
558 if( aLayerSet.count() == 0 )
559 return;
560
561 std::scoped_lock lock( m_layerSetMutex, m_filledPolysListMutex );
562
563 if( m_layerSet != aLayerSet )
564 {
565 SetNeedRefill( true );
566
567 unFillLocked();
568
569 m_FilledPolysList.clear();
570 m_filledPolysHash.clear();
571 m_insulatedIslands.clear();
572
573 aLayerSet.RunOnLayers(
574 [&]( PCB_LAYER_ID layer )
575 {
576 m_FilledPolysList[layer] = std::make_shared<SHAPE_POLY_SET>();
577 m_filledPolysHash[layer] = {};
578 m_insulatedIslands[layer] = {};
579 } );
580
581 std::erase_if( m_layerProperties,
582 [&]( const auto& item )
583 {
584 return !aLayerSet.Contains( item.first );
585 } );
586 }
587
588 m_layerSet = aLayerSet;
589}
590
591
592void ZONE::SetLayerProperties( const std::map<PCB_LAYER_ID, ZONE_LAYER_PROPERTIES>& aOther )
593{
594 m_layerProperties = aOther;
595}
596
597
598std::vector<int> ZONE::ViewGetLayers() const
599{
600 std::lock_guard<std::mutex> lock( m_layerSetMutex );
601
602 std::vector<int> layers;
603 layers.reserve( 2 * m_layerSet.count() + 1 );
604
605 m_layerSet.RunOnLayers(
606 [&]( PCB_LAYER_ID layer )
607 {
608 layers.push_back( layer );
609 layers.push_back( layer + static_cast<int>( LAYER_ZONE_START ) );
610 } );
611
612 layers.push_back( LAYER_CONFLICTS_SHADOW );
613
614 return layers;
615}
616
617
618double ZONE::ViewGetLOD( int aLayer, const KIGFX::VIEW* aView ) const
619{
620 if( !aView )
621 return LOD_SHOW;
622
623 if( !aView->IsLayerVisible( LAYER_ZONES ) )
624 return LOD_HIDE;
625
626 if( FOOTPRINT* parentFP = GetParentFootprint() )
627 {
628 bool flipped = parentFP->GetLayer() == B_Cu;
629
630 // Handle Render tab switches
631 if( !flipped && !aView->IsLayerVisible( LAYER_FOOTPRINTS_FR ) )
632 return LOD_HIDE;
633
634 if( flipped && !aView->IsLayerVisible( LAYER_FOOTPRINTS_BK ) )
635 return LOD_HIDE;
636 }
637
638 // Other layers are shown without any conditions
639 return LOD_SHOW;
640}
641
642
643bool ZONE::IsOnLayer( PCB_LAYER_ID aLayer ) const
644{
645 std::lock_guard<std::mutex> lock( m_layerSetMutex );
646 return m_layerSet.test( aLayer );
647}
648
649
651{
652 if( const BOARD* board = GetBoard() )
653 {
654 std::unordered_map<const ZONE*, BOX2I>& cache = board->m_ZoneBBoxCache;
655
656 {
657 std::shared_lock<std::shared_mutex> readLock( board->m_CachesMutex );
658
659 auto cacheIter = cache.find( this );
660
661 if( cacheIter != cache.end() )
662 return cacheIter->second;
663 }
664
665 BOX2I bbox = m_Poly->BBox();
666
667 {
668 std::unique_lock<std::shared_mutex> writeLock( board->m_CachesMutex );
669 cache[ this ] = bbox;
670 }
671
672 return bbox;
673 }
674
675 return m_Poly->BBox();
676}
677
678
680{
681 // GetBoundingBox() will cache it for us, and there's no sense duplicating the somewhat tricky
682 // locking code.
684}
685
686
687int ZONE::GetThermalReliefGap( PAD* aPad, wxString* aSource ) const
688{
689 if( aPad->GetLocalThermalGapOverride() == 0 )
690 {
691 if( aSource )
692 *aSource = _( "zone" );
693
694 return m_thermalReliefGap;
695 }
696
697 return aPad->GetLocalThermalGapOverride( aSource );
698
699}
700
701
702void ZONE::SetCornerRadius( unsigned int aRadius )
703{
704 if( m_cornerRadius != aRadius )
705 SetNeedRefill( true );
706
707 m_cornerRadius = aRadius;
708}
709
710
712
713
715{
716 if( !m_filledPolysHash.count( aLayer ) )
717 return g_nullPoly.GetHash();
718 else
719 return m_filledPolysHash.at( aLayer );
720}
721
722
724{
725 std::lock_guard<std::mutex> lock( m_filledPolysListMutex );
726
727 if( !m_FilledPolysList.count( aLayer ) )
728 m_filledPolysHash[aLayer] = g_nullPoly.GetHash();
729 else
730 m_filledPolysHash[aLayer] = m_FilledPolysList.at( aLayer )->GetHash();
731}
732
733
734bool ZONE::HitTest( const VECTOR2I& aPosition, int aAccuracy ) const
735{
736 // When looking for an "exact" hit aAccuracy will be 0 which works poorly for very thin
737 // lines. Give it a floor.
738 int accuracy = std::max( aAccuracy, pcbIUScale.mmToIU( 0.1 ) );
739
740 return HitTestForCorner( aPosition, accuracy * 2 ) || HitTestForEdge( aPosition, accuracy );
741}
742
743
744bool ZONE::HitTestForCorner( const VECTOR2I& refPos, int aAccuracy,
745 SHAPE_POLY_SET::VERTEX_INDEX* aCornerHit ) const
746{
747 return m_Poly->CollideVertex( VECTOR2I( refPos ), aCornerHit, aAccuracy );
748}
749
750
751bool ZONE::HitTestForEdge( const VECTOR2I& refPos, int aAccuracy,
752 SHAPE_POLY_SET::VERTEX_INDEX* aCornerHit ) const
753{
754 return m_Poly->CollideEdge( VECTOR2I( refPos ), aCornerHit, aAccuracy );
755}
756
757
758bool ZONE::HitTest( const BOX2I& aRect, bool aContained, int aAccuracy ) const
759{
760 // Calculate bounding box for zone
761 BOX2I bbox = GetBoundingBox();
762 bbox.Normalize();
763
764 BOX2I arect = aRect;
765 arect.Normalize();
766 arect.Inflate( aAccuracy );
767
768 if( aContained )
769 {
770 return arect.Contains( bbox );
771 }
772 else
773 {
774 // Fast test: if aBox is outside the polygon bounding box, rectangles cannot intersect
775 if( !arect.Intersects( bbox ) )
776 return false;
777
778 int count = m_Poly->TotalVertices();
779
780 for( int ii = 0; ii < count; ii++ )
781 {
782 VECTOR2I vertex = m_Poly->CVertex( ii );
783 VECTOR2I vertexNext = m_Poly->CVertex( ( ii + 1 ) % count );
784
785 // Test if the point is within the rect
786 if( arect.Contains( vertex ) )
787 return true;
788
789 // Test if this edge intersects the rect
790 if( arect.Intersects( vertex, vertexNext ) )
791 return true;
792 }
793
794 return false;
795 }
796}
797
798
799bool ZONE::HitTest( const SHAPE_LINE_CHAIN& aPoly, bool aContained ) const
800{
801 if( aContained )
802 {
803 auto outlineIntersectingSelection =
804 [&]()
805 {
806 for( auto segment = m_Poly->IterateSegments(); segment; segment++ )
807 {
808 if( aPoly.Intersects( *segment ) )
809 return true;
810 }
811
812 return false;
813 };
814
815 // In the case of contained selection, all vertices of the zone outline must be inside
816 // the selection polygon, so we can check only the first vertex.
817 auto vertexInsideSelection =
818 [&]()
819 {
820 return aPoly.PointInside( m_Poly->CVertex( 0 ) );
821 };
822
823 return vertexInsideSelection() && !outlineIntersectingSelection();
824 }
825 else
826 {
827 // Touching selection - check if any segment of the zone contours collides with the
828 // selection shape.
829 for( auto segment = m_Poly->IterateSegmentsWithHoles(); segment; segment++ )
830 {
831 if( aPoly.PointInside( ( *segment ).A ) )
832 return true;
833
834 if( aPoly.Intersects( *segment ) )
835 return true;
836
837 // Note: aPoly.Collide() could be used instead of two test above, but it is 3x slower.
838 }
839
840 return false;
841 }
842}
843
844
845std::optional<int> ZONE::GetLocalClearance() const
846{
847 return m_isRuleArea ? 0 : m_ZoneClearance;
848}
849
850
851bool ZONE::HitTestFilledArea( PCB_LAYER_ID aLayer, const VECTOR2I& aRefPos, int aAccuracy ) const
852{
853 // Rule areas have no filled area, but it's generally nice to treat their interior as if it were
854 // filled so that people don't have to select them by their outline (which is min-width)
855 if( GetIsRuleArea() )
856 return m_Poly->Contains( aRefPos, -1, aAccuracy );
857
858 std::shared_ptr<SHAPE_POLY_SET> fillPolys;
859
860 {
861 std::lock_guard<std::mutex> lock( m_filledPolysListMutex );
862
863 if( !m_FilledPolysList.count( aLayer ) )
864 return false;
865
866 fillPolys = m_FilledPolysList.at( aLayer );
867 }
868
869 return fillPolys->Contains( aRefPos, -1, aAccuracy );
870}
871
872
873bool ZONE::HitTestCutout( const VECTOR2I& aRefPos, int* aOutlineIdx, int* aHoleIdx ) const
874{
875 // Iterate over each outline polygon in the zone and then iterate over
876 // each hole it has to see if the point is in it.
877 for( int i = 0; i < m_Poly->OutlineCount(); i++ )
878 {
879 for( int j = 0; j < m_Poly->HoleCount( i ); j++ )
880 {
881 if( m_Poly->Hole( i, j ).PointInside( aRefPos ) )
882 {
883 if( aOutlineIdx )
884 *aOutlineIdx = i;
885
886 if( aHoleIdx )
887 *aHoleIdx = j;
888
889 return true;
890 }
891 }
892 }
893
894 return false;
895}
896
897
898void ZONE::GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_ITEM>& aList )
899{
900 wxString msg = GetFriendlyName();
901
902 aList.emplace_back( _( "Type" ), msg );
903
904 if( GetIsRuleArea() )
905 {
906 msg.Empty();
907
908 if( GetDoNotAllowVias() )
909 AccumulateDescription( msg, _( "No vias" ) );
910
911 if( GetDoNotAllowTracks() )
912 AccumulateDescription( msg, _( "No tracks" ) );
913
914 if( GetDoNotAllowPads() )
915 AccumulateDescription( msg, _( "No pads" ) );
916
918 AccumulateDescription( msg, _( "No zone fills" ) );
919
921 AccumulateDescription( msg, _( "No footprints" ) );
922
923 if( !msg.IsEmpty() )
924 aList.emplace_back( _( "Restrictions" ), msg );
925
927 aList.emplace_back( _( "Placement source" ), UnescapeString( GetPlacementAreaSource() ) );
928 }
929 else if( IsOnCopperLayer() )
930 {
931 if( aFrame->GetName() == PCB_EDIT_FRAME_NAME )
932 {
933 aList.emplace_back( _( "Net" ), UnescapeString( GetNetname() ) );
934
935 aList.emplace_back( _( "Resolved Netclass" ),
936 UnescapeString( GetEffectiveNetClass()->GetHumanReadableName() ) );
937 }
938
939 // Display priority level
940 aList.emplace_back( _( "Priority" ), wxString::Format( wxT( "%d" ), GetAssignedPriority() ) );
941 }
942
943 if( aFrame->GetName() == PCB_EDIT_FRAME_NAME )
944 {
945 if( IsLocked() )
946 aList.emplace_back( _( "Status" ), _( "Locked" ) );
947 }
948
949 LSEQ layers = m_layerSet.Seq();
950 wxString layerDesc;
951
952 if( layers.size() == 1 )
953 {
954 layerDesc.Printf( _( "%s" ), GetBoard()->GetLayerName( layers[0] ) );
955 }
956 else if (layers.size() == 2 )
957 {
958 layerDesc.Printf( _( "%s and %s" ),
959 GetBoard()->GetLayerName( layers[0] ),
960 GetBoard()->GetLayerName( layers[1] ) );
961 }
962 else if (layers.size() == 3 )
963 {
964 layerDesc.Printf( _( "%s, %s and %s" ),
965 GetBoard()->GetLayerName( layers[0] ),
966 GetBoard()->GetLayerName( layers[1] ),
967 GetBoard()->GetLayerName( layers[2] ) );
968 }
969 else if( layers.size() > 3 )
970 {
971 layerDesc.Printf( _( "%s, %s and %d more" ),
972 GetBoard()->GetLayerName( layers[0] ),
973 GetBoard()->GetLayerName( layers[1] ),
974 static_cast<int>( layers.size() - 2 ) );
975 }
976
977 aList.emplace_back( _( "Layer" ), layerDesc );
978
979 if( !m_zoneName.empty() )
980 aList.emplace_back( _( "Name" ), m_zoneName );
981
982 if( !GetIsRuleArea() ) // Show fill mode only for not rule areas
983 {
984 switch( m_fillMode )
985 {
986 case ZONE_FILL_MODE::POLYGONS: msg = _( "Solid" ); break;
987 case ZONE_FILL_MODE::HATCH_PATTERN: msg = _( "Hatched" ); break;
988 default: msg = _( "Unknown" ); break;
989 }
990
991 aList.emplace_back( _( "Fill Mode" ), msg );
992
993 aList.emplace_back( _( "Filled Area" ),
995
996 wxString source;
997 int clearance = GetOwnClearance( UNDEFINED_LAYER, &source );
998
999 if( !source.IsEmpty() )
1000 {
1001 aList.emplace_back( wxString::Format( _( "Min Clearance: %s" ), aFrame->MessageTextFromValue( clearance ) ),
1002 wxString::Format( _( "(from %s)" ), source ) );
1003 }
1004 }
1005
1006 int count = 0;
1007
1008 if( GetIsRuleArea() )
1009 {
1010 double outline_area = CalculateOutlineArea();
1011 aList.emplace_back( _( "Outline Area" ),
1012 aFrame->MessageTextFromValue( outline_area, true, EDA_DATA_TYPE::AREA ) );
1013
1014 const SHAPE_POLY_SET* area_outline = Outline();
1015 count = area_outline->FullPointCount();
1016 }
1017 else if( !m_FilledPolysList.empty() )
1018 {
1019 for( std::pair<const PCB_LAYER_ID, std::shared_ptr<SHAPE_POLY_SET>>& ii: m_FilledPolysList )
1020 count += ii.second->TotalVertices();
1021 }
1022
1023 aList.emplace_back( _( "Corner Count" ), wxString::Format( wxT( "%d" ), count ) );
1024}
1025
1026
1027void ZONE::Move( const VECTOR2I& offset )
1028{
1029 /* move outlines */
1030 m_Poly->Move( offset );
1031
1032 // Translate existing hatch lines instead of regenerating them. HatchBorder() is expensive
1033 // (O(n*m) segment intersections + point-in-polygon tests) and the hatch pattern is
1034 // invariant under translation.
1035 for( SEG& seg : m_borderHatchLines )
1036 {
1037 seg.A += offset;
1038 seg.B += offset;
1039 }
1040
1041 /* move fills */
1042 for( std::pair<const PCB_LAYER_ID, std::shared_ptr<SHAPE_POLY_SET>>& pair : m_FilledPolysList )
1043 pair.second->Move( offset );
1044
1045 /*
1046 * move boundingbox cache
1047 *
1048 * While the cache will get nuked at the conclusion of the operation, we use it for some
1049 * things (such as drawing the parent group) during the move.
1050 */
1051 if( GetBoard() )
1052 {
1053 auto it = GetBoard()->m_ZoneBBoxCache.find( this );
1054
1055 if( it != GetBoard()->m_ZoneBBoxCache.end() )
1056 it->second.Move( offset );
1057 }
1058}
1059
1060
1062{
1063 if( GetIsRuleArea() )
1064 return _( "Rule Area" );
1065 else if( IsTeardropArea() )
1066 return _( "Teardrop Area" );
1067 else if( IsOnCopperLayer() )
1068 return _( "Copper Zone" );
1069 else
1070 return _( "Non-copper Zone" );
1071}
1072
1073
1074void ZONE::MoveEdge( const VECTOR2I& offset, int aEdge )
1075{
1076 int next_corner;
1077
1078 if( m_Poly->GetNeighbourIndexes( aEdge, nullptr, &next_corner ) )
1079 {
1080 m_Poly->SetVertex( aEdge, m_Poly->CVertex( aEdge ) + VECTOR2I( offset ) );
1081 m_Poly->SetVertex( next_corner, m_Poly->CVertex( next_corner ) + VECTOR2I( offset ) );
1082 HatchBorder();
1083
1084 SetNeedRefill( true );
1085 }
1086}
1087
1088
1089void ZONE::Rotate( const VECTOR2I& aCentre, const EDA_ANGLE& aAngle )
1090{
1091 m_Poly->Rotate( aAngle, aCentre );
1092 HatchBorder();
1093
1094 /* rotate filled areas: */
1095 for( std::pair<const PCB_LAYER_ID, std::shared_ptr<SHAPE_POLY_SET>>& pair : m_FilledPolysList )
1096 pair.second->Rotate( aAngle, aCentre );
1097}
1098
1099
1100void ZONE::Flip( const VECTOR2I& aCentre, FLIP_DIRECTION aFlipDirection )
1101{
1102 Mirror( aCentre, aFlipDirection );
1103
1104 std::map<PCB_LAYER_ID, SHAPE_POLY_SET> fillsCopy;
1105
1106 for( auto& [oldLayer, shapePtr] : m_FilledPolysList )
1107 fillsCopy[oldLayer] = *shapePtr;
1108
1109 std::map<PCB_LAYER_ID, ZONE_LAYER_PROPERTIES> layerPropertiesCopy = m_layerProperties;
1110
1111 LSET flipped;
1112
1113 for( PCB_LAYER_ID layer : GetLayerSet() )
1114 flipped.set( GetBoard()->FlipLayer( layer ) );
1115
1116 SetLayerSet( flipped );
1117
1118 for( auto& [oldLayer, properties] : layerPropertiesCopy )
1119 {
1120 PCB_LAYER_ID newLayer = GetBoard()->FlipLayer( oldLayer );
1121 m_layerProperties[newLayer] = properties;
1122 }
1123
1124 for( auto& [oldLayer, shape] : fillsCopy )
1125 {
1126 PCB_LAYER_ID newLayer = GetBoard()->FlipLayer( oldLayer );
1127 SetFilledPolysList( newLayer, shape );
1128 }
1129}
1130
1131
1132void ZONE::Mirror( const VECTOR2I& aMirrorRef, FLIP_DIRECTION aFlipDirection )
1133{
1134 m_Poly->Mirror( aMirrorRef, aFlipDirection );
1135
1136 HatchBorder();
1137
1138 for( std::pair<const PCB_LAYER_ID, std::shared_ptr<SHAPE_POLY_SET>>& pair : m_FilledPolysList )
1139 pair.second->Mirror( aMirrorRef, aFlipDirection );
1140}
1141
1142
1143void ZONE::RemoveCutout( int aOutlineIdx, int aHoleIdx )
1144{
1145 // Ensure the requested cutout is valid
1146 if( m_Poly->OutlineCount() < aOutlineIdx || m_Poly->HoleCount( aOutlineIdx ) < aHoleIdx )
1147 return;
1148
1149 SHAPE_POLY_SET cutPoly( m_Poly->Hole( aOutlineIdx, aHoleIdx ) );
1150
1151 // Add the cutout back to the zone
1152 m_Poly->BooleanAdd( cutPoly );
1153
1154 SetNeedRefill( true );
1155}
1156
1157
1158void ZONE::AddPolygon( const SHAPE_LINE_CHAIN& aPolygon )
1159{
1160 wxASSERT( aPolygon.IsClosed() );
1161
1162 // Add the outline as a new polygon in the polygon set
1163 if( m_Poly->OutlineCount() == 0 )
1164 m_Poly->AddOutline( aPolygon );
1165 else
1166 m_Poly->AddHole( aPolygon );
1167
1168 SetNeedRefill( true );
1169}
1170
1171
1172void ZONE::AddPolygon( std::vector<VECTOR2I>& aPolygon )
1173{
1174 if( aPolygon.empty() )
1175 return;
1176
1177 SHAPE_LINE_CHAIN outline;
1178
1179 // Create an outline and populate it with the points of aPolygon
1180 for( const VECTOR2I& pt : aPolygon )
1181 outline.Append( pt );
1182
1183 outline.SetClosed( true );
1184
1185 AddPolygon( outline );
1186}
1187
1188
1189bool ZONE::AppendCorner( VECTOR2I aPosition, int aHoleIdx, bool aAllowDuplication )
1190{
1191 // Ensure the main outline exists:
1192 if( m_Poly->OutlineCount() == 0 )
1193 m_Poly->NewOutline();
1194
1195 // If aHoleIdx >= 0, the corner musty be added to the hole, index aHoleIdx.
1196 // (remember: the index of the first hole is 0)
1197 // Return error if it does not exist.
1198 if( aHoleIdx >= m_Poly->HoleCount( 0 ) )
1199 return false;
1200
1201 m_Poly->Append( aPosition.x, aPosition.y, -1, aHoleIdx, aAllowDuplication );
1202
1203 SetNeedRefill( true );
1204
1205 return true;
1206}
1207
1208
1209wxString ZONE::GetItemDescription( UNITS_PROVIDER* aUnitsProvider, bool aFull ) const
1210{
1211 LSEQ layers = m_layerSet.Seq();
1212 wxString layerDesc;
1213
1214 if( layers.size() == 1 )
1215 {
1216 layerDesc.Printf( _( "on %s" ), GetBoard()->GetLayerName( layers[0] ) );
1217 }
1218 else if (layers.size() == 2 )
1219 {
1220 layerDesc.Printf( _( "on %s and %s" ),
1221 GetBoard()->GetLayerName( layers[0] ),
1222 GetBoard()->GetLayerName( layers[1] ) );
1223 }
1224 else if (layers.size() == 3 )
1225 {
1226 layerDesc.Printf( _( "on %s, %s and %s" ),
1227 GetBoard()->GetLayerName( layers[0] ),
1228 GetBoard()->GetLayerName( layers[1] ),
1229 GetBoard()->GetLayerName( layers[2] ) );
1230 }
1231 else if( layers.size() > 3 )
1232 {
1233 layerDesc.Printf( _( "on %s, %s and %zu more" ),
1234 GetBoard()->GetLayerName( layers[0] ),
1235 GetBoard()->GetLayerName( layers[1] ),
1236 layers.size() - 2 );
1237 }
1238
1239 if( GetIsRuleArea() )
1240 {
1241 if( GetZoneName().IsEmpty() )
1242 {
1243 return wxString::Format( _( "Rule Area %s" ),
1244 layerDesc );
1245 }
1246 else
1247 {
1248 return wxString::Format( _( "Rule area '%s' %s" ),
1249 GetZoneName(),
1250 layerDesc );
1251 }
1252 }
1253 else if( IsTeardropArea() )
1254 {
1255 return wxString::Format( _( "Teardrop %s %s" ),
1256 GetNetnameMsg(),
1257 layerDesc );
1258 }
1259 else
1260 {
1261 if( GetZoneName().IsEmpty() )
1262 {
1263 return wxString::Format( _( "Zone %s %s, priority %d" ),
1264 GetNetnameMsg(),
1265 layerDesc,
1267 }
1268 else
1269 {
1270 return wxString::Format( _( "Zone '%s' %s %s, priority %d" ),
1271 GetZoneName(),
1272 GetNetnameMsg(),
1273 layerDesc,
1275 }
1276 }
1277}
1278
1279
1281 int aBorderHatchPitch, bool aRebuildBorderHatch )
1282{
1283 aBorderHatchPitch = std::max( aBorderHatchPitch, pcbIUScale.mmToIU( ZONE_BORDER_HATCH_MINDIST_MM ) );
1284 aBorderHatchPitch = std::min( aBorderHatchPitch, pcbIUScale.mmToIU( ZONE_BORDER_HATCH_MAXDIST_MM ) );
1285 SetBorderHatchPitch( aBorderHatchPitch );
1286 m_borderStyle = aBorderHatchStyle;
1287
1288 if( aRebuildBorderHatch )
1289 HatchBorder();
1290}
1291
1292
1294{
1295 m_borderHatchLines.clear();
1296}
1297
1298
1300{
1301 UnHatchBorder();
1302
1304 || m_borderHatchPitch == 0
1305 || m_Poly->IsEmpty() )
1306 {
1307 return;
1308 }
1309
1310 // set the "length" of hatch lines (the length on horizontal axis)
1311 int hatch_line_len = m_borderHatchPitch; // OK for DIAGONAL_EDGE style
1312
1313 // Calculate spacing between 2 hatch lines
1314 int spacing = m_borderHatchPitch; // OK for DIAGONAL_EDGE style
1315
1317 {
1318 // The spacing is twice the spacing for DIAGONAL_EDGE because one
1319 // full diagonal replaces 2 edge diagonal hatch segments in code
1320 spacing = m_borderHatchPitch * 2;
1321 hatch_line_len = -1; // Use full diagonal hatch line
1322 }
1323
1324 // To have a better look, give a slope depending on the layer
1325 int layer = GetFirstLayer();
1326 std::vector<double> slopes;
1327
1328 if( IsTeardropArea() )
1329 slopes = { 0.7, -0.7 };
1330 else if( layer & 1 )
1331 slopes = { 1 };
1332 else
1333 slopes = { -1 };
1334
1335 m_borderHatchLines = m_Poly->GenerateHatchLines( slopes, spacing, hatch_line_len );
1336}
1337
1338
1340{
1341 return pcbIUScale.mmToIU( ZONE_BORDER_HATCH_DIST_MM );
1342}
1343
1344
1346{
1347 return BITMAPS::add_zone;
1348}
1349
1350
1352{
1353 assert( aImage->Type() == PCB_ZONE_T );
1354
1355 std::swap( *static_cast<ZONE*>( this ), *static_cast<ZONE*>( aImage) );
1356}
1357
1358
1360{
1361 if( aLayer == UNDEFINED_LAYER )
1362 {
1363 std::lock_guard<std::mutex> lock( m_filledPolysListMutex );
1364
1365 for( auto& [ layer, poly ] : m_FilledPolysList )
1366 poly->CacheTriangulation( false, aSubmitter );
1367
1368 m_Poly->CacheTriangulation();
1369 }
1370 else
1371 {
1372 // Grab a shared_ptr copy under the lock, then triangulate outside it.
1373 // Each layer's SHAPE_POLY_SET is independent, so concurrent triangulation
1374 // of different layers is safe once we have the shared_ptr.
1375 std::shared_ptr<SHAPE_POLY_SET> poly;
1376
1377 {
1378 std::lock_guard<std::mutex> lock( m_filledPolysListMutex );
1379
1380 auto it = m_FilledPolysList.find( aLayer );
1381
1382 if( it != m_FilledPolysList.end() )
1383 poly = it->second;
1384 }
1385
1386 if( poly )
1387 poly->CacheTriangulation( false, aSubmitter );
1388 }
1389}
1390
1391
1392bool ZONE::IsIsland( PCB_LAYER_ID aLayer, int aPolyIdx ) const
1393{
1394 if( GetNetCode() < 1 )
1395 return true;
1396
1397 if( !m_insulatedIslands.count( aLayer ) )
1398 return false;
1399
1400 return m_insulatedIslands.at( aLayer ).count( aPolyIdx );
1401}
1402
1403
1404void ZONE::GetInteractingZones( PCB_LAYER_ID aLayer, std::vector<ZONE*>* aSameNetCollidingZones,
1405 std::vector<ZONE*>* aOtherNetIntersectingZones ) const
1406{
1407 int epsilon = pcbIUScale.mmToIU( 0.001 );
1408 BOX2I bbox = GetBoundingBox();
1409
1410 bbox.Inflate( epsilon );
1411
1412 for( ZONE* candidate : GetBoard()->Zones() )
1413 {
1414 if( candidate == this )
1415 continue;
1416
1417 if( !candidate->GetLayerSet().test( aLayer ) )
1418 continue;
1419
1420 if( candidate->GetIsRuleArea() || candidate->IsTeardropArea() )
1421 continue;
1422
1423 if( !candidate->GetBoundingBox().Intersects( bbox ) )
1424 continue;
1425
1426 if( candidate->GetNetCode() == GetNetCode() )
1427 {
1428 if( m_Poly->Collide( candidate->m_Poly ) )
1429 aSameNetCollidingZones->push_back( candidate );
1430 }
1431 else
1432 {
1433 aOtherNetIntersectingZones->push_back( candidate );
1434 }
1435 }
1436}
1437
1438
1440 SHAPE_POLY_SET* aBoardOutline,
1441 SHAPE_POLY_SET* aSmoothedPolyWithApron ) const
1442{
1443 if( GetNumCorners() <= 2 ) // malformed zone. polygon calculations will not like it ...
1444 return false;
1445
1446 // Processing of arc shapes in zones is not yet supported because Clipper can't do boolean
1447 // operations on them. The poly outline must be converted to segments first.
1448 SHAPE_POLY_SET flattened = m_Poly->CloneDropTriangulation();
1449 flattened.ClearArcs();
1450
1451 if( GetIsRuleArea() )
1452 {
1453 // We like keepouts just the way they are....
1454 aSmoothedPoly = std::move( flattened );
1455 return true;
1456 }
1457
1458 const BOARD* board = GetBoard();
1459 bool keepExternalFillets = false;
1462
1463 if( IsTeardropArea() )
1464 {
1465 // We use teardrop shapes with no smoothing; these shapes are already optimized
1466 smooth_requested = false;
1467 }
1468
1469 if( board )
1470 keepExternalFillets = board->GetDesignSettings().m_ZoneKeepExternalFillets;
1471
1472 auto smooth =
1473 [&]( SHAPE_POLY_SET& aPoly )
1474 {
1475 if( !smooth_requested )
1476 return;
1477
1478 switch( m_cornerSmoothingType )
1479 {
1481 aPoly = aPoly.Chamfer( (int) m_cornerRadius );
1482 break;
1483
1485 aPoly = aPoly.Fillet( (int) m_cornerRadius, GetMaxError() );
1486 break;
1487
1488 default:
1489 break;
1490 }
1491 };
1492
1493 SHAPE_POLY_SET* maxExtents = &flattened;
1494 SHAPE_POLY_SET withFillets;
1495
1496 aSmoothedPoly = flattened;
1497
1498 // Should external fillets (that is, those applied to concave corners) be kept? While it
1499 // seems safer to never have copper extend outside the zone outline, 5.1.x and prior did
1500 // indeed fill them so we leave the mode available.
1501 if( keepExternalFillets && smooth_requested )
1502 {
1503 withFillets = flattened;
1504 smooth( withFillets );
1505 withFillets.BooleanAdd( flattened );
1506 maxExtents = &withFillets;
1507 }
1508
1509 // We now add in the areas of any same-net, intersecting zones. This keeps us from smoothing
1510 // corners at an intersection (which often produces undesired divots between the intersecting
1511 // zones -- see #2752).
1512 //
1513 // After smoothing, we'll subtract back out everything outside of our zone.
1514 std::vector<ZONE*> sameNetCollidingZones;
1515 std::vector<ZONE*> diffNetIntersectingZones;
1516 GetInteractingZones( aLayer, &sameNetCollidingZones, &diffNetIntersectingZones );
1517
1518 for( ZONE* sameNetZone : sameNetCollidingZones )
1519 {
1520 BOX2I sameNetBoundingBox = sameNetZone->GetBoundingBox();
1521
1522 // Note: a two-pass algorithm could use sameNetZone's actual fill instead of its outline.
1523 // This would obviate the need for the below wrinkles, in addition to fixing both issues
1524 // in #16095.
1525 // (And we wouldn't need to collect all the diffNetIntersectingZones either.)
1526
1527 SHAPE_POLY_SET sameNetPoly = sameNetZone->Outline()->CloneDropTriangulation();
1528 sameNetPoly.ClearArcs();
1529
1530 SHAPE_POLY_SET diffNetPoly;
1531
1532 // Of course there's always a wrinkle. The same-net intersecting zone *might* get knocked
1533 // out along the border by a higher-priority, different-net zone. #12797
1534 for( ZONE* diffNetZone : diffNetIntersectingZones )
1535 {
1536 if( diffNetZone->HigherPriority( sameNetZone )
1537 && diffNetZone->GetBoundingBox().Intersects( sameNetBoundingBox ) )
1538 {
1539 SHAPE_POLY_SET diffNetOutline = diffNetZone->Outline()->CloneDropTriangulation();
1540 diffNetOutline.ClearArcs();
1541
1542 diffNetPoly.BooleanAdd( diffNetOutline );
1543 }
1544 }
1545
1546 // Second wrinkle. After unioning the higher priority, different net zones together, we
1547 // need to check to see if they completely enclose our zone. If they do, then we need to
1548 // treat the enclosed zone as isolated, not connected to the outer zone. #13915
1549 bool isolated = false;
1550
1551 if( diffNetPoly.OutlineCount() )
1552 {
1554 thisPoly.ClearArcs();
1555
1556 thisPoly.BooleanSubtract( diffNetPoly );
1557 isolated = thisPoly.OutlineCount() == 0;
1558 }
1559
1560 if( !isolated )
1561 aSmoothedPoly.BooleanAdd( sameNetPoly );
1562 }
1563
1564 if( aBoardOutline )
1565 {
1566 SHAPE_POLY_SET boardOutline = aBoardOutline->CloneDropTriangulation();
1567 boardOutline.ClearArcs();
1568
1569 aSmoothedPoly.BooleanIntersection( boardOutline );
1570 }
1571
1572 SHAPE_POLY_SET withSameNetIntersectingZones = aSmoothedPoly.CloneDropTriangulation();
1573
1574 smooth( aSmoothedPoly );
1575
1576 if( aSmoothedPolyWithApron )
1577 {
1578 // The same-net intersecting-zone code above makes sure the corner-smoothing algorithm
1579 // doesn't produce divots. But the min-thickness algorithm applied in fillCopperZone()
1580 // is *also* going to perform a deflate/inflate cycle, again leading to divots. So we
1581 // pre-inflate the contour by the min-thickness within the same-net-intersecting-zones
1582 // envelope.
1583 SHAPE_POLY_SET poly = maxExtents->CloneDropTriangulation();
1585
1586 if( !keepExternalFillets )
1587 poly.BooleanIntersection( withSameNetIntersectingZones );
1588
1589 *aSmoothedPolyWithApron = aSmoothedPoly;
1590 aSmoothedPolyWithApron->BooleanIntersection( poly );
1591 }
1592
1593 aSmoothedPoly.BooleanIntersection( *maxExtents );
1594
1595 return true;
1596}
1597
1598
1600{
1601 m_area = 0.0;
1602
1603 for( const auto& [layer, poly] : m_FilledPolysList )
1604 m_area += poly->Area();
1605
1606 return m_area;
1607}
1608
1609
1611{
1612 m_outlinearea = std::abs( m_Poly->Area() );
1613 return m_outlinearea;
1614}
1615
1616
1618 int aMaxError, ERROR_LOC aErrorLoc,
1619 SHAPE_POLY_SET* aBoardOutline ) const
1620{
1621 // Creates the zone outline polygon (with holes if any)
1622 SHAPE_POLY_SET polybuffer;
1623
1624 // TODO: using GetFirstLayer() means it only works for single-layer zones....
1625 BuildSmoothedPoly( polybuffer, GetFirstLayer(), aBoardOutline );
1626
1627 // Calculate the polygon with clearance
1628 // holes are linked to the main outline, so only one polygon is created.
1629 if( aClearance )
1630 {
1631 if( aErrorLoc == ERROR_OUTSIDE )
1632 aClearance += GetMaxError();
1633
1634 polybuffer.Inflate( aClearance, CORNER_STRATEGY::ROUND_ALL_CORNERS, GetMaxError() );
1635 }
1636
1637 polybuffer.Fracture();
1638 aBuffer.Append( polybuffer );
1639}
1640
1641
1642std::shared_ptr<SHAPE> ZONE::GetEffectiveShape( PCB_LAYER_ID aLayer, FLASHING aFlash ) const
1643{
1644 // Rule areas are never filled, so fall back to the outline. DRC relies on this
1645 // to collide tracks, vias and pads against keepout areas.
1646 if( GetIsRuleArea() )
1647 return std::make_shared<SHAPE_POLY_SET>( *Outline() );
1648
1649 std::lock_guard<std::mutex> lock( m_filledPolysListMutex );
1650
1651 if( m_FilledPolysList.find( aLayer ) == m_FilledPolysList.end() )
1652 return std::make_shared<SHAPE_NULL>();
1653 else
1654 return m_FilledPolysList.at( aLayer );
1655}
1656
1657
1658void ZONE::TransformShapeToPolygon( SHAPE_POLY_SET& aBuffer, PCB_LAYER_ID aLayer, int aClearance,
1659 int aError, ERROR_LOC aErrorLoc, bool aIgnoreLineWidth ) const
1660{
1661 wxASSERT_MSG( !aIgnoreLineWidth, wxT( "IgnoreLineWidth has no meaning for zones." ) );
1662
1663 std::shared_ptr<SHAPE_POLY_SET> fillPolys;
1664
1665 {
1666 std::lock_guard<std::mutex> lock( m_filledPolysListMutex );
1667
1668 if( !m_FilledPolysList.count( aLayer ) )
1669 return;
1670
1671 fillPolys = m_FilledPolysList.at( aLayer );
1672 }
1673
1674 if( !aClearance )
1675 {
1676 aBuffer.Append( *fillPolys );
1677 return;
1678 }
1679
1680 SHAPE_POLY_SET temp_buf = fillPolys->CloneDropTriangulation();
1681
1682 // Rebuild filled areas only if clearance is not 0
1683 if( aClearance > 0 || aErrorLoc == ERROR_OUTSIDE )
1684 {
1685 if( aErrorLoc == ERROR_OUTSIDE )
1686 aClearance += aError;
1687
1688 temp_buf.InflateWithLinkedHoles( aClearance, CORNER_STRATEGY::ROUND_ALL_CORNERS, aError );
1689 }
1690
1691 aBuffer.Append( temp_buf );
1692}
1693
1694
1696{
1697 std::lock_guard<std::mutex> lock( m_filledPolysListMutex );
1698
1699 if( m_FilledPolysList.count( aLayer ) && !m_FilledPolysList.at( aLayer )->IsEmpty() )
1700 aBuffer.Append( *m_FilledPolysList.at( aLayer ) );
1701}
1702
1703
1705{
1706 if( aLayerSet.count() == 0 )
1707 return;
1708
1709 std::scoped_lock lock( m_layerSetMutex, m_filledPolysListMutex );
1710
1711 if( m_layerSet != aLayerSet )
1712 {
1713 aLayerSet.RunOnLayers(
1714 [&]( PCB_LAYER_ID layer )
1715 {
1716 // Only keep layers that are present in the new set
1717 if( !aLayerSet.Contains( layer ) )
1718 {
1719 m_FilledPolysList[layer] = std::make_shared<SHAPE_POLY_SET>();
1720 m_filledPolysHash[layer] = {};
1721 m_insulatedIslands[layer] = {};
1722 }
1723 } );
1724 }
1725
1726 m_layerSet = aLayerSet;
1727}
1728
1729
1730bool ZONE::operator==( const BOARD_ITEM& aOther ) const
1731{
1732 if( aOther.Type() != Type() )
1733 return false;
1734
1735 const ZONE& other = static_cast<const ZONE&>( aOther );
1736 return *this == other;
1737}
1738
1739
1740bool ZONE::operator==( const ZONE& aOther ) const
1741
1742{
1743 if( aOther.Type() != Type() )
1744 return false;
1745
1746 const ZONE& other = static_cast<const ZONE&>( aOther );
1747
1748 if( GetIsRuleArea() != other.GetIsRuleArea() )
1749 return false;
1750
1751 if( GetIsRuleArea() )
1752 {
1754 return false;
1755
1756 if( GetDoNotAllowTracks() != other.GetDoNotAllowTracks() )
1757 return false;
1758
1759 if( GetDoNotAllowVias() != other.GetDoNotAllowVias() )
1760 return false;
1761
1763 return false;
1764
1765 if( GetDoNotAllowPads() != other.GetDoNotAllowPads() )
1766 return false;
1767
1769 return false;
1770
1772 return false;
1773
1775 return false;
1776 }
1777 else
1778 {
1779 if( GetAssignedPriority() != other.GetAssignedPriority() )
1780 return false;
1781
1782 if( GetMinThickness() != other.GetMinThickness() )
1783 return false;
1784
1786 return false;
1787
1788 if( GetCornerRadius() != other.GetCornerRadius() )
1789 return false;
1790
1791 if( GetTeardropParams() != other.GetTeardropParams() )
1792 return false;
1793 }
1794
1795 if( GetNumCorners() != other.GetNumCorners() )
1796 return false;
1797
1798 for( int ii = 0; ii < GetNumCorners(); ii++ )
1799 {
1800 if( GetCornerPosition( ii ) != other.GetCornerPosition( ii ) )
1801 return false;
1802 }
1803
1804 return true;
1805}
1806
1807
1808double ZONE::Similarity( const BOARD_ITEM& aOther ) const
1809{
1810 if( aOther.Type() != Type() )
1811 return 0.0;
1812
1813 const ZONE& other = static_cast<const ZONE&>( aOther );
1814
1815 if( GetIsRuleArea() != other.GetIsRuleArea() )
1816 return 0.0;
1817
1818 double similarity = 1.0;
1819
1820 if( GetLayerSet() != other.GetLayerSet() )
1821 similarity *= 0.9;
1822
1823 if( GetNetCode() != other.GetNetCode() )
1824 similarity *= 0.9;
1825
1826 if( !GetIsRuleArea() )
1827 {
1828 if( GetAssignedPriority() != other.GetAssignedPriority() )
1829 similarity *= 0.9;
1830
1831 if( GetMinThickness() != other.GetMinThickness() )
1832 similarity *= 0.9;
1833
1835 similarity *= 0.9;
1836
1837 if( GetCornerRadius() != other.GetCornerRadius() )
1838 similarity *= 0.9;
1839
1840 if( GetTeardropParams() != other.GetTeardropParams() )
1841 similarity *= 0.9;
1842 }
1843 else
1844 {
1846 similarity *= 0.9;
1847 if( GetDoNotAllowTracks() != other.GetDoNotAllowTracks() )
1848 similarity *= 0.9;
1849 if( GetDoNotAllowVias() != other.GetDoNotAllowVias() )
1850 similarity *= 0.9;
1852 similarity *= 0.9;
1853 if( GetDoNotAllowPads() != other.GetDoNotAllowPads() )
1854 similarity *= 0.9;
1855 }
1856
1857 std::vector<VECTOR2I> corners;
1858 std::vector<VECTOR2I> otherCorners;
1859 VECTOR2I lastCorner( 0, 0 );
1860
1861 for( int ii = 0; ii < GetNumCorners(); ii++ )
1862 {
1863 corners.push_back( lastCorner - GetCornerPosition( ii ) );
1864 lastCorner = GetCornerPosition( ii );
1865 }
1866
1867 lastCorner = VECTOR2I( 0, 0 );
1868 for( int ii = 0; ii < other.GetNumCorners(); ii++ )
1869 {
1870 otherCorners.push_back( lastCorner - other.GetCornerPosition( ii ) );
1871 lastCorner = other.GetCornerPosition( ii );
1872 }
1873
1874 size_t longest = alg::longest_common_subset( corners, otherCorners );
1875
1876 similarity *= std::pow( 0.9, GetNumCorners() + other.GetNumCorners() - 2 * longest );
1877
1878 return similarity;
1879}
1880
1881
1882static struct ZONE_DESC
1883{
1885 {
1887
1888 if( layerEnum.Choices().GetCount() == 0 )
1889 {
1890 layerEnum.Undefined( UNDEFINED_LAYER );
1891
1892 for( PCB_LAYER_ID layer : LSET::AllLayersMask() )
1893 layerEnum.Map( layer, LSET::Name( layer ) );
1894 }
1895
1897
1898 if( zcMap.Choices().GetCount() == 0 )
1899 {
1901 zcMap.Map( ZONE_CONNECTION::INHERITED, _HKI( "Inherited" ) )
1902 .Map( ZONE_CONNECTION::NONE, _HKI( "None" ) )
1903 .Map( ZONE_CONNECTION::THERMAL, _HKI( "Thermal reliefs" ) )
1904 .Map( ZONE_CONNECTION::FULL, _HKI( "Solid" ) )
1905 .Map( ZONE_CONNECTION::THT_THERMAL, _HKI( "Thermal reliefs for PTH" ) );
1906 }
1907
1909
1910 if( zfmMap.Choices().GetCount() == 0 )
1911 {
1913 zfmMap.Map( ZONE_FILL_MODE::POLYGONS, _HKI( "Solid fill" ) )
1914 .Map( ZONE_FILL_MODE::HATCH_PATTERN, _HKI( "Hatch pattern" ) );
1915 }
1916
1918
1919 if( irmMap.Choices().GetCount() == 0 )
1920 {
1922 irmMap.Map( ISLAND_REMOVAL_MODE::ALWAYS, _HKI( "Always" ) )
1923 .Map( ISLAND_REMOVAL_MODE::NEVER, _HKI( "Never" ) )
1924 .Map( ISLAND_REMOVAL_MODE::AREA, _HKI( "Below area limit" ) );
1925 }
1926
1928
1929 if( rapstMap.Choices().GetCount() == 0 )
1930 {
1932 rapstMap.Map( PLACEMENT_SOURCE_T::SHEETNAME, _HKI( "Sheet Name" ) )
1933 .Map( PLACEMENT_SOURCE_T::COMPONENT_CLASS, _HKI( "Component Class" ) )
1935 }
1936
1940
1941 // Mask layer and position properties; they aren't useful in current form
1942 auto posX = new PROPERTY<ZONE, int>( _HKI( "Position X" ), NO_SETTER( ZONE, int ),
1943 static_cast<int ( ZONE::* )() const>( &ZONE::GetX ),
1946 posX->SetIsHiddenFromPropertiesManager();
1947
1948 auto posY = new PROPERTY<ZONE, int>( _HKI( "Position Y" ), NO_SETTER( ZONE, int ),
1949 static_cast<int ( ZONE::* )() const>( &ZONE::GetY ),
1952 posY->SetIsHiddenFromPropertiesManager();
1953
1954 propMgr.ReplaceProperty( TYPE_HASH( BOARD_ITEM ), _HKI( "Position X" ), posX );
1955 propMgr.ReplaceProperty( TYPE_HASH( BOARD_ITEM ), _HKI( "Position Y" ), posY );
1956
1957 auto isCopperZone =
1958 []( INSPECTABLE* aItem ) -> bool
1959 {
1960 if( ZONE* zone = dynamic_cast<ZONE*>( aItem ) )
1961 return !zone->GetIsRuleArea() && IsCopperLayer( zone->GetFirstLayer() );
1962
1963 return false;
1964 };
1965
1966 auto isRuleArea =
1967 []( INSPECTABLE* aItem ) -> bool
1968 {
1969 if( ZONE* zone = dynamic_cast<ZONE*>( aItem ) )
1970 return zone->GetIsRuleArea();
1971
1972 return false;
1973 };
1974
1975 auto isHatchedFill =
1976 []( INSPECTABLE* aItem ) -> bool
1977 {
1978 if( ZONE* zone = dynamic_cast<ZONE*>( aItem ) )
1979 return zone->GetFillMode() == ZONE_FILL_MODE::HATCH_PATTERN;
1980
1981 return false;
1982 };
1983
1984 auto isAreaBasedIslandRemoval =
1985 []( INSPECTABLE* aItem ) -> bool
1986 {
1987 if( ZONE* zone = dynamic_cast<ZONE*>( aItem ) )
1988 return zone->GetIslandRemovalMode() == ISLAND_REMOVAL_MODE::AREA;
1989
1990 return false;
1991 };
1992
1993 // Layer property is hidden because it only holds a single layer and zones actually use
1994 // a layer set
1995 propMgr.ReplaceProperty( TYPE_HASH( BOARD_CONNECTED_ITEM ), _HKI( "Layer" ),
1999
2001 isCopperZone );
2002 propMgr.OverrideAvailability( TYPE_HASH( ZONE ), TYPE_HASH( BOARD_CONNECTED_ITEM ), _HKI( "Net Class" ),
2003 isCopperZone );
2004
2007 .SetAvailableFunc( isCopperZone );
2008
2009 propMgr.AddProperty( new PROPERTY<ZONE, wxString>( _HKI( "Name" ),
2011
2012 const wxString groupKeepout = _HKI( "Keepout" );
2013
2014 propMgr.AddProperty( new PROPERTY<ZONE, bool>( _HKI( "Keep Out Tracks" ),
2016 groupKeepout )
2017 .SetAvailableFunc( isRuleArea );
2018
2019 propMgr.AddProperty( new PROPERTY<ZONE, bool>( _HKI( "Keep Out Vias" ),
2021 groupKeepout )
2022 .SetAvailableFunc( isRuleArea );
2023
2024 propMgr.AddProperty( new PROPERTY<ZONE, bool>( _HKI( "Keep Out Pads" ),
2026 groupKeepout )
2027 .SetAvailableFunc( isRuleArea );
2028
2029 propMgr.AddProperty( new PROPERTY<ZONE, bool>( _HKI( "Keep Out Zone Fills" ),
2031 groupKeepout )
2032 .SetAvailableFunc( isRuleArea );
2033
2034 propMgr.AddProperty( new PROPERTY<ZONE, bool>( _HKI( "Keep Out Footprints" ),
2036 groupKeepout )
2037 .SetAvailableFunc( isRuleArea );
2038
2039
2040 const wxString groupPlacement = _HKI( "Placement" );
2041
2042 propMgr.AddProperty( new PROPERTY<ZONE, bool>( _HKI( "Enable" ),
2044 groupPlacement )
2045 .SetAvailableFunc( isRuleArea );
2046
2047 propMgr.AddProperty( new PROPERTY_ENUM<ZONE, PLACEMENT_SOURCE_T>( _HKI( "Source Type" ),
2049 groupPlacement )
2050 .SetAvailableFunc( isRuleArea );
2051
2052 propMgr.AddProperty( new PROPERTY<ZONE, wxString>( _HKI( "Source Name" ),
2054 groupPlacement )
2055 .SetAvailableFunc( isRuleArea );
2056
2057
2058 const wxString groupFill = _HKI( "Fill Style" );
2059
2060 propMgr.AddProperty( new PROPERTY_ENUM<ZONE, ZONE_FILL_MODE>( _HKI( "Fill Mode" ),
2062 groupFill )
2063 .SetAvailableFunc( isCopperZone );
2064
2065 propMgr.AddProperty( new PROPERTY<ZONE, EDA_ANGLE>( _HKI( "Hatch Orientation" ),
2068 groupFill )
2069 .SetAvailableFunc( isCopperZone )
2070 .SetWriteableFunc( isHatchedFill );
2071
2072 auto atLeastMinWidthValidator =
2073 []( const wxAny&& aValue, EDA_ITEM* aZone ) -> VALIDATOR_RESULT
2074 {
2075 int val = aValue.As<int>();
2076 ZONE* zone = dynamic_cast<ZONE*>( aZone );
2077 wxCHECK( zone, std::nullopt );
2078
2079 if( val < zone->GetMinThickness() )
2080 return std::make_unique<VALIDATION_ERROR_MSG>( _( "Cannot be less than zone minimum width" ) );
2081
2082 return std::nullopt;
2083 };
2084
2085 propMgr.AddProperty( new PROPERTY<ZONE, int>( _HKI( "Hatch Width" ),
2087 groupFill )
2088 .SetAvailableFunc( isCopperZone )
2089 .SetWriteableFunc( isHatchedFill )
2090 .SetValidator( atLeastMinWidthValidator );
2091
2092 propMgr.AddProperty( new PROPERTY<ZONE, int>( _HKI( "Hatch Gap" ),
2094 groupFill )
2095 .SetAvailableFunc( isCopperZone )
2096 .SetWriteableFunc( isHatchedFill )
2097 .SetValidator( atLeastMinWidthValidator );
2098
2099 propMgr.AddProperty( new PROPERTY<ZONE, double>( _HKI( "Hatch Minimum Hole Ratio" ),
2101 groupFill )
2102 .SetAvailableFunc( isCopperZone )
2103 .SetWriteableFunc( isHatchedFill )
2105
2106 // TODO: Smoothing effort needs to change to enum (in dialog too)
2107 propMgr.AddProperty( new PROPERTY<ZONE, int>( _HKI( "Smoothing Effort" ),
2109 groupFill )
2110 .SetAvailableFunc( isCopperZone )
2111 .SetWriteableFunc( isHatchedFill );
2112
2113 propMgr.AddProperty( new PROPERTY<ZONE, double>( _HKI( "Smoothing Amount" ),
2115 groupFill )
2116 .SetAvailableFunc( isCopperZone )
2117 .SetWriteableFunc( isHatchedFill );
2118
2119 propMgr.AddProperty( new PROPERTY_ENUM<ZONE, ISLAND_REMOVAL_MODE>( _HKI( "Remove Islands" ),
2121 groupFill )
2122 .SetAvailableFunc( isCopperZone );
2123
2124 propMgr.AddProperty( new PROPERTY<ZONE, long long int>( _HKI( "Minimum Island Area" ),
2126 groupFill )
2127 .SetAvailableFunc( isCopperZone )
2128 .SetWriteableFunc( isAreaBasedIslandRemoval );
2129
2130 const wxString groupElectrical = _HKI( "Electrical" );
2131
2132 auto clearance = new PROPERTY<ZONE, std::optional<int>>( _HKI( "Clearance" ),
2134 clearance->SetAvailableFunc( isCopperZone );
2135 constexpr int maxClearance = pcbIUScale.mmToIU( ZONE_CLEARANCE_MAX_VALUE_MM );
2137
2138 auto minWidth = new PROPERTY<ZONE, int>( _HKI( "Minimum Width" ),
2140 minWidth->SetAvailableFunc( isCopperZone );
2141 constexpr int minMinWidth = pcbIUScale.mmToIU( ZONE_THICKNESS_MIN_VALUE_MM );
2143
2144 auto padConnections = new PROPERTY_ENUM<ZONE, ZONE_CONNECTION>( _HKI( "Pad Connections" ),
2146 padConnections->SetAvailableFunc( isCopperZone );
2147
2148 auto thermalGap = new PROPERTY<ZONE, int>( _HKI( "Thermal Relief Gap" ),
2150 thermalGap->SetAvailableFunc( isCopperZone );
2151 thermalGap->SetValidator( PROPERTY_VALIDATORS::PositiveIntValidator );
2152
2153 auto thermalSpokeWidth = new PROPERTY<ZONE, int>( _HKI( "Thermal Relief Spoke Width" ),
2155 thermalSpokeWidth->SetAvailableFunc( isCopperZone );
2156 thermalSpokeWidth->SetValidator( atLeastMinWidthValidator );
2157
2158 propMgr.AddProperty( clearance, groupElectrical );
2159 propMgr.AddProperty( minWidth, groupElectrical );
2160 propMgr.AddProperty( padConnections, groupElectrical );
2161 propMgr.AddProperty( thermalGap, groupElectrical );
2162 propMgr.AddProperty( thermalSpokeWidth, groupElectrical );
2163 }
2165
types::KiCadObjectType ToProtoEnum(KICAD_T aValue)
KICAD_T FromProtoEnum(types::KiCadObjectType aValue)
Definition api_enums.cpp:44
ERROR_LOC
When approximating an arc or circle, should the error be placed on the outside or inside of the curve...
@ ERROR_OUTSIDE
constexpr EDA_IU_SCALE pcbIUScale
Definition base_units.h:125
BITMAPS
A list of all bitmap identifiers.
BOX2< VECTOR2I > BOX2I
Definition box2.h:922
BASE_SET & set(size_t pos)
Definition base_set.h:116
A base class derived from BOARD_ITEM for items that can be connected and have a net,...
virtual NETCLASS * GetEffectiveNetClass() const
Return the NETCLASS for this item.
BOARD_CONNECTED_ITEM(BOARD_ITEM *aParent, KICAD_T idtype)
void PackNet(kiapi::board::types::Net *aProto) const
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.
void UnpackNet(const kiapi::board::types::Net &aProto)
Assigns a net to this item from an API message.
TEARDROP_PARAMETERS & GetTeardropParams()
ZONE_SETTINGS & GetDefaultZoneSettings()
Abstract interface for BOARD_ITEMs capable of storing other items inside.
A base class for any item which can be embedded within the BOARD container class, and therefore insta...
Definition board_item.h:84
BOARD_ITEM(BOARD_ITEM *aParent, KICAD_T idtype, PCB_LAYER_ID aLayer=F_Cu)
Definition board_item.h:86
friend class BOARD
Definition board_item.h:494
void SetUuidDirect(const KIID &aUuid)
Raw UUID assignment.
int GetY() const
Definition board_item.h:125
int GetX() const
Definition board_item.h:119
bool IsLocked() const override
virtual const BOARD * GetBoard() const
Return the BOARD in which this BOARD_ITEM resides, or NULL if none.
FOOTPRINT * GetParentFootprint() const
BOARD_ITEM & operator=(const BOARD_ITEM &aOther)
Definition board_item.h:103
BOARD_ITEM_CONTAINER * GetParent() const
Definition board_item.h:234
wxString GetLayerName() const
Return the name of the PCB layer on which the item resides.
int GetMaxError() const
PCB_LAYER_ID FlipLayer(PCB_LAYER_ID aLayer) const
Definition board.cpp:930
std::unordered_map< const ZONE *, BOX2I > m_ZoneBBoxCache
Definition board.h:1548
BOARD_DESIGN_SETTINGS & GetDesignSettings() const
Definition board.cpp:1101
constexpr BOX2< Vec > & Inflate(coord_type dx, coord_type dy)
Inflates the rectangle horizontally by dx and vertically by dy.
Definition box2.h:558
constexpr BOX2< Vec > & Normalize()
Ensure that the height and width are positive.
Definition box2.h:146
constexpr bool Contains(const Vec &aPoint) const
Definition box2.h:168
constexpr bool Intersects(const BOX2< Vec > &aRect) const
Definition box2.h:311
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:100
const KIID m_Uuid
Definition eda_item.h:528
bool m_forceVisible
Definition eda_item.h:545
KICAD_T Type() const
Returns the type of object.
Definition eda_item.h:112
EDA_ITEM_FLAGS m_flags
Definition eda_item.h:539
bool HasFlag(EDA_ITEM_FLAGS aFlag) const
Definition eda_item.h:153
EDA_ITEM(EDA_ITEM *parent, KICAD_T idType, bool isSCH_ITEM=false, bool isBOARD_ITEM=false)
Definition eda_item.cpp:41
ENUM_MAP & Map(T aValue, const wxString &aName)
Definition property.h:727
static ENUM_MAP< T > & Instance()
Definition property.h:721
ENUM_MAP & Undefined(T aValue)
Definition property.h:734
wxPGChoices & Choices()
Definition property.h:770
Class that other classes need to inherit from, in order to be inspectable.
Definition inspectable.h:38
static constexpr double LOD_HIDE
Return this constant from ViewGetLOD() to hide the item unconditionally.
Definition view_item.h:180
static constexpr double LOD_SHOW
Return this constant from ViewGetLOD() to show the item unconditionally.
Definition view_item.h:185
Hold a (potentially large) number of VIEW_ITEMs and renders them on a graphics device provided by the...
Definition view.h:67
bool IsLayerVisible(int aLayer) const
Return information about visibility of a particular layer.
Definition view.h:431
Definition kiid.h:48
LSEQ is a sequence (and therefore also a set) of PCB_LAYER_IDs.
Definition lseq.h:47
LSET is a set of PCB_LAYER_IDs.
Definition lset.h:37
void RunOnLayers(const std::function< void(PCB_LAYER_ID)> &aFunction) const
Execute a function on each layer of the LSET.
Definition lset.h:263
static LSET AllCuMask(int aCuLayerCount)
Return a mask holding the requested number of Cu PCB_LAYER_IDs.
Definition lset.cpp:599
static const LSET & AllLayersMask()
Definition lset.cpp:641
static wxString Name(PCB_LAYER_ID aLayerId)
Return the fixed name association with aLayerId.
Definition lset.cpp:188
bool Contains(PCB_LAYER_ID aLayer) const
See if the layer set contains a PCB layer.
Definition lset.h:63
Definition pad.h:55
int GetLocalThermalGapOverride(wxString *aSource) const
Definition pad.cpp:1877
PROPERTY_BASE & SetAvailableFunc(std::function< bool(INSPECTABLE *)> aFunc)
Set a callback function to determine whether an object provides this property.
Definition property.h:262
PROPERTY_BASE & SetWriteableFunc(std::function< bool(INSPECTABLE *)> aFunc)
Definition property.h:287
PROPERTY_BASE & SetValidator(PROPERTY_VALIDATOR_FN &&aValidator)
Definition property.h:349
PROPERTY_BASE & SetIsHiddenFromPropertiesManager(bool aHide=true)
Definition property.h:319
Provide class metadata.Helper macro to map type hashes to names.
void InheritsAfter(TYPE_ID aDerived, TYPE_ID aBase)
Declare an inheritance relationship between types.
static PROPERTY_MANAGER & Instance()
PROPERTY_BASE & AddProperty(PROPERTY_BASE *aProperty, const wxString &aGroup=wxEmptyString)
Register a property.
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 PositiveRatioValidator(const wxAny &&aValue, EDA_ITEM *aItem)
static VALIDATOR_RESULT PositiveIntValidator(const wxAny &&aValue, EDA_ITEM *aItem)
static VALIDATOR_RESULT RangeIntValidator(const wxAny &&aValue, EDA_ITEM *aItem)
Definition seg.h:42
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.
bool Intersects(const SEG &aSeg) const
void Append(int aX, int aY, bool aAllowDuplication=false)
Append a new point at the end of the line chain.
bool PointInside(const VECTOR2I &aPt, int aAccuracy=0, bool aUseBBoxCache=false) const override
Check if point aP lies inside a closed shape.
Represent a set of closed polygons.
void BooleanAdd(const SHAPE_POLY_SET &b)
Perform boolean polyset union.
void ClearArcs()
Removes all arc references from all the outlines and holes in the polyset.
int FullPointCount() const
Return the number of points in the shape poly set.
void Inflate(int aAmount, CORNER_STRATEGY aCornerStrategy, int aMaxError, bool aSimplify=false)
Perform outline inflation/deflation.
int Append(int x, int y, int aOutline=-1, int aHole=-1, bool aAllowDuplication=false)
Appends a vertex at the end of the given outline/hole (default: the last outline)
SHAPE_LINE_CHAIN & Outline(int aIndex)
Return the reference to aIndex-th outline in the set.
void BooleanIntersection(const SHAPE_POLY_SET &b)
Perform boolean polyset intersection.
int OutlineCount() const
Return the number of outlines in the set.
void InflateWithLinkedHoles(int aFactor, CORNER_STRATEGY aCornerStrategy, int aMaxError)
Perform outline inflation/deflation, using round corners.
void Fracture(bool aSimplify=true)
Convert a set of polygons with holes to a single outline with "slits"/"fractures" connecting the oute...
SHAPE_POLY_SET CloneDropTriangulation() const
void BooleanSubtract(const SHAPE_POLY_SET &b)
Perform boolean polyset difference.
std::function< void(std::function< void()>)> TASK_SUBMITTER
Callback that submits a unit of work for asynchronous execution.
wxString MessageTextFromValue(double aValue, bool aAddUnitLabel=true, EDA_DATA_TYPE aType=EDA_DATA_TYPE::DISTANCE) const
A lower-precision version of StringFromValue().
ZONE_SETTINGS handles zones parameters.
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:74
void SetHatchThickness(int aThickness)
Definition zone.h:312
void CacheTriangulation(PCB_LAYER_ID aLayer=UNDEFINED_LAYER, const SHAPE_POLY_SET::TASK_SUBMITTER &aSubmitter={})
Create a list of triangles that "fill" the solid areas used for instance to draw these solid areas on...
Definition zone.cpp:1359
void SetNeedRefill(bool aNeedRefill)
Definition zone.h:297
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:734
wxString GetItemDescription(UNITS_PROVIDER *aUnitsProvider, bool aFull) const override
Return a user-visible description string of this item.
Definition zone.cpp:1209
int m_borderHatchPitch
Definition zone.h:931
wxString m_placementAreaSource
Definition zone.h:855
bool m_isRuleArea
Definition zone.h:848
void SetDoNotAllowPads(bool aEnable)
Definition zone.h:735
void SetLayerProperties(const std::map< PCB_LAYER_ID, ZONE_LAYER_PROPERTIES > &aOther)
Definition zone.cpp:592
ZONE & operator=(const ZONE &aOther)
Definition zone.cpp:105
int m_cornerSmoothingType
Definition zone.h:828
bool GetIsRuleArea() const
Accessors to parameters used in Rule Area zones:
Definition zone.h:716
PLACEMENT_SOURCE_T m_placementAreaSourceType
Definition zone.h:854
std::optional< int > GetLocalClearance() const override
Definition zone.cpp:845
void SetLocalClearance(std::optional< int > aClearance)
Definition zone.h:187
bool m_doNotAllowVias
Definition zone.h:867
bool UnFill()
Removes the zone filling.
Definition zone.cpp:456
bool GetDoNotAllowVias() const
Definition zone.h:727
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:1695
void SetCornerRadius(unsigned int aRadius)
Definition zone.cpp:702
ZONE_FILL_MODE m_fillMode
Definition zone.h:898
bool m_doNotAllowFootprints
Definition zone.h:870
bool unFillLocked()
Internal implementation of UnFill() that assumes the caller already holds m_filledPolysListMutex.
Definition zone.cpp:464
int m_ZoneMinThickness
Definition zone.h:874
void AddPolygon(std::vector< VECTOR2I > &aPolygon)
Add a polygon to the zone outline.
Definition zone.cpp:1172
double m_hatchSmoothingValue
Definition zone.h:906
void SetLocalFlags(int aFlags)
Definition zone.h:334
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:1617
int m_thermalReliefSpokeWidth
Definition zone.h:896
wxString GetPlacementAreaSource() const
Definition zone.h:721
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:873
EDA_ANGLE m_hatchOrientation
Definition zone.h:901
void Mirror(const VECTOR2I &aMirrorRef, FLIP_DIRECTION aFlipDirection) override
Mirror the outlines relative to a given horizontal axis the layer is not changed.
Definition zone.cpp:1132
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:935
wxString m_zoneName
An optional unique name for this zone, used for identifying it in DRC checking.
Definition zone.h:832
void HatchBorder()
Compute the hatch lines depending on the hatch parameters and stores it in the zone's attribute m_bor...
Definition zone.cpp:1299
std::map< PCB_LAYER_ID, std::shared_ptr< SHAPE_POLY_SET > > m_FilledPolysList
Definition zone.h:921
void SetBorderDisplayStyle(ZONE_BORDER_DISPLAY_STYLE aBorderHatchStyle, int aBorderHatchPitch, bool aRebuilBorderdHatch)
Set all hatch parameters for the zone.
Definition zone.cpp:1280
bool GetDoNotAllowPads() const
Definition zone.h:729
const BOX2I GetBoundingBox() const override
Definition zone.cpp:650
void SetMinThickness(int aMinThickness)
Definition zone.h:303
void SetPlacementAreaSource(const wxString &aSource)
Definition zone.h:722
double ViewGetLOD(int aLayer, const KIGFX::VIEW *aView) const override
Return the level of detail (LOD) of the item.
Definition zone.cpp:618
PLACEMENT_SOURCE_T GetPlacementAreaSourceType() const
Definition zone.h:723
double m_outlinearea
Definition zone.h:938
std::mutex m_filledPolysListMutex
Definition zone.h:920
wxString GetFriendlyName() const override
Definition zone.cpp:1061
bool GetDoNotAllowTracks() const
Definition zone.h:728
int GetLocalFlags() const
Definition zone.h:333
EDA_ITEM * Clone() const override
Create a duplicate of this item with linked list members set to NULL.
Definition zone.cpp:218
void SetHatchOrientation(const EDA_ANGLE &aStep)
Definition zone.h:318
void SetHatchSmoothingValue(double aValue)
Definition zone.h:324
std::map< PCB_LAYER_ID, ZONE_LAYER_PROPERTIES > m_layerProperties
Definition zone.h:837
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:744
void SetHatchSmoothingLevel(int aLevel)
Definition zone.h:321
bool m_doNotAllowTracks
Definition zone.h:868
void SetThermalReliefSpokeWidth(int aThermalReliefSpokeWidth)
Definition zone.h:238
virtual PCB_LAYER_ID GetLayer() const override
Return the primary layer this item is on.
Definition zone.cpp:501
void SetPlacementAreaSourceType(PLACEMENT_SOURCE_T aType)
Definition zone.h:724
virtual void SetLayer(PCB_LAYER_ID aLayer) override
Set the layer this item is on.
Definition zone.cpp:550
ISLAND_REMOVAL_MODE GetIslandRemovalMode() const
Definition zone.h:738
LSET m_fillFlags
Definition zone.h:925
SHAPE_POLY_SET * Outline()
Definition zone.h:336
bool m_doNotAllowPads
Definition zone.h:869
ZONE(BOARD_ITEM_CONTAINER *parent)
Definition zone.cpp:56
void Serialize(google::protobuf::Any &aContainer) const override
Serializes this object to the given Any message.
Definition zone.cpp:232
void Move(const VECTOR2I &offset) override
Move the outlines.
Definition zone.cpp:1027
bool IsIsland(PCB_LAYER_ID aLayer, int aPolyIdx) const
Check if a given filled polygon is an insulated island.
Definition zone.cpp:1392
SHAPE_POLY_SET * m_Poly
Outline of the zone.
Definition zone.h:827
TEARDROP_TYPE m_teardropType
Definition zone.h:861
std::map< PCB_LAYER_ID, HASH_128 > m_filledPolysHash
A hash value used in zone filling calculations to see if the filled areas are up to date.
Definition zone.h:928
~ZONE()
Definition zone.cpp:122
long long int GetMinIslandArea() const
Definition zone.h:741
int m_hatchSmoothingLevel
Definition zone.h:902
double Similarity(const BOARD_ITEM &aOther) const override
Return a measure of how likely the other object is to represent the same object.
Definition zone.cpp:1808
LSET m_layerSet
Definition zone.h:835
void SetIsRuleArea(bool aEnable)
Definition zone.h:717
int m_ZoneClearance
Definition zone.h:873
void CopyFrom(const BOARD_ITEM *aOther) override
Definition zone.cpp:115
void SetDoNotAllowTracks(bool aEnable)
Definition zone.h:734
void SetFilledPolysList(PCB_LAYER_ID aLayer, const SHAPE_POLY_SET &aPolysList)
Set the list of filled polygons.
Definition zone.h:631
bool m_placementAreaEnabled
Placement rule area data.
Definition zone.h:853
const wxString & GetZoneName() const
Definition zone.h:164
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:679
int GetMinThickness() const
Definition zone.h:302
virtual void swapData(BOARD_ITEM *aImage) override
Definition zone.cpp:1351
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:751
void RemoveCutout(int aOutlineIdx, int aHoleIdx)
Remove a cutout from the zone.
Definition zone.cpp:1143
void Rotate(const VECTOR2I &aCentre, const EDA_ANGLE &aAngle) override
Rotate the outlines.
Definition zone.cpp:1089
bool HigherPriority(const ZONE *aOther) const
Definition zone.cpp:436
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:851
void SetIsFilled(bool isFilled)
Definition zone.h:294
std::mutex m_layerSetMutex
Definition zone.h:834
void SetFillMode(ZONE_FILL_MODE aFillMode)
Definition zone.h:224
BITMAPS GetMenuImage() const override
Return a pointer to an image to be used in menus.
Definition zone.cpp:1345
int m_hatchGap
Definition zone.h:900
ZONE_CONNECTION GetPadConnection() const
Definition zone.h:299
int GetHatchThickness() const
Definition zone.h:311
double GetHatchHoleMinArea() const
Definition zone.h:326
void SetLayerSet(const LSET &aLayerSet) override
Definition zone.cpp:556
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:898
virtual bool IsOnLayer(PCB_LAYER_ID) const override
Test to see if this object is on the given layer.
Definition zone.cpp:643
int m_hatchBorderAlgorithm
Definition zone.h:908
bool GetPlacementAreaEnabled() const
Definition zone.h:718
void SetDoNotAllowVias(bool aEnable)
Definition zone.h:733
bool IsTeardropArea() const
Definition zone.h:691
std::vector< SEG > m_borderHatchLines
Definition zone.h:932
VECTOR2I GetPosition() const override
Definition zone.cpp:492
int GetThermalReliefSpokeWidth() const
Definition zone.h:246
virtual void Flip(const VECTOR2I &aCentre, FLIP_DIRECTION aFlipDirection) override
Flip this object, i.e.
Definition zone.cpp:1100
void BuildHashValue(PCB_LAYER_ID aLayer)
Build the hash value of m_FilledPolysList, and store it internally in m_filledPolysHash.
Definition zone.cpp:723
void SetThermalReliefGap(int aThermalReliefGap)
Definition zone.h:227
EDA_ANGLE GetHatchOrientation() const
Definition zone.h:317
bool BuildSmoothedPoly(SHAPE_POLY_SET &aSmoothedPoly, PCB_LAYER_ID aLayer, SHAPE_POLY_SET *aBoardOutline, SHAPE_POLY_SET *aSmoothedPolyWithApron=nullptr) const
Definition zone.cpp:1439
int m_fillVersion
Definition zone.h:875
const VECTOR2I & GetCornerPosition(int aCornerIndex) const
Definition zone.h:560
bool GetDoNotAllowFootprints() const
Definition zone.h:730
ZONE_FILL_MODE GetFillMode() const
Definition zone.h:225
double m_hatchHoleMinArea
Definition zone.h:907
virtual LSET GetLayerSet() const override
Return a std::bitset of all layers on which the item physically resides.
Definition zone.h:137
void SetDoNotAllowFootprints(bool aEnable)
Definition zone.h:736
void SetBorderHatchPitch(int aPitch)
Definition zone.h:752
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:1404
void SetLayerSetAndRemoveUnusedFills(const LSET &aLayerSet)
Set the zone to be on the aLayerSet layers and only remove the fill polygons from the unused layers,...
Definition zone.cpp:1704
int GetHatchGap() const
Definition zone.h:314
double CalculateOutlineArea()
Compute the area of the zone outline (not the filled area).
Definition zone.cpp:1610
void SetHatchHoleMinArea(double aPct)
Definition zone.h:327
unsigned m_priority
Definition zone.h:843
bool Deserialize(const google::protobuf::Any &aContainer) override
Deserializes the given protobuf message into this object.
Definition zone.cpp:334
bool IsConflicting() const
For rule areas which exclude footprints (and therefore participate in courtyard conflicts during move...
Definition zone.cpp:486
bool m_doNotAllowZoneFills
Definition zone.h:866
ISLAND_REMOVAL_MODE m_islandRemovalMode
Definition zone.h:877
bool m_isFilled
True when a zone was filled, false after deleting the filled areas.
Definition zone.h:886
double GetHatchSmoothingValue() const
Definition zone.h:323
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:1189
std::atomic< bool > m_needRefill
False when a zone was refilled, true after changes in zone params.
Definition zone.h:893
bool GetDoNotAllowZoneFills() const
Definition zone.h:726
void MoveEdge(const VECTOR2I &offset, int aEdge)
Move the outline Edge.
Definition zone.cpp:1074
int GetHatchSmoothingLevel() const
Definition zone.h:320
unsigned int GetCornerRadius() const
Definition zone.h:661
int GetCornerSmoothingType() const
Definition zone.h:657
int m_thermalReliefGap
Definition zone.h:895
bool IsOnCopperLayer() const override
Definition zone.cpp:543
double CalculateFilledArea()
Compute the area currently occupied by the zone fill.
Definition zone.cpp:1599
void SetDoNotAllowZoneFills(bool aEnable)
Definition zone.h:732
int m_hatchThickness
Definition zone.h:899
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:1658
void SetAssignedPriority(unsigned aPriority)
Definition zone.h:121
double m_area
Definition zone.h:937
unsigned int m_cornerRadius
Definition zone.h:829
void SetPadConnection(ZONE_CONNECTION aPadConnection)
Definition zone.h:300
void SetZoneName(const wxString &aName)
Definition zone.h:165
bool operator==(const ZONE &aOther) const
Definition zone.cpp:1740
void UnHatchBorder()
Clear the zone's hatch.
Definition zone.cpp:1293
void SetIslandRemovalMode(ISLAND_REMOVAL_MODE aRemove)
Definition zone.h:739
void SetOutline(SHAPE_POLY_SET *aOutline)
Definition zone.h:339
PCB_LAYER_ID GetFirstLayer() const
Definition zone.cpp:523
void SetMinIslandArea(long long int aArea)
Definition zone.h:742
virtual std::vector< int > ViewGetLayers() const override
Return the all the layers within the VIEW the object is painted on.
Definition zone.cpp:598
HASH_128 GetHashValue(PCB_LAYER_ID aLayer)
Definition zone.cpp:714
ZONE_CONNECTION m_PadConnection
Definition zone.h:872
void InitDataFromSrcInCopyCtor(const ZONE &aZone, PCB_LAYER_ID aLayer=UNDEFINED_LAYER)
Copy aZone data to me.
Definition zone.cpp:131
int GetThermalReliefGap() const
Definition zone.h:235
void SetHatchGap(int aStep)
Definition zone.h:315
static int GetDefaultHatchPitch()
Definition zone.cpp:1339
void SetPlacementAreaEnabled(bool aEnabled)
Definition zone.h:719
unsigned GetAssignedPriority() const
Definition zone.h:126
int GetNumCorners(void) const
Access to m_Poly parameters.
Definition zone.h:520
bool SameNet(const ZONE *aOther) const
Definition zone.cpp:450
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:1642
ZONE_BORDER_DISPLAY_STYLE m_borderStyle
Definition zone.h:930
long long int m_minIslandArea
When island removal mode is set to AREA, islands below this area will be removed.
Definition zone.h:883
@ ROUND_ALL_CORNERS
All angles are rounded.
#define _(s)
static constexpr EDA_ANGLE ANGLE_0
Definition eda_angle.h:411
@ DEGREES_T
Definition eda_angle.h:31
#define PCB_EDIT_FRAME_NAME
#define COURTYARD_CONFLICT
temporary set when moving footprints having courtyard overlapping
@ NONE
Definition eda_shape.h:72
a few functions useful in geometry calculations.
Some functions to handle hotkeys in KiCad.
PCB_LAYER_ID FlipLayer(PCB_LAYER_ID aLayerId, int aCopperLayersCount)
Definition layer_id.cpp:173
FLASHING
Enum used during connectivity building to ensure we do not query connectivity while building the data...
Definition layer_ids.h:184
bool IsCopperLayer(int aLayerId)
Test whether a layer is a copper layer.
Definition layer_ids.h:679
@ LAYER_CONFLICTS_SHADOW
Shadow layer for items flagged conflicting.
Definition layer_ids.h:310
@ LAYER_FOOTPRINTS_FR
Show footprints on front.
Definition layer_ids.h:259
@ LAYER_ZONES
Control for copper zone opacity/visibility (color ignored).
Definition layer_ids.h:295
@ LAYER_ZONE_START
Virtual layers for stacking zones and tracks on a given copper layer.
Definition layer_ids.h:335
@ LAYER_FOOTPRINTS_BK
Show footprints on back.
Definition layer_ids.h:260
PCB_LAYER_ID
A quick note on layer IDs:
Definition layer_ids.h:60
@ B_Cu
Definition layer_ids.h:65
@ UNDEFINED_LAYER
Definition layer_ids.h:61
FLIP_DIRECTION
Definition mirror.h:27
size_t longest_common_subset(const _Container &__c1, const _Container &__c2)
Returns the length of the longest common subset of values between two containers.
Definition kicad_algo.h:186
void PackLayerSet(google::protobuf::RepeatedField< int > &aOutput, const LSET &aLayerSet)
LSET UnpackLayerSet(const google::protobuf::RepeatedField< int > &aProtoLayerSet)
KICOMMON_API void PackPolySet(types::PolySet &aOutput, const SHAPE_POLY_SET &aInput, const EDA_IU_SCALE &aScale)
KICOMMON_API VECTOR2I UnpackVector2(const types::Vector2 &aInput, const EDA_IU_SCALE &aScale)
KICOMMON_API void PackVector2(types::Vector2 &aOutput, const VECTOR2I &aInput, const EDA_IU_SCALE &aScale)
KICOMMON_API SHAPE_POLY_SET UnpackPolySet(const types::PolySet &aInput, const EDA_IU_SCALE &aScale)
EDA_ANGLE abs(const EDA_ANGLE &aAngle)
Definition eda_angle.h:400
#define _HKI(x)
Definition page_info.cpp:44
#define TYPE_HASH(x)
Definition property.h:74
#define IMPLEMENT_ENUM_TO_WXANY(type)
Definition property.h:821
#define NO_SETTER(owner, type)
Definition property.h:828
@ PT_DEGREE
Angle expressed in degrees.
Definition property.h:66
@ PT_COORD
Coordinate expressed in distance units (mm/inch)
Definition property.h:65
@ PT_AREA
Area expressed in distance units-squared (mm/inch)
Definition property.h:64
@ PT_SIZE
Size expressed in distance units (mm/inch)
Definition property.h:63
#define REGISTER_TYPE(x)
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.
A storage class for 128-bit hash value.
Definition hash_128.h:36
Structure to hold the necessary information in order to index a vertex on a SHAPE_POLY_SET object: th...
ZONE_DESC()
Definition zone.cpp:1884
std::optional< VECTOR2I > hatching_offset
TEARDROP_TYPE
define the type of a teardrop: on a via or pad, or a track end
int clearance
const int accuracy
@ PCB_ZONE_T
class ZONE, a copper pour area
Definition typeinfo.h:105
VECTOR2< int32_t > VECTOR2I
Definition vector2d.h:687
static SHAPE_POLY_SET g_nullPoly
Definition zone.cpp:711
static struct ZONE_DESC _ZONE_DESC
ISLAND_REMOVAL_MODE
Whether or not to remove isolated islands from a zone.
ZONE_FILL_MODE
ZONE_BORDER_DISPLAY_STYLE
Zone border styles.
PLACEMENT_SOURCE_T
#define ZONE_CLEARANCE_MAX_VALUE_MM
Definition zones.h:37
ZONE_CONNECTION
How pads are covered by copper in zone.
Definition zones.h:47
@ THERMAL
Use thermal relief for pads.
Definition zones.h:50
@ THT_THERMAL
Thermal relief only for THT pads.
Definition zones.h:52
@ NONE
Pads are not covered.
Definition zones.h:49
@ FULL
pads are covered by copper
Definition zones.h:51
#define ZONE_BORDER_HATCH_DIST_MM
Definition zones.h:38
#define ZONE_BORDER_HATCH_MINDIST_MM
Definition zones.h:39
#define ZONE_THICKNESS_MIN_VALUE_MM
Definition zones.h:35
#define ZONE_BORDER_HATCH_MAXDIST_MM
Definition zones.h:40