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