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