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