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