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 if( !GetIsRuleArea() ) // Show fill mode only for not rule areas
936 {
937 switch( m_fillMode )
938 {
939 case ZONE_FILL_MODE::POLYGONS: msg = _( "Solid" ); break;
940 case ZONE_FILL_MODE::HATCH_PATTERN: msg = _( "Hatched" ); break;
941 default: msg = _( "Unknown" ); break;
942 }
943
944 aList.emplace_back( _( "Fill Mode" ), msg );
945
946 aList.emplace_back( _( "Filled Area" ),
948
949 wxString source;
950 int clearance = GetOwnClearance( UNDEFINED_LAYER, &source );
951
952 if( !source.IsEmpty() )
953 {
954 aList.emplace_back( wxString::Format( _( "Min Clearance: %s" ), aFrame->MessageTextFromValue( clearance ) ),
955 wxString::Format( _( "(from %s)" ), source ) );
956 }
957 }
958
959 int count = 0;
960
961 if( GetIsRuleArea() )
962 {
963 double outline_area = CalculateOutlineArea();
964 aList.emplace_back( _( "Outline Area" ),
965 aFrame->MessageTextFromValue( outline_area, true, EDA_DATA_TYPE::AREA ) );
966
967 const SHAPE_POLY_SET* area_outline = Outline();
968 count = area_outline->FullPointCount();
969 }
970 else if( !m_FilledPolysList.empty() )
971 {
972 for( std::pair<const PCB_LAYER_ID, std::shared_ptr<SHAPE_POLY_SET>>& ii: m_FilledPolysList )
973 count += ii.second->TotalVertices();
974 }
975
976 aList.emplace_back( _( "Corner Count" ), wxString::Format( wxT( "%d" ), count ) );
977}
978
979
980void ZONE::Move( const VECTOR2I& offset )
981{
982 /* move outlines */
983 m_Poly->Move( offset );
984
985 HatchBorder();
986
987 /* move fills */
988 for( std::pair<const PCB_LAYER_ID, std::shared_ptr<SHAPE_POLY_SET>>& pair : m_FilledPolysList )
989 pair.second->Move( offset );
990
991 /*
992 * move boundingbox cache
993 *
994 * While the cache will get nuked at the conclusion of the operation, we use it for some
995 * things (such as drawing the parent group) during the move.
996 */
997 if( GetBoard() )
998 {
999 auto it = GetBoard()->m_ZoneBBoxCache.find( this );
1000
1001 if( it != GetBoard()->m_ZoneBBoxCache.end() )
1002 it->second.Move( offset );
1003 }
1004}
1005
1006
1008{
1009 if( GetIsRuleArea() )
1010 return _( "Rule Area" );
1011 else if( IsTeardropArea() )
1012 return _( "Teardrop Area" );
1013 else if( IsOnCopperLayer() )
1014 return _( "Copper Zone" );
1015 else
1016 return _( "Non-copper Zone" );
1017}
1018
1019
1020void ZONE::MoveEdge( const VECTOR2I& offset, int aEdge )
1021{
1022 int next_corner;
1023
1024 if( m_Poly->GetNeighbourIndexes( aEdge, nullptr, &next_corner ) )
1025 {
1026 m_Poly->SetVertex( aEdge, m_Poly->CVertex( aEdge ) + VECTOR2I( offset ) );
1027 m_Poly->SetVertex( next_corner, m_Poly->CVertex( next_corner ) + VECTOR2I( offset ) );
1028 HatchBorder();
1029
1030 SetNeedRefill( true );
1031 }
1032}
1033
1034
1035void ZONE::Rotate( const VECTOR2I& aCentre, const EDA_ANGLE& aAngle )
1036{
1037 m_Poly->Rotate( aAngle, aCentre );
1038 HatchBorder();
1039
1040 /* rotate filled areas: */
1041 for( std::pair<const PCB_LAYER_ID, std::shared_ptr<SHAPE_POLY_SET>>& pair : m_FilledPolysList )
1042 pair.second->Rotate( aAngle, aCentre );
1043}
1044
1045
1046void ZONE::Flip( const VECTOR2I& aCentre, FLIP_DIRECTION aFlipDirection )
1047{
1048 Mirror( aCentre, aFlipDirection );
1049
1050 std::map<PCB_LAYER_ID, SHAPE_POLY_SET> fillsCopy;
1051
1052 for( auto& [oldLayer, shapePtr] : m_FilledPolysList )
1053 fillsCopy[oldLayer] = *shapePtr;
1054
1055 std::map<PCB_LAYER_ID, ZONE_LAYER_PROPERTIES> layerPropertiesCopy = m_layerProperties;
1056
1057 LSET flipped;
1058
1059 for( PCB_LAYER_ID layer : GetLayerSet() )
1060 flipped.set( GetBoard()->FlipLayer( layer ) );
1061
1062 SetLayerSet( flipped );
1063
1064 for( auto& [oldLayer, properties] : layerPropertiesCopy )
1065 {
1066 PCB_LAYER_ID newLayer = GetBoard()->FlipLayer( oldLayer );
1067 m_layerProperties[newLayer] = properties;
1068 }
1069
1070 for( auto& [oldLayer, shape] : fillsCopy )
1071 {
1072 PCB_LAYER_ID newLayer = GetBoard()->FlipLayer( oldLayer );
1073 SetFilledPolysList( newLayer, shape );
1074 }
1075}
1076
1077
1078void ZONE::Mirror( const VECTOR2I& aMirrorRef, FLIP_DIRECTION aFlipDirection )
1079{
1080 m_Poly->Mirror( aMirrorRef, aFlipDirection );
1081
1082 HatchBorder();
1083
1084 for( std::pair<const PCB_LAYER_ID, std::shared_ptr<SHAPE_POLY_SET>>& pair : m_FilledPolysList )
1085 pair.second->Mirror( aMirrorRef, aFlipDirection );
1086}
1087
1088
1089void ZONE::RemoveCutout( int aOutlineIdx, int aHoleIdx )
1090{
1091 // Ensure the requested cutout is valid
1092 if( m_Poly->OutlineCount() < aOutlineIdx || m_Poly->HoleCount( aOutlineIdx ) < aHoleIdx )
1093 return;
1094
1095 SHAPE_POLY_SET cutPoly( m_Poly->Hole( aOutlineIdx, aHoleIdx ) );
1096
1097 // Add the cutout back to the zone
1098 m_Poly->BooleanAdd( cutPoly );
1099
1100 SetNeedRefill( true );
1101}
1102
1103
1104void ZONE::AddPolygon( const SHAPE_LINE_CHAIN& aPolygon )
1105{
1106 wxASSERT( aPolygon.IsClosed() );
1107
1108 // Add the outline as a new polygon in the polygon set
1109 if( m_Poly->OutlineCount() == 0 )
1110 m_Poly->AddOutline( aPolygon );
1111 else
1112 m_Poly->AddHole( aPolygon );
1113
1114 SetNeedRefill( true );
1115}
1116
1117
1118void ZONE::AddPolygon( std::vector<VECTOR2I>& aPolygon )
1119{
1120 if( aPolygon.empty() )
1121 return;
1122
1123 SHAPE_LINE_CHAIN outline;
1124
1125 // Create an outline and populate it with the points of aPolygon
1126 for( const VECTOR2I& pt : aPolygon )
1127 outline.Append( pt );
1128
1129 outline.SetClosed( true );
1130
1131 AddPolygon( outline );
1132}
1133
1134
1135bool ZONE::AppendCorner( VECTOR2I aPosition, int aHoleIdx, bool aAllowDuplication )
1136{
1137 // Ensure the main outline exists:
1138 if( m_Poly->OutlineCount() == 0 )
1139 m_Poly->NewOutline();
1140
1141 // If aHoleIdx >= 0, the corner musty be added to the hole, index aHoleIdx.
1142 // (remember: the index of the first hole is 0)
1143 // Return error if it does not exist.
1144 if( aHoleIdx >= m_Poly->HoleCount( 0 ) )
1145 return false;
1146
1147 m_Poly->Append( aPosition.x, aPosition.y, -1, aHoleIdx, aAllowDuplication );
1148
1149 SetNeedRefill( true );
1150
1151 return true;
1152}
1153
1154
1155wxString ZONE::GetItemDescription( UNITS_PROVIDER* aUnitsProvider, bool aFull ) const
1156{
1157 LSEQ layers = m_layerSet.Seq();
1158 wxString layerDesc;
1159
1160 if( layers.size() == 1 )
1161 {
1162 layerDesc.Printf( _( "on %s" ), GetBoard()->GetLayerName( layers[0] ) );
1163 }
1164 else if (layers.size() == 2 )
1165 {
1166 layerDesc.Printf( _( "on %s and %s" ),
1167 GetBoard()->GetLayerName( layers[0] ),
1168 GetBoard()->GetLayerName( layers[1] ) );
1169 }
1170 else if (layers.size() == 3 )
1171 {
1172 layerDesc.Printf( _( "on %s, %s and %s" ),
1173 GetBoard()->GetLayerName( layers[0] ),
1174 GetBoard()->GetLayerName( layers[1] ),
1175 GetBoard()->GetLayerName( layers[2] ) );
1176 }
1177 else if( layers.size() > 3 )
1178 {
1179 layerDesc.Printf( _( "on %s, %s and %zu more" ),
1180 GetBoard()->GetLayerName( layers[0] ),
1181 GetBoard()->GetLayerName( layers[1] ),
1182 layers.size() - 2 );
1183 }
1184
1185 if( GetIsRuleArea() )
1186 {
1187 if( GetZoneName().IsEmpty() )
1188 {
1189 return wxString::Format( _( "Rule Area %s" ),
1190 layerDesc );
1191 }
1192 else
1193 {
1194 return wxString::Format( _( "Rule area '%s' %s" ),
1195 GetZoneName(),
1196 layerDesc );
1197 }
1198 }
1199 else if( IsTeardropArea() )
1200 {
1201 return wxString::Format( _( "Teardrop %s %s" ),
1202 GetNetnameMsg(),
1203 layerDesc );
1204 }
1205 else
1206 {
1207 if( GetZoneName().IsEmpty() )
1208 {
1209 return wxString::Format( _( "Zone %s %s, priority %d" ),
1210 GetNetnameMsg(),
1211 layerDesc,
1213 }
1214 else
1215 {
1216 return wxString::Format( _( "Zone '%s' %s %s, priority %d" ),
1217 GetZoneName(),
1218 GetNetnameMsg(),
1219 layerDesc,
1221 }
1222 }
1223}
1224
1225
1227 int aBorderHatchPitch, bool aRebuildBorderHatch )
1228{
1229 aBorderHatchPitch = std::max( aBorderHatchPitch, pcbIUScale.mmToIU( ZONE_BORDER_HATCH_MINDIST_MM ) );
1230 aBorderHatchPitch = std::min( aBorderHatchPitch, pcbIUScale.mmToIU( ZONE_BORDER_HATCH_MAXDIST_MM ) );
1231 SetBorderHatchPitch( aBorderHatchPitch );
1232 m_borderStyle = aBorderHatchStyle;
1233
1234 if( aRebuildBorderHatch )
1235 HatchBorder();
1236}
1237
1238
1240{
1241 m_borderHatchLines.clear();
1242}
1243
1244
1246{
1247 UnHatchBorder();
1248
1250 || m_borderHatchPitch == 0
1251 || m_Poly->IsEmpty() )
1252 {
1253 return;
1254 }
1255
1256 // set the "length" of hatch lines (the length on horizontal axis)
1257 int hatch_line_len = m_borderHatchPitch; // OK for DIAGONAL_EDGE style
1258
1259 // Calculate spacing between 2 hatch lines
1260 int spacing = m_borderHatchPitch; // OK for DIAGONAL_EDGE style
1261
1263 {
1264 // The spacing is twice the spacing for DIAGONAL_EDGE because one
1265 // full diagonal replaces 2 edge diagonal hatch segments in code
1266 spacing = m_borderHatchPitch * 2;
1267 hatch_line_len = -1; // Use full diagonal hatch line
1268 }
1269
1270 // To have a better look, give a slope depending on the layer
1271 int layer = GetFirstLayer();
1272 std::vector<double> slopes;
1273
1274 if( IsTeardropArea() )
1275 slopes = { 0.7, -0.7 };
1276 else if( layer & 1 )
1277 slopes = { 1 };
1278 else
1279 slopes = { -1 };
1280
1281 m_borderHatchLines = m_Poly->GenerateHatchLines( slopes, spacing, hatch_line_len );
1282}
1283
1284
1286{
1287 return pcbIUScale.mmToIU( ZONE_BORDER_HATCH_DIST_MM );
1288}
1289
1290
1292{
1293 return BITMAPS::add_zone;
1294}
1295
1296
1298{
1299 assert( aImage->Type() == PCB_ZONE_T );
1300
1301 std::swap( *static_cast<ZONE*>( this ), *static_cast<ZONE*>( aImage) );
1302}
1303
1304
1306{
1307 if( aLayer == UNDEFINED_LAYER )
1308 {
1309 for( auto& [ layer, poly ] : m_FilledPolysList )
1310 poly->CacheTriangulation();
1311
1312 m_Poly->CacheTriangulation( false );
1313 }
1314 else
1315 {
1316 if( m_FilledPolysList.count( aLayer ) )
1317 m_FilledPolysList[ aLayer ]->CacheTriangulation();
1318 }
1319}
1320
1321
1322bool ZONE::IsIsland( PCB_LAYER_ID aLayer, int aPolyIdx ) const
1323{
1324 if( GetNetCode() < 1 )
1325 return true;
1326
1327 if( !m_insulatedIslands.count( aLayer ) )
1328 return false;
1329
1330 return m_insulatedIslands.at( aLayer ).count( aPolyIdx );
1331}
1332
1333
1334void ZONE::GetInteractingZones( PCB_LAYER_ID aLayer, std::vector<ZONE*>* aSameNetCollidingZones,
1335 std::vector<ZONE*>* aOtherNetIntersectingZones ) const
1336{
1337 int epsilon = pcbIUScale.mmToIU( 0.001 );
1338 BOX2I bbox = GetBoundingBox();
1339
1340 bbox.Inflate( epsilon );
1341
1342 for( ZONE* candidate : GetBoard()->Zones() )
1343 {
1344 if( candidate == this )
1345 continue;
1346
1347 if( !candidate->GetLayerSet().test( aLayer ) )
1348 continue;
1349
1350 if( candidate->GetIsRuleArea() || candidate->IsTeardropArea() )
1351 continue;
1352
1353 if( !candidate->GetBoundingBox().Intersects( bbox ) )
1354 continue;
1355
1356 if( candidate->GetNetCode() == GetNetCode() )
1357 {
1358 if( m_Poly->Collide( candidate->m_Poly ) )
1359 aSameNetCollidingZones->push_back( candidate );
1360 }
1361 else
1362 {
1363 aOtherNetIntersectingZones->push_back( candidate );
1364 }
1365 }
1366}
1367
1368
1370 SHAPE_POLY_SET* aBoardOutline,
1371 SHAPE_POLY_SET* aSmoothedPolyWithApron ) const
1372{
1373 if( GetNumCorners() <= 2 ) // malformed zone. polygon calculations will not like it ...
1374 return false;
1375
1376 // Processing of arc shapes in zones is not yet supported because Clipper can't do boolean
1377 // operations on them. The poly outline must be converted to segments first.
1378 SHAPE_POLY_SET flattened = m_Poly->CloneDropTriangulation();
1379 flattened.ClearArcs();
1380
1381 if( GetIsRuleArea() )
1382 {
1383 // We like keepouts just the way they are....
1384 aSmoothedPoly = std::move( flattened );
1385 return true;
1386 }
1387
1388 const BOARD* board = GetBoard();
1389 bool keepExternalFillets = false;
1392
1393 if( IsTeardropArea() )
1394 {
1395 // We use teardrop shapes with no smoothing; these shapes are already optimized
1396 smooth_requested = false;
1397 }
1398
1399 if( board )
1400 keepExternalFillets = board->GetDesignSettings().m_ZoneKeepExternalFillets;
1401
1402 auto smooth =
1403 [&]( SHAPE_POLY_SET& aPoly )
1404 {
1405 if( !smooth_requested )
1406 return;
1407
1408 switch( m_cornerSmoothingType )
1409 {
1411 aPoly = aPoly.Chamfer( (int) m_cornerRadius );
1412 break;
1413
1415 aPoly = aPoly.Fillet( (int) m_cornerRadius, GetMaxError() );
1416 break;
1417
1418 default:
1419 break;
1420 }
1421 };
1422
1423 SHAPE_POLY_SET* maxExtents = &flattened;
1424 SHAPE_POLY_SET withFillets;
1425
1426 aSmoothedPoly = flattened;
1427
1428 // Should external fillets (that is, those applied to concave corners) be kept? While it
1429 // seems safer to never have copper extend outside the zone outline, 5.1.x and prior did
1430 // indeed fill them so we leave the mode available.
1431 if( keepExternalFillets && smooth_requested )
1432 {
1433 withFillets = flattened;
1434 smooth( withFillets );
1435 withFillets.BooleanAdd( flattened );
1436 maxExtents = &withFillets;
1437 }
1438
1439 // We now add in the areas of any same-net, intersecting zones. This keeps us from smoothing
1440 // corners at an intersection (which often produces undesired divots between the intersecting
1441 // zones -- see #2752).
1442 //
1443 // After smoothing, we'll subtract back out everything outside of our zone.
1444 std::vector<ZONE*> sameNetCollidingZones;
1445 std::vector<ZONE*> diffNetIntersectingZones;
1446 GetInteractingZones( aLayer, &sameNetCollidingZones, &diffNetIntersectingZones );
1447
1448 for( ZONE* sameNetZone : sameNetCollidingZones )
1449 {
1450 BOX2I sameNetBoundingBox = sameNetZone->GetBoundingBox();
1451
1452 // Note: a two-pass algorithm could use sameNetZone's actual fill instead of its outline.
1453 // This would obviate the need for the below wrinkles, in addition to fixing both issues
1454 // in #16095.
1455 // (And we wouldn't need to collect all the diffNetIntersectingZones either.)
1456
1457 SHAPE_POLY_SET sameNetPoly = sameNetZone->Outline()->CloneDropTriangulation();
1458 sameNetPoly.ClearArcs();
1459
1460 SHAPE_POLY_SET diffNetPoly;
1461
1462 // Of course there's always a wrinkle. The same-net intersecting zone *might* get knocked
1463 // out along the border by a higher-priority, different-net zone. #12797
1464 for( ZONE* diffNetZone : diffNetIntersectingZones )
1465 {
1466 if( diffNetZone->HigherPriority( sameNetZone )
1467 && diffNetZone->GetBoundingBox().Intersects( sameNetBoundingBox ) )
1468 {
1469 SHAPE_POLY_SET diffNetOutline = diffNetZone->Outline()->CloneDropTriangulation();
1470 diffNetOutline.ClearArcs();
1471
1472 diffNetPoly.BooleanAdd( diffNetOutline );
1473 }
1474 }
1475
1476 // Second wrinkle. After unioning the higher priority, different net zones together, we
1477 // need to check to see if they completely enclose our zone. If they do, then we need to
1478 // treat the enclosed zone as isolated, not connected to the outer zone. #13915
1479 bool isolated = false;
1480
1481 if( diffNetPoly.OutlineCount() )
1482 {
1484 thisPoly.ClearArcs();
1485
1486 thisPoly.BooleanSubtract( diffNetPoly );
1487 isolated = thisPoly.OutlineCount() == 0;
1488 }
1489
1490 if( !isolated )
1491 aSmoothedPoly.BooleanAdd( sameNetPoly );
1492 }
1493
1494 if( aBoardOutline )
1495 {
1496 SHAPE_POLY_SET boardOutline = aBoardOutline->CloneDropTriangulation();
1497 boardOutline.ClearArcs();
1498
1499 aSmoothedPoly.BooleanIntersection( boardOutline );
1500 }
1501
1502 SHAPE_POLY_SET withSameNetIntersectingZones = aSmoothedPoly.CloneDropTriangulation();
1503
1504 smooth( aSmoothedPoly );
1505
1506 if( aSmoothedPolyWithApron )
1507 {
1508 // The same-net intersecting-zone code above makes sure the corner-smoothing algorithm
1509 // doesn't produce divots. But the min-thickness algorithm applied in fillCopperZone()
1510 // is *also* going to perform a deflate/inflate cycle, again leading to divots. So we
1511 // pre-inflate the contour by the min-thickness within the same-net-intersecting-zones
1512 // envelope.
1513 SHAPE_POLY_SET poly = maxExtents->CloneDropTriangulation();
1515
1516 if( !keepExternalFillets )
1517 poly.BooleanIntersection( withSameNetIntersectingZones );
1518
1519 *aSmoothedPolyWithApron = aSmoothedPoly;
1520 aSmoothedPolyWithApron->BooleanIntersection( poly );
1521 }
1522
1523 aSmoothedPoly.BooleanIntersection( *maxExtents );
1524
1525 return true;
1526}
1527
1528
1530{
1531 m_area = 0.0;
1532
1533 for( const auto& [layer, poly] : m_FilledPolysList )
1534 m_area += poly->Area();
1535
1536 return m_area;
1537}
1538
1539
1541{
1542 m_outlinearea = std::abs( m_Poly->Area() );
1543 return m_outlinearea;
1544}
1545
1546
1548 int aMaxError, ERROR_LOC aErrorLoc,
1549 SHAPE_POLY_SET* aBoardOutline ) const
1550{
1551 // Creates the zone outline polygon (with holes if any)
1552 SHAPE_POLY_SET polybuffer;
1553
1554 // TODO: using GetFirstLayer() means it only works for single-layer zones....
1555 BuildSmoothedPoly( polybuffer, GetFirstLayer(), aBoardOutline );
1556
1557 // Calculate the polygon with clearance
1558 // holes are linked to the main outline, so only one polygon is created.
1559 if( aClearance )
1560 {
1561 if( aErrorLoc == ERROR_OUTSIDE )
1562 aClearance += GetMaxError();
1563
1564 polybuffer.Inflate( aClearance, CORNER_STRATEGY::ROUND_ALL_CORNERS, GetMaxError() );
1565 }
1566
1567 polybuffer.Fracture();
1568 aBuffer.Append( polybuffer );
1569}
1570
1571
1572std::shared_ptr<SHAPE> ZONE::GetEffectiveShape( PCB_LAYER_ID aLayer, FLASHING aFlash ) const
1573{
1574 if( m_FilledPolysList.find( aLayer ) == m_FilledPolysList.end() )
1575 return std::make_shared<SHAPE_NULL>();
1576 else
1577 return m_FilledPolysList.at( aLayer );
1578}
1579
1580
1581void ZONE::TransformShapeToPolygon( SHAPE_POLY_SET& aBuffer, PCB_LAYER_ID aLayer, int aClearance,
1582 int aError, ERROR_LOC aErrorLoc, bool aIgnoreLineWidth ) const
1583{
1584 wxASSERT_MSG( !aIgnoreLineWidth, wxT( "IgnoreLineWidth has no meaning for zones." ) );
1585
1586 if( !m_FilledPolysList.count( aLayer ) )
1587 return;
1588
1589 if( !aClearance )
1590 {
1591 aBuffer.Append( *m_FilledPolysList.at( aLayer ) );
1592 return;
1593 }
1594
1595 SHAPE_POLY_SET temp_buf = m_FilledPolysList.at( aLayer )->CloneDropTriangulation();
1596
1597 // Rebuild filled areas only if clearance is not 0
1598 if( aClearance > 0 || aErrorLoc == ERROR_OUTSIDE )
1599 {
1600 if( aErrorLoc == ERROR_OUTSIDE )
1601 aClearance += aError;
1602
1603 temp_buf.InflateWithLinkedHoles( aClearance, CORNER_STRATEGY::ROUND_ALL_CORNERS, aError );
1604 }
1605
1606 aBuffer.Append( temp_buf );
1607}
1608
1609
1611{
1612 if( m_FilledPolysList.count( aLayer ) && !m_FilledPolysList.at( aLayer )->IsEmpty() )
1613 aBuffer.Append( *m_FilledPolysList.at( aLayer ) );
1614}
1615
1616
1618{
1619 if( aLayerSet.count() == 0 )
1620 return;
1621
1622 if( m_layerSet != aLayerSet )
1623 {
1624 aLayerSet.RunOnLayers(
1625 [&]( PCB_LAYER_ID layer )
1626 {
1627 // Only keep layers that are present in the new set
1628 if( !aLayerSet.Contains( layer ) )
1629 {
1630 m_FilledPolysList[layer] = std::make_shared<SHAPE_POLY_SET>();
1631 m_filledPolysHash[layer] = {};
1632 m_insulatedIslands[layer] = {};
1633 }
1634 } );
1635 }
1636
1637 m_layerSet = aLayerSet;
1638}
1639
1640
1641bool ZONE::operator==( const BOARD_ITEM& aOther ) const
1642{
1643 if( aOther.Type() != Type() )
1644 return false;
1645
1646 const ZONE& other = static_cast<const ZONE&>( aOther );
1647 return *this == other;
1648}
1649
1650
1651bool ZONE::operator==( const ZONE& aOther ) const
1652
1653{
1654 if( aOther.Type() != Type() )
1655 return false;
1656
1657 const ZONE& other = static_cast<const ZONE&>( aOther );
1658
1659 if( GetIsRuleArea() != other.GetIsRuleArea() )
1660 return false;
1661
1662 if( GetIsRuleArea() )
1663 {
1665 return false;
1666
1667 if( GetDoNotAllowTracks() != other.GetDoNotAllowTracks() )
1668 return false;
1669
1670 if( GetDoNotAllowVias() != other.GetDoNotAllowVias() )
1671 return false;
1672
1674 return false;
1675
1676 if( GetDoNotAllowPads() != other.GetDoNotAllowPads() )
1677 return false;
1678
1680 return false;
1681
1683 return false;
1684
1686 return false;
1687 }
1688 else
1689 {
1690 if( GetAssignedPriority() != other.GetAssignedPriority() )
1691 return false;
1692
1693 if( GetMinThickness() != other.GetMinThickness() )
1694 return false;
1695
1697 return false;
1698
1699 if( GetCornerRadius() != other.GetCornerRadius() )
1700 return false;
1701
1702 if( GetTeardropParams() != other.GetTeardropParams() )
1703 return false;
1704 }
1705
1706 if( GetNumCorners() != other.GetNumCorners() )
1707 return false;
1708
1709 for( int ii = 0; ii < GetNumCorners(); ii++ )
1710 {
1711 if( GetCornerPosition( ii ) != other.GetCornerPosition( ii ) )
1712 return false;
1713 }
1714
1715 return true;
1716}
1717
1718
1719double ZONE::Similarity( const BOARD_ITEM& aOther ) const
1720{
1721 if( aOther.Type() != Type() )
1722 return 0.0;
1723
1724 const ZONE& other = static_cast<const ZONE&>( aOther );
1725
1726 if( GetIsRuleArea() != other.GetIsRuleArea() )
1727 return 0.0;
1728
1729 double similarity = 1.0;
1730
1731 if( GetLayerSet() != other.GetLayerSet() )
1732 similarity *= 0.9;
1733
1734 if( GetNetCode() != other.GetNetCode() )
1735 similarity *= 0.9;
1736
1737 if( !GetIsRuleArea() )
1738 {
1739 if( GetAssignedPriority() != other.GetAssignedPriority() )
1740 similarity *= 0.9;
1741
1742 if( GetMinThickness() != other.GetMinThickness() )
1743 similarity *= 0.9;
1744
1746 similarity *= 0.9;
1747
1748 if( GetCornerRadius() != other.GetCornerRadius() )
1749 similarity *= 0.9;
1750
1751 if( GetTeardropParams() != other.GetTeardropParams() )
1752 similarity *= 0.9;
1753 }
1754 else
1755 {
1757 similarity *= 0.9;
1758 if( GetDoNotAllowTracks() != other.GetDoNotAllowTracks() )
1759 similarity *= 0.9;
1760 if( GetDoNotAllowVias() != other.GetDoNotAllowVias() )
1761 similarity *= 0.9;
1763 similarity *= 0.9;
1764 if( GetDoNotAllowPads() != other.GetDoNotAllowPads() )
1765 similarity *= 0.9;
1766 }
1767
1768 std::vector<VECTOR2I> corners;
1769 std::vector<VECTOR2I> otherCorners;
1770 VECTOR2I lastCorner( 0, 0 );
1771
1772 for( int ii = 0; ii < GetNumCorners(); ii++ )
1773 {
1774 corners.push_back( lastCorner - GetCornerPosition( ii ) );
1775 lastCorner = GetCornerPosition( ii );
1776 }
1777
1778 lastCorner = VECTOR2I( 0, 0 );
1779 for( int ii = 0; ii < other.GetNumCorners(); ii++ )
1780 {
1781 otherCorners.push_back( lastCorner - other.GetCornerPosition( ii ) );
1782 lastCorner = other.GetCornerPosition( ii );
1783 }
1784
1785 size_t longest = alg::longest_common_subset( corners, otherCorners );
1786
1787 similarity *= std::pow( 0.9, GetNumCorners() + other.GetNumCorners() - 2 * longest );
1788
1789 return similarity;
1790}
1791
1792
1793static struct ZONE_DESC
1794{
1796 {
1798
1799 if( layerEnum.Choices().GetCount() == 0 )
1800 {
1801 layerEnum.Undefined( UNDEFINED_LAYER );
1802
1803 for( PCB_LAYER_ID layer : LSET::AllLayersMask() )
1804 layerEnum.Map( layer, LSET::Name( layer ) );
1805 }
1806
1808
1809 if( zcMap.Choices().GetCount() == 0 )
1810 {
1812 zcMap.Map( ZONE_CONNECTION::INHERITED, _HKI( "Inherited" ) )
1813 .Map( ZONE_CONNECTION::NONE, _HKI( "None" ) )
1814 .Map( ZONE_CONNECTION::THERMAL, _HKI( "Thermal reliefs" ) )
1815 .Map( ZONE_CONNECTION::FULL, _HKI( "Solid" ) )
1816 .Map( ZONE_CONNECTION::THT_THERMAL, _HKI( "Thermal reliefs for PTH" ) );
1817 }
1818
1820
1821 if( zfmMap.Choices().GetCount() == 0 )
1822 {
1824 zfmMap.Map( ZONE_FILL_MODE::POLYGONS, _HKI( "Solid fill" ) )
1825 .Map( ZONE_FILL_MODE::HATCH_PATTERN, _HKI( "Hatch pattern" ) );
1826 }
1827
1829
1830 if( irmMap.Choices().GetCount() == 0 )
1831 {
1833 irmMap.Map( ISLAND_REMOVAL_MODE::ALWAYS, _HKI( "Always" ) )
1834 .Map( ISLAND_REMOVAL_MODE::NEVER, _HKI( "Never" ) )
1835 .Map( ISLAND_REMOVAL_MODE::AREA, _HKI( "Below area limit" ) );
1836 }
1837
1839
1840 if( rapstMap.Choices().GetCount() == 0 )
1841 {
1843 rapstMap.Map( PLACEMENT_SOURCE_T::SHEETNAME, _HKI( "Sheet Name" ) )
1844 .Map( PLACEMENT_SOURCE_T::COMPONENT_CLASS, _HKI( "Component Class" ) )
1846 }
1847
1851
1852 // Mask layer and position properties; they aren't useful in current form
1853 auto posX = new PROPERTY<ZONE, int>( _HKI( "Position X" ), NO_SETTER( ZONE, int ),
1854 static_cast<int ( ZONE::* )() const>( &ZONE::GetX ),
1857 posX->SetIsHiddenFromPropertiesManager();
1858
1859 auto posY = new PROPERTY<ZONE, int>( _HKI( "Position Y" ), NO_SETTER( ZONE, int ),
1860 static_cast<int ( ZONE::* )() const>( &ZONE::GetY ),
1863 posY->SetIsHiddenFromPropertiesManager();
1864
1865 propMgr.ReplaceProperty( TYPE_HASH( BOARD_ITEM ), _HKI( "Position X" ), posX );
1866 propMgr.ReplaceProperty( TYPE_HASH( BOARD_ITEM ), _HKI( "Position Y" ), posY );
1867
1868 auto isCopperZone =
1869 []( INSPECTABLE* aItem ) -> bool
1870 {
1871 if( ZONE* zone = dynamic_cast<ZONE*>( aItem ) )
1872 return !zone->GetIsRuleArea() && IsCopperLayer( zone->GetFirstLayer() );
1873
1874 return false;
1875 };
1876
1877 auto isRuleArea =
1878 []( INSPECTABLE* aItem ) -> bool
1879 {
1880 if( ZONE* zone = dynamic_cast<ZONE*>( aItem ) )
1881 return zone->GetIsRuleArea();
1882
1883 return false;
1884 };
1885
1886 auto isHatchedFill =
1887 []( INSPECTABLE* aItem ) -> bool
1888 {
1889 if( ZONE* zone = dynamic_cast<ZONE*>( aItem ) )
1890 return zone->GetFillMode() == ZONE_FILL_MODE::HATCH_PATTERN;
1891
1892 return false;
1893 };
1894
1895 auto isAreaBasedIslandRemoval =
1896 []( INSPECTABLE* aItem ) -> bool
1897 {
1898 if( ZONE* zone = dynamic_cast<ZONE*>( aItem ) )
1899 return zone->GetIslandRemovalMode() == ISLAND_REMOVAL_MODE::AREA;
1900
1901 return false;
1902 };
1903
1904 // Layer property is hidden because it only holds a single layer and zones actually use
1905 // a layer set
1906 propMgr.ReplaceProperty( TYPE_HASH( BOARD_CONNECTED_ITEM ), _HKI( "Layer" ),
1909 &ZONE::GetLayer ) )
1911
1913 _HKI( "Net" ), isCopperZone );
1915 _HKI( "Net Class" ), isCopperZone );
1916
1917 propMgr.AddProperty( new PROPERTY<ZONE, unsigned>( _HKI( "Priority" ),
1919 .SetAvailableFunc( isCopperZone );
1920
1921 propMgr.AddProperty( new PROPERTY<ZONE, wxString>( _HKI( "Name" ),
1923
1924 const wxString groupKeepout = _HKI( "Keepout" );
1925
1926 propMgr.AddProperty( new PROPERTY<ZONE, bool>( _HKI( "Keep Out Tracks" ),
1929 groupKeepout )
1930 .SetAvailableFunc( isRuleArea );
1931
1932 propMgr.AddProperty( new PROPERTY<ZONE, bool>( _HKI( "Keep Out Vias" ),
1935 groupKeepout )
1936 .SetAvailableFunc( isRuleArea );
1937
1938 propMgr.AddProperty( new PROPERTY<ZONE, bool>( _HKI( "Keep Out Pads" ),
1941 groupKeepout )
1942 .SetAvailableFunc( isRuleArea );
1943
1944 propMgr.AddProperty( new PROPERTY<ZONE, bool>( _HKI( "Keep Out Zone Fills" ),
1947 groupKeepout )
1948 .SetAvailableFunc( isRuleArea );
1949
1950 propMgr.AddProperty( new PROPERTY<ZONE, bool>( _HKI( "Keep Out Footprints" ),
1953 groupKeepout )
1954 .SetAvailableFunc( isRuleArea );
1955
1956
1957 const wxString groupPlacement = _HKI( "Placement" );
1958
1959 propMgr.AddProperty( new PROPERTY<ZONE, bool>( _HKI( "Enable" ),
1962 groupPlacement )
1963 .SetAvailableFunc( isRuleArea );
1964
1965 propMgr.AddProperty( new PROPERTY_ENUM<ZONE, PLACEMENT_SOURCE_T>( _HKI( "Source Type" ),
1968 groupPlacement )
1969 .SetAvailableFunc( isRuleArea );
1970
1971 propMgr.AddProperty( new PROPERTY<ZONE, wxString>( _HKI( "Source Name" ),
1974 groupPlacement )
1975 .SetAvailableFunc( isRuleArea );
1976
1977
1978 const wxString groupFill = _HKI( "Fill Style" );
1979
1980 propMgr.AddProperty( new PROPERTY_ENUM<ZONE, ZONE_FILL_MODE>( _HKI( "Fill Mode" ),
1982 groupFill )
1983 .SetAvailableFunc( isCopperZone );
1984
1985 propMgr.AddProperty( new PROPERTY<ZONE, EDA_ANGLE>( _HKI( "Hatch Orientation" ),
1988 groupFill )
1989 .SetAvailableFunc( isCopperZone )
1990 .SetWriteableFunc( isHatchedFill );
1991
1992 auto atLeastMinWidthValidator =
1993 []( const wxAny&& aValue, EDA_ITEM* aZone ) -> VALIDATOR_RESULT
1994 {
1995 int val = aValue.As<int>();
1996 ZONE* zone = dynamic_cast<ZONE*>( aZone );
1997 wxCHECK( zone, std::nullopt );
1998
1999 if( val < zone->GetMinThickness() )
2000 return std::make_unique<VALIDATION_ERROR_MSG>( _( "Cannot be less than zone minimum width" ) );
2001
2002 return std::nullopt;
2003 };
2004
2005 propMgr.AddProperty( new PROPERTY<ZONE, int>( _HKI( "Hatch Width" ),
2007 groupFill )
2008 .SetAvailableFunc( isCopperZone )
2009 .SetWriteableFunc( isHatchedFill )
2010 .SetValidator( atLeastMinWidthValidator );
2011
2012 propMgr.AddProperty( new PROPERTY<ZONE, int>( _HKI( "Hatch Gap" ),
2014 groupFill )
2015 .SetAvailableFunc( isCopperZone )
2016 .SetWriteableFunc( isHatchedFill )
2017 .SetValidator( atLeastMinWidthValidator );
2018
2019 propMgr.AddProperty( new PROPERTY<ZONE, double>( _HKI( "Hatch Minimum Hole Ratio" ),
2021 groupFill )
2022 .SetAvailableFunc( isCopperZone )
2023 .SetWriteableFunc( isHatchedFill )
2025
2026 // TODO: Smoothing effort needs to change to enum (in dialog too)
2027 propMgr.AddProperty( new PROPERTY<ZONE, int>( _HKI( "Smoothing Effort" ),
2029 groupFill )
2030 .SetAvailableFunc( isCopperZone )
2031 .SetWriteableFunc( isHatchedFill );
2032
2033 propMgr.AddProperty( new PROPERTY<ZONE, double>( _HKI( "Smoothing Amount" ),
2035 groupFill )
2036 .SetAvailableFunc( isCopperZone )
2037 .SetWriteableFunc( isHatchedFill );
2038
2039 propMgr.AddProperty( new PROPERTY_ENUM<ZONE, ISLAND_REMOVAL_MODE>( _HKI( "Remove Islands" ),
2041 groupFill )
2042 .SetAvailableFunc( isCopperZone );
2043
2044 propMgr.AddProperty( new PROPERTY<ZONE, long long int>( _HKI( "Minimum Island Area" ),
2046 groupFill )
2047 .SetAvailableFunc( isCopperZone )
2048 .SetWriteableFunc( isAreaBasedIslandRemoval );
2049
2050 const wxString groupElectrical = _HKI( "Electrical" );
2051
2052 auto clearance = new PROPERTY<ZONE, std::optional<int>>( _HKI( "Clearance" ),
2055 clearance->SetAvailableFunc( isCopperZone );
2056 constexpr int maxClearance = pcbIUScale.mmToIU( ZONE_CLEARANCE_MAX_VALUE_MM );
2058
2059 auto minWidth = new PROPERTY<ZONE, int>( _HKI( "Minimum Width" ),
2062 minWidth->SetAvailableFunc( isCopperZone );
2063 constexpr int minMinWidth = pcbIUScale.mmToIU( ZONE_THICKNESS_MIN_VALUE_MM );
2065
2066 auto padConnections = new PROPERTY_ENUM<ZONE, ZONE_CONNECTION>( _HKI( "Pad Connections" ),
2068 padConnections->SetAvailableFunc( isCopperZone );
2069
2070 auto thermalGap = new PROPERTY<ZONE, int>( _HKI( "Thermal Relief Gap" ),
2073 thermalGap->SetAvailableFunc( isCopperZone );
2074 thermalGap->SetValidator( PROPERTY_VALIDATORS::PositiveIntValidator );
2075
2076 auto thermalSpokeWidth = new PROPERTY<ZONE, int>( _HKI( "Thermal Relief Spoke Width" ),
2079 thermalSpokeWidth->SetAvailableFunc( isCopperZone );
2080 thermalSpokeWidth->SetValidator( atLeastMinWidthValidator );
2081
2082 propMgr.AddProperty( clearance, groupElectrical );
2083 propMgr.AddProperty( minWidth, groupElectrical );
2084 propMgr.AddProperty( padConnections, groupElectrical );
2085 propMgr.AddProperty( thermalGap, groupElectrical );
2086 propMgr.AddProperty( thermalSpokeWidth, groupElectrical );
2087 }
2089
types::KiCadObjectType ToProtoEnum(KICAD_T aValue)
Definition api_enums.cpp:97
KICAD_T FromProtoEnum(types::KiCadObjectType aValue)
Definition api_enums.cpp:36
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:83
BOARD_ITEM(BOARD_ITEM *aParent, KICAD_T idtype, PCB_LAYER_ID aLayer=F_Cu)
Definition board_item.h:85
int GetY() const
Definition board_item.h:105
int GetX() const
Definition board_item.h:99
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:214
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:899
std::unordered_map< const ZONE *, BOX2I > m_ZoneBBoxCache
Definition board.h:1408
BOARD_DESIGN_SETTINGS & GetDesignSettings() const
Definition board.cpp:1069
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:55
int GetLocalThermalGapOverride(wxString *aSource) const
Definition pad.cpp:1768
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...
int FullPointCount() const
Return the number of points in the shape poly set.
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:1155
int m_borderHatchPitch
Definition zone.h:901
wxString m_placementAreaSource
Definition zone.h:827
bool m_isRuleArea
Definition zone.h:820
void SetDoNotAllowPads(bool aEnable)
Definition zone.h:720
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:801
bool GetIsRuleArea() const
Accessors to parameters used in Rule Area zones:
Definition zone.h:701
PLACEMENT_SOURCE_T m_placementAreaSourceType
Definition zone.h:826
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:839
bool UnFill()
Removes the zone filling.
Definition zone.cpp:454
bool GetDoNotAllowVias() const
Definition zone.h:712
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:1610
void SetCornerRadius(unsigned int aRadius)
Definition zone.cpp:665
ZONE_FILL_MODE m_fillMode
Definition zone.h:870
bool m_doNotAllowFootprints
Definition zone.h:842
int m_ZoneMinThickness
Definition zone.h:846
void AddPolygon(std::vector< VECTOR2I > &aPolygon)
Add a polygon to the zone outline.
Definition zone.cpp:1118
double m_hatchSmoothingValue
Definition zone.h:878
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:1547
int m_thermalReliefSpokeWidth
Definition zone.h:868
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:873
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:1305
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:1078
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:905
wxString m_zoneName
An optional unique name for this zone, used for identifying it in DRC checking.
Definition zone.h:805
void HatchBorder()
Compute the hatch lines depending on the hatch parameters and stores it in the zone's attribute m_bor...
Definition zone.cpp:1245
std::map< PCB_LAYER_ID, std::shared_ptr< SHAPE_POLY_SET > > m_FilledPolysList
Definition zone.h:892
void SetBorderDisplayStyle(ZONE_BORDER_DISPLAY_STYLE aBorderHatchStyle, int aBorderHatchPitch, bool aRebuilBorderdHatch)
Set all hatch parameters for the zone.
Definition zone.cpp:1226
bool GetDoNotAllowPads() const
Definition zone.h:714
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:908
wxString GetFriendlyName() const override
Definition zone.cpp:1007
bool GetDoNotAllowTracks() const
Definition zone.h:713
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:865
std::map< PCB_LAYER_ID, ZONE_LAYER_PROPERTIES > m_layerProperties
Definition zone.h:809
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:840
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:709
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:723
LSET m_fillFlags
Temp variables used while filling.
Definition zone.h:895
SHAPE_POLY_SET * Outline()
Definition zone.h:331
bool m_doNotAllowPads
Definition zone.h:841
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:980
bool IsIsland(PCB_LAYER_ID aLayer, int aPolyIdx) const
Check if a given filled polygon is an insulated island.
Definition zone.cpp:1322
SHAPE_POLY_SET * m_Poly
Outline of the zone.
Definition zone.h:800
TEARDROP_TYPE m_teardropType
Definition zone.h:833
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:898
~ZONE()
Definition zone.cpp:120
long long int GetMinIslandArea() const
Definition zone.h:726
int m_hatchSmoothingLevel
Definition zone.h:874
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:1719
LSET m_layerSet
Definition zone.h:807
void SetIsRuleArea(bool aEnable)
Definition zone.h:702
int m_ZoneClearance
Definition zone.h:845
void CopyFrom(const BOARD_ITEM *aOther) override
Definition zone.cpp:113
void SetDoNotAllowTracks(bool aEnable)
Definition zone.h:719
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:825
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:1297
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:1089
void Rotate(const VECTOR2I &aCentre, const EDA_ANGLE &aAngle) override
Rotate the outlines.
Definition zone.cpp:1035
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:1291
int m_hatchGap
Definition zone.h:872
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:880
bool GetPlacementAreaEnabled() const
Definition zone.h:703
void SetDoNotAllowVias(bool aEnable)
Definition zone.h:718
bool IsTeardropArea() const
Definition zone.h:676
std::vector< SEG > m_borderHatchLines
Definition zone.h:902
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:1046
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:1369
int m_fillVersion
Definition zone.h:847
const VECTOR2I & GetCornerPosition(int aCornerIndex) const
Definition zone.h:555
bool GetDoNotAllowFootprints() const
Definition zone.h:715
ZONE_FILL_MODE GetFillMode() const
Definition zone.h:220
double m_hatchHoleMinArea
Definition zone.h:879
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:721
void SetBorderHatchPitch(int aPitch)
Definition zone.h:737
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:1334
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:1617
int GetHatchGap() const
Definition zone.h:309
double CalculateOutlineArea()
Compute the area of the zone outline (not the filled area).
Definition zone.cpp:1540
void SetHatchHoleMinArea(double aPct)
Definition zone.h:322
unsigned m_priority
Definition zone.h:815
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:838
ISLAND_REMOVAL_MODE m_islandRemovalMode
Definition zone.h:849
bool m_isFilled
True when a zone was filled, false after deleting the filled areas.
Definition zone.h:858
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:1135
bool GetDoNotAllowZoneFills() const
Definition zone.h:711
void MoveEdge(const VECTOR2I &offset, int aEdge)
Move the outline Edge.
Definition zone.cpp:1020
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:867
bool IsOnCopperLayer() const override
Definition zone.cpp:511
double CalculateFilledArea()
Compute the area currently occupied by the zone fill.
Definition zone.cpp:1529
void SetDoNotAllowZoneFills(bool aEnable)
Definition zone.h:717
int m_hatchThickness
Definition zone.h:871
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:1581
void SetAssignedPriority(unsigned aPriority)
Definition zone.h:121
double m_area
Definition zone.h:907
unsigned int m_cornerRadius
Definition zone.h:802
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:1651
void UnHatchBorder()
Clear the zone's hatch.
Definition zone.cpp:1239
void SetIslandRemovalMode(ISLAND_REMOVAL_MODE aRemove)
Definition zone.h:724
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:727
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:844
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:1285
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:1572
ZONE_BORDER_DISPLAY_STYLE m_borderStyle
Definition zone.h:900
long long int m_minIslandArea
When island removal mode is set to AREA, islands below this area will be removed.
Definition zone.h:855
@ 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:1795
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:37
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:38
#define ZONE_BORDER_HATCH_MINDIST_MM
Definition zones.h:39
#define ZONE_THICKNESS_MIN_VALUE_MM
Definition zones.h:35
#define ZONE_BORDER_HATCH_MAXDIST_MM
Definition zones.h:40