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