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>
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->mutable_width()->set_value_nm( m_thermalReliefSpokeWidth );
259 thermals->mutable_gap()->set_value_nm( 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_Poly->OutlineCount() == 0 )
326 return false;
327
328 if( m_isRuleArea )
329 {
330 const types::RuleAreaSettings& ra = zone.rule_area_settings();
331 m_doNotAllowCopperPour = ra.keepout_copper();
332 m_doNotAllowFootprints = ra.keepout_footprints();
333 m_doNotAllowPads = ra.keepout_pads();
334 m_doNotAllowTracks = ra.keepout_tracks();
335 m_doNotAllowVias = ra.keepout_vias();
336
337 m_ruleAreaPlacementEnabled = ra.placement_enabled();
338 m_ruleAreaPlacementSource = wxString::FromUTF8( ra.placement_source() );
340 FromProtoEnum<RULE_AREA_PLACEMENT_SOURCE_TYPE>( ra.placement_source_type() );
341 }
342 else
343 {
344 const types::CopperZoneSettings& cu = zone.copper_settings();
345 m_PadConnection = FromProtoEnum<ZONE_CONNECTION>( cu.connection().zone_connection() );
346 m_thermalReliefSpokeWidth = cu.connection().thermal_spokes().width().value_nm();
347 m_thermalReliefGap = cu.connection().thermal_spokes().gap().value_nm();
348 m_ZoneClearance = cu.clearance().value_nm();
349 m_ZoneMinThickness = cu.min_thickness().value_nm();
350 m_islandRemovalMode = FromProtoEnum<ISLAND_REMOVAL_MODE>( cu.island_mode() );
351 m_minIslandArea = cu.min_island_area();
352 m_fillMode = FromProtoEnum<ZONE_FILL_MODE>( cu.fill_mode() );
353
354 m_hatchThickness = cu.hatch_settings().thickness().value_nm();
355 m_hatchGap = cu.hatch_settings().gap().value_nm();
357 EDA_ANGLE( cu.hatch_settings().orientation().value_degrees(), DEGREES_T );
358 m_hatchSmoothingValue = cu.hatch_settings().hatch_smoothing_ratio();
359 m_hatchHoleMinArea = cu.hatch_settings().hatch_hole_min_area_ratio();
360
361 switch( cu.hatch_settings().border_mode() )
362 {
363 default:
364 case types::ZHFBM_USE_MIN_ZONE_THICKNESS: m_hatchBorderAlgorithm = 0; break;
365 case types::ZHFBM_USE_HATCH_THICKNESS: m_hatchBorderAlgorithm = 1; break;
366 }
367
368 SetNetCode( cu.net().code().value() );
369 m_teardropType = FromProtoEnum<TEARDROP_TYPE>( cu.teardrop().type() );
370 }
371
372 m_borderStyle = FromProtoEnum<ZONE_BORDER_DISPLAY_STYLE>( zone.border().style() );
373 m_borderHatchPitch = zone.border().pitch().value_nm();
374
375 if( zone.filled() )
376 {
377 // TODO(JE) check what else has to happen here
378 SetIsFilled( true );
379 SetNeedRefill( false );
380
381 for( const types::ZoneFilledPolygons& fillLayer : zone.filled_polygons() )
382 {
383 PCB_LAYER_ID layer = FromProtoEnum<PCB_LAYER_ID>( fillLayer.layer() );
384 SHAPE_POLY_SET shape = kiapi::common::UnpackPolySet( fillLayer.shapes() );
385 m_FilledPolysList[layer] = std::make_shared<SHAPE_POLY_SET>( shape );
386 }
387 }
388
389 HatchBorder();
390
391 return true;
392}
393
394
395bool ZONE::HigherPriority( const ZONE* aOther ) const
396{
397 // Teardrops are always higher priority than regular zones, so if one zone is a teardrop
398 // and the other is not, then return higher priority as the teardrop
399 if( ( m_teardropType == TEARDROP_TYPE::TD_NONE )
400 ^ ( aOther->m_teardropType == TEARDROP_TYPE::TD_NONE ) )
401 {
402 return static_cast<int>( m_teardropType ) > static_cast<int>( aOther->m_teardropType );
403 }
404
405 if( m_priority != aOther->m_priority )
406 return m_priority > aOther->m_priority;
407
408 return m_Uuid > aOther->m_Uuid;
409}
410
411
412bool ZONE::SameNet( const ZONE* aOther ) const
413{
414 return GetNetCode() == aOther->GetNetCode();
415}
416
417
419{
420 bool change = false;
421
422 for( std::pair<const PCB_LAYER_ID, std::shared_ptr<SHAPE_POLY_SET>>& pair : m_FilledPolysList )
423 {
424 change |= !pair.second->IsEmpty();
425 m_insulatedIslands[pair.first].clear();
426 pair.second->RemoveAllContours();
427 }
428
429 m_isFilled = false;
431
432 return change;
433}
434
435
437{
438 return HasFlag( COURTYARD_CONFLICT );
439}
440
441
443{
444 return GetCornerPosition( 0 );
445}
446
447
449{
450 if( m_layerSet.count() == 1 )
451 {
452 return GetFirstLayer();
453 }
454 return UNDEFINED_LAYER;
455}
456
457
459{
460 if( m_layerSet.count() == 0 )
461 {
462 return UNDEFINED_LAYER;
463 }
464
465 const LSEQ uiLayers = m_layerSet.UIOrder();
466
467 // This can't use m_layerSet.count() because it's possible to have a zone on
468 // a rescue layer that is not in the UI order.
469 if( uiLayers.size() )
470 {
471 return uiLayers[0];
472 }
473
474 // If it's not in the UI set at all, just return the first layer in the set.
475 // (we know the count > 0)
476 return m_layerSet.Seq()[0];
477}
478
479
481{
482 return ( m_layerSet & LSET::AllCuMask() ).count() > 0;
483}
484
485
487{
488 SetLayerSet( LSET( { aLayer } ) );
489}
490
491
492void ZONE::SetLayerSet( const LSET& aLayerSet )
493{
494 if( aLayerSet.count() == 0 )
495 return;
496
497 if( m_layerSet != aLayerSet )
498 {
499 SetNeedRefill( true );
500
501 UnFill();
502
503 m_FilledPolysList.clear();
504 m_filledPolysHash.clear();
505 m_insulatedIslands.clear();
506
507 aLayerSet.RunOnLayers(
508 [&]( PCB_LAYER_ID layer )
509 {
510 m_FilledPolysList[layer] = std::make_shared<SHAPE_POLY_SET>();
511 m_filledPolysHash[layer] = {};
512 m_insulatedIslands[layer] = {};
513 } );
514 }
515
516 m_layerSet = aLayerSet;
517}
518
519
520std::vector<int> ZONE::ViewGetLayers() const
521{
522 std::vector<int> layers;
523 layers.reserve( 2 * m_layerSet.count() + 1 );
524
526 [&]( PCB_LAYER_ID layer )
527 {
528 layers.push_back( layer );
529 layers.push_back( layer + static_cast<int>( LAYER_ZONE_START ) );
530 } );
531
532 if( IsConflicting() )
533 layers.push_back( LAYER_CONFLICTS_SHADOW );
534
535 return layers;
536}
537
538
539double ZONE::ViewGetLOD( int aLayer, const KIGFX::VIEW* aView ) const
540{
541 if( !aView )
542 return LOD_SHOW;
543
544 if( !aView->IsLayerVisible( LAYER_ZONES ) )
545 return LOD_HIDE;
546
547 if( FOOTPRINT* parentFP = GetParentFootprint() )
548 {
549 bool flipped = parentFP->GetLayer() == B_Cu;
550
551 // Handle Render tab switches
552 if( !flipped && !aView->IsLayerVisible( LAYER_FOOTPRINTS_FR ) )
553 return LOD_HIDE;
554
555 if( flipped && !aView->IsLayerVisible( LAYER_FOOTPRINTS_BK ) )
556 return LOD_HIDE;
557 }
558
559 // Other layers are shown without any conditions
560 return LOD_SHOW;
561}
562
563
564bool ZONE::IsOnLayer( PCB_LAYER_ID aLayer ) const
565{
566 return m_layerSet.test( aLayer );
567}
568
569
571{
572 if( const BOARD* board = GetBoard() )
573 {
574 std::unordered_map<const ZONE*, BOX2I>& cache = board->m_ZoneBBoxCache;
575
576 {
577 std::shared_lock<std::shared_mutex> readLock( board->m_CachesMutex );
578
579 auto cacheIter = cache.find( this );
580
581 if( cacheIter != cache.end() )
582 return cacheIter->second;
583 }
584
585 BOX2I bbox = m_Poly->BBox();
586
587 {
588 std::unique_lock<std::shared_mutex> writeLock( board->m_CachesMutex );
589 cache[ this ] = bbox;
590 }
591
592 return bbox;
593 }
594
595 return m_Poly->BBox();
596}
597
598
600{
601 // GetBoundingBox() will cache it for us, and there's no sense duplicating the somewhat tricky
602 // locking code.
604}
605
606
607int ZONE::GetThermalReliefGap( PAD* aPad, wxString* aSource ) const
608{
609 if( aPad->GetLocalThermalGapOverride() == 0 )
610 {
611 if( aSource )
612 *aSource = _( "zone" );
613
614 return m_thermalReliefGap;
615 }
616
617 return aPad->GetLocalThermalGapOverride( aSource );
618
619}
620
621
622void ZONE::SetCornerRadius( unsigned int aRadius )
623{
624 if( m_cornerRadius != aRadius )
625 SetNeedRefill( true );
626
627 m_cornerRadius = aRadius;
628}
629
630
632
633
635{
636 if( !m_filledPolysHash.count( aLayer ) )
637 return g_nullPoly.GetHash();
638 else
639 return m_filledPolysHash.at( aLayer );
640}
641
642
644{
645 if( !m_FilledPolysList.count( aLayer ) )
647 else
648 m_filledPolysHash[aLayer] = m_FilledPolysList.at( aLayer )->GetHash();
649}
650
651
652bool ZONE::HitTest( const VECTOR2I& aPosition, int aAccuracy ) const
653{
654 // When looking for an "exact" hit aAccuracy will be 0 which works poorly for very thin
655 // lines. Give it a floor.
656 int accuracy = std::max( aAccuracy, pcbIUScale.mmToIU( 0.1 ) );
657
658 return HitTestForCorner( aPosition, accuracy * 2 ) || HitTestForEdge( aPosition, accuracy );
659}
660
661
662bool ZONE::HitTestForCorner( const VECTOR2I& refPos, int aAccuracy,
663 SHAPE_POLY_SET::VERTEX_INDEX* aCornerHit ) const
664{
665 return m_Poly->CollideVertex( VECTOR2I( refPos ), aCornerHit, aAccuracy );
666}
667
668
669bool ZONE::HitTestForEdge( const VECTOR2I& refPos, int aAccuracy,
670 SHAPE_POLY_SET::VERTEX_INDEX* aCornerHit ) const
671{
672 return m_Poly->CollideEdge( VECTOR2I( refPos ), aCornerHit, aAccuracy );
673}
674
675
676bool ZONE::HitTest( const BOX2I& aRect, bool aContained, int aAccuracy ) const
677{
678 // Calculate bounding box for zone
679 BOX2I bbox = GetBoundingBox();
680 bbox.Normalize();
681
682 BOX2I arect = aRect;
683 arect.Normalize();
684 arect.Inflate( aAccuracy );
685
686 if( aContained )
687 {
688 return arect.Contains( bbox );
689 }
690 else
691 {
692 // Fast test: if aBox is outside the polygon bounding box, rectangles cannot intersect
693 if( !arect.Intersects( bbox ) )
694 return false;
695
696 int count = m_Poly->TotalVertices();
697
698 for( int ii = 0; ii < count; ii++ )
699 {
700 VECTOR2I vertex = m_Poly->CVertex( ii );
701 VECTOR2I vertexNext = m_Poly->CVertex( ( ii + 1 ) % count );
702
703 // Test if the point is within the rect
704 if( arect.Contains( vertex ) )
705 return true;
706
707 // Test if this edge intersects the rect
708 if( arect.Intersects( vertex, vertexNext ) )
709 return true;
710 }
711
712 return false;
713 }
714}
715
716
717std::optional<int> ZONE::GetLocalClearance() const
718{
719 return m_isRuleArea ? 0 : m_ZoneClearance;
720}
721
722
723bool ZONE::HitTestFilledArea( PCB_LAYER_ID aLayer, const VECTOR2I& aRefPos, int aAccuracy ) const
724{
725 // Rule areas have no filled area, but it's generally nice to treat their interior as if it were
726 // filled so that people don't have to select them by their outline (which is min-width)
727 if( GetIsRuleArea() )
728 return m_Poly->Contains( aRefPos, -1, aAccuracy );
729
730 if( !m_FilledPolysList.count( aLayer ) )
731 return false;
732
733 return m_FilledPolysList.at( aLayer )->Contains( aRefPos, -1, aAccuracy );
734}
735
736
737bool ZONE::HitTestCutout( const VECTOR2I& aRefPos, int* aOutlineIdx, int* aHoleIdx ) const
738{
739 // Iterate over each outline polygon in the zone and then iterate over
740 // each hole it has to see if the point is in it.
741 for( int i = 0; i < m_Poly->OutlineCount(); i++ )
742 {
743 for( int j = 0; j < m_Poly->HoleCount( i ); j++ )
744 {
745 if( m_Poly->Hole( i, j ).PointInside( aRefPos ) )
746 {
747 if( aOutlineIdx )
748 *aOutlineIdx = i;
749
750 if( aHoleIdx )
751 *aHoleIdx = j;
752
753 return true;
754 }
755 }
756 }
757
758 return false;
759}
760
761
762void ZONE::GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_ITEM>& aList )
763{
764 wxString msg = GetFriendlyName();
765
766 // Display Cutout instead of Outline for holes inside a zone (i.e. when num contour !=0).
767 // Check whether the selected corner is in a hole; i.e., in any contour but the first one.
768 if( m_CornerSelection != nullptr && m_CornerSelection->m_contour > 0 )
769 msg << wxT( " " ) << _( "Cutout" );
770
771 aList.emplace_back( _( "Type" ), msg );
772
773 if( GetIsRuleArea() )
774 {
775 msg.Empty();
776
777 if( GetDoNotAllowVias() )
778 AccumulateDescription( msg, _( "No vias" ) );
779
780 if( GetDoNotAllowTracks() )
781 AccumulateDescription( msg, _( "No tracks" ) );
782
783 if( GetDoNotAllowPads() )
784 AccumulateDescription( msg, _( "No pads" ) );
785
787 AccumulateDescription( msg, _( "No copper zones" ) );
788
790 AccumulateDescription( msg, _( "No footprints" ) );
791
792 if( !msg.IsEmpty() )
793 aList.emplace_back( _( "Restrictions" ), msg );
794
796 {
797 aList.emplace_back( _( "Placement source" ),
799 }
800 }
801 else if( IsOnCopperLayer() )
802 {
803 if( aFrame->GetName() == PCB_EDIT_FRAME_NAME )
804 {
805 aList.emplace_back( _( "Net" ), UnescapeString( GetNetname() ) );
806
807 aList.emplace_back( _( "Resolved Netclass" ),
808 UnescapeString( GetEffectiveNetClass()->GetHumanReadableName() ) );
809 }
810
811 // Display priority level
812 aList.emplace_back( _( "Priority" ),
813 wxString::Format( wxT( "%d" ), GetAssignedPriority() ) );
814 }
815
816 if( aFrame->GetName() == PCB_EDIT_FRAME_NAME )
817 {
818 if( IsLocked() )
819 aList.emplace_back( _( "Status" ), _( "Locked" ) );
820 }
821
822 LSEQ layers = m_layerSet.Seq();
823 wxString layerDesc;
824
825 if( layers.size() == 1 )
826 {
827 layerDesc.Printf( _( "%s" ), GetBoard()->GetLayerName( layers[0] ) );
828 }
829 else if (layers.size() == 2 )
830 {
831 layerDesc.Printf( _( "%s and %s" ),
832 GetBoard()->GetLayerName( layers[0] ),
833 GetBoard()->GetLayerName( layers[1] ) );
834 }
835 else if (layers.size() == 3 )
836 {
837 layerDesc.Printf( _( "%s, %s and %s" ),
838 GetBoard()->GetLayerName( layers[0] ),
839 GetBoard()->GetLayerName( layers[1] ),
840 GetBoard()->GetLayerName( layers[2] ) );
841 }
842 else if( layers.size() > 3 )
843 {
844 layerDesc.Printf( _( "%s, %s and %d more" ),
845 GetBoard()->GetLayerName( layers[0] ),
846 GetBoard()->GetLayerName( layers[1] ),
847 static_cast<int>( layers.size() - 2 ) );
848 }
849
850 aList.emplace_back( _( "Layer" ), layerDesc );
851
852 if( !m_zoneName.empty() )
853 aList.emplace_back( _( "Name" ), m_zoneName );
854
855 switch( m_fillMode )
856 {
857 case ZONE_FILL_MODE::POLYGONS: msg = _( "Solid" ); break;
858 case ZONE_FILL_MODE::HATCH_PATTERN: msg = _( "Hatched" ); break;
859 default: msg = _( "Unknown" ); break;
860 }
861
862 aList.emplace_back( _( "Fill Mode" ), msg );
863
864 aList.emplace_back( _( "Filled Area" ),
865 aFrame->MessageTextFromValue( m_area, true, EDA_DATA_TYPE::AREA ) );
866
867 wxString source;
868 int clearance = GetOwnClearance( UNDEFINED_LAYER, &source );
869
870 if( !source.IsEmpty() )
871 {
872 aList.emplace_back( wxString::Format( _( "Min Clearance: %s" ),
873 aFrame->MessageTextFromValue( clearance ) ),
874 wxString::Format( _( "(from %s)" ),
875 source ) );
876 }
877
878 if( !m_FilledPolysList.empty() )
879 {
880 int count = 0;
881
882 for( std::pair<const PCB_LAYER_ID, std::shared_ptr<SHAPE_POLY_SET>>& ii: m_FilledPolysList )
883 count += ii.second->TotalVertices();
884
885 aList.emplace_back( _( "Corner Count" ), wxString::Format( wxT( "%d" ), count ) );
886 }
887}
888
889
890void ZONE::Move( const VECTOR2I& offset )
891{
892 /* move outlines */
893 m_Poly->Move( offset );
894
895 HatchBorder();
896
897 /* move fills */
898 for( std::pair<const PCB_LAYER_ID, std::shared_ptr<SHAPE_POLY_SET>>& pair : m_FilledPolysList )
899 pair.second->Move( offset );
900
901 /*
902 * move boundingbox cache
903 *
904 * While the cache will get nuked at the conclusion of the operation, we use it for some
905 * things (such as drawing the parent group) during the move.
906 */
907 if( GetBoard() )
908 {
909 auto it = GetBoard()->m_ZoneBBoxCache.find( this );
910
911 if( it != GetBoard()->m_ZoneBBoxCache.end() )
912 it->second.Move( offset );
913 }
914}
915
916
917wxString ZONE::GetFriendlyName() const
918{
919 if( GetIsRuleArea() )
920 return _( "Rule Area" );
921 else if( IsTeardropArea() )
922 return _( "Teardrop Area" );
923 else if( IsOnCopperLayer() )
924 return _( "Copper Zone" );
925 else
926 return _( "Non-copper Zone" );
927}
928
929
930void ZONE::MoveEdge( const VECTOR2I& offset, int aEdge )
931{
932 int next_corner;
933
934 if( m_Poly->GetNeighbourIndexes( aEdge, nullptr, &next_corner ) )
935 {
936 m_Poly->SetVertex( aEdge, m_Poly->CVertex( aEdge ) + VECTOR2I( offset ) );
937 m_Poly->SetVertex( next_corner, m_Poly->CVertex( next_corner ) + VECTOR2I( offset ) );
938 HatchBorder();
939
940 SetNeedRefill( true );
941 }
942}
943
944
945void ZONE::Rotate( const VECTOR2I& aCentre, const EDA_ANGLE& aAngle )
946{
947 m_Poly->Rotate( aAngle, aCentre );
948 HatchBorder();
949
950 /* rotate filled areas: */
951 for( std::pair<const PCB_LAYER_ID, std::shared_ptr<SHAPE_POLY_SET>>& pair : m_FilledPolysList )
952 pair.second->Rotate( aAngle, aCentre );
953}
954
955
956void ZONE::Flip( const VECTOR2I& aCentre, FLIP_DIRECTION aFlipDirection )
957{
958 Mirror( aCentre, aFlipDirection );
959
960 std::map<PCB_LAYER_ID, SHAPE_POLY_SET> fillsCopy;
961
962 for( auto& [oldLayer, shapePtr] : m_FilledPolysList )
963 {
964 fillsCopy[oldLayer] = *shapePtr;
965 }
966
967 SetLayerSet( GetLayerSet().Flip( GetBoard()->GetCopperLayerCount() ) );
968
969 for( auto& [oldLayer, shape] : fillsCopy )
970 {
971 PCB_LAYER_ID newLayer = GetBoard()->FlipLayer( oldLayer );
972 SetFilledPolysList( newLayer, shape );
973 }
974}
975
976
977void ZONE::Mirror( const VECTOR2I& aMirrorRef, FLIP_DIRECTION aFlipDirection )
978{
979 m_Poly->Mirror( aMirrorRef, aFlipDirection );
980
981 HatchBorder();
982
983 for( std::pair<const PCB_LAYER_ID, std::shared_ptr<SHAPE_POLY_SET>>& pair : m_FilledPolysList )
984 pair.second->Mirror( aMirrorRef, aFlipDirection );
985}
986
987
988void ZONE::RemoveCutout( int aOutlineIdx, int aHoleIdx )
989{
990 // Ensure the requested cutout is valid
991 if( m_Poly->OutlineCount() < aOutlineIdx || m_Poly->HoleCount( aOutlineIdx ) < aHoleIdx )
992 return;
993
994 SHAPE_POLY_SET cutPoly( m_Poly->Hole( aOutlineIdx, aHoleIdx ) );
995
996 // Add the cutout back to the zone
997 m_Poly->BooleanAdd( cutPoly );
998
999 SetNeedRefill( true );
1000}
1001
1002
1003void ZONE::AddPolygon( const SHAPE_LINE_CHAIN& aPolygon )
1004{
1005 wxASSERT( aPolygon.IsClosed() );
1006
1007 // Add the outline as a new polygon in the polygon set
1008 if( m_Poly->OutlineCount() == 0 )
1009 m_Poly->AddOutline( aPolygon );
1010 else
1011 m_Poly->AddHole( aPolygon );
1012
1013 SetNeedRefill( true );
1014}
1015
1016
1017void ZONE::AddPolygon( std::vector<VECTOR2I>& aPolygon )
1018{
1019 if( aPolygon.empty() )
1020 return;
1021
1022 SHAPE_LINE_CHAIN outline;
1023
1024 // Create an outline and populate it with the points of aPolygon
1025 for( const VECTOR2I& pt : aPolygon )
1026 outline.Append( pt );
1027
1028 outline.SetClosed( true );
1029
1030 AddPolygon( outline );
1031}
1032
1033
1034bool ZONE::AppendCorner( VECTOR2I aPosition, int aHoleIdx, bool aAllowDuplication )
1035{
1036 // Ensure the main outline exists:
1037 if( m_Poly->OutlineCount() == 0 )
1038 m_Poly->NewOutline();
1039
1040 // If aHoleIdx >= 0, the corner musty be added to the hole, index aHoleIdx.
1041 // (remember: the index of the first hole is 0)
1042 // Return error if it does not exist.
1043 if( aHoleIdx >= m_Poly->HoleCount( 0 ) )
1044 return false;
1045
1046 m_Poly->Append( aPosition.x, aPosition.y, -1, aHoleIdx, aAllowDuplication );
1047
1048 SetNeedRefill( true );
1049
1050 return true;
1051}
1052
1053
1054wxString ZONE::GetItemDescription( UNITS_PROVIDER* aUnitsProvider, bool aFull ) const
1055{
1056 LSEQ layers = m_layerSet.Seq();
1057 wxString layerDesc;
1058
1059 if( layers.size() == 1 )
1060 {
1061 layerDesc.Printf( _( "on %s" ), GetBoard()->GetLayerName( layers[0] ) );
1062 }
1063 else if (layers.size() == 2 )
1064 {
1065 layerDesc.Printf( _( "on %s and %s" ),
1066 GetBoard()->GetLayerName( layers[0] ),
1067 GetBoard()->GetLayerName( layers[1] ) );
1068 }
1069 else if (layers.size() == 3 )
1070 {
1071 layerDesc.Printf( _( "on %s, %s and %s" ),
1072 GetBoard()->GetLayerName( layers[0] ),
1073 GetBoard()->GetLayerName( layers[1] ),
1074 GetBoard()->GetLayerName( layers[2] ) );
1075 }
1076 else if( layers.size() > 3 )
1077 {
1078 layerDesc.Printf( _( "on %s, %s and %zu more" ),
1079 GetBoard()->GetLayerName( layers[0] ),
1080 GetBoard()->GetLayerName( layers[1] ),
1081 layers.size() - 2 );
1082 }
1083
1084 // Check whether the selected contour is a hole (contour index > 0)
1085 if( m_CornerSelection != nullptr && m_CornerSelection->m_contour > 0 )
1086 {
1087 if( GetIsRuleArea() )
1088 return wxString::Format( _( "Rule Area Cutout %s" ), layerDesc );
1089 else
1090 return wxString::Format( _( "Zone Cutout %s" ), layerDesc );
1091 }
1092 else
1093 {
1094 if( GetIsRuleArea() )
1095 return wxString::Format( _( "Rule Area %s" ), layerDesc );
1096 else if( IsTeardropArea() )
1097 return wxString::Format( _( "Teardrop %s %s" ), GetNetnameMsg(), layerDesc );
1098 else
1099 return wxString::Format( _( "Zone %s %s" ), GetNetnameMsg(), layerDesc );
1100 }
1101}
1102
1103
1105{
1106 return m_borderHatchPitch;
1107}
1108
1109
1111 int aBorderHatchPitch, bool aRebuildBorderHatch )
1112{
1113 aBorderHatchPitch = std::max( aBorderHatchPitch,
1115 aBorderHatchPitch = std::min( aBorderHatchPitch,
1117 SetBorderHatchPitch( aBorderHatchPitch );
1118 m_borderStyle = aBorderHatchStyle;
1119
1120 if( aRebuildBorderHatch )
1121 HatchBorder();
1122}
1123
1124
1126{
1127 m_borderHatchPitch = aPitch;
1128}
1129
1130
1132{
1133 m_borderHatchLines.clear();
1134}
1135
1136
1137// Creates hatch lines inside the outline of the complex polygon
1138// sort function used in ::HatchBorder to sort points by descending VECTOR2I.x values
1139bool sortEndsByDescendingX( const VECTOR2I& ref, const VECTOR2I& tst )
1140{
1141 return tst.x < ref.x;
1142}
1143
1144
1146{
1147 UnHatchBorder();
1148
1149 if( m_borderStyle == ZONE_BORDER_DISPLAY_STYLE::NO_HATCH
1150 || m_borderHatchPitch == 0
1151 || m_Poly->IsEmpty() )
1152 {
1153 return;
1154 }
1155
1156 // define range for hatch lines
1157 int min_x = m_Poly->CVertex( 0 ).x;
1158 int max_x = m_Poly->CVertex( 0 ).x;
1159 int min_y = m_Poly->CVertex( 0 ).y;
1160 int max_y = m_Poly->CVertex( 0 ).y;
1161
1162 for( auto iterator = m_Poly->IterateWithHoles(); iterator; iterator++ )
1163 {
1164 if( iterator->x < min_x )
1165 min_x = iterator->x;
1166
1167 if( iterator->x > max_x )
1168 max_x = iterator->x;
1169
1170 if( iterator->y < min_y )
1171 min_y = iterator->y;
1172
1173 if( iterator->y > max_y )
1174 max_y = iterator->y;
1175 }
1176
1177 // Calculate spacing between 2 hatch lines
1178 int spacing;
1179
1180 if( m_borderStyle == ZONE_BORDER_DISPLAY_STYLE::DIAGONAL_EDGE )
1181 spacing = m_borderHatchPitch;
1182 else
1183 spacing = m_borderHatchPitch * 2;
1184
1185 // set the "length" of hatch lines (the length on horizontal axis)
1186 int hatch_line_len = m_borderHatchPitch;
1187
1188 // To have a better look, give a slope depending on the layer
1189 int layer = GetFirstLayer();
1190 std::vector<int> slope_flags;
1191
1192 if( IsTeardropArea() )
1193 slope_flags = { 1, -1 };
1194 else if( layer & 1 )
1195 slope_flags = { 1 };
1196 else
1197 slope_flags = { -1 };
1198
1199 for( int slope_flag : slope_flags )
1200 {
1201 double slope = 0.707106 * slope_flag; // 45 degrees slope
1202 int64_t max_a, min_a;
1203
1204 if( slope_flag == 1 )
1205 {
1206 max_a = KiROUND<double, int64_t>( max_y - slope * min_x );
1207 min_a = KiROUND<double, int64_t>( min_y - slope * max_x );
1208 }
1209 else
1210 {
1211 max_a = KiROUND<double, int64_t>( max_y - slope * max_x );
1212 min_a = KiROUND<double, int64_t>( min_y - slope * min_x );
1213 }
1214
1215 min_a = (min_a / spacing) * spacing;
1216
1217 // calculate an offset depending on layer number,
1218 // for a better look of hatches on a multilayer board
1219 int offset = (layer * 7) / 8;
1220 min_a += offset;
1221
1222 // loop through hatch lines
1223 std::vector<VECTOR2I> pointbuffer;
1224 pointbuffer.reserve( 256 );
1225
1226 for( int64_t a = min_a; a < max_a; a += spacing )
1227 {
1228 pointbuffer.clear();
1229
1230 // Iterate through all vertices
1231 for( auto iterator = m_Poly->IterateSegmentsWithHoles(); iterator; iterator++ )
1232 {
1233 const SEG seg = *iterator;
1234 double x, y;
1235
1236 if( FindLineSegmentIntersection( a, slope, seg.A.x, seg.A.y, seg.B.x, seg.B.y, x, y ) )
1237 pointbuffer.emplace_back( KiROUND( x ), KiROUND( y ) );
1238 }
1239
1240 // sort points in order of descending x (if more than 2) to
1241 // ensure the starting point and the ending point of the same segment
1242 // are stored one just after the other.
1243 if( pointbuffer.size() > 2 )
1244 sort( pointbuffer.begin(), pointbuffer.end(), sortEndsByDescendingX );
1245
1246 // creates lines or short segments inside the complex polygon
1247 for( size_t ip = 0; ip + 1 < pointbuffer.size(); ip += 2 )
1248 {
1249 int dx = pointbuffer[ip + 1].x - pointbuffer[ip].x;
1250
1251 // Push only one line for diagonal hatch,
1252 // or for small lines < twice the line length
1253 // else push 2 small lines
1254 if( m_borderStyle == ZONE_BORDER_DISPLAY_STYLE::DIAGONAL_FULL
1255 || std::abs( dx ) < 2 * hatch_line_len )
1256 {
1257 m_borderHatchLines.emplace_back( SEG( pointbuffer[ip], pointbuffer[ ip + 1] ) );
1258 }
1259 else
1260 {
1261 double dy = pointbuffer[ip + 1].y - pointbuffer[ip].y;
1262 slope = dy / dx;
1263
1264 if( dx > 0 )
1265 dx = hatch_line_len;
1266 else
1267 dx = -hatch_line_len;
1268
1269 int x1 = KiROUND( pointbuffer[ip].x + dx );
1270 int x2 = KiROUND( pointbuffer[ip + 1].x - dx );
1271 int y1 = KiROUND( pointbuffer[ip].y + dx * slope );
1272 int y2 = KiROUND( pointbuffer[ip + 1].y - dx * slope );
1273
1274 m_borderHatchLines.emplace_back( SEG( pointbuffer[ip].x, pointbuffer[ip].y,
1275 x1, y1 ) );
1276
1277 m_borderHatchLines.emplace_back( SEG( pointbuffer[ip+1].x, pointbuffer[ip+1].y,
1278 x2, y2 ) );
1279 }
1280 }
1281 }
1282 }
1283}
1284
1285
1287{
1289}
1290
1291
1293{
1294 return BITMAPS::add_zone;
1295}
1296
1297
1299{
1300 assert( aImage->Type() == PCB_ZONE_T );
1301
1302 std::swap( *static_cast<ZONE*>( this ), *static_cast<ZONE*>( aImage) );
1303}
1304
1305
1307{
1308 if( aLayer == UNDEFINED_LAYER )
1309 {
1310 for( auto& [ layer, poly ] : m_FilledPolysList )
1311 poly->CacheTriangulation();
1312
1313 m_Poly->CacheTriangulation( false );
1314 }
1315 else
1316 {
1317 if( m_FilledPolysList.count( aLayer ) )
1318 m_FilledPolysList[ aLayer ]->CacheTriangulation();
1319 }
1320}
1321
1322
1323bool ZONE::IsIsland( PCB_LAYER_ID aLayer, int aPolyIdx ) const
1324{
1325 if( GetNetCode() < 1 )
1326 return true;
1327
1328 if( !m_insulatedIslands.count( aLayer ) )
1329 return false;
1330
1331 return m_insulatedIslands.at( aLayer ).count( aPolyIdx );
1332}
1333
1334
1335void ZONE::GetInteractingZones( PCB_LAYER_ID aLayer, std::vector<ZONE*>* aSameNetCollidingZones,
1336 std::vector<ZONE*>* aOtherNetIntersectingZones ) const
1337{
1338 int epsilon = pcbIUScale.mmToIU( 0.001 );
1339 BOX2I bbox = GetBoundingBox();
1340
1341 bbox.Inflate( epsilon );
1342
1343 for( ZONE* candidate : GetBoard()->Zones() )
1344 {
1345 if( candidate == this )
1346 continue;
1347
1348 if( !candidate->GetLayerSet().test( aLayer ) )
1349 continue;
1350
1351 if( candidate->GetIsRuleArea() || candidate->IsTeardropArea() )
1352 continue;
1353
1354 if( !candidate->GetBoundingBox().Intersects( bbox ) )
1355 continue;
1356
1357 if( candidate->GetNetCode() == GetNetCode() )
1358 {
1359 if( m_Poly->Collide( candidate->m_Poly ) )
1360 aSameNetCollidingZones->push_back( candidate );
1361 }
1362 else
1363 {
1364 aOtherNetIntersectingZones->push_back( candidate );
1365 }
1366 }
1367}
1368
1369
1371 SHAPE_POLY_SET* aBoardOutline,
1372 SHAPE_POLY_SET* aSmoothedPolyWithApron ) const
1373{
1374 if( GetNumCorners() <= 2 ) // malformed zone. polygon calculations will not like it ...
1375 return false;
1376
1377 // Processing of arc shapes in zones is not yet supported because Clipper can't do boolean
1378 // operations on them. The poly outline must be converted to segments first.
1380 flattened.ClearArcs();
1381
1382 if( GetIsRuleArea() )
1383 {
1384 // We like keepouts just the way they are....
1385 aSmoothedPoly = flattened;
1386 return true;
1387 }
1388
1389 const BOARD* board = GetBoard();
1390 int maxError = ARC_HIGH_DEF;
1391 bool keepExternalFillets = false;
1394
1395 if( IsTeardropArea() )
1396 {
1397 // We use teardrop shapes with no smoothing; these shapes are already optimized
1398 smooth_requested = false;
1399 }
1400
1401 if( board )
1402 {
1404
1405 maxError = bds.m_MaxError;
1406 keepExternalFillets = bds.m_ZoneKeepExternalFillets;
1407 }
1408
1409 auto smooth =
1410 [&]( SHAPE_POLY_SET& aPoly )
1411 {
1412 if( !smooth_requested )
1413 return;
1414
1415 switch( m_cornerSmoothingType )
1416 {
1418 aPoly = aPoly.Chamfer( (int) m_cornerRadius );
1419 break;
1420
1422 aPoly = aPoly.Fillet( (int) m_cornerRadius, maxError );
1423 break;
1424
1425 default:
1426 break;
1427 }
1428 };
1429
1430 SHAPE_POLY_SET* maxExtents = &flattened;
1431 SHAPE_POLY_SET withFillets;
1432
1433 aSmoothedPoly = flattened;
1434
1435 // Should external fillets (that is, those applied to concave corners) be kept? While it
1436 // seems safer to never have copper extend outside the zone outline, 5.1.x and prior did
1437 // indeed fill them so we leave the mode available.
1438 if( keepExternalFillets && smooth_requested )
1439 {
1440 withFillets = flattened;
1441 smooth( withFillets );
1442 withFillets.BooleanAdd( flattened );
1443 maxExtents = &withFillets;
1444 }
1445
1446 // We now add in the areas of any same-net, intersecting zones. This keeps us from smoothing
1447 // corners at an intersection (which often produces undesired divots between the intersecting
1448 // zones -- see #2752).
1449 //
1450 // After smoothing, we'll subtract back out everything outside of our zone.
1451 std::vector<ZONE*> sameNetCollidingZones;
1452 std::vector<ZONE*> diffNetIntersectingZones;
1453 GetInteractingZones( aLayer, &sameNetCollidingZones, &diffNetIntersectingZones );
1454
1455 for( ZONE* sameNetZone : sameNetCollidingZones )
1456 {
1457 BOX2I sameNetBoundingBox = sameNetZone->GetBoundingBox();
1458
1459 // Note: a two-pass algorithm could use sameNetZone's actual fill instead of its outline.
1460 // This would obviate the need for the below wrinkles, in addition to fixing both issues
1461 // in #16095.
1462 // (And we wouldn't need to collect all the diffNetIntersectingZones either.)
1463
1464 SHAPE_POLY_SET sameNetPoly = sameNetZone->Outline()->CloneDropTriangulation();
1465 SHAPE_POLY_SET diffNetPoly;
1466
1467 // Of course there's always a wrinkle. The same-net intersecting zone *might* get knocked
1468 // out along the border by a higher-priority, different-net zone. #12797
1469 for( ZONE* diffNetZone : diffNetIntersectingZones )
1470 {
1471 if( diffNetZone->HigherPriority( sameNetZone )
1472 && diffNetZone->GetBoundingBox().Intersects( sameNetBoundingBox ) )
1473 {
1474 diffNetPoly.BooleanAdd( *diffNetZone->Outline() );
1475 }
1476 }
1477
1478 // Second wrinkle. After unioning the higher priority, different net zones together, we
1479 // need to check to see if they completely enclose our zone. If they do, then we need to
1480 // treat the enclosed zone as isolated, not connected to the outer zone. #13915
1481 bool isolated = false;
1482
1483 if( diffNetPoly.OutlineCount() )
1484 {
1486
1487 thisPoly.BooleanSubtract( diffNetPoly );
1488 isolated = thisPoly.OutlineCount() == 0;
1489 }
1490
1491 if( !isolated )
1492 {
1493 sameNetPoly.ClearArcs();
1494 aSmoothedPoly.BooleanAdd( sameNetPoly );
1495 }
1496 }
1497
1498 if( aBoardOutline )
1499 aSmoothedPoly.BooleanIntersection( *aBoardOutline );
1500
1501 SHAPE_POLY_SET withSameNetIntersectingZones = aSmoothedPoly.CloneDropTriangulation();
1502
1503 smooth( aSmoothedPoly );
1504
1505 if( aSmoothedPolyWithApron )
1506 {
1507 // The same-net intersecting-zone code above makes sure the corner-smoothing algorithm
1508 // doesn't produce divots. But the min-thickness algorithm applied in fillCopperZone()
1509 // is *also* going to perform a deflate/inflate cycle, again leading to divots. So we
1510 // pre-inflate the contour by the min-thickness within the same-net-intersecting-zones
1511 // envelope.
1512 SHAPE_POLY_SET poly = maxExtents->CloneDropTriangulation();
1513 poly.Inflate( m_ZoneMinThickness, CORNER_STRATEGY::ROUND_ALL_CORNERS, maxError );
1514
1515 if( !keepExternalFillets )
1516 poly.BooleanIntersection( withSameNetIntersectingZones );
1517
1518 *aSmoothedPolyWithApron = aSmoothedPoly;
1519 aSmoothedPolyWithApron->BooleanIntersection( poly );
1520 }
1521
1522 aSmoothedPoly.BooleanIntersection( *maxExtents );
1523
1524 return true;
1525}
1526
1527
1529{
1530 m_area = 0.0;
1531
1532 // Iterate over each outline polygon in the zone and then iterate over
1533 // each hole it has to compute the total area.
1534 for( std::pair<const PCB_LAYER_ID, std::shared_ptr<SHAPE_POLY_SET>>& pair : m_FilledPolysList )
1535 {
1536 std::shared_ptr<SHAPE_POLY_SET>& poly = pair.second;
1537
1538 for( int i = 0; i < poly->OutlineCount(); i++ )
1539 {
1540 m_area += poly->Outline( i ).Area();
1541
1542 for( int j = 0; j < poly->HoleCount( i ); j++ )
1543 m_area -= poly->Hole( i, j ).Area();
1544 }
1545 }
1546
1547 return m_area;
1548}
1549
1550
1552{
1554 return m_outlinearea;
1555}
1556
1557
1559 int aMaxError, ERROR_LOC aErrorLoc,
1560 SHAPE_POLY_SET* aBoardOutline ) const
1561{
1562 // Creates the zone outline polygon (with holes if any)
1563 SHAPE_POLY_SET polybuffer;
1564
1565 // TODO: using GetFirstLayer() means it only works for single-layer zones....
1566 BuildSmoothedPoly( polybuffer, GetFirstLayer(), aBoardOutline );
1567
1568 // Calculate the polygon with clearance
1569 // holes are linked to the main outline, so only one polygon is created.
1570 if( aClearance )
1571 {
1572 const BOARD* board = GetBoard();
1573 int maxError = ARC_HIGH_DEF;
1574
1575 if( board )
1576 maxError = board->GetDesignSettings().m_MaxError;
1577
1578 if( aErrorLoc == ERROR_OUTSIDE )
1579 aClearance += maxError;
1580
1581 polybuffer.Inflate( aClearance, CORNER_STRATEGY::ROUND_ALL_CORNERS, maxError );
1582 }
1583
1584 polybuffer.Fracture();
1585 aBuffer.Append( polybuffer );
1586}
1587
1588
1589std::shared_ptr<SHAPE> ZONE::GetEffectiveShape( PCB_LAYER_ID aLayer, FLASHING aFlash ) const
1590{
1591 if( m_FilledPolysList.find( aLayer ) == m_FilledPolysList.end() )
1592 return std::make_shared<SHAPE_NULL>();
1593 else
1594 return m_FilledPolysList.at( aLayer );
1595}
1596
1597
1598void ZONE::TransformShapeToPolygon( SHAPE_POLY_SET& aBuffer, PCB_LAYER_ID aLayer, int aClearance,
1599 int aError, ERROR_LOC aErrorLoc, bool aIgnoreLineWidth ) const
1600{
1601 wxASSERT_MSG( !aIgnoreLineWidth, wxT( "IgnoreLineWidth has no meaning for zones." ) );
1602
1603 if( !m_FilledPolysList.count( aLayer ) )
1604 return;
1605
1606 if( !aClearance )
1607 {
1608 aBuffer.Append( *m_FilledPolysList.at( aLayer ) );
1609 return;
1610 }
1611
1612 SHAPE_POLY_SET temp_buf = m_FilledPolysList.at( aLayer )->CloneDropTriangulation();
1613
1614 // Rebuild filled areas only if clearance is not 0
1615 if( aClearance > 0 || aErrorLoc == ERROR_OUTSIDE )
1616 {
1617 if( aErrorLoc == ERROR_OUTSIDE )
1618 aClearance += aError;
1619
1620 temp_buf.InflateWithLinkedHoles( aClearance, CORNER_STRATEGY::ROUND_ALL_CORNERS, aError );
1621 }
1622
1623 aBuffer.Append( temp_buf );
1624}
1625
1626
1628{
1629 if( m_FilledPolysList.count( aLayer ) && !m_FilledPolysList.at( aLayer )->IsEmpty() )
1630 aBuffer.Append( *m_FilledPolysList.at( aLayer ) );
1631}
1632
1633
1635{
1636 if( aLayerSet.count() == 0 )
1637 return;
1638
1639 if( m_layerSet != aLayerSet )
1640 {
1641 aLayerSet.RunOnLayers(
1642 [&]( PCB_LAYER_ID layer )
1643 {
1644 // Only keep layers that are present in the new set
1645 if( !aLayerSet.Contains( layer ) )
1646 {
1647 m_FilledPolysList[layer] = std::make_shared<SHAPE_POLY_SET>();
1648 m_filledPolysHash[layer] = {};
1649 m_insulatedIslands[layer] = {};
1650 }
1651 } );
1652 }
1653
1654 m_layerSet = aLayerSet;
1655}
1656
1657
1658bool ZONE::operator==( const BOARD_ITEM& aOther ) const
1659{
1660 if( aOther.Type() != Type() )
1661 return false;
1662
1663 const ZONE& other = static_cast<const ZONE&>( aOther );
1664 return *this == other;
1665}
1666
1667
1668bool ZONE::operator==( const ZONE& aOther ) const
1669
1670{
1671 if( aOther.Type() != Type() )
1672 return false;
1673
1674 const ZONE& other = static_cast<const ZONE&>( aOther );
1675
1676 if( GetIsRuleArea() != other.GetIsRuleArea() )
1677 return false;
1678
1679 if( GetIsRuleArea() )
1680 {
1682 return false;
1683
1684 if( GetDoNotAllowTracks() != other.GetDoNotAllowTracks() )
1685 return false;
1686
1687 if( GetDoNotAllowVias() != other.GetDoNotAllowVias() )
1688 return false;
1689
1691 return false;
1692
1693 if( GetDoNotAllowPads() != other.GetDoNotAllowPads() )
1694 return false;
1695
1697 return false;
1698
1700 return false;
1701
1703 return false;
1704 }
1705 else
1706 {
1707 if( GetAssignedPriority() != other.GetAssignedPriority() )
1708 return false;
1709
1710 if( GetMinThickness() != other.GetMinThickness() )
1711 return false;
1712
1714 return false;
1715
1716 if( GetCornerRadius() != other.GetCornerRadius() )
1717 return false;
1718
1719 if( GetTeardropParams() != other.GetTeardropParams() )
1720 return false;
1721 }
1722
1723 if( GetNumCorners() != other.GetNumCorners() )
1724 return false;
1725
1726 for( int ii = 0; ii < GetNumCorners(); ii++ )
1727 {
1728 if( GetCornerPosition( ii ) != other.GetCornerPosition( ii ) )
1729 return false;
1730 }
1731
1732 return true;
1733}
1734
1735
1736double ZONE::Similarity( const BOARD_ITEM& aOther ) const
1737{
1738 if( aOther.Type() != Type() )
1739 return 0.0;
1740
1741 const ZONE& other = static_cast<const ZONE&>( aOther );
1742
1743 if( GetIsRuleArea() != other.GetIsRuleArea() )
1744 return 0.0;
1745
1746 double similarity = 1.0;
1747
1748 if( GetLayerSet() != other.GetLayerSet() )
1749 similarity *= 0.9;
1750
1751 if( GetNetCode() != other.GetNetCode() )
1752 similarity *= 0.9;
1753
1754 if( !GetIsRuleArea() )
1755 {
1756 if( GetAssignedPriority() != other.GetAssignedPriority() )
1757 similarity *= 0.9;
1758
1759 if( GetMinThickness() != other.GetMinThickness() )
1760 similarity *= 0.9;
1761
1763 similarity *= 0.9;
1764
1765 if( GetCornerRadius() != other.GetCornerRadius() )
1766 similarity *= 0.9;
1767
1768 if( GetTeardropParams() != other.GetTeardropParams() )
1769 similarity *= 0.9;
1770 }
1771 else
1772 {
1774 similarity *= 0.9;
1775 if( GetDoNotAllowTracks() != other.GetDoNotAllowTracks() )
1776 similarity *= 0.9;
1777 if( GetDoNotAllowVias() != other.GetDoNotAllowVias() )
1778 similarity *= 0.9;
1780 similarity *= 0.9;
1781 if( GetDoNotAllowPads() != other.GetDoNotAllowPads() )
1782 similarity *= 0.9;
1783 }
1784
1785 std::vector<VECTOR2I> corners;
1786 std::vector<VECTOR2I> otherCorners;
1787 VECTOR2I lastCorner( 0, 0 );
1788
1789 for( int ii = 0; ii < GetNumCorners(); ii++ )
1790 {
1791 corners.push_back( lastCorner - GetCornerPosition( ii ) );
1792 lastCorner = GetCornerPosition( ii );
1793 }
1794
1795 lastCorner = VECTOR2I( 0, 0 );
1796 for( int ii = 0; ii < other.GetNumCorners(); ii++ )
1797 {
1798 otherCorners.push_back( lastCorner - other.GetCornerPosition( ii ) );
1799 lastCorner = other.GetCornerPosition( ii );
1800 }
1801
1802 size_t longest = alg::longest_common_subset( corners, otherCorners );
1803
1804 similarity *= std::pow( 0.9, GetNumCorners() + other.GetNumCorners() - 2 * longest );
1805
1806 return similarity;
1807}
1808
1809
1810static struct ZONE_DESC
1811{
1813 {
1815
1816 if( layerEnum.Choices().GetCount() == 0 )
1817 {
1818 layerEnum.Undefined( UNDEFINED_LAYER );
1819
1820 for( PCB_LAYER_ID layer : LSET::AllLayersMask().Seq() )
1821 layerEnum.Map( layer, LSET::Name( layer ) );
1822 }
1823
1825
1826 if( zcMap.Choices().GetCount() == 0 )
1827 {
1828 zcMap.Undefined( ZONE_CONNECTION::INHERITED );
1829 zcMap.Map( ZONE_CONNECTION::INHERITED, _HKI( "Inherited" ) )
1830 .Map( ZONE_CONNECTION::NONE, _HKI( "None" ) )
1831 .Map( ZONE_CONNECTION::THERMAL, _HKI( "Thermal reliefs" ) )
1832 .Map( ZONE_CONNECTION::FULL, _HKI( "Solid" ) )
1833 .Map( ZONE_CONNECTION::THT_THERMAL, _HKI( "Thermal reliefs for PTH" ) );
1834 }
1835
1837
1838 if( zfmMap.Choices().GetCount() == 0 )
1839 {
1840 zfmMap.Undefined( ZONE_FILL_MODE::POLYGONS );
1841 zfmMap.Map( ZONE_FILL_MODE::POLYGONS, _HKI( "Solid fill" ) )
1842 .Map( ZONE_FILL_MODE::HATCH_PATTERN, _HKI( "Hatch pattern" ) );
1843 }
1844
1846
1847 if( irmMap.Choices().GetCount() == 0 )
1848 {
1849 irmMap.Undefined( ISLAND_REMOVAL_MODE::ALWAYS );
1850 irmMap.Map( ISLAND_REMOVAL_MODE::ALWAYS, _HKI( "Always" ) )
1851 .Map( ISLAND_REMOVAL_MODE::NEVER, _HKI( "Never" ) )
1852 .Map( ISLAND_REMOVAL_MODE::AREA, _HKI( "Below area limit" ) );
1853 }
1854
1857
1858 if( rapstMap.Choices().GetCount() == 0 )
1859 {
1860 rapstMap.Undefined( RULE_AREA_PLACEMENT_SOURCE_TYPE::SHEETNAME );
1861 rapstMap.Map( RULE_AREA_PLACEMENT_SOURCE_TYPE::SHEETNAME, _HKI( "Sheet Name" ) )
1862 .Map( RULE_AREA_PLACEMENT_SOURCE_TYPE::COMPONENT_CLASS,
1863 _HKI( "Component Class" ) );
1864 }
1865
1869
1870 // Mask layer and position properties; they aren't useful in current form
1871 auto posX = new PROPERTY<ZONE, int>( _HKI( "Position X" ), NO_SETTER( ZONE, int ),
1872 static_cast<int ( ZONE::* )() const>( &ZONE::GetX ),
1873 PROPERTY_DISPLAY::PT_COORD,
1875 posX->SetIsHiddenFromPropertiesManager();
1876
1877 auto posY = new PROPERTY<ZONE, int>( _HKI( "Position Y" ), NO_SETTER( ZONE, int ),
1878 static_cast<int ( ZONE::* )() const>( &ZONE::GetY ),
1879 PROPERTY_DISPLAY::PT_COORD,
1881 posY->SetIsHiddenFromPropertiesManager();
1882
1883 propMgr.ReplaceProperty( TYPE_HASH( BOARD_ITEM ), _HKI( "Position X" ), posX );
1884 propMgr.ReplaceProperty( TYPE_HASH( BOARD_ITEM ), _HKI( "Position Y" ), posY );
1885
1886 auto isCopperZone =
1887 []( INSPECTABLE* aItem ) -> bool
1888 {
1889 if( ZONE* zone = dynamic_cast<ZONE*>( aItem ) )
1890 return !zone->GetIsRuleArea() && IsCopperLayer( zone->GetFirstLayer() );
1891
1892 return false;
1893 };
1894
1895 auto isRuleArea =
1896 []( INSPECTABLE* aItem ) -> bool
1897 {
1898 if( ZONE* zone = dynamic_cast<ZONE*>( aItem ) )
1899 return zone->GetIsRuleArea();
1900
1901 return false;
1902 };
1903
1904 auto isHatchedFill =
1905 []( INSPECTABLE* aItem ) -> bool
1906 {
1907 if( ZONE* zone = dynamic_cast<ZONE*>( aItem ) )
1908 return zone->GetFillMode() == ZONE_FILL_MODE::HATCH_PATTERN;
1909
1910 return false;
1911 };
1912
1913 auto isAreaBasedIslandRemoval =
1914 []( INSPECTABLE* aItem ) -> bool
1915 {
1916 if( ZONE* zone = dynamic_cast<ZONE*>( aItem ) )
1917 return zone->GetIslandRemovalMode() == ISLAND_REMOVAL_MODE::AREA;
1918
1919 return false;
1920 };
1921
1922 // Layer property is hidden because it only holds a single layer and zones actually use
1923 // a layer set
1924 propMgr.ReplaceProperty( TYPE_HASH( BOARD_CONNECTED_ITEM ), _HKI( "Layer" ),
1927 &ZONE::GetLayer ) )
1928 .SetIsHiddenFromPropertiesManager();
1929
1931 _HKI( "Net" ), isCopperZone );
1933 _HKI( "Net Class" ), isCopperZone );
1934
1935 propMgr.AddProperty( new PROPERTY<ZONE, unsigned>( _HKI( "Priority" ),
1937 .SetAvailableFunc( isCopperZone );
1938
1939 propMgr.AddProperty( new PROPERTY<ZONE, wxString>( _HKI( "Name" ),
1941
1942 const wxString groupKeepout = _HKI( "Keepout" );
1943
1944 propMgr.AddProperty( new PROPERTY<ZONE, bool>( _HKI( "Keep Out Tracks" ),
1947 groupKeepout )
1948 .SetAvailableFunc( isRuleArea );
1949
1950 propMgr.AddProperty( new PROPERTY<ZONE, bool>( _HKI( "Keep Out Vias" ),
1953 groupKeepout )
1954 .SetAvailableFunc( isRuleArea );
1955
1956 propMgr.AddProperty( new PROPERTY<ZONE, bool>( _HKI( "Keep Out Pads" ),
1959 groupKeepout )
1960 .SetAvailableFunc( isRuleArea );
1961
1962 propMgr.AddProperty( new PROPERTY<ZONE, bool>( _HKI( "Keep Out Copper Pours" ),
1965 groupKeepout )
1966 .SetAvailableFunc( isRuleArea );
1967
1968 propMgr.AddProperty( new PROPERTY<ZONE, bool>( _HKI( "Keep Out Footprints" ),
1971 groupKeepout )
1972 .SetAvailableFunc( isRuleArea );
1973
1974
1975 const wxString groupPlacement = _HKI( "Placement" );
1976
1977 propMgr.AddProperty( new PROPERTY<ZONE, bool>( _HKI( "Enable" ),
1980 groupPlacement )
1981 .SetAvailableFunc( isRuleArea );
1982
1984 _HKI( "Source Type" ), &ZONE::SetRuleAreaPlacementSourceType,
1986 groupPlacement )
1987 .SetAvailableFunc( isRuleArea );
1988
1989 propMgr.AddProperty( new PROPERTY<ZONE, wxString>( _HKI( "Source Name" ),
1992 groupPlacement )
1993 .SetAvailableFunc( isRuleArea );
1994
1995
1996 const wxString groupFill = _HKI( "Fill Style" );
1997
1998 propMgr.AddProperty( new PROPERTY_ENUM<ZONE, ZONE_FILL_MODE>( _HKI( "Fill Mode" ),
2000 groupFill )
2001 .SetAvailableFunc( isCopperZone );
2002
2003 propMgr.AddProperty( new PROPERTY<ZONE, EDA_ANGLE>( _HKI( "Orientation" ),
2005 PROPERTY_DISPLAY::PT_DEGREE ),
2006 groupFill )
2007 .SetAvailableFunc( isCopperZone )
2008 .SetWriteableFunc( isHatchedFill );
2009
2010 // TODO: Switch to translated
2011 auto atLeastMinWidthValidator =
2012 []( const wxAny&& aValue, EDA_ITEM* aZone ) -> VALIDATOR_RESULT
2013 {
2014 int val = aValue.As<int>();
2015 ZONE* zone = dynamic_cast<ZONE*>( aZone );
2016 wxCHECK( zone, std::nullopt );
2017
2018 if( val < zone->GetMinThickness() )
2019 {
2020 return std::make_unique<VALIDATION_ERROR_MSG>(
2021 _( "Cannot be less than zone minimum width" ) );
2022 }
2023
2024 return std::nullopt;
2025 };
2026
2027 propMgr.AddProperty( new PROPERTY<ZONE, int>( _HKI( "Hatch Width" ),
2028 &ZONE::SetHatchThickness, &ZONE::GetHatchThickness, PROPERTY_DISPLAY::PT_SIZE ),
2029 groupFill )
2030 .SetAvailableFunc( isCopperZone )
2031 .SetWriteableFunc( isHatchedFill )
2032 .SetValidator( atLeastMinWidthValidator );
2033
2034 propMgr.AddProperty( new PROPERTY<ZONE, int>( _HKI( "Hatch Gap" ),
2035 &ZONE::SetHatchGap, &ZONE::GetHatchGap, PROPERTY_DISPLAY::PT_SIZE ),
2036 groupFill )
2037 .SetAvailableFunc( isCopperZone )
2038 .SetWriteableFunc( isHatchedFill )
2039 .SetValidator( atLeastMinWidthValidator );
2040
2041 propMgr.AddProperty( new PROPERTY<ZONE, double>( _HKI( "Hatch Minimum Hole Ratio" ),
2043 groupFill )
2044 .SetAvailableFunc( isCopperZone )
2045 .SetWriteableFunc( isHatchedFill )
2047
2048 // TODO: Smoothing effort needs to change to enum (in dialog too)
2049 propMgr.AddProperty( new PROPERTY<ZONE, int>( _HKI( "Smoothing Effort" ),
2051 groupFill )
2052 .SetAvailableFunc( isCopperZone )
2053 .SetWriteableFunc( isHatchedFill );
2054
2055 propMgr.AddProperty( new PROPERTY<ZONE, double>( _HKI( "Smoothing Amount" ),
2057 groupFill )
2058 .SetAvailableFunc( isCopperZone )
2059 .SetWriteableFunc( isHatchedFill );
2060
2061 propMgr.AddProperty( new PROPERTY_ENUM<ZONE, ISLAND_REMOVAL_MODE>( _HKI( "Remove Islands" ),
2063 groupFill )
2064 .SetAvailableFunc( isCopperZone );
2065
2066 propMgr.AddProperty( new PROPERTY<ZONE, long long int>( _HKI( "Minimum Island Area" ),
2067 &ZONE::SetMinIslandArea, &ZONE::GetMinIslandArea, PROPERTY_DISPLAY::PT_AREA ),
2068 groupFill )
2069 .SetAvailableFunc( isCopperZone )
2070 .SetWriteableFunc( isAreaBasedIslandRemoval );
2071
2072 const wxString groupElectrical = _HKI( "Electrical" );
2073
2074 auto clearanceOverride = new PROPERTY<ZONE, std::optional<int>>( _HKI( "Clearance" ),
2076 PROPERTY_DISPLAY::PT_SIZE );
2077 clearanceOverride->SetAvailableFunc( isCopperZone );
2078 constexpr int maxClearance = pcbIUScale.mmToIU( ZONE_CLEARANCE_MAX_VALUE_MM );
2079 clearanceOverride->SetValidator( PROPERTY_VALIDATORS::RangeIntValidator<0, maxClearance> );
2080
2081 auto minWidth = new PROPERTY<ZONE, int>( _HKI( "Minimum Width" ),
2083 PROPERTY_DISPLAY::PT_SIZE );
2084 minWidth->SetAvailableFunc( isCopperZone );
2085 constexpr int minMinWidth = pcbIUScale.mmToIU( ZONE_THICKNESS_MIN_VALUE_MM );
2086 minWidth->SetValidator( PROPERTY_VALIDATORS::RangeIntValidator<minMinWidth,
2087 INT_MAX> );
2088
2089 auto padConnections = new PROPERTY_ENUM<ZONE, ZONE_CONNECTION>( _HKI( "Pad Connections" ),
2091 padConnections->SetAvailableFunc( isCopperZone );
2092
2093 auto thermalGap = new PROPERTY<ZONE, int>( _HKI( "Thermal Relief Gap" ),
2095 PROPERTY_DISPLAY::PT_SIZE );
2096 thermalGap->SetAvailableFunc( isCopperZone );
2097 thermalGap->SetValidator( PROPERTY_VALIDATORS::PositiveIntValidator );
2098
2099 auto thermalSpokeWidth = new PROPERTY<ZONE, int>( _HKI( "Thermal Relief Spoke Width" ),
2101 PROPERTY_DISPLAY::PT_SIZE );
2102 thermalSpokeWidth->SetAvailableFunc( isCopperZone );
2103 thermalSpokeWidth->SetValidator( atLeastMinWidthValidator );
2104
2105 propMgr.AddProperty( clearanceOverride, groupElectrical );
2106 propMgr.AddProperty( minWidth, groupElectrical );
2107 propMgr.AddProperty( padConnections, groupElectrical );
2108 propMgr.AddProperty( thermalGap, groupElectrical );
2109 propMgr.AddProperty( thermalSpokeWidth, groupElectrical );
2110 }
2112
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:143
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:295
PCB_LAYER_ID FlipLayer(PCB_LAYER_ID aLayer) const
Definition: board.cpp:776
std::unordered_map< const ZONE *, BOX2I > m_ZoneBBoxCache
Definition: board.h:1322
BOARD_DESIGN_SETTINGS & GetDesignSettings() const
Definition: board.cpp:948
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:488
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:129
ENUM_MAP & Map(T aValue, const wxString &aName)
Definition: property.h:686
static ENUM_MAP< T > & Instance()
Definition: property.h:680
ENUM_MAP & Undefined(T aValue)
Definition: property.h:693
wxPGChoices & Choices()
Definition: property.h:729
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:174
static constexpr double LOD_SHOW
Return this constant from ViewGetLOD() to show the item unconditionally.
Definition: view_item.h:179
Hold a (potentially large) number of VIEW_ITEMs and renders them on a graphics device provided by the...
Definition: view.h:67
bool IsLayerVisible(int aLayer) const
Return information about visibility of a particular layer.
Definition: view.h:418
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:703
static LSET AllLayersMask()
Definition: lset.cpp:593
void RunOnLayers(const std::function< void(PCB_LAYER_ID)> &aFunction) const
Execute a function on each layer of the LSET.
Definition: lset.h:255
static LSET AllCuMask(int aCuLayerCount=MAX_CU_LAYERS)
Return a mask holding the requested number of Cu PCB_LAYER_IDs.
Definition: lset.cpp:564
LSEQ Seq(const LSEQ &aSequence) const
Return an LSEQ from the union of this LSET and a desired sequence.
Definition: lset.cpp:297
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:1262
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 BooleanAdd(const SHAPE_POLY_SET &b)
Perform boolean polyset union.
ITERATOR IterateWithHoles(int aOutline)
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)
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.
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: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:296
SHAPE_POLY_SET::VERTEX_INDEX * m_CornerSelection
The index of the corner being moved or nullptr if no corner is selected.
Definition: zone.h:932
void SetNeedRefill(bool aNeedRefill)
Definition: zone.h:275
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:652
wxString GetItemDescription(UNITS_PROVIDER *aUnitsProvider, bool aFull) const override
Return a user-visible description string of this item.
Definition: zone.cpp:1054
int m_borderHatchPitch
Definition: zone.h:953
bool m_isRuleArea
Definition: zone.h:861
void SetDoNotAllowPads(bool aEnable)
Definition: zone.h:757
ZONE & operator=(const ZONE &aOther)
Definition: zone.cpp:105
int m_cornerSmoothingType
Definition: zone.h:844
bool GetIsRuleArea() const
Accessors to parameters used in Rule Area zones:
Definition: zone.h:731
std::optional< int > GetLocalClearance() const override
Definition: zone.cpp:717
void SetRuleAreaPlacementEnabled(bool aEnabled)
Definition: zone.h:745
void SetLocalClearance(std::optional< int > aClearance)
Definition: zone.h:165
bool m_doNotAllowVias
Definition: zone.h:880
bool UnFill()
Removes the zone filling.
Definition: zone.cpp:418
wxString GetRuleAreaPlacementSource() const
Definition: zone.h:737
bool GetDoNotAllowVias() const
Definition: zone.h:739
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:1627
void SetCornerRadius(unsigned int aRadius)
Definition: zone.cpp:622
ZONE_FILL_MODE m_fillMode
How to fill areas:
Definition: zone.h:918
bool m_doNotAllowFootprints
Definition: zone.h:883
int m_ZoneMinThickness
Definition: zone.h:887
void AddPolygon(std::vector< VECTOR2I > &aPolygon)
Add a polygon to the zone outline.
Definition: zone.cpp:1017
double m_hatchSmoothingValue
Definition: zone.h:926
void SetLocalFlags(int aFlags)
Definition: zone.h:345
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:1558
int m_thermalReliefSpokeWidth
Definition: zone.h:909
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:737
EDA_ANGLE m_hatchOrientation
Definition: zone.h:921
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:1306
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:977
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:957
wxString m_zoneName
An optional unique name for this zone, used for identifying it in DRC checking.
Definition: zone.h:848
void HatchBorder()
Compute the hatch lines depending on the hatch parameters and stores it in the zone's attribute m_bor...
Definition: zone.cpp:1145
std::map< PCB_LAYER_ID, std::shared_ptr< SHAPE_POLY_SET > > m_FilledPolysList
Definition: zone.h:944
void SetBorderDisplayStyle(ZONE_BORDER_DISPLAY_STYLE aBorderHatchStyle, int aBorderHatchPitch, bool aRebuilBorderdHatch)
Set all hatch parameters for the zone.
Definition: zone.cpp:1110
bool GetDoNotAllowPads() const
Definition: zone.h:741
const BOX2I GetBoundingBox() const override
Definition: zone.cpp:570
void SetMinThickness(int aMinThickness)
Definition: zone.h:281
double ViewGetLOD(int aLayer, const KIGFX::VIEW *aView) const override
Return the level of detail (LOD) of the item.
Definition: zone.cpp:539
double m_outlinearea
Definition: zone.h:960
wxString GetFriendlyName() const override
Definition: zone.cpp:917
bool GetDoNotAllowTracks() const
Definition: zone.h:740
int GetLocalFlags() const
Definition: zone.h:344
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:302
bool m_doNotAllowCopperPour
Definition: zone.h:879
bool GetRuleAreaPlacementEnabled() const
Definition: zone.h:732
void SetHatchSmoothingValue(double aValue)
Definition: zone.h:308
bool m_needRefill
False when a zone was refilled, true after changes in zone params.
Definition: zone.h:906
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:662
void SetHatchSmoothingLevel(int aLevel)
Definition: zone.h:305
bool m_doNotAllowTracks
Definition: zone.h:881
RULE_AREA_PLACEMENT_SOURCE_TYPE m_ruleAreaPlacementSourceType
Definition: zone.h:867
void SetDoNotAllowCopperPour(bool aEnable)
Definition: zone.h:754
void SetThermalReliefSpokeWidth(int aThermalReliefSpokeWidth)
Definition: zone.h:216
virtual PCB_LAYER_ID GetLayer() const override
Return the primary layer this item is on.
Definition: zone.cpp:448
virtual void SetLayer(PCB_LAYER_ID aLayer) override
Set the layer this item is on.
Definition: zone.cpp:486
ISLAND_REMOVAL_MODE GetIslandRemovalMode() const
Definition: zone.h:760
LSET m_fillFlags
Temp variables used while filling.
Definition: zone.h:947
SHAPE_POLY_SET * Outline()
Definition: zone.h:347
bool m_doNotAllowPads
Definition: zone.h:882
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:890
bool IsIsland(PCB_LAYER_ID aLayer, int aPolyIdx) const
Check if a given filled polygon is an insulated island.
Definition: zone.cpp:1323
SHAPE_POLY_SET * m_Poly
Outline of the zone.
Definition: zone.h:843
TEARDROP_TYPE m_teardropType
Definition: zone.h:874
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:950
~ZONE()
Definition: zone.cpp:115
long long int GetMinIslandArea() const
Definition: zone.h:763
int m_hatchSmoothingLevel
Definition: zone.h:922
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:1736
LSET m_layerSet
Definition: zone.h:850
void SetRuleAreaPlacementSourceType(RULE_AREA_PLACEMENT_SOURCE_TYPE aType)
Definition: zone.h:746
void SetIsRuleArea(bool aEnable)
Definition: zone.h:744
int m_ZoneClearance
Definition: zone.h:886
void SetDoNotAllowTracks(bool aEnable)
Definition: zone.h:756
void SetFilledPolysList(PCB_LAYER_ID aLayer, const SHAPE_POLY_SET &aPolysList)
Set the list of filled polygons.
Definition: zone.h:648
const wxString & GetZoneName() const
Definition: zone.h:142
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:599
int GetMinThickness() const
Definition: zone.h:280
virtual void swapData(BOARD_ITEM *aImage) override
Definition: zone.cpp:1298
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:669
void RemoveCutout(int aOutlineIdx, int aHoleIdx)
Remove a cutout from the zone.
Definition: zone.cpp:988
void Rotate(const VECTOR2I &aCentre, const EDA_ANGLE &aAngle) override
Rotate the outlines.
Definition: zone.cpp:945
bool HigherPriority(const ZONE *aOther) const
Definition: zone.cpp:395
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:723
void SetIsFilled(bool isFilled)
Definition: zone.h:272
void SetFillMode(ZONE_FILL_MODE aFillMode)
Definition: zone.h:202
BITMAPS GetMenuImage() const override
Return a pointer to an image to be used in menus.
Definition: zone.cpp:1292
int m_hatchGap
Definition: zone.h:920
ZONE_CONNECTION GetPadConnection() const
Definition: zone.h:277
void InitDataFromSrcInCopyCtor(const ZONE &aZone)
Copy aZone data to me.
Definition: zone.cpp:125
int GetHatchThickness() const
Definition: zone.h:295
double GetHatchHoleMinArea() const
Definition: zone.h:310
void SetLayerSet(const LSET &aLayerSet) override
Definition: zone.cpp:492
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:762
virtual bool IsOnLayer(PCB_LAYER_ID) const override
Test to see if this object is on the given layer.
Definition: zone.cpp:564
int m_hatchBorderAlgorithm
Definition: zone.h:928
void SetDoNotAllowVias(bool aEnable)
Definition: zone.h:755
bool IsTeardropArea() const
Definition: zone.h:706
std::vector< SEG > m_borderHatchLines
Definition: zone.h:954
wxString m_ruleAreaPlacementSource
Definition: zone.h:868
VECTOR2I GetPosition() const override
Definition: zone.cpp:442
int GetThermalReliefSpokeWidth() const
Definition: zone.h:224
int GetBorderHatchPitch() const
HatchBorder related methods.
Definition: zone.cpp:1104
virtual void Flip(const VECTOR2I &aCentre, FLIP_DIRECTION aFlipDirection) override
Flip this object, i.e.
Definition: zone.cpp:956
void BuildHashValue(PCB_LAYER_ID aLayer)
Build the hash value of m_FilledPolysList, and store it internally in m_filledPolysHash.
Definition: zone.cpp:643
void SetThermalReliefGap(int aThermalReliefGap)
Definition: zone.h:205
EDA_ANGLE GetHatchOrientation() const
Definition: zone.h:301
bool BuildSmoothedPoly(SHAPE_POLY_SET &aSmoothedPoly, PCB_LAYER_ID aLayer, SHAPE_POLY_SET *aBoardOutline, SHAPE_POLY_SET *aSmoothedPolyWithApron=nullptr) const
Definition: zone.cpp:1370
int m_fillVersion
Definition: zone.h:888
const VECTOR2I & GetCornerPosition(int aCornerIndex) const
Definition: zone.h:566
bool GetDoNotAllowFootprints() const
Definition: zone.h:742
ZONE_FILL_MODE GetFillMode() const
Definition: zone.h:203
double m_hatchHoleMinArea
Definition: zone.h:927
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:758
bool GetDoNotAllowCopperPour() const
Definition: zone.h:738
void SetBorderHatchPitch(int aPitch)
Set the hatch pitch parameter for the zone.
Definition: zone.cpp:1125
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:1335
bool m_ruleAreaPlacementEnabled
Placement rule area data.
Definition: zone.h:866
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:1634
int GetHatchGap() const
Definition: zone.h:298
double CalculateOutlineArea()
Compute the area of the zone outline (not the filled area).
Definition: zone.cpp:1551
RULE_AREA_PLACEMENT_SOURCE_TYPE GetRuleAreaPlacementSourceType() const
Definition: zone.h:733
void SetHatchHoleMinArea(double aPct)
Definition: zone.h:311
unsigned m_priority
Definition: zone.h:856
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:436
ISLAND_REMOVAL_MODE m_islandRemovalMode
Definition: zone.h:890
bool m_isFilled
True when a zone was filled, false after deleting the filled areas.
Definition: zone.h:899
double GetHatchSmoothingValue() const
Definition: zone.h:307
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:1034
void MoveEdge(const VECTOR2I &offset, int aEdge)
Move the outline Edge.
Definition: zone.cpp:930
int GetHatchSmoothingLevel() const
Definition: zone.h:304
unsigned int GetCornerRadius() const
Definition: zone.h:677
int GetCornerSmoothingType() const
Definition: zone.h:673
int m_thermalReliefGap
Definition: zone.h:908
bool IsOnCopperLayer() const override
Definition: zone.cpp:480
double CalculateFilledArea()
Compute the area currently occupied by the zone fill.
Definition: zone.cpp:1528
int m_hatchThickness
Definition: zone.h:919
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:1598
void SetAssignedPriority(unsigned aPriority)
Definition: zone.h:118
double m_area
Definition: zone.h:959
unsigned int m_cornerRadius
Definition: zone.h:845
void SetPadConnection(ZONE_CONNECTION aPadConnection)
Definition: zone.h:278
void SetZoneName(const wxString &aName)
Definition: zone.h:143
bool operator==(const ZONE &aOther) const
Definition: zone.cpp:1668
void UnHatchBorder()
Clear the zone's hatch.
Definition: zone.cpp:1131
void SetIslandRemovalMode(ISLAND_REMOVAL_MODE aRemove)
Definition: zone.h:761
void SetOutline(SHAPE_POLY_SET *aOutline)
Definition: zone.h:350
PCB_LAYER_ID GetFirstLayer() const
Definition: zone.cpp:458
void SetMinIslandArea(long long int aArea)
Definition: zone.h:764
virtual std::vector< int > ViewGetLayers() const override
Return the all the layers within the VIEW the object is painted on.
Definition: zone.cpp:520
HASH_128 GetHashValue(PCB_LAYER_ID aLayer)
Definition: zone.cpp:634
ZONE_CONNECTION m_PadConnection
Definition: zone.h:885
void SetRuleAreaPlacementSource(const wxString &aSource)
Definition: zone.h:750
int GetThermalReliefGap() const
Definition: zone.h:213
void SetHatchGap(int aStep)
Definition: zone.h:299
static int GetDefaultHatchPitch()
Definition: zone.cpp:1286
unsigned GetAssignedPriority() const
Definition: zone.h:123
int GetNumCorners(void) const
Access to m_Poly parameters.
Definition: zone.h:526
bool SameNet(const ZONE *aOther) const
Definition: zone.cpp:412
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:1589
ZONE_BORDER_DISPLAY_STYLE m_borderStyle
Definition: zone.h:952
long long int m_minIslandArea
When island removal mode is set to AREA, islands below this area will be removed.
Definition: zone.h:896
#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:184
bool IsCopperLayer(int aLayerId)
Test whether a layer is a copper layer.
Definition: layer_ids.h:618
@ 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:327
@ 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: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:780
#define NO_SETTER(owner, type)
Definition: property.h:791
#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:348
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:1812
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:631
bool sortEndsByDescendingX(const VECTOR2I &ref, const VECTOR2I &tst)
Definition: zone.cpp:1139
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