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 if( IsConflicting() )
613 layers.push_back( LAYER_CONFLICTS_SHADOW );
614
615 return layers;
616}
617
618
619double ZONE::ViewGetLOD( int aLayer, const KIGFX::VIEW* aView ) const
620{
621 if( !aView )
622 return LOD_SHOW;
623
624 if( !aView->IsLayerVisible( LAYER_ZONES ) )
625 return LOD_HIDE;
626
627 if( FOOTPRINT* parentFP = GetParentFootprint() )
628 {
629 bool flipped = parentFP->GetLayer() == B_Cu;
630
631 // Handle Render tab switches
632 if( !flipped && !aView->IsLayerVisible( LAYER_FOOTPRINTS_FR ) )
633 return LOD_HIDE;
634
635 if( flipped && !aView->IsLayerVisible( LAYER_FOOTPRINTS_BK ) )
636 return LOD_HIDE;
637 }
638
639 // Other layers are shown without any conditions
640 return LOD_SHOW;
641}
642
643
644bool ZONE::IsOnLayer( PCB_LAYER_ID aLayer ) const
645{
646 std::lock_guard<std::mutex> lock( m_layerSetMutex );
647 return m_layerSet.test( aLayer );
648}
649
650
652{
653 if( const BOARD* board = GetBoard() )
654 {
655 std::unordered_map<const ZONE*, BOX2I>& cache = board->m_ZoneBBoxCache;
656
657 {
658 std::shared_lock<std::shared_mutex> readLock( board->m_CachesMutex );
659
660 auto cacheIter = cache.find( this );
661
662 if( cacheIter != cache.end() )
663 return cacheIter->second;
664 }
665
666 BOX2I bbox = m_Poly->BBox();
667
668 {
669 std::unique_lock<std::shared_mutex> writeLock( board->m_CachesMutex );
670 cache[ this ] = bbox;
671 }
672
673 return bbox;
674 }
675
676 return m_Poly->BBox();
677}
678
679
681{
682 // GetBoundingBox() will cache it for us, and there's no sense duplicating the somewhat tricky
683 // locking code.
685}
686
687
688int ZONE::GetThermalReliefGap( PAD* aPad, wxString* aSource ) const
689{
690 if( aPad->GetLocalThermalGapOverride() == 0 )
691 {
692 if( aSource )
693 *aSource = _( "zone" );
694
695 return m_thermalReliefGap;
696 }
697
698 return aPad->GetLocalThermalGapOverride( aSource );
699
700}
701
702
703void ZONE::SetCornerRadius( unsigned int aRadius )
704{
705 if( m_cornerRadius != aRadius )
706 SetNeedRefill( true );
707
708 m_cornerRadius = aRadius;
709}
710
711
713
714
716{
717 if( !m_filledPolysHash.count( aLayer ) )
718 return g_nullPoly.GetHash();
719 else
720 return m_filledPolysHash.at( aLayer );
721}
722
723
725{
726 std::lock_guard<std::mutex> lock( m_filledPolysListMutex );
727
728 if( !m_FilledPolysList.count( aLayer ) )
729 m_filledPolysHash[aLayer] = g_nullPoly.GetHash();
730 else
731 m_filledPolysHash[aLayer] = m_FilledPolysList.at( aLayer )->GetHash();
732}
733
734
735bool ZONE::HitTest( const VECTOR2I& aPosition, int aAccuracy ) const
736{
737 // When looking for an "exact" hit aAccuracy will be 0 which works poorly for very thin
738 // lines. Give it a floor.
739 int accuracy = std::max( aAccuracy, pcbIUScale.mmToIU( 0.1 ) );
740
741 return HitTestForCorner( aPosition, accuracy * 2 ) || HitTestForEdge( aPosition, accuracy );
742}
743
744
745bool ZONE::HitTestForCorner( const VECTOR2I& refPos, int aAccuracy,
746 SHAPE_POLY_SET::VERTEX_INDEX* aCornerHit ) const
747{
748 return m_Poly->CollideVertex( VECTOR2I( refPos ), aCornerHit, aAccuracy );
749}
750
751
752bool ZONE::HitTestForEdge( const VECTOR2I& refPos, int aAccuracy,
753 SHAPE_POLY_SET::VERTEX_INDEX* aCornerHit ) const
754{
755 return m_Poly->CollideEdge( VECTOR2I( refPos ), aCornerHit, aAccuracy );
756}
757
758
759bool ZONE::HitTest( const BOX2I& aRect, bool aContained, int aAccuracy ) const
760{
761 // Calculate bounding box for zone
762 BOX2I bbox = GetBoundingBox();
763 bbox.Normalize();
764
765 BOX2I arect = aRect;
766 arect.Normalize();
767 arect.Inflate( aAccuracy );
768
769 if( aContained )
770 {
771 return arect.Contains( bbox );
772 }
773 else
774 {
775 // Fast test: if aBox is outside the polygon bounding box, rectangles cannot intersect
776 if( !arect.Intersects( bbox ) )
777 return false;
778
779 int count = m_Poly->TotalVertices();
780
781 for( int ii = 0; ii < count; ii++ )
782 {
783 VECTOR2I vertex = m_Poly->CVertex( ii );
784 VECTOR2I vertexNext = m_Poly->CVertex( ( ii + 1 ) % count );
785
786 // Test if the point is within the rect
787 if( arect.Contains( vertex ) )
788 return true;
789
790 // Test if this edge intersects the rect
791 if( arect.Intersects( vertex, vertexNext ) )
792 return true;
793 }
794
795 return false;
796 }
797}
798
799
800bool ZONE::HitTest( const SHAPE_LINE_CHAIN& aPoly, bool aContained ) const
801{
802 if( aContained )
803 {
804 auto outlineIntersectingSelection =
805 [&]()
806 {
807 for( auto segment = m_Poly->IterateSegments(); segment; segment++ )
808 {
809 if( aPoly.Intersects( *segment ) )
810 return true;
811 }
812
813 return false;
814 };
815
816 // In the case of contained selection, all vertices of the zone outline must be inside
817 // the selection polygon, so we can check only the first vertex.
818 auto vertexInsideSelection =
819 [&]()
820 {
821 return aPoly.PointInside( m_Poly->CVertex( 0 ) );
822 };
823
824 return vertexInsideSelection() && !outlineIntersectingSelection();
825 }
826 else
827 {
828 // Touching selection - check if any segment of the zone contours collides with the
829 // selection shape.
830 for( auto segment = m_Poly->IterateSegmentsWithHoles(); segment; segment++ )
831 {
832 if( aPoly.PointInside( ( *segment ).A ) )
833 return true;
834
835 if( aPoly.Intersects( *segment ) )
836 return true;
837
838 // Note: aPoly.Collide() could be used instead of two test above, but it is 3x slower.
839 }
840
841 return false;
842 }
843}
844
845
846std::optional<int> ZONE::GetLocalClearance() const
847{
848 return m_isRuleArea ? 0 : m_ZoneClearance;
849}
850
851
852bool ZONE::HitTestFilledArea( PCB_LAYER_ID aLayer, const VECTOR2I& aRefPos, int aAccuracy ) const
853{
854 // Rule areas have no filled area, but it's generally nice to treat their interior as if it were
855 // filled so that people don't have to select them by their outline (which is min-width)
856 if( GetIsRuleArea() )
857 return m_Poly->Contains( aRefPos, -1, aAccuracy );
858
859 std::shared_ptr<SHAPE_POLY_SET> fillPolys;
860
861 {
862 std::lock_guard<std::mutex> lock( m_filledPolysListMutex );
863
864 if( !m_FilledPolysList.count( aLayer ) )
865 return false;
866
867 fillPolys = m_FilledPolysList.at( aLayer );
868 }
869
870 return fillPolys->Contains( aRefPos, -1, aAccuracy );
871}
872
873
874bool ZONE::HitTestCutout( const VECTOR2I& aRefPos, int* aOutlineIdx, int* aHoleIdx ) const
875{
876 // Iterate over each outline polygon in the zone and then iterate over
877 // each hole it has to see if the point is in it.
878 for( int i = 0; i < m_Poly->OutlineCount(); i++ )
879 {
880 for( int j = 0; j < m_Poly->HoleCount( i ); j++ )
881 {
882 if( m_Poly->Hole( i, j ).PointInside( aRefPos ) )
883 {
884 if( aOutlineIdx )
885 *aOutlineIdx = i;
886
887 if( aHoleIdx )
888 *aHoleIdx = j;
889
890 return true;
891 }
892 }
893 }
894
895 return false;
896}
897
898
899void ZONE::GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_ITEM>& aList )
900{
901 wxString msg = GetFriendlyName();
902
903 aList.emplace_back( _( "Type" ), msg );
904
905 if( GetIsRuleArea() )
906 {
907 msg.Empty();
908
909 if( GetDoNotAllowVias() )
910 AccumulateDescription( msg, _( "No vias" ) );
911
912 if( GetDoNotAllowTracks() )
913 AccumulateDescription( msg, _( "No tracks" ) );
914
915 if( GetDoNotAllowPads() )
916 AccumulateDescription( msg, _( "No pads" ) );
917
919 AccumulateDescription( msg, _( "No zone fills" ) );
920
922 AccumulateDescription( msg, _( "No footprints" ) );
923
924 if( !msg.IsEmpty() )
925 aList.emplace_back( _( "Restrictions" ), msg );
926
928 aList.emplace_back( _( "Placement source" ), UnescapeString( GetPlacementAreaSource() ) );
929 }
930 else if( IsOnCopperLayer() )
931 {
932 if( aFrame->GetName() == PCB_EDIT_FRAME_NAME )
933 {
934 aList.emplace_back( _( "Net" ), UnescapeString( GetNetname() ) );
935
936 aList.emplace_back( _( "Resolved Netclass" ),
937 UnescapeString( GetEffectiveNetClass()->GetHumanReadableName() ) );
938 }
939
940 // Display priority level
941 aList.emplace_back( _( "Priority" ), wxString::Format( wxT( "%d" ), GetAssignedPriority() ) );
942 }
943
944 if( aFrame->GetName() == PCB_EDIT_FRAME_NAME )
945 {
946 if( IsLocked() )
947 aList.emplace_back( _( "Status" ), _( "Locked" ) );
948 }
949
950 LSEQ layers = m_layerSet.Seq();
951 wxString layerDesc;
952
953 if( layers.size() == 1 )
954 {
955 layerDesc.Printf( _( "%s" ), GetBoard()->GetLayerName( layers[0] ) );
956 }
957 else if (layers.size() == 2 )
958 {
959 layerDesc.Printf( _( "%s and %s" ),
960 GetBoard()->GetLayerName( layers[0] ),
961 GetBoard()->GetLayerName( layers[1] ) );
962 }
963 else if (layers.size() == 3 )
964 {
965 layerDesc.Printf( _( "%s, %s and %s" ),
966 GetBoard()->GetLayerName( layers[0] ),
967 GetBoard()->GetLayerName( layers[1] ),
968 GetBoard()->GetLayerName( layers[2] ) );
969 }
970 else if( layers.size() > 3 )
971 {
972 layerDesc.Printf( _( "%s, %s and %d more" ),
973 GetBoard()->GetLayerName( layers[0] ),
974 GetBoard()->GetLayerName( layers[1] ),
975 static_cast<int>( layers.size() - 2 ) );
976 }
977
978 aList.emplace_back( _( "Layer" ), layerDesc );
979
980 if( !m_zoneName.empty() )
981 aList.emplace_back( _( "Name" ), m_zoneName );
982
983 if( !GetIsRuleArea() ) // Show fill mode only for not rule areas
984 {
985 switch( m_fillMode )
986 {
987 case ZONE_FILL_MODE::POLYGONS: msg = _( "Solid" ); break;
988 case ZONE_FILL_MODE::HATCH_PATTERN: msg = _( "Hatched" ); break;
989 default: msg = _( "Unknown" ); break;
990 }
991
992 aList.emplace_back( _( "Fill Mode" ), msg );
993
994 aList.emplace_back( _( "Filled Area" ),
996
997 wxString source;
998 int clearance = GetOwnClearance( UNDEFINED_LAYER, &source );
999
1000 if( !source.IsEmpty() )
1001 {
1002 aList.emplace_back( wxString::Format( _( "Min Clearance: %s" ), aFrame->MessageTextFromValue( clearance ) ),
1003 wxString::Format( _( "(from %s)" ), source ) );
1004 }
1005 }
1006
1007 int count = 0;
1008
1009 if( GetIsRuleArea() )
1010 {
1011 double outline_area = CalculateOutlineArea();
1012 aList.emplace_back( _( "Outline Area" ),
1013 aFrame->MessageTextFromValue( outline_area, true, EDA_DATA_TYPE::AREA ) );
1014
1015 const SHAPE_POLY_SET* area_outline = Outline();
1016 count = area_outline->FullPointCount();
1017 }
1018 else if( !m_FilledPolysList.empty() )
1019 {
1020 for( std::pair<const PCB_LAYER_ID, std::shared_ptr<SHAPE_POLY_SET>>& ii: m_FilledPolysList )
1021 count += ii.second->TotalVertices();
1022 }
1023
1024 aList.emplace_back( _( "Corner Count" ), wxString::Format( wxT( "%d" ), count ) );
1025}
1026
1027
1028void ZONE::Move( const VECTOR2I& offset )
1029{
1030 /* move outlines */
1031 m_Poly->Move( offset );
1032
1033 // Translate existing hatch lines instead of regenerating them. HatchBorder() is expensive
1034 // (O(n*m) segment intersections + point-in-polygon tests) and the hatch pattern is
1035 // invariant under translation.
1036 for( SEG& seg : m_borderHatchLines )
1037 {
1038 seg.A += offset;
1039 seg.B += offset;
1040 }
1041
1042 /* move fills */
1043 for( std::pair<const PCB_LAYER_ID, std::shared_ptr<SHAPE_POLY_SET>>& pair : m_FilledPolysList )
1044 pair.second->Move( offset );
1045
1046 /*
1047 * move boundingbox cache
1048 *
1049 * While the cache will get nuked at the conclusion of the operation, we use it for some
1050 * things (such as drawing the parent group) during the move.
1051 */
1052 if( GetBoard() )
1053 {
1054 auto it = GetBoard()->m_ZoneBBoxCache.find( this );
1055
1056 if( it != GetBoard()->m_ZoneBBoxCache.end() )
1057 it->second.Move( offset );
1058 }
1059}
1060
1061
1063{
1064 if( GetIsRuleArea() )
1065 return _( "Rule Area" );
1066 else if( IsTeardropArea() )
1067 return _( "Teardrop Area" );
1068 else if( IsOnCopperLayer() )
1069 return _( "Copper Zone" );
1070 else
1071 return _( "Non-copper Zone" );
1072}
1073
1074
1075void ZONE::MoveEdge( const VECTOR2I& offset, int aEdge )
1076{
1077 int next_corner;
1078
1079 if( m_Poly->GetNeighbourIndexes( aEdge, nullptr, &next_corner ) )
1080 {
1081 m_Poly->SetVertex( aEdge, m_Poly->CVertex( aEdge ) + VECTOR2I( offset ) );
1082 m_Poly->SetVertex( next_corner, m_Poly->CVertex( next_corner ) + VECTOR2I( offset ) );
1083 HatchBorder();
1084
1085 SetNeedRefill( true );
1086 }
1087}
1088
1089
1090void ZONE::Rotate( const VECTOR2I& aCentre, const EDA_ANGLE& aAngle )
1091{
1092 m_Poly->Rotate( aAngle, aCentre );
1093 HatchBorder();
1094
1095 /* rotate filled areas: */
1096 for( std::pair<const PCB_LAYER_ID, std::shared_ptr<SHAPE_POLY_SET>>& pair : m_FilledPolysList )
1097 pair.second->Rotate( aAngle, aCentre );
1098}
1099
1100
1101void ZONE::Flip( const VECTOR2I& aCentre, FLIP_DIRECTION aFlipDirection )
1102{
1103 Mirror( aCentre, aFlipDirection );
1104
1105 std::map<PCB_LAYER_ID, SHAPE_POLY_SET> fillsCopy;
1106
1107 for( auto& [oldLayer, shapePtr] : m_FilledPolysList )
1108 fillsCopy[oldLayer] = *shapePtr;
1109
1110 std::map<PCB_LAYER_ID, ZONE_LAYER_PROPERTIES> layerPropertiesCopy = m_layerProperties;
1111
1112 LSET flipped;
1113
1114 for( PCB_LAYER_ID layer : GetLayerSet() )
1115 flipped.set( GetBoard()->FlipLayer( layer ) );
1116
1117 SetLayerSet( flipped );
1118
1119 for( auto& [oldLayer, properties] : layerPropertiesCopy )
1120 {
1121 PCB_LAYER_ID newLayer = GetBoard()->FlipLayer( oldLayer );
1122 m_layerProperties[newLayer] = properties;
1123 }
1124
1125 for( auto& [oldLayer, shape] : fillsCopy )
1126 {
1127 PCB_LAYER_ID newLayer = GetBoard()->FlipLayer( oldLayer );
1128 SetFilledPolysList( newLayer, shape );
1129 }
1130}
1131
1132
1133void ZONE::Mirror( const VECTOR2I& aMirrorRef, FLIP_DIRECTION aFlipDirection )
1134{
1135 m_Poly->Mirror( aMirrorRef, aFlipDirection );
1136
1137 HatchBorder();
1138
1139 for( std::pair<const PCB_LAYER_ID, std::shared_ptr<SHAPE_POLY_SET>>& pair : m_FilledPolysList )
1140 pair.second->Mirror( aMirrorRef, aFlipDirection );
1141}
1142
1143
1144void ZONE::RemoveCutout( int aOutlineIdx, int aHoleIdx )
1145{
1146 // Ensure the requested cutout is valid
1147 if( m_Poly->OutlineCount() < aOutlineIdx || m_Poly->HoleCount( aOutlineIdx ) < aHoleIdx )
1148 return;
1149
1150 SHAPE_POLY_SET cutPoly( m_Poly->Hole( aOutlineIdx, aHoleIdx ) );
1151
1152 // Add the cutout back to the zone
1153 m_Poly->BooleanAdd( cutPoly );
1154
1155 SetNeedRefill( true );
1156}
1157
1158
1159void ZONE::AddPolygon( const SHAPE_LINE_CHAIN& aPolygon )
1160{
1161 wxASSERT( aPolygon.IsClosed() );
1162
1163 // Add the outline as a new polygon in the polygon set
1164 if( m_Poly->OutlineCount() == 0 )
1165 m_Poly->AddOutline( aPolygon );
1166 else
1167 m_Poly->AddHole( aPolygon );
1168
1169 SetNeedRefill( true );
1170}
1171
1172
1173void ZONE::AddPolygon( std::vector<VECTOR2I>& aPolygon )
1174{
1175 if( aPolygon.empty() )
1176 return;
1177
1178 SHAPE_LINE_CHAIN outline;
1179
1180 // Create an outline and populate it with the points of aPolygon
1181 for( const VECTOR2I& pt : aPolygon )
1182 outline.Append( pt );
1183
1184 outline.SetClosed( true );
1185
1186 AddPolygon( outline );
1187}
1188
1189
1190bool ZONE::AppendCorner( VECTOR2I aPosition, int aHoleIdx, bool aAllowDuplication )
1191{
1192 // Ensure the main outline exists:
1193 if( m_Poly->OutlineCount() == 0 )
1194 m_Poly->NewOutline();
1195
1196 // If aHoleIdx >= 0, the corner musty be added to the hole, index aHoleIdx.
1197 // (remember: the index of the first hole is 0)
1198 // Return error if it does not exist.
1199 if( aHoleIdx >= m_Poly->HoleCount( 0 ) )
1200 return false;
1201
1202 m_Poly->Append( aPosition.x, aPosition.y, -1, aHoleIdx, aAllowDuplication );
1203
1204 SetNeedRefill( true );
1205
1206 return true;
1207}
1208
1209
1210wxString ZONE::GetItemDescription( UNITS_PROVIDER* aUnitsProvider, bool aFull ) const
1211{
1212 LSEQ layers = m_layerSet.Seq();
1213 wxString layerDesc;
1214
1215 if( layers.size() == 1 )
1216 {
1217 layerDesc.Printf( _( "on %s" ), GetBoard()->GetLayerName( layers[0] ) );
1218 }
1219 else if (layers.size() == 2 )
1220 {
1221 layerDesc.Printf( _( "on %s and %s" ),
1222 GetBoard()->GetLayerName( layers[0] ),
1223 GetBoard()->GetLayerName( layers[1] ) );
1224 }
1225 else if (layers.size() == 3 )
1226 {
1227 layerDesc.Printf( _( "on %s, %s and %s" ),
1228 GetBoard()->GetLayerName( layers[0] ),
1229 GetBoard()->GetLayerName( layers[1] ),
1230 GetBoard()->GetLayerName( layers[2] ) );
1231 }
1232 else if( layers.size() > 3 )
1233 {
1234 layerDesc.Printf( _( "on %s, %s and %zu more" ),
1235 GetBoard()->GetLayerName( layers[0] ),
1236 GetBoard()->GetLayerName( layers[1] ),
1237 layers.size() - 2 );
1238 }
1239
1240 if( GetIsRuleArea() )
1241 {
1242 if( GetZoneName().IsEmpty() )
1243 {
1244 return wxString::Format( _( "Rule Area %s" ),
1245 layerDesc );
1246 }
1247 else
1248 {
1249 return wxString::Format( _( "Rule area '%s' %s" ),
1250 GetZoneName(),
1251 layerDesc );
1252 }
1253 }
1254 else if( IsTeardropArea() )
1255 {
1256 return wxString::Format( _( "Teardrop %s %s" ),
1257 GetNetnameMsg(),
1258 layerDesc );
1259 }
1260 else
1261 {
1262 if( GetZoneName().IsEmpty() )
1263 {
1264 return wxString::Format( _( "Zone %s %s, priority %d" ),
1265 GetNetnameMsg(),
1266 layerDesc,
1268 }
1269 else
1270 {
1271 return wxString::Format( _( "Zone '%s' %s %s, priority %d" ),
1272 GetZoneName(),
1273 GetNetnameMsg(),
1274 layerDesc,
1276 }
1277 }
1278}
1279
1280
1282 int aBorderHatchPitch, bool aRebuildBorderHatch )
1283{
1284 aBorderHatchPitch = std::max( aBorderHatchPitch, pcbIUScale.mmToIU( ZONE_BORDER_HATCH_MINDIST_MM ) );
1285 aBorderHatchPitch = std::min( aBorderHatchPitch, pcbIUScale.mmToIU( ZONE_BORDER_HATCH_MAXDIST_MM ) );
1286 SetBorderHatchPitch( aBorderHatchPitch );
1287 m_borderStyle = aBorderHatchStyle;
1288
1289 if( aRebuildBorderHatch )
1290 HatchBorder();
1291}
1292
1293
1295{
1296 m_borderHatchLines.clear();
1297}
1298
1299
1301{
1302 UnHatchBorder();
1303
1305 || m_borderHatchPitch == 0
1306 || m_Poly->IsEmpty() )
1307 {
1308 return;
1309 }
1310
1311 // set the "length" of hatch lines (the length on horizontal axis)
1312 int hatch_line_len = m_borderHatchPitch; // OK for DIAGONAL_EDGE style
1313
1314 // Calculate spacing between 2 hatch lines
1315 int spacing = m_borderHatchPitch; // OK for DIAGONAL_EDGE style
1316
1318 {
1319 // The spacing is twice the spacing for DIAGONAL_EDGE because one
1320 // full diagonal replaces 2 edge diagonal hatch segments in code
1321 spacing = m_borderHatchPitch * 2;
1322 hatch_line_len = -1; // Use full diagonal hatch line
1323 }
1324
1325 // To have a better look, give a slope depending on the layer
1326 int layer = GetFirstLayer();
1327 std::vector<double> slopes;
1328
1329 if( IsTeardropArea() )
1330 slopes = { 0.7, -0.7 };
1331 else if( layer & 1 )
1332 slopes = { 1 };
1333 else
1334 slopes = { -1 };
1335
1336 m_borderHatchLines = m_Poly->GenerateHatchLines( slopes, spacing, hatch_line_len );
1337}
1338
1339
1341{
1342 return pcbIUScale.mmToIU( ZONE_BORDER_HATCH_DIST_MM );
1343}
1344
1345
1347{
1348 return BITMAPS::add_zone;
1349}
1350
1351
1353{
1354 assert( aImage->Type() == PCB_ZONE_T );
1355
1356 std::swap( *static_cast<ZONE*>( this ), *static_cast<ZONE*>( aImage) );
1357}
1358
1359
1361{
1362 if( aLayer == UNDEFINED_LAYER )
1363 {
1364 std::lock_guard<std::mutex> lock( m_filledPolysListMutex );
1365
1366 for( auto& [ layer, poly ] : m_FilledPolysList )
1367 poly->CacheTriangulation( false, aSubmitter );
1368
1369 m_Poly->CacheTriangulation();
1370 }
1371 else
1372 {
1373 // Grab a shared_ptr copy under the lock, then triangulate outside it.
1374 // Each layer's SHAPE_POLY_SET is independent, so concurrent triangulation
1375 // of different layers is safe once we have the shared_ptr.
1376 std::shared_ptr<SHAPE_POLY_SET> poly;
1377
1378 {
1379 std::lock_guard<std::mutex> lock( m_filledPolysListMutex );
1380
1381 auto it = m_FilledPolysList.find( aLayer );
1382
1383 if( it != m_FilledPolysList.end() )
1384 poly = it->second;
1385 }
1386
1387 if( poly )
1388 poly->CacheTriangulation( false, aSubmitter );
1389 }
1390}
1391
1392
1393bool ZONE::IsIsland( PCB_LAYER_ID aLayer, int aPolyIdx ) const
1394{
1395 if( GetNetCode() < 1 )
1396 return true;
1397
1398 if( !m_insulatedIslands.count( aLayer ) )
1399 return false;
1400
1401 return m_insulatedIslands.at( aLayer ).count( aPolyIdx );
1402}
1403
1404
1405void ZONE::GetInteractingZones( PCB_LAYER_ID aLayer, std::vector<ZONE*>* aSameNetCollidingZones,
1406 std::vector<ZONE*>* aOtherNetIntersectingZones ) const
1407{
1408 int epsilon = pcbIUScale.mmToIU( 0.001 );
1409 BOX2I bbox = GetBoundingBox();
1410
1411 bbox.Inflate( epsilon );
1412
1413 for( ZONE* candidate : GetBoard()->Zones() )
1414 {
1415 if( candidate == this )
1416 continue;
1417
1418 if( !candidate->GetLayerSet().test( aLayer ) )
1419 continue;
1420
1421 if( candidate->GetIsRuleArea() || candidate->IsTeardropArea() )
1422 continue;
1423
1424 if( !candidate->GetBoundingBox().Intersects( bbox ) )
1425 continue;
1426
1427 if( candidate->GetNetCode() == GetNetCode() )
1428 {
1429 if( m_Poly->Collide( candidate->m_Poly ) )
1430 aSameNetCollidingZones->push_back( candidate );
1431 }
1432 else
1433 {
1434 aOtherNetIntersectingZones->push_back( candidate );
1435 }
1436 }
1437}
1438
1439
1441 SHAPE_POLY_SET* aBoardOutline,
1442 SHAPE_POLY_SET* aSmoothedPolyWithApron ) const
1443{
1444 if( GetNumCorners() <= 2 ) // malformed zone. polygon calculations will not like it ...
1445 return false;
1446
1447 // Processing of arc shapes in zones is not yet supported because Clipper can't do boolean
1448 // operations on them. The poly outline must be converted to segments first.
1449 SHAPE_POLY_SET flattened = m_Poly->CloneDropTriangulation();
1450 flattened.ClearArcs();
1451
1452 if( GetIsRuleArea() )
1453 {
1454 // We like keepouts just the way they are....
1455 aSmoothedPoly = std::move( flattened );
1456 return true;
1457 }
1458
1459 const BOARD* board = GetBoard();
1460 bool keepExternalFillets = false;
1463
1464 if( IsTeardropArea() )
1465 {
1466 // We use teardrop shapes with no smoothing; these shapes are already optimized
1467 smooth_requested = false;
1468 }
1469
1470 if( board )
1471 keepExternalFillets = board->GetDesignSettings().m_ZoneKeepExternalFillets;
1472
1473 auto smooth =
1474 [&]( SHAPE_POLY_SET& aPoly )
1475 {
1476 if( !smooth_requested )
1477 return;
1478
1479 switch( m_cornerSmoothingType )
1480 {
1482 aPoly = aPoly.Chamfer( (int) m_cornerRadius );
1483 break;
1484
1486 aPoly = aPoly.Fillet( (int) m_cornerRadius, GetMaxError() );
1487 break;
1488
1489 default:
1490 break;
1491 }
1492 };
1493
1494 SHAPE_POLY_SET* maxExtents = &flattened;
1495 SHAPE_POLY_SET withFillets;
1496
1497 aSmoothedPoly = flattened;
1498
1499 // Should external fillets (that is, those applied to concave corners) be kept? While it
1500 // seems safer to never have copper extend outside the zone outline, 5.1.x and prior did
1501 // indeed fill them so we leave the mode available.
1502 if( keepExternalFillets && smooth_requested )
1503 {
1504 withFillets = flattened;
1505 smooth( withFillets );
1506 withFillets.BooleanAdd( flattened );
1507 maxExtents = &withFillets;
1508 }
1509
1510 // We now add in the areas of any same-net, intersecting zones. This keeps us from smoothing
1511 // corners at an intersection (which often produces undesired divots between the intersecting
1512 // zones -- see #2752).
1513 //
1514 // After smoothing, we'll subtract back out everything outside of our zone.
1515 std::vector<ZONE*> sameNetCollidingZones;
1516 std::vector<ZONE*> diffNetIntersectingZones;
1517 GetInteractingZones( aLayer, &sameNetCollidingZones, &diffNetIntersectingZones );
1518
1519 for( ZONE* sameNetZone : sameNetCollidingZones )
1520 {
1521 BOX2I sameNetBoundingBox = sameNetZone->GetBoundingBox();
1522
1523 // Note: a two-pass algorithm could use sameNetZone's actual fill instead of its outline.
1524 // This would obviate the need for the below wrinkles, in addition to fixing both issues
1525 // in #16095.
1526 // (And we wouldn't need to collect all the diffNetIntersectingZones either.)
1527
1528 SHAPE_POLY_SET sameNetPoly = sameNetZone->Outline()->CloneDropTriangulation();
1529 sameNetPoly.ClearArcs();
1530
1531 SHAPE_POLY_SET diffNetPoly;
1532
1533 // Of course there's always a wrinkle. The same-net intersecting zone *might* get knocked
1534 // out along the border by a higher-priority, different-net zone. #12797
1535 for( ZONE* diffNetZone : diffNetIntersectingZones )
1536 {
1537 if( diffNetZone->HigherPriority( sameNetZone )
1538 && diffNetZone->GetBoundingBox().Intersects( sameNetBoundingBox ) )
1539 {
1540 SHAPE_POLY_SET diffNetOutline = diffNetZone->Outline()->CloneDropTriangulation();
1541 diffNetOutline.ClearArcs();
1542
1543 diffNetPoly.BooleanAdd( diffNetOutline );
1544 }
1545 }
1546
1547 // Second wrinkle. After unioning the higher priority, different net zones together, we
1548 // need to check to see if they completely enclose our zone. If they do, then we need to
1549 // treat the enclosed zone as isolated, not connected to the outer zone. #13915
1550 bool isolated = false;
1551
1552 if( diffNetPoly.OutlineCount() )
1553 {
1555 thisPoly.ClearArcs();
1556
1557 thisPoly.BooleanSubtract( diffNetPoly );
1558 isolated = thisPoly.OutlineCount() == 0;
1559 }
1560
1561 if( !isolated )
1562 aSmoothedPoly.BooleanAdd( sameNetPoly );
1563 }
1564
1565 if( aBoardOutline )
1566 {
1567 SHAPE_POLY_SET boardOutline = aBoardOutline->CloneDropTriangulation();
1568 boardOutline.ClearArcs();
1569
1570 aSmoothedPoly.BooleanIntersection( boardOutline );
1571 }
1572
1573 SHAPE_POLY_SET withSameNetIntersectingZones = aSmoothedPoly.CloneDropTriangulation();
1574
1575 smooth( aSmoothedPoly );
1576
1577 if( aSmoothedPolyWithApron )
1578 {
1579 // The same-net intersecting-zone code above makes sure the corner-smoothing algorithm
1580 // doesn't produce divots. But the min-thickness algorithm applied in fillCopperZone()
1581 // is *also* going to perform a deflate/inflate cycle, again leading to divots. So we
1582 // pre-inflate the contour by the min-thickness within the same-net-intersecting-zones
1583 // envelope.
1584 SHAPE_POLY_SET poly = maxExtents->CloneDropTriangulation();
1586
1587 if( !keepExternalFillets )
1588 poly.BooleanIntersection( withSameNetIntersectingZones );
1589
1590 *aSmoothedPolyWithApron = aSmoothedPoly;
1591 aSmoothedPolyWithApron->BooleanIntersection( poly );
1592 }
1593
1594 aSmoothedPoly.BooleanIntersection( *maxExtents );
1595
1596 return true;
1597}
1598
1599
1601{
1602 m_area = 0.0;
1603
1604 for( const auto& [layer, poly] : m_FilledPolysList )
1605 m_area += poly->Area();
1606
1607 return m_area;
1608}
1609
1610
1612{
1613 m_outlinearea = std::abs( m_Poly->Area() );
1614 return m_outlinearea;
1615}
1616
1617
1619 int aMaxError, ERROR_LOC aErrorLoc,
1620 SHAPE_POLY_SET* aBoardOutline ) const
1621{
1622 // Creates the zone outline polygon (with holes if any)
1623 SHAPE_POLY_SET polybuffer;
1624
1625 // TODO: using GetFirstLayer() means it only works for single-layer zones....
1626 BuildSmoothedPoly( polybuffer, GetFirstLayer(), aBoardOutline );
1627
1628 // Calculate the polygon with clearance
1629 // holes are linked to the main outline, so only one polygon is created.
1630 if( aClearance )
1631 {
1632 if( aErrorLoc == ERROR_OUTSIDE )
1633 aClearance += GetMaxError();
1634
1635 polybuffer.Inflate( aClearance, CORNER_STRATEGY::ROUND_ALL_CORNERS, GetMaxError() );
1636 }
1637
1638 polybuffer.Fracture();
1639 aBuffer.Append( polybuffer );
1640}
1641
1642
1643std::shared_ptr<SHAPE> ZONE::GetEffectiveShape( PCB_LAYER_ID aLayer, FLASHING aFlash ) const
1644{
1645 std::lock_guard<std::mutex> lock( m_filledPolysListMutex );
1646
1647 if( m_FilledPolysList.find( aLayer ) == m_FilledPolysList.end() )
1648 return std::make_shared<SHAPE_NULL>();
1649 else
1650 return m_FilledPolysList.at( aLayer );
1651}
1652
1653
1654void ZONE::TransformShapeToPolygon( SHAPE_POLY_SET& aBuffer, PCB_LAYER_ID aLayer, int aClearance,
1655 int aError, ERROR_LOC aErrorLoc, bool aIgnoreLineWidth ) const
1656{
1657 wxASSERT_MSG( !aIgnoreLineWidth, wxT( "IgnoreLineWidth has no meaning for zones." ) );
1658
1659 std::shared_ptr<SHAPE_POLY_SET> fillPolys;
1660
1661 {
1662 std::lock_guard<std::mutex> lock( m_filledPolysListMutex );
1663
1664 if( !m_FilledPolysList.count( aLayer ) )
1665 return;
1666
1667 fillPolys = m_FilledPolysList.at( aLayer );
1668 }
1669
1670 if( !aClearance )
1671 {
1672 aBuffer.Append( *fillPolys );
1673 return;
1674 }
1675
1676 SHAPE_POLY_SET temp_buf = fillPolys->CloneDropTriangulation();
1677
1678 // Rebuild filled areas only if clearance is not 0
1679 if( aClearance > 0 || aErrorLoc == ERROR_OUTSIDE )
1680 {
1681 if( aErrorLoc == ERROR_OUTSIDE )
1682 aClearance += aError;
1683
1684 temp_buf.InflateWithLinkedHoles( aClearance, CORNER_STRATEGY::ROUND_ALL_CORNERS, aError );
1685 }
1686
1687 aBuffer.Append( temp_buf );
1688}
1689
1690
1692{
1693 std::lock_guard<std::mutex> lock( m_filledPolysListMutex );
1694
1695 if( m_FilledPolysList.count( aLayer ) && !m_FilledPolysList.at( aLayer )->IsEmpty() )
1696 aBuffer.Append( *m_FilledPolysList.at( aLayer ) );
1697}
1698
1699
1701{
1702 if( aLayerSet.count() == 0 )
1703 return;
1704
1705 std::scoped_lock lock( m_layerSetMutex, m_filledPolysListMutex );
1706
1707 if( m_layerSet != aLayerSet )
1708 {
1709 aLayerSet.RunOnLayers(
1710 [&]( PCB_LAYER_ID layer )
1711 {
1712 // Only keep layers that are present in the new set
1713 if( !aLayerSet.Contains( layer ) )
1714 {
1715 m_FilledPolysList[layer] = std::make_shared<SHAPE_POLY_SET>();
1716 m_filledPolysHash[layer] = {};
1717 m_insulatedIslands[layer] = {};
1718 }
1719 } );
1720 }
1721
1722 m_layerSet = aLayerSet;
1723}
1724
1725
1726bool ZONE::operator==( const BOARD_ITEM& aOther ) const
1727{
1728 if( aOther.Type() != Type() )
1729 return false;
1730
1731 const ZONE& other = static_cast<const ZONE&>( aOther );
1732 return *this == other;
1733}
1734
1735
1736bool ZONE::operator==( const ZONE& aOther ) const
1737
1738{
1739 if( aOther.Type() != Type() )
1740 return false;
1741
1742 const ZONE& other = static_cast<const ZONE&>( aOther );
1743
1744 if( GetIsRuleArea() != other.GetIsRuleArea() )
1745 return false;
1746
1747 if( GetIsRuleArea() )
1748 {
1750 return false;
1751
1752 if( GetDoNotAllowTracks() != other.GetDoNotAllowTracks() )
1753 return false;
1754
1755 if( GetDoNotAllowVias() != other.GetDoNotAllowVias() )
1756 return false;
1757
1759 return false;
1760
1761 if( GetDoNotAllowPads() != other.GetDoNotAllowPads() )
1762 return false;
1763
1765 return false;
1766
1768 return false;
1769
1771 return false;
1772 }
1773 else
1774 {
1775 if( GetAssignedPriority() != other.GetAssignedPriority() )
1776 return false;
1777
1778 if( GetMinThickness() != other.GetMinThickness() )
1779 return false;
1780
1782 return false;
1783
1784 if( GetCornerRadius() != other.GetCornerRadius() )
1785 return false;
1786
1787 if( GetTeardropParams() != other.GetTeardropParams() )
1788 return false;
1789 }
1790
1791 if( GetNumCorners() != other.GetNumCorners() )
1792 return false;
1793
1794 for( int ii = 0; ii < GetNumCorners(); ii++ )
1795 {
1796 if( GetCornerPosition( ii ) != other.GetCornerPosition( ii ) )
1797 return false;
1798 }
1799
1800 return true;
1801}
1802
1803
1804double ZONE::Similarity( const BOARD_ITEM& aOther ) const
1805{
1806 if( aOther.Type() != Type() )
1807 return 0.0;
1808
1809 const ZONE& other = static_cast<const ZONE&>( aOther );
1810
1811 if( GetIsRuleArea() != other.GetIsRuleArea() )
1812 return 0.0;
1813
1814 double similarity = 1.0;
1815
1816 if( GetLayerSet() != other.GetLayerSet() )
1817 similarity *= 0.9;
1818
1819 if( GetNetCode() != other.GetNetCode() )
1820 similarity *= 0.9;
1821
1822 if( !GetIsRuleArea() )
1823 {
1824 if( GetAssignedPriority() != other.GetAssignedPriority() )
1825 similarity *= 0.9;
1826
1827 if( GetMinThickness() != other.GetMinThickness() )
1828 similarity *= 0.9;
1829
1831 similarity *= 0.9;
1832
1833 if( GetCornerRadius() != other.GetCornerRadius() )
1834 similarity *= 0.9;
1835
1836 if( GetTeardropParams() != other.GetTeardropParams() )
1837 similarity *= 0.9;
1838 }
1839 else
1840 {
1842 similarity *= 0.9;
1843 if( GetDoNotAllowTracks() != other.GetDoNotAllowTracks() )
1844 similarity *= 0.9;
1845 if( GetDoNotAllowVias() != other.GetDoNotAllowVias() )
1846 similarity *= 0.9;
1848 similarity *= 0.9;
1849 if( GetDoNotAllowPads() != other.GetDoNotAllowPads() )
1850 similarity *= 0.9;
1851 }
1852
1853 std::vector<VECTOR2I> corners;
1854 std::vector<VECTOR2I> otherCorners;
1855 VECTOR2I lastCorner( 0, 0 );
1856
1857 for( int ii = 0; ii < GetNumCorners(); ii++ )
1858 {
1859 corners.push_back( lastCorner - GetCornerPosition( ii ) );
1860 lastCorner = GetCornerPosition( ii );
1861 }
1862
1863 lastCorner = VECTOR2I( 0, 0 );
1864 for( int ii = 0; ii < other.GetNumCorners(); ii++ )
1865 {
1866 otherCorners.push_back( lastCorner - other.GetCornerPosition( ii ) );
1867 lastCorner = other.GetCornerPosition( ii );
1868 }
1869
1870 size_t longest = alg::longest_common_subset( corners, otherCorners );
1871
1872 similarity *= std::pow( 0.9, GetNumCorners() + other.GetNumCorners() - 2 * longest );
1873
1874 return similarity;
1875}
1876
1877
1878static struct ZONE_DESC
1879{
1881 {
1883
1884 if( layerEnum.Choices().GetCount() == 0 )
1885 {
1886 layerEnum.Undefined( UNDEFINED_LAYER );
1887
1888 for( PCB_LAYER_ID layer : LSET::AllLayersMask() )
1889 layerEnum.Map( layer, LSET::Name( layer ) );
1890 }
1891
1893
1894 if( zcMap.Choices().GetCount() == 0 )
1895 {
1897 zcMap.Map( ZONE_CONNECTION::INHERITED, _HKI( "Inherited" ) )
1898 .Map( ZONE_CONNECTION::NONE, _HKI( "None" ) )
1899 .Map( ZONE_CONNECTION::THERMAL, _HKI( "Thermal reliefs" ) )
1900 .Map( ZONE_CONNECTION::FULL, _HKI( "Solid" ) )
1901 .Map( ZONE_CONNECTION::THT_THERMAL, _HKI( "Thermal reliefs for PTH" ) );
1902 }
1903
1905
1906 if( zfmMap.Choices().GetCount() == 0 )
1907 {
1909 zfmMap.Map( ZONE_FILL_MODE::POLYGONS, _HKI( "Solid fill" ) )
1910 .Map( ZONE_FILL_MODE::HATCH_PATTERN, _HKI( "Hatch pattern" ) );
1911 }
1912
1914
1915 if( irmMap.Choices().GetCount() == 0 )
1916 {
1918 irmMap.Map( ISLAND_REMOVAL_MODE::ALWAYS, _HKI( "Always" ) )
1919 .Map( ISLAND_REMOVAL_MODE::NEVER, _HKI( "Never" ) )
1920 .Map( ISLAND_REMOVAL_MODE::AREA, _HKI( "Below area limit" ) );
1921 }
1922
1924
1925 if( rapstMap.Choices().GetCount() == 0 )
1926 {
1928 rapstMap.Map( PLACEMENT_SOURCE_T::SHEETNAME, _HKI( "Sheet Name" ) )
1929 .Map( PLACEMENT_SOURCE_T::COMPONENT_CLASS, _HKI( "Component Class" ) )
1931 }
1932
1936
1937 // Mask layer and position properties; they aren't useful in current form
1938 auto posX = new PROPERTY<ZONE, int>( _HKI( "Position X" ), NO_SETTER( ZONE, int ),
1939 static_cast<int ( ZONE::* )() const>( &ZONE::GetX ),
1942 posX->SetIsHiddenFromPropertiesManager();
1943
1944 auto posY = new PROPERTY<ZONE, int>( _HKI( "Position Y" ), NO_SETTER( ZONE, int ),
1945 static_cast<int ( ZONE::* )() const>( &ZONE::GetY ),
1948 posY->SetIsHiddenFromPropertiesManager();
1949
1950 propMgr.ReplaceProperty( TYPE_HASH( BOARD_ITEM ), _HKI( "Position X" ), posX );
1951 propMgr.ReplaceProperty( TYPE_HASH( BOARD_ITEM ), _HKI( "Position Y" ), posY );
1952
1953 auto isCopperZone =
1954 []( INSPECTABLE* aItem ) -> bool
1955 {
1956 if( ZONE* zone = dynamic_cast<ZONE*>( aItem ) )
1957 return !zone->GetIsRuleArea() && IsCopperLayer( zone->GetFirstLayer() );
1958
1959 return false;
1960 };
1961
1962 auto isRuleArea =
1963 []( INSPECTABLE* aItem ) -> bool
1964 {
1965 if( ZONE* zone = dynamic_cast<ZONE*>( aItem ) )
1966 return zone->GetIsRuleArea();
1967
1968 return false;
1969 };
1970
1971 auto isHatchedFill =
1972 []( INSPECTABLE* aItem ) -> bool
1973 {
1974 if( ZONE* zone = dynamic_cast<ZONE*>( aItem ) )
1975 return zone->GetFillMode() == ZONE_FILL_MODE::HATCH_PATTERN;
1976
1977 return false;
1978 };
1979
1980 auto isAreaBasedIslandRemoval =
1981 []( INSPECTABLE* aItem ) -> bool
1982 {
1983 if( ZONE* zone = dynamic_cast<ZONE*>( aItem ) )
1984 return zone->GetIslandRemovalMode() == ISLAND_REMOVAL_MODE::AREA;
1985
1986 return false;
1987 };
1988
1989 // Layer property is hidden because it only holds a single layer and zones actually use
1990 // a layer set
1991 propMgr.ReplaceProperty( TYPE_HASH( BOARD_CONNECTED_ITEM ), _HKI( "Layer" ),
1995
1997 isCopperZone );
1998 propMgr.OverrideAvailability( TYPE_HASH( ZONE ), TYPE_HASH( BOARD_CONNECTED_ITEM ), _HKI( "Net Class" ),
1999 isCopperZone );
2000
2003 .SetAvailableFunc( isCopperZone );
2004
2005 propMgr.AddProperty( new PROPERTY<ZONE, wxString>( _HKI( "Name" ),
2007
2008 const wxString groupKeepout = _HKI( "Keepout" );
2009
2010 propMgr.AddProperty( new PROPERTY<ZONE, bool>( _HKI( "Keep Out Tracks" ),
2012 groupKeepout )
2013 .SetAvailableFunc( isRuleArea );
2014
2015 propMgr.AddProperty( new PROPERTY<ZONE, bool>( _HKI( "Keep Out Vias" ),
2017 groupKeepout )
2018 .SetAvailableFunc( isRuleArea );
2019
2020 propMgr.AddProperty( new PROPERTY<ZONE, bool>( _HKI( "Keep Out Pads" ),
2022 groupKeepout )
2023 .SetAvailableFunc( isRuleArea );
2024
2025 propMgr.AddProperty( new PROPERTY<ZONE, bool>( _HKI( "Keep Out Zone Fills" ),
2027 groupKeepout )
2028 .SetAvailableFunc( isRuleArea );
2029
2030 propMgr.AddProperty( new PROPERTY<ZONE, bool>( _HKI( "Keep Out Footprints" ),
2032 groupKeepout )
2033 .SetAvailableFunc( isRuleArea );
2034
2035
2036 const wxString groupPlacement = _HKI( "Placement" );
2037
2038 propMgr.AddProperty( new PROPERTY<ZONE, bool>( _HKI( "Enable" ),
2040 groupPlacement )
2041 .SetAvailableFunc( isRuleArea );
2042
2043 propMgr.AddProperty( new PROPERTY_ENUM<ZONE, PLACEMENT_SOURCE_T>( _HKI( "Source Type" ),
2045 groupPlacement )
2046 .SetAvailableFunc( isRuleArea );
2047
2048 propMgr.AddProperty( new PROPERTY<ZONE, wxString>( _HKI( "Source Name" ),
2050 groupPlacement )
2051 .SetAvailableFunc( isRuleArea );
2052
2053
2054 const wxString groupFill = _HKI( "Fill Style" );
2055
2056 propMgr.AddProperty( new PROPERTY_ENUM<ZONE, ZONE_FILL_MODE>( _HKI( "Fill Mode" ),
2058 groupFill )
2059 .SetAvailableFunc( isCopperZone );
2060
2061 propMgr.AddProperty( new PROPERTY<ZONE, EDA_ANGLE>( _HKI( "Hatch Orientation" ),
2064 groupFill )
2065 .SetAvailableFunc( isCopperZone )
2066 .SetWriteableFunc( isHatchedFill );
2067
2068 auto atLeastMinWidthValidator =
2069 []( const wxAny&& aValue, EDA_ITEM* aZone ) -> VALIDATOR_RESULT
2070 {
2071 int val = aValue.As<int>();
2072 ZONE* zone = dynamic_cast<ZONE*>( aZone );
2073 wxCHECK( zone, std::nullopt );
2074
2075 if( val < zone->GetMinThickness() )
2076 return std::make_unique<VALIDATION_ERROR_MSG>( _( "Cannot be less than zone minimum width" ) );
2077
2078 return std::nullopt;
2079 };
2080
2081 propMgr.AddProperty( new PROPERTY<ZONE, int>( _HKI( "Hatch Width" ),
2083 groupFill )
2084 .SetAvailableFunc( isCopperZone )
2085 .SetWriteableFunc( isHatchedFill )
2086 .SetValidator( atLeastMinWidthValidator );
2087
2088 propMgr.AddProperty( new PROPERTY<ZONE, int>( _HKI( "Hatch Gap" ),
2090 groupFill )
2091 .SetAvailableFunc( isCopperZone )
2092 .SetWriteableFunc( isHatchedFill )
2093 .SetValidator( atLeastMinWidthValidator );
2094
2095 propMgr.AddProperty( new PROPERTY<ZONE, double>( _HKI( "Hatch Minimum Hole Ratio" ),
2097 groupFill )
2098 .SetAvailableFunc( isCopperZone )
2099 .SetWriteableFunc( isHatchedFill )
2101
2102 // TODO: Smoothing effort needs to change to enum (in dialog too)
2103 propMgr.AddProperty( new PROPERTY<ZONE, int>( _HKI( "Smoothing Effort" ),
2105 groupFill )
2106 .SetAvailableFunc( isCopperZone )
2107 .SetWriteableFunc( isHatchedFill );
2108
2109 propMgr.AddProperty( new PROPERTY<ZONE, double>( _HKI( "Smoothing Amount" ),
2111 groupFill )
2112 .SetAvailableFunc( isCopperZone )
2113 .SetWriteableFunc( isHatchedFill );
2114
2115 propMgr.AddProperty( new PROPERTY_ENUM<ZONE, ISLAND_REMOVAL_MODE>( _HKI( "Remove Islands" ),
2117 groupFill )
2118 .SetAvailableFunc( isCopperZone );
2119
2120 propMgr.AddProperty( new PROPERTY<ZONE, long long int>( _HKI( "Minimum Island Area" ),
2122 groupFill )
2123 .SetAvailableFunc( isCopperZone )
2124 .SetWriteableFunc( isAreaBasedIslandRemoval );
2125
2126 const wxString groupElectrical = _HKI( "Electrical" );
2127
2128 auto clearance = new PROPERTY<ZONE, std::optional<int>>( _HKI( "Clearance" ),
2130 clearance->SetAvailableFunc( isCopperZone );
2131 constexpr int maxClearance = pcbIUScale.mmToIU( ZONE_CLEARANCE_MAX_VALUE_MM );
2133
2134 auto minWidth = new PROPERTY<ZONE, int>( _HKI( "Minimum Width" ),
2136 minWidth->SetAvailableFunc( isCopperZone );
2137 constexpr int minMinWidth = pcbIUScale.mmToIU( ZONE_THICKNESS_MIN_VALUE_MM );
2139
2140 auto padConnections = new PROPERTY_ENUM<ZONE, ZONE_CONNECTION>( _HKI( "Pad Connections" ),
2142 padConnections->SetAvailableFunc( isCopperZone );
2143
2144 auto thermalGap = new PROPERTY<ZONE, int>( _HKI( "Thermal Relief Gap" ),
2146 thermalGap->SetAvailableFunc( isCopperZone );
2147 thermalGap->SetValidator( PROPERTY_VALIDATORS::PositiveIntValidator );
2148
2149 auto thermalSpokeWidth = new PROPERTY<ZONE, int>( _HKI( "Thermal Relief Spoke Width" ),
2151 thermalSpokeWidth->SetAvailableFunc( isCopperZone );
2152 thermalSpokeWidth->SetValidator( atLeastMinWidthValidator );
2153
2154 propMgr.AddProperty( clearance, groupElectrical );
2155 propMgr.AddProperty( minWidth, groupElectrical );
2156 propMgr.AddProperty( padConnections, groupElectrical );
2157 propMgr.AddProperty( thermalGap, groupElectrical );
2158 propMgr.AddProperty( thermalSpokeWidth, groupElectrical );
2159 }
2161
types::KiCadObjectType ToProtoEnum(KICAD_T aValue)
KICAD_T FromProtoEnum(types::KiCadObjectType aValue)
Definition api_enums.cpp:41
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:112
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:921
std::unordered_map< const ZONE *, BOX2I > m_ZoneBBoxCache
Definition board.h:1548
BOARD_DESIGN_SETTINGS & GetDesignSettings() const
Definition board.cpp:1091
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:1859
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:1360
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:735
wxString GetItemDescription(UNITS_PROVIDER *aUnitsProvider, bool aFull) const override
Return a user-visible description string of this item.
Definition zone.cpp:1210
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:846
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:1691
void SetCornerRadius(unsigned int aRadius)
Definition zone.cpp:703
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:1173
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:1618
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:874
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:1133
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:1300
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:1281
bool GetDoNotAllowPads() const
Definition zone.h:729
const BOX2I GetBoundingBox() const override
Definition zone.cpp:651
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:619
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:1062
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:745
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:1028
bool IsIsland(PCB_LAYER_ID aLayer, int aPolyIdx) const
Check if a given filled polygon is an insulated island.
Definition zone.cpp:1393
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:1804
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:680
int GetMinThickness() const
Definition zone.h:302
virtual void swapData(BOARD_ITEM *aImage) override
Definition zone.cpp:1352
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:752
void RemoveCutout(int aOutlineIdx, int aHoleIdx)
Remove a cutout from the zone.
Definition zone.cpp:1144
void Rotate(const VECTOR2I &aCentre, const EDA_ANGLE &aAngle) override
Rotate the outlines.
Definition zone.cpp:1090
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:852
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:1346
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:899
virtual bool IsOnLayer(PCB_LAYER_ID) const override
Test to see if this object is on the given layer.
Definition zone.cpp:644
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:1101
void BuildHashValue(PCB_LAYER_ID aLayer)
Build the hash value of m_FilledPolysList, and store it internally in m_filledPolysHash.
Definition zone.cpp:724
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:1440
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:1405
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:1700
int GetHatchGap() const
Definition zone.h:314
double CalculateOutlineArea()
Compute the area of the zone outline (not the filled area).
Definition zone.cpp:1611
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:1190
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:1075
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:1600
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:1654
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:1736
void UnHatchBorder()
Clear the zone's hatch.
Definition zone.cpp:1294
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:715
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:1340
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:1643
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:71
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 VECTOR2I UnpackVector2(const types::Vector2 &aInput)
Definition api_utils.cpp:86
KICOMMON_API SHAPE_POLY_SET UnpackPolySet(const types::PolySet &aInput)
KICOMMON_API void PackVector2(types::Vector2 &aOutput, const VECTOR2I &aInput)
Definition api_utils.cpp:79
KICOMMON_API void PackPolySet(types::PolySet &aOutput, const SHAPE_POLY_SET &aInput)
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:1880
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:712
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