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;
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 const_cast<KIID&>( m_Uuid ) = 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 HatchBorder();
1034
1035 /* move fills */
1036 for( std::pair<const PCB_LAYER_ID, std::shared_ptr<SHAPE_POLY_SET>>& pair : m_FilledPolysList )
1037 pair.second->Move( offset );
1038
1039 /*
1040 * move boundingbox cache
1041 *
1042 * While the cache will get nuked at the conclusion of the operation, we use it for some
1043 * things (such as drawing the parent group) during the move.
1044 */
1045 if( GetBoard() )
1046 {
1047 auto it = GetBoard()->m_ZoneBBoxCache.find( this );
1048
1049 if( it != GetBoard()->m_ZoneBBoxCache.end() )
1050 it->second.Move( offset );
1051 }
1052}
1053
1054
1056{
1057 if( GetIsRuleArea() )
1058 return _( "Rule Area" );
1059 else if( IsTeardropArea() )
1060 return _( "Teardrop Area" );
1061 else if( IsOnCopperLayer() )
1062 return _( "Copper Zone" );
1063 else
1064 return _( "Non-copper Zone" );
1065}
1066
1067
1068void ZONE::MoveEdge( const VECTOR2I& offset, int aEdge )
1069{
1070 int next_corner;
1071
1072 if( m_Poly->GetNeighbourIndexes( aEdge, nullptr, &next_corner ) )
1073 {
1074 m_Poly->SetVertex( aEdge, m_Poly->CVertex( aEdge ) + VECTOR2I( offset ) );
1075 m_Poly->SetVertex( next_corner, m_Poly->CVertex( next_corner ) + VECTOR2I( offset ) );
1076 HatchBorder();
1077
1078 SetNeedRefill( true );
1079 }
1080}
1081
1082
1083void ZONE::Rotate( const VECTOR2I& aCentre, const EDA_ANGLE& aAngle )
1084{
1085 m_Poly->Rotate( aAngle, aCentre );
1086 HatchBorder();
1087
1088 /* rotate filled areas: */
1089 for( std::pair<const PCB_LAYER_ID, std::shared_ptr<SHAPE_POLY_SET>>& pair : m_FilledPolysList )
1090 pair.second->Rotate( aAngle, aCentre );
1091}
1092
1093
1094void ZONE::Flip( const VECTOR2I& aCentre, FLIP_DIRECTION aFlipDirection )
1095{
1096 Mirror( aCentre, aFlipDirection );
1097
1098 std::map<PCB_LAYER_ID, SHAPE_POLY_SET> fillsCopy;
1099
1100 for( auto& [oldLayer, shapePtr] : m_FilledPolysList )
1101 fillsCopy[oldLayer] = *shapePtr;
1102
1103 std::map<PCB_LAYER_ID, ZONE_LAYER_PROPERTIES> layerPropertiesCopy = m_layerProperties;
1104
1105 LSET flipped;
1106
1107 for( PCB_LAYER_ID layer : GetLayerSet() )
1108 flipped.set( GetBoard()->FlipLayer( layer ) );
1109
1110 SetLayerSet( flipped );
1111
1112 for( auto& [oldLayer, properties] : layerPropertiesCopy )
1113 {
1114 PCB_LAYER_ID newLayer = GetBoard()->FlipLayer( oldLayer );
1115 m_layerProperties[newLayer] = properties;
1116 }
1117
1118 for( auto& [oldLayer, shape] : fillsCopy )
1119 {
1120 PCB_LAYER_ID newLayer = GetBoard()->FlipLayer( oldLayer );
1121 SetFilledPolysList( newLayer, shape );
1122 }
1123}
1124
1125
1126void ZONE::Mirror( const VECTOR2I& aMirrorRef, FLIP_DIRECTION aFlipDirection )
1127{
1128 m_Poly->Mirror( aMirrorRef, aFlipDirection );
1129
1130 HatchBorder();
1131
1132 for( std::pair<const PCB_LAYER_ID, std::shared_ptr<SHAPE_POLY_SET>>& pair : m_FilledPolysList )
1133 pair.second->Mirror( aMirrorRef, aFlipDirection );
1134}
1135
1136
1137void ZONE::RemoveCutout( int aOutlineIdx, int aHoleIdx )
1138{
1139 // Ensure the requested cutout is valid
1140 if( m_Poly->OutlineCount() < aOutlineIdx || m_Poly->HoleCount( aOutlineIdx ) < aHoleIdx )
1141 return;
1142
1143 SHAPE_POLY_SET cutPoly( m_Poly->Hole( aOutlineIdx, aHoleIdx ) );
1144
1145 // Add the cutout back to the zone
1146 m_Poly->BooleanAdd( cutPoly );
1147
1148 SetNeedRefill( true );
1149}
1150
1151
1152void ZONE::AddPolygon( const SHAPE_LINE_CHAIN& aPolygon )
1153{
1154 wxASSERT( aPolygon.IsClosed() );
1155
1156 // Add the outline as a new polygon in the polygon set
1157 if( m_Poly->OutlineCount() == 0 )
1158 m_Poly->AddOutline( aPolygon );
1159 else
1160 m_Poly->AddHole( aPolygon );
1161
1162 SetNeedRefill( true );
1163}
1164
1165
1166void ZONE::AddPolygon( std::vector<VECTOR2I>& aPolygon )
1167{
1168 if( aPolygon.empty() )
1169 return;
1170
1171 SHAPE_LINE_CHAIN outline;
1172
1173 // Create an outline and populate it with the points of aPolygon
1174 for( const VECTOR2I& pt : aPolygon )
1175 outline.Append( pt );
1176
1177 outline.SetClosed( true );
1178
1179 AddPolygon( outline );
1180}
1181
1182
1183bool ZONE::AppendCorner( VECTOR2I aPosition, int aHoleIdx, bool aAllowDuplication )
1184{
1185 // Ensure the main outline exists:
1186 if( m_Poly->OutlineCount() == 0 )
1187 m_Poly->NewOutline();
1188
1189 // If aHoleIdx >= 0, the corner musty be added to the hole, index aHoleIdx.
1190 // (remember: the index of the first hole is 0)
1191 // Return error if it does not exist.
1192 if( aHoleIdx >= m_Poly->HoleCount( 0 ) )
1193 return false;
1194
1195 m_Poly->Append( aPosition.x, aPosition.y, -1, aHoleIdx, aAllowDuplication );
1196
1197 SetNeedRefill( true );
1198
1199 return true;
1200}
1201
1202
1203wxString ZONE::GetItemDescription( UNITS_PROVIDER* aUnitsProvider, bool aFull ) const
1204{
1205 LSEQ layers = m_layerSet.Seq();
1206 wxString layerDesc;
1207
1208 if( layers.size() == 1 )
1209 {
1210 layerDesc.Printf( _( "on %s" ), GetBoard()->GetLayerName( layers[0] ) );
1211 }
1212 else if (layers.size() == 2 )
1213 {
1214 layerDesc.Printf( _( "on %s and %s" ),
1215 GetBoard()->GetLayerName( layers[0] ),
1216 GetBoard()->GetLayerName( layers[1] ) );
1217 }
1218 else if (layers.size() == 3 )
1219 {
1220 layerDesc.Printf( _( "on %s, %s and %s" ),
1221 GetBoard()->GetLayerName( layers[0] ),
1222 GetBoard()->GetLayerName( layers[1] ),
1223 GetBoard()->GetLayerName( layers[2] ) );
1224 }
1225 else if( layers.size() > 3 )
1226 {
1227 layerDesc.Printf( _( "on %s, %s and %zu more" ),
1228 GetBoard()->GetLayerName( layers[0] ),
1229 GetBoard()->GetLayerName( layers[1] ),
1230 layers.size() - 2 );
1231 }
1232
1233 if( GetIsRuleArea() )
1234 {
1235 if( GetZoneName().IsEmpty() )
1236 {
1237 return wxString::Format( _( "Rule Area %s" ),
1238 layerDesc );
1239 }
1240 else
1241 {
1242 return wxString::Format( _( "Rule area '%s' %s" ),
1243 GetZoneName(),
1244 layerDesc );
1245 }
1246 }
1247 else if( IsTeardropArea() )
1248 {
1249 return wxString::Format( _( "Teardrop %s %s" ),
1250 GetNetnameMsg(),
1251 layerDesc );
1252 }
1253 else
1254 {
1255 if( GetZoneName().IsEmpty() )
1256 {
1257 return wxString::Format( _( "Zone %s %s, priority %d" ),
1258 GetNetnameMsg(),
1259 layerDesc,
1261 }
1262 else
1263 {
1264 return wxString::Format( _( "Zone '%s' %s %s, priority %d" ),
1265 GetZoneName(),
1266 GetNetnameMsg(),
1267 layerDesc,
1269 }
1270 }
1271}
1272
1273
1275 int aBorderHatchPitch, bool aRebuildBorderHatch )
1276{
1277 aBorderHatchPitch = std::max( aBorderHatchPitch, pcbIUScale.mmToIU( ZONE_BORDER_HATCH_MINDIST_MM ) );
1278 aBorderHatchPitch = std::min( aBorderHatchPitch, pcbIUScale.mmToIU( ZONE_BORDER_HATCH_MAXDIST_MM ) );
1279 SetBorderHatchPitch( aBorderHatchPitch );
1280 m_borderStyle = aBorderHatchStyle;
1281
1282 if( aRebuildBorderHatch )
1283 HatchBorder();
1284}
1285
1286
1288{
1289 m_borderHatchLines.clear();
1290}
1291
1292
1294{
1295 UnHatchBorder();
1296
1298 || m_borderHatchPitch == 0
1299 || m_Poly->IsEmpty() )
1300 {
1301 return;
1302 }
1303
1304 // set the "length" of hatch lines (the length on horizontal axis)
1305 int hatch_line_len = m_borderHatchPitch; // OK for DIAGONAL_EDGE style
1306
1307 // Calculate spacing between 2 hatch lines
1308 int spacing = m_borderHatchPitch; // OK for DIAGONAL_EDGE style
1309
1311 {
1312 // The spacing is twice the spacing for DIAGONAL_EDGE because one
1313 // full diagonal replaces 2 edge diagonal hatch segments in code
1314 spacing = m_borderHatchPitch * 2;
1315 hatch_line_len = -1; // Use full diagonal hatch line
1316 }
1317
1318 // To have a better look, give a slope depending on the layer
1319 int layer = GetFirstLayer();
1320 std::vector<double> slopes;
1321
1322 if( IsTeardropArea() )
1323 slopes = { 0.7, -0.7 };
1324 else if( layer & 1 )
1325 slopes = { 1 };
1326 else
1327 slopes = { -1 };
1328
1329 m_borderHatchLines = m_Poly->GenerateHatchLines( slopes, spacing, hatch_line_len );
1330}
1331
1332
1334{
1335 return pcbIUScale.mmToIU( ZONE_BORDER_HATCH_DIST_MM );
1336}
1337
1338
1340{
1341 return BITMAPS::add_zone;
1342}
1343
1344
1346{
1347 assert( aImage->Type() == PCB_ZONE_T );
1348
1349 std::swap( *static_cast<ZONE*>( this ), *static_cast<ZONE*>( aImage) );
1350}
1351
1352
1354{
1355 std::lock_guard<std::mutex> lock( m_filledPolysListMutex );
1356
1357 if( aLayer == UNDEFINED_LAYER )
1358 {
1359 for( auto& [ layer, poly ] : m_FilledPolysList )
1360 poly->CacheTriangulation();
1361
1362 m_Poly->CacheTriangulation( false );
1363 }
1364 else
1365 {
1366 if( m_FilledPolysList.count( aLayer ) )
1367 m_FilledPolysList[ aLayer ]->CacheTriangulation();
1368 }
1369}
1370
1371
1372bool ZONE::IsIsland( PCB_LAYER_ID aLayer, int aPolyIdx ) const
1373{
1374 if( GetNetCode() < 1 )
1375 return true;
1376
1377 if( !m_insulatedIslands.count( aLayer ) )
1378 return false;
1379
1380 return m_insulatedIslands.at( aLayer ).count( aPolyIdx );
1381}
1382
1383
1384void ZONE::GetInteractingZones( PCB_LAYER_ID aLayer, std::vector<ZONE*>* aSameNetCollidingZones,
1385 std::vector<ZONE*>* aOtherNetIntersectingZones ) const
1386{
1387 int epsilon = pcbIUScale.mmToIU( 0.001 );
1388 BOX2I bbox = GetBoundingBox();
1389
1390 bbox.Inflate( epsilon );
1391
1392 for( ZONE* candidate : GetBoard()->Zones() )
1393 {
1394 if( candidate == this )
1395 continue;
1396
1397 if( !candidate->GetLayerSet().test( aLayer ) )
1398 continue;
1399
1400 if( candidate->GetIsRuleArea() || candidate->IsTeardropArea() )
1401 continue;
1402
1403 if( !candidate->GetBoundingBox().Intersects( bbox ) )
1404 continue;
1405
1406 if( candidate->GetNetCode() == GetNetCode() )
1407 {
1408 if( m_Poly->Collide( candidate->m_Poly ) )
1409 aSameNetCollidingZones->push_back( candidate );
1410 }
1411 else
1412 {
1413 aOtherNetIntersectingZones->push_back( candidate );
1414 }
1415 }
1416}
1417
1418
1420 SHAPE_POLY_SET* aBoardOutline,
1421 SHAPE_POLY_SET* aSmoothedPolyWithApron ) const
1422{
1423 if( GetNumCorners() <= 2 ) // malformed zone. polygon calculations will not like it ...
1424 return false;
1425
1426 // Processing of arc shapes in zones is not yet supported because Clipper can't do boolean
1427 // operations on them. The poly outline must be converted to segments first.
1428 SHAPE_POLY_SET flattened = m_Poly->CloneDropTriangulation();
1429 flattened.ClearArcs();
1430
1431 if( GetIsRuleArea() )
1432 {
1433 // We like keepouts just the way they are....
1434 aSmoothedPoly = std::move( flattened );
1435 return true;
1436 }
1437
1438 const BOARD* board = GetBoard();
1439 bool keepExternalFillets = false;
1442
1443 if( IsTeardropArea() )
1444 {
1445 // We use teardrop shapes with no smoothing; these shapes are already optimized
1446 smooth_requested = false;
1447 }
1448
1449 if( board )
1450 keepExternalFillets = board->GetDesignSettings().m_ZoneKeepExternalFillets;
1451
1452 auto smooth =
1453 [&]( SHAPE_POLY_SET& aPoly )
1454 {
1455 if( !smooth_requested )
1456 return;
1457
1458 switch( m_cornerSmoothingType )
1459 {
1461 aPoly = aPoly.Chamfer( (int) m_cornerRadius );
1462 break;
1463
1465 aPoly = aPoly.Fillet( (int) m_cornerRadius, GetMaxError() );
1466 break;
1467
1468 default:
1469 break;
1470 }
1471 };
1472
1473 SHAPE_POLY_SET* maxExtents = &flattened;
1474 SHAPE_POLY_SET withFillets;
1475
1476 aSmoothedPoly = flattened;
1477
1478 // Should external fillets (that is, those applied to concave corners) be kept? While it
1479 // seems safer to never have copper extend outside the zone outline, 5.1.x and prior did
1480 // indeed fill them so we leave the mode available.
1481 if( keepExternalFillets && smooth_requested )
1482 {
1483 withFillets = flattened;
1484 smooth( withFillets );
1485 withFillets.BooleanAdd( flattened );
1486 maxExtents = &withFillets;
1487 }
1488
1489 // We now add in the areas of any same-net, intersecting zones. This keeps us from smoothing
1490 // corners at an intersection (which often produces undesired divots between the intersecting
1491 // zones -- see #2752).
1492 //
1493 // After smoothing, we'll subtract back out everything outside of our zone.
1494 std::vector<ZONE*> sameNetCollidingZones;
1495 std::vector<ZONE*> diffNetIntersectingZones;
1496 GetInteractingZones( aLayer, &sameNetCollidingZones, &diffNetIntersectingZones );
1497
1498 for( ZONE* sameNetZone : sameNetCollidingZones )
1499 {
1500 BOX2I sameNetBoundingBox = sameNetZone->GetBoundingBox();
1501
1502 // Note: a two-pass algorithm could use sameNetZone's actual fill instead of its outline.
1503 // This would obviate the need for the below wrinkles, in addition to fixing both issues
1504 // in #16095.
1505 // (And we wouldn't need to collect all the diffNetIntersectingZones either.)
1506
1507 SHAPE_POLY_SET sameNetPoly = sameNetZone->Outline()->CloneDropTriangulation();
1508 sameNetPoly.ClearArcs();
1509
1510 SHAPE_POLY_SET diffNetPoly;
1511
1512 // Of course there's always a wrinkle. The same-net intersecting zone *might* get knocked
1513 // out along the border by a higher-priority, different-net zone. #12797
1514 for( ZONE* diffNetZone : diffNetIntersectingZones )
1515 {
1516 if( diffNetZone->HigherPriority( sameNetZone )
1517 && diffNetZone->GetBoundingBox().Intersects( sameNetBoundingBox ) )
1518 {
1519 SHAPE_POLY_SET diffNetOutline = diffNetZone->Outline()->CloneDropTriangulation();
1520 diffNetOutline.ClearArcs();
1521
1522 diffNetPoly.BooleanAdd( diffNetOutline );
1523 }
1524 }
1525
1526 // Second wrinkle. After unioning the higher priority, different net zones together, we
1527 // need to check to see if they completely enclose our zone. If they do, then we need to
1528 // treat the enclosed zone as isolated, not connected to the outer zone. #13915
1529 bool isolated = false;
1530
1531 if( diffNetPoly.OutlineCount() )
1532 {
1534 thisPoly.ClearArcs();
1535
1536 thisPoly.BooleanSubtract( diffNetPoly );
1537 isolated = thisPoly.OutlineCount() == 0;
1538 }
1539
1540 if( !isolated )
1541 aSmoothedPoly.BooleanAdd( sameNetPoly );
1542 }
1543
1544 if( aBoardOutline )
1545 {
1546 SHAPE_POLY_SET boardOutline = aBoardOutline->CloneDropTriangulation();
1547 boardOutline.ClearArcs();
1548
1549 aSmoothedPoly.BooleanIntersection( boardOutline );
1550 }
1551
1552 SHAPE_POLY_SET withSameNetIntersectingZones = aSmoothedPoly.CloneDropTriangulation();
1553
1554 smooth( aSmoothedPoly );
1555
1556 if( aSmoothedPolyWithApron )
1557 {
1558 // The same-net intersecting-zone code above makes sure the corner-smoothing algorithm
1559 // doesn't produce divots. But the min-thickness algorithm applied in fillCopperZone()
1560 // is *also* going to perform a deflate/inflate cycle, again leading to divots. So we
1561 // pre-inflate the contour by the min-thickness within the same-net-intersecting-zones
1562 // envelope.
1563 SHAPE_POLY_SET poly = maxExtents->CloneDropTriangulation();
1565
1566 if( !keepExternalFillets )
1567 poly.BooleanIntersection( withSameNetIntersectingZones );
1568
1569 *aSmoothedPolyWithApron = aSmoothedPoly;
1570 aSmoothedPolyWithApron->BooleanIntersection( poly );
1571 }
1572
1573 aSmoothedPoly.BooleanIntersection( *maxExtents );
1574
1575 return true;
1576}
1577
1578
1580{
1581 m_area = 0.0;
1582
1583 for( const auto& [layer, poly] : m_FilledPolysList )
1584 m_area += poly->Area();
1585
1586 return m_area;
1587}
1588
1589
1591{
1592 m_outlinearea = std::abs( m_Poly->Area() );
1593 return m_outlinearea;
1594}
1595
1596
1598 int aMaxError, ERROR_LOC aErrorLoc,
1599 SHAPE_POLY_SET* aBoardOutline ) const
1600{
1601 // Creates the zone outline polygon (with holes if any)
1602 SHAPE_POLY_SET polybuffer;
1603
1604 // TODO: using GetFirstLayer() means it only works for single-layer zones....
1605 BuildSmoothedPoly( polybuffer, GetFirstLayer(), aBoardOutline );
1606
1607 // Calculate the polygon with clearance
1608 // holes are linked to the main outline, so only one polygon is created.
1609 if( aClearance )
1610 {
1611 if( aErrorLoc == ERROR_OUTSIDE )
1612 aClearance += GetMaxError();
1613
1614 polybuffer.Inflate( aClearance, CORNER_STRATEGY::ROUND_ALL_CORNERS, GetMaxError() );
1615 }
1616
1617 polybuffer.Fracture();
1618 aBuffer.Append( polybuffer );
1619}
1620
1621
1622std::shared_ptr<SHAPE> ZONE::GetEffectiveShape( PCB_LAYER_ID aLayer, FLASHING aFlash ) const
1623{
1624 std::lock_guard<std::mutex> lock( m_filledPolysListMutex );
1625
1626 if( m_FilledPolysList.find( aLayer ) == m_FilledPolysList.end() )
1627 return std::make_shared<SHAPE_NULL>();
1628 else
1629 return m_FilledPolysList.at( aLayer );
1630}
1631
1632
1633void ZONE::TransformShapeToPolygon( SHAPE_POLY_SET& aBuffer, PCB_LAYER_ID aLayer, int aClearance,
1634 int aError, ERROR_LOC aErrorLoc, bool aIgnoreLineWidth ) const
1635{
1636 wxASSERT_MSG( !aIgnoreLineWidth, wxT( "IgnoreLineWidth has no meaning for zones." ) );
1637
1638 std::shared_ptr<SHAPE_POLY_SET> fillPolys;
1639
1640 {
1641 std::lock_guard<std::mutex> lock( m_filledPolysListMutex );
1642
1643 if( !m_FilledPolysList.count( aLayer ) )
1644 return;
1645
1646 fillPolys = m_FilledPolysList.at( aLayer );
1647 }
1648
1649 if( !aClearance )
1650 {
1651 aBuffer.Append( *fillPolys );
1652 return;
1653 }
1654
1655 SHAPE_POLY_SET temp_buf = fillPolys->CloneDropTriangulation();
1656
1657 // Rebuild filled areas only if clearance is not 0
1658 if( aClearance > 0 || aErrorLoc == ERROR_OUTSIDE )
1659 {
1660 if( aErrorLoc == ERROR_OUTSIDE )
1661 aClearance += aError;
1662
1663 temp_buf.InflateWithLinkedHoles( aClearance, CORNER_STRATEGY::ROUND_ALL_CORNERS, aError );
1664 }
1665
1666 aBuffer.Append( temp_buf );
1667}
1668
1669
1671{
1672 std::lock_guard<std::mutex> lock( m_filledPolysListMutex );
1673
1674 if( m_FilledPolysList.count( aLayer ) && !m_FilledPolysList.at( aLayer )->IsEmpty() )
1675 aBuffer.Append( *m_FilledPolysList.at( aLayer ) );
1676}
1677
1678
1680{
1681 if( aLayerSet.count() == 0 )
1682 return;
1683
1684 std::scoped_lock lock( m_layerSetMutex, m_filledPolysListMutex );
1685
1686 if( m_layerSet != aLayerSet )
1687 {
1688 aLayerSet.RunOnLayers(
1689 [&]( PCB_LAYER_ID layer )
1690 {
1691 // Only keep layers that are present in the new set
1692 if( !aLayerSet.Contains( layer ) )
1693 {
1694 m_FilledPolysList[layer] = std::make_shared<SHAPE_POLY_SET>();
1695 m_filledPolysHash[layer] = {};
1696 m_insulatedIslands[layer] = {};
1697 }
1698 } );
1699 }
1700
1701 m_layerSet = aLayerSet;
1702}
1703
1704
1705bool ZONE::operator==( const BOARD_ITEM& aOther ) const
1706{
1707 if( aOther.Type() != Type() )
1708 return false;
1709
1710 const ZONE& other = static_cast<const ZONE&>( aOther );
1711 return *this == other;
1712}
1713
1714
1715bool ZONE::operator==( const ZONE& aOther ) const
1716
1717{
1718 if( aOther.Type() != Type() )
1719 return false;
1720
1721 const ZONE& other = static_cast<const ZONE&>( aOther );
1722
1723 if( GetIsRuleArea() != other.GetIsRuleArea() )
1724 return false;
1725
1726 if( GetIsRuleArea() )
1727 {
1729 return false;
1730
1731 if( GetDoNotAllowTracks() != other.GetDoNotAllowTracks() )
1732 return false;
1733
1734 if( GetDoNotAllowVias() != other.GetDoNotAllowVias() )
1735 return false;
1736
1738 return false;
1739
1740 if( GetDoNotAllowPads() != other.GetDoNotAllowPads() )
1741 return false;
1742
1744 return false;
1745
1747 return false;
1748
1750 return false;
1751 }
1752 else
1753 {
1754 if( GetAssignedPriority() != other.GetAssignedPriority() )
1755 return false;
1756
1757 if( GetMinThickness() != other.GetMinThickness() )
1758 return false;
1759
1761 return false;
1762
1763 if( GetCornerRadius() != other.GetCornerRadius() )
1764 return false;
1765
1766 if( GetTeardropParams() != other.GetTeardropParams() )
1767 return false;
1768 }
1769
1770 if( GetNumCorners() != other.GetNumCorners() )
1771 return false;
1772
1773 for( int ii = 0; ii < GetNumCorners(); ii++ )
1774 {
1775 if( GetCornerPosition( ii ) != other.GetCornerPosition( ii ) )
1776 return false;
1777 }
1778
1779 return true;
1780}
1781
1782
1783double ZONE::Similarity( const BOARD_ITEM& aOther ) const
1784{
1785 if( aOther.Type() != Type() )
1786 return 0.0;
1787
1788 const ZONE& other = static_cast<const ZONE&>( aOther );
1789
1790 if( GetIsRuleArea() != other.GetIsRuleArea() )
1791 return 0.0;
1792
1793 double similarity = 1.0;
1794
1795 if( GetLayerSet() != other.GetLayerSet() )
1796 similarity *= 0.9;
1797
1798 if( GetNetCode() != other.GetNetCode() )
1799 similarity *= 0.9;
1800
1801 if( !GetIsRuleArea() )
1802 {
1803 if( GetAssignedPriority() != other.GetAssignedPriority() )
1804 similarity *= 0.9;
1805
1806 if( GetMinThickness() != other.GetMinThickness() )
1807 similarity *= 0.9;
1808
1810 similarity *= 0.9;
1811
1812 if( GetCornerRadius() != other.GetCornerRadius() )
1813 similarity *= 0.9;
1814
1815 if( GetTeardropParams() != other.GetTeardropParams() )
1816 similarity *= 0.9;
1817 }
1818 else
1819 {
1821 similarity *= 0.9;
1822 if( GetDoNotAllowTracks() != other.GetDoNotAllowTracks() )
1823 similarity *= 0.9;
1824 if( GetDoNotAllowVias() != other.GetDoNotAllowVias() )
1825 similarity *= 0.9;
1827 similarity *= 0.9;
1828 if( GetDoNotAllowPads() != other.GetDoNotAllowPads() )
1829 similarity *= 0.9;
1830 }
1831
1832 std::vector<VECTOR2I> corners;
1833 std::vector<VECTOR2I> otherCorners;
1834 VECTOR2I lastCorner( 0, 0 );
1835
1836 for( int ii = 0; ii < GetNumCorners(); ii++ )
1837 {
1838 corners.push_back( lastCorner - GetCornerPosition( ii ) );
1839 lastCorner = GetCornerPosition( ii );
1840 }
1841
1842 lastCorner = VECTOR2I( 0, 0 );
1843 for( int ii = 0; ii < other.GetNumCorners(); ii++ )
1844 {
1845 otherCorners.push_back( lastCorner - other.GetCornerPosition( ii ) );
1846 lastCorner = other.GetCornerPosition( ii );
1847 }
1848
1849 size_t longest = alg::longest_common_subset( corners, otherCorners );
1850
1851 similarity *= std::pow( 0.9, GetNumCorners() + other.GetNumCorners() - 2 * longest );
1852
1853 return similarity;
1854}
1855
1856
1857static struct ZONE_DESC
1858{
1860 {
1862
1863 if( layerEnum.Choices().GetCount() == 0 )
1864 {
1865 layerEnum.Undefined( UNDEFINED_LAYER );
1866
1867 for( PCB_LAYER_ID layer : LSET::AllLayersMask() )
1868 layerEnum.Map( layer, LSET::Name( layer ) );
1869 }
1870
1872
1873 if( zcMap.Choices().GetCount() == 0 )
1874 {
1876 zcMap.Map( ZONE_CONNECTION::INHERITED, _HKI( "Inherited" ) )
1877 .Map( ZONE_CONNECTION::NONE, _HKI( "None" ) )
1878 .Map( ZONE_CONNECTION::THERMAL, _HKI( "Thermal reliefs" ) )
1879 .Map( ZONE_CONNECTION::FULL, _HKI( "Solid" ) )
1880 .Map( ZONE_CONNECTION::THT_THERMAL, _HKI( "Thermal reliefs for PTH" ) );
1881 }
1882
1884
1885 if( zfmMap.Choices().GetCount() == 0 )
1886 {
1888 zfmMap.Map( ZONE_FILL_MODE::POLYGONS, _HKI( "Solid fill" ) )
1889 .Map( ZONE_FILL_MODE::HATCH_PATTERN, _HKI( "Hatch pattern" ) );
1890 }
1891
1893
1894 if( irmMap.Choices().GetCount() == 0 )
1895 {
1897 irmMap.Map( ISLAND_REMOVAL_MODE::ALWAYS, _HKI( "Always" ) )
1898 .Map( ISLAND_REMOVAL_MODE::NEVER, _HKI( "Never" ) )
1899 .Map( ISLAND_REMOVAL_MODE::AREA, _HKI( "Below area limit" ) );
1900 }
1901
1903
1904 if( rapstMap.Choices().GetCount() == 0 )
1905 {
1907 rapstMap.Map( PLACEMENT_SOURCE_T::SHEETNAME, _HKI( "Sheet Name" ) )
1908 .Map( PLACEMENT_SOURCE_T::COMPONENT_CLASS, _HKI( "Component Class" ) )
1910 }
1911
1915
1916 // Mask layer and position properties; they aren't useful in current form
1917 auto posX = new PROPERTY<ZONE, int>( _HKI( "Position X" ), NO_SETTER( ZONE, int ),
1918 static_cast<int ( ZONE::* )() const>( &ZONE::GetX ),
1921 posX->SetIsHiddenFromPropertiesManager();
1922
1923 auto posY = new PROPERTY<ZONE, int>( _HKI( "Position Y" ), NO_SETTER( ZONE, int ),
1924 static_cast<int ( ZONE::* )() const>( &ZONE::GetY ),
1927 posY->SetIsHiddenFromPropertiesManager();
1928
1929 propMgr.ReplaceProperty( TYPE_HASH( BOARD_ITEM ), _HKI( "Position X" ), posX );
1930 propMgr.ReplaceProperty( TYPE_HASH( BOARD_ITEM ), _HKI( "Position Y" ), posY );
1931
1932 auto isCopperZone =
1933 []( INSPECTABLE* aItem ) -> bool
1934 {
1935 if( ZONE* zone = dynamic_cast<ZONE*>( aItem ) )
1936 return !zone->GetIsRuleArea() && IsCopperLayer( zone->GetFirstLayer() );
1937
1938 return false;
1939 };
1940
1941 auto isRuleArea =
1942 []( INSPECTABLE* aItem ) -> bool
1943 {
1944 if( ZONE* zone = dynamic_cast<ZONE*>( aItem ) )
1945 return zone->GetIsRuleArea();
1946
1947 return false;
1948 };
1949
1950 auto isHatchedFill =
1951 []( INSPECTABLE* aItem ) -> bool
1952 {
1953 if( ZONE* zone = dynamic_cast<ZONE*>( aItem ) )
1954 return zone->GetFillMode() == ZONE_FILL_MODE::HATCH_PATTERN;
1955
1956 return false;
1957 };
1958
1959 auto isAreaBasedIslandRemoval =
1960 []( INSPECTABLE* aItem ) -> bool
1961 {
1962 if( ZONE* zone = dynamic_cast<ZONE*>( aItem ) )
1963 return zone->GetIslandRemovalMode() == ISLAND_REMOVAL_MODE::AREA;
1964
1965 return false;
1966 };
1967
1968 // Layer property is hidden because it only holds a single layer and zones actually use
1969 // a layer set
1970 propMgr.ReplaceProperty( TYPE_HASH( BOARD_CONNECTED_ITEM ), _HKI( "Layer" ),
1974
1976 isCopperZone );
1977 propMgr.OverrideAvailability( TYPE_HASH( ZONE ), TYPE_HASH( BOARD_CONNECTED_ITEM ), _HKI( "Net Class" ),
1978 isCopperZone );
1979
1980 propMgr.AddProperty( new PROPERTY<ZONE, wxString>( _HKI( "Name" ),
1982
1983 const wxString groupKeepout = _HKI( "Keepout" );
1984
1985 propMgr.AddProperty( new PROPERTY<ZONE, bool>( _HKI( "Keep Out Tracks" ),
1987 groupKeepout )
1988 .SetAvailableFunc( isRuleArea );
1989
1990 propMgr.AddProperty( new PROPERTY<ZONE, bool>( _HKI( "Keep Out Vias" ),
1992 groupKeepout )
1993 .SetAvailableFunc( isRuleArea );
1994
1995 propMgr.AddProperty( new PROPERTY<ZONE, bool>( _HKI( "Keep Out Pads" ),
1997 groupKeepout )
1998 .SetAvailableFunc( isRuleArea );
1999
2000 propMgr.AddProperty( new PROPERTY<ZONE, bool>( _HKI( "Keep Out Zone Fills" ),
2002 groupKeepout )
2003 .SetAvailableFunc( isRuleArea );
2004
2005 propMgr.AddProperty( new PROPERTY<ZONE, bool>( _HKI( "Keep Out Footprints" ),
2007 groupKeepout )
2008 .SetAvailableFunc( isRuleArea );
2009
2010
2011 const wxString groupPlacement = _HKI( "Placement" );
2012
2013 propMgr.AddProperty( new PROPERTY<ZONE, bool>( _HKI( "Enable" ),
2015 groupPlacement )
2016 .SetAvailableFunc( isRuleArea );
2017
2018 propMgr.AddProperty( new PROPERTY_ENUM<ZONE, PLACEMENT_SOURCE_T>( _HKI( "Source Type" ),
2020 groupPlacement )
2021 .SetAvailableFunc( isRuleArea );
2022
2023 propMgr.AddProperty( new PROPERTY<ZONE, wxString>( _HKI( "Source Name" ),
2025 groupPlacement )
2026 .SetAvailableFunc( isRuleArea );
2027
2028
2029 const wxString groupFill = _HKI( "Fill Style" );
2030
2031 propMgr.AddProperty( new PROPERTY_ENUM<ZONE, ZONE_FILL_MODE>( _HKI( "Fill Mode" ),
2033 groupFill )
2034 .SetAvailableFunc( isCopperZone );
2035
2036 propMgr.AddProperty( new PROPERTY<ZONE, EDA_ANGLE>( _HKI( "Hatch Orientation" ),
2039 groupFill )
2040 .SetAvailableFunc( isCopperZone )
2041 .SetWriteableFunc( isHatchedFill );
2042
2043 auto atLeastMinWidthValidator =
2044 []( const wxAny&& aValue, EDA_ITEM* aZone ) -> VALIDATOR_RESULT
2045 {
2046 int val = aValue.As<int>();
2047 ZONE* zone = dynamic_cast<ZONE*>( aZone );
2048 wxCHECK( zone, std::nullopt );
2049
2050 if( val < zone->GetMinThickness() )
2051 return std::make_unique<VALIDATION_ERROR_MSG>( _( "Cannot be less than zone minimum width" ) );
2052
2053 return std::nullopt;
2054 };
2055
2056 propMgr.AddProperty( new PROPERTY<ZONE, int>( _HKI( "Hatch Width" ),
2058 groupFill )
2059 .SetAvailableFunc( isCopperZone )
2060 .SetWriteableFunc( isHatchedFill )
2061 .SetValidator( atLeastMinWidthValidator );
2062
2063 propMgr.AddProperty( new PROPERTY<ZONE, int>( _HKI( "Hatch Gap" ),
2065 groupFill )
2066 .SetAvailableFunc( isCopperZone )
2067 .SetWriteableFunc( isHatchedFill )
2068 .SetValidator( atLeastMinWidthValidator );
2069
2070 propMgr.AddProperty( new PROPERTY<ZONE, double>( _HKI( "Hatch Minimum Hole Ratio" ),
2072 groupFill )
2073 .SetAvailableFunc( isCopperZone )
2074 .SetWriteableFunc( isHatchedFill )
2076
2077 // TODO: Smoothing effort needs to change to enum (in dialog too)
2078 propMgr.AddProperty( new PROPERTY<ZONE, int>( _HKI( "Smoothing Effort" ),
2080 groupFill )
2081 .SetAvailableFunc( isCopperZone )
2082 .SetWriteableFunc( isHatchedFill );
2083
2084 propMgr.AddProperty( new PROPERTY<ZONE, double>( _HKI( "Smoothing Amount" ),
2086 groupFill )
2087 .SetAvailableFunc( isCopperZone )
2088 .SetWriteableFunc( isHatchedFill );
2089
2090 propMgr.AddProperty( new PROPERTY_ENUM<ZONE, ISLAND_REMOVAL_MODE>( _HKI( "Remove Islands" ),
2092 groupFill )
2093 .SetAvailableFunc( isCopperZone );
2094
2095 propMgr.AddProperty( new PROPERTY<ZONE, long long int>( _HKI( "Minimum Island Area" ),
2097 groupFill )
2098 .SetAvailableFunc( isCopperZone )
2099 .SetWriteableFunc( isAreaBasedIslandRemoval );
2100
2101 const wxString groupElectrical = _HKI( "Electrical" );
2102
2103 auto clearance = new PROPERTY<ZONE, std::optional<int>>( _HKI( "Clearance" ),
2105 clearance->SetAvailableFunc( isCopperZone );
2106 constexpr int maxClearance = pcbIUScale.mmToIU( ZONE_CLEARANCE_MAX_VALUE_MM );
2108
2109 auto minWidth = new PROPERTY<ZONE, int>( _HKI( "Minimum Width" ),
2111 minWidth->SetAvailableFunc( isCopperZone );
2112 constexpr int minMinWidth = pcbIUScale.mmToIU( ZONE_THICKNESS_MIN_VALUE_MM );
2114
2115 auto padConnections = new PROPERTY_ENUM<ZONE, ZONE_CONNECTION>( _HKI( "Pad Connections" ),
2117 padConnections->SetAvailableFunc( isCopperZone );
2118
2119 auto thermalGap = new PROPERTY<ZONE, int>( _HKI( "Thermal Relief Gap" ),
2121 thermalGap->SetAvailableFunc( isCopperZone );
2122 thermalGap->SetValidator( PROPERTY_VALIDATORS::PositiveIntValidator );
2123
2124 auto thermalSpokeWidth = new PROPERTY<ZONE, int>( _HKI( "Thermal Relief Spoke Width" ),
2126 thermalSpokeWidth->SetAvailableFunc( isCopperZone );
2127 thermalSpokeWidth->SetValidator( atLeastMinWidthValidator );
2128
2129 propMgr.AddProperty( clearance, groupElectrical );
2130 propMgr.AddProperty( minWidth, groupElectrical );
2131 propMgr.AddProperty( padConnections, groupElectrical );
2132 propMgr.AddProperty( thermalGap, groupElectrical );
2133 propMgr.AddProperty( thermalSpokeWidth, groupElectrical );
2134 }
2136
types::KiCadObjectType ToProtoEnum(KICAD_T aValue)
Definition api_enums.cpp:97
KICAD_T FromProtoEnum(types::KiCadObjectType aValue)
Definition api_enums.cpp:36
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
int GetY() const
Definition board_item.h:106
int GetX() const
Definition board_item.h:100
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_CONTAINER * GetParent() const
Definition board_item.h:215
wxString GetLayerName() const
Return the name of the PCB layer on which the item resides.
int GetMaxError() const
Information pertinent to a Pcbnew printed circuit board.
Definition board.h:322
PCB_LAYER_ID FlipLayer(PCB_LAYER_ID aLayer) const
Definition board.cpp:912
std::unordered_map< const ZONE *, BOX2I > m_ZoneBBoxCache
Definition board.h:1474
BOARD_DESIGN_SETTINGS & GetDesignSettings() const
Definition board.cpp:1082
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:99
EDA_ITEM & operator=(const EDA_ITEM &aItem)
Assign the members of aItem to another object.
Definition eda_item.cpp:338
const KIID m_Uuid
Definition eda_item.h:522
bool m_forceVisible
Definition eda_item.h:539
KICAD_T Type() const
Returns the type of object.
Definition eda_item.h:111
EDA_ITEM_FLAGS m_flags
Definition eda_item.h:533
bool HasFlag(EDA_ITEM_FLAGS aFlag) const
Definition eda_item.h:152
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:423
Definition kiid.h:49
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:1795
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.
PROPERTY_BASE & ReplaceProperty(PROPERTY_BASE *aProperty, const wxString &aGroup)
Replace an existing 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.
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)
bool PointInside(const VECTOR2I &aPt, int aAccuracy=0, bool aUseBBoxCache=false) const override
Check if point aP lies inside a closed shape.
Represent a polyline containing arcs as well as line segments: A chain of connected line and/or arc s...
bool IsClosed() const override
void SetClosed(bool aClosed)
Mark the line chain as closed (i.e.
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.
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.
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:73
void SetHatchThickness(int aThickness)
Definition zone.h:316
void SetNeedRefill(bool aNeedRefill)
Definition zone.h:301
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:1203
int m_borderHatchPitch
Definition zone.h:934
wxString m_placementAreaSource
Definition zone.h:858
bool m_isRuleArea
Definition zone.h:851
void SetDoNotAllowPads(bool aEnable)
Definition zone.h:738
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:831
bool GetIsRuleArea() const
Accessors to parameters used in Rule Area zones:
Definition zone.h:719
PLACEMENT_SOURCE_T m_placementAreaSourceType
Definition zone.h:857
std::optional< int > GetLocalClearance() const override
Definition zone.cpp:846
void SetLocalClearance(std::optional< int > aClearance)
Definition zone.h:186
bool m_doNotAllowVias
Definition zone.h:870
bool UnFill()
Removes the zone filling.
Definition zone.cpp:456
bool GetDoNotAllowVias() const
Definition zone.h:730
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:1670
void SetCornerRadius(unsigned int aRadius)
Definition zone.cpp:703
ZONE_FILL_MODE m_fillMode
Definition zone.h:901
bool m_doNotAllowFootprints
Definition zone.h:873
bool unFillLocked()
Internal implementation of UnFill() that assumes the caller already holds m_filledPolysListMutex.
Definition zone.cpp:464
int m_ZoneMinThickness
Definition zone.h:877
void AddPolygon(std::vector< VECTOR2I > &aPolygon)
Add a polygon to the zone outline.
Definition zone.cpp:1166
double m_hatchSmoothingValue
Definition zone.h:909
void SetLocalFlags(int aFlags)
Definition zone.h:338
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:1597
int m_thermalReliefSpokeWidth
Definition zone.h:899
wxString GetPlacementAreaSource() const
Definition zone.h:724
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:904
void CacheTriangulation(PCB_LAYER_ID aLayer=UNDEFINED_LAYER)
Create a list of triangles that "fill" the solid areas used for instance to draw these solid areas on...
Definition zone.cpp:1353
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:1126
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:938
wxString m_zoneName
An optional unique name for this zone, used for identifying it in DRC checking.
Definition zone.h:835
void HatchBorder()
Compute the hatch lines depending on the hatch parameters and stores it in the zone's attribute m_bor...
Definition zone.cpp:1293
std::map< PCB_LAYER_ID, std::shared_ptr< SHAPE_POLY_SET > > m_FilledPolysList
Definition zone.h:924
void SetBorderDisplayStyle(ZONE_BORDER_DISPLAY_STYLE aBorderHatchStyle, int aBorderHatchPitch, bool aRebuilBorderdHatch)
Set all hatch parameters for the zone.
Definition zone.cpp:1274
bool GetDoNotAllowPads() const
Definition zone.h:732
const BOX2I GetBoundingBox() const override
Definition zone.cpp:651
void SetMinThickness(int aMinThickness)
Definition zone.h:307
void SetPlacementAreaSource(const wxString &aSource)
Definition zone.h:725
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:726
double m_outlinearea
Definition zone.h:941
std::mutex m_filledPolysListMutex
Definition zone.h:923
wxString GetFriendlyName() const override
Definition zone.cpp:1055
bool GetDoNotAllowTracks() const
Definition zone.h:731
int GetLocalFlags() const
Definition zone.h:337
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:322
void SetHatchSmoothingValue(double aValue)
Definition zone.h:328
bool m_needRefill
False when a zone was refilled, true after changes in zone params.
Definition zone.h:896
std::map< PCB_LAYER_ID, ZONE_LAYER_PROPERTIES > m_layerProperties
Definition zone.h:840
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:325
bool m_doNotAllowTracks
Definition zone.h:871
void SetThermalReliefSpokeWidth(int aThermalReliefSpokeWidth)
Definition zone.h:237
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:727
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:741
LSET m_fillFlags
Definition zone.h:928
SHAPE_POLY_SET * Outline()
Definition zone.h:340
bool m_doNotAllowPads
Definition zone.h:872
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:1372
SHAPE_POLY_SET * m_Poly
Outline of the zone.
Definition zone.h:830
TEARDROP_TYPE m_teardropType
Definition zone.h:864
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:931
~ZONE()
Definition zone.cpp:122
long long int GetMinIslandArea() const
Definition zone.h:744
int m_hatchSmoothingLevel
Definition zone.h:905
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:1783
LSET m_layerSet
Definition zone.h:838
void SetIsRuleArea(bool aEnable)
Definition zone.h:720
int m_ZoneClearance
Definition zone.h:876
void CopyFrom(const BOARD_ITEM *aOther) override
Definition zone.cpp:115
void SetDoNotAllowTracks(bool aEnable)
Definition zone.h:737
void SetFilledPolysList(PCB_LAYER_ID aLayer, const SHAPE_POLY_SET &aPolysList)
Set the list of filled polygons.
Definition zone.h:634
bool m_placementAreaEnabled
Placement rule area data.
Definition zone.h:856
const wxString & GetZoneName() const
Definition zone.h:163
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:306
virtual void swapData(BOARD_ITEM *aImage) override
Definition zone.cpp:1345
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:1137
void Rotate(const VECTOR2I &aCentre, const EDA_ANGLE &aAngle) override
Rotate the outlines.
Definition zone.cpp:1083
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:298
std::mutex m_layerSetMutex
Definition zone.h:837
void SetFillMode(ZONE_FILL_MODE aFillMode)
Definition zone.h:223
BITMAPS GetMenuImage() const override
Return a pointer to an image to be used in menus.
Definition zone.cpp:1339
int m_hatchGap
Definition zone.h:903
ZONE_CONNECTION GetPadConnection() const
Definition zone.h:303
int GetHatchThickness() const
Definition zone.h:315
double GetHatchHoleMinArea() const
Definition zone.h:330
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:911
bool GetPlacementAreaEnabled() const
Definition zone.h:721
void SetDoNotAllowVias(bool aEnable)
Definition zone.h:736
bool IsTeardropArea() const
Definition zone.h:694
std::vector< SEG > m_borderHatchLines
Definition zone.h:935
VECTOR2I GetPosition() const override
Definition zone.cpp:492
int GetThermalReliefSpokeWidth() const
Definition zone.h:245
virtual void Flip(const VECTOR2I &aCentre, FLIP_DIRECTION aFlipDirection) override
Flip this object, i.e.
Definition zone.cpp:1094
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:226
EDA_ANGLE GetHatchOrientation() const
Definition zone.h:321
bool BuildSmoothedPoly(SHAPE_POLY_SET &aSmoothedPoly, PCB_LAYER_ID aLayer, SHAPE_POLY_SET *aBoardOutline, SHAPE_POLY_SET *aSmoothedPolyWithApron=nullptr) const
Definition zone.cpp:1419
int m_fillVersion
Definition zone.h:878
const VECTOR2I & GetCornerPosition(int aCornerIndex) const
Definition zone.h:564
bool GetDoNotAllowFootprints() const
Definition zone.h:733
ZONE_FILL_MODE GetFillMode() const
Definition zone.h:224
double m_hatchHoleMinArea
Definition zone.h:910
virtual LSET GetLayerSet() const override
Return a std::bitset of all layers on which the item physically resides.
Definition zone.h:136
void SetDoNotAllowFootprints(bool aEnable)
Definition zone.h:739
void SetBorderHatchPitch(int aPitch)
Definition zone.h:755
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:1384
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:1679
int GetHatchGap() const
Definition zone.h:318
double CalculateOutlineArea()
Compute the area of the zone outline (not the filled area).
Definition zone.cpp:1590
void SetHatchHoleMinArea(double aPct)
Definition zone.h:331
unsigned m_priority
Definition zone.h:846
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:869
ISLAND_REMOVAL_MODE m_islandRemovalMode
Definition zone.h:880
bool m_isFilled
True when a zone was filled, false after deleting the filled areas.
Definition zone.h:889
double GetHatchSmoothingValue() const
Definition zone.h:327
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:1183
bool GetDoNotAllowZoneFills() const
Definition zone.h:729
void MoveEdge(const VECTOR2I &offset, int aEdge)
Move the outline Edge.
Definition zone.cpp:1068
int GetHatchSmoothingLevel() const
Definition zone.h:324
unsigned int GetCornerRadius() const
Definition zone.h:664
int GetCornerSmoothingType() const
Definition zone.h:660
int m_thermalReliefGap
Definition zone.h:898
bool IsOnCopperLayer() const override
Definition zone.cpp:543
double CalculateFilledArea()
Compute the area currently occupied by the zone fill.
Definition zone.cpp:1579
void SetDoNotAllowZoneFills(bool aEnable)
Definition zone.h:735
int m_hatchThickness
Definition zone.h:902
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:1633
void SetAssignedPriority(unsigned aPriority)
Definition zone.h:120
double m_area
Definition zone.h:940
unsigned int m_cornerRadius
Definition zone.h:832
void SetPadConnection(ZONE_CONNECTION aPadConnection)
Definition zone.h:304
void SetZoneName(const wxString &aName)
Definition zone.h:164
bool operator==(const ZONE &aOther) const
Definition zone.cpp:1715
void UnHatchBorder()
Clear the zone's hatch.
Definition zone.cpp:1287
void SetIslandRemovalMode(ISLAND_REMOVAL_MODE aRemove)
Definition zone.h:742
void SetOutline(SHAPE_POLY_SET *aOutline)
Definition zone.h:343
PCB_LAYER_ID GetFirstLayer() const
Definition zone.cpp:523
void SetMinIslandArea(long long int aArea)
Definition zone.h:745
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:875
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:234
void SetHatchGap(int aStep)
Definition zone.h:319
static int GetDefaultHatchPitch()
Definition zone.cpp:1333
void SetPlacementAreaEnabled(bool aEnabled)
Definition zone.h:722
unsigned GetAssignedPriority() const
Definition zone.h:125
int GetNumCorners(void) const
Access to m_Poly parameters.
Definition zone.h:524
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:1622
ZONE_BORDER_DISPLAY_STYLE m_borderStyle
Definition zone.h:933
long long int m_minIslandArea
When island removal mode is set to AREA, islands below this area will be removed.
Definition zone.h:886
@ 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:69
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:172
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:677
@ 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:333
@ 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:1859
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:108
VECTOR2< int32_t > VECTOR2I
Definition vector2d.h:695
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