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