KiCad PCB EDA Suite
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 (C) 1992-2022 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 <bitmaps.h>
28#include <geometry/shape_null.h>
29#include <pcb_edit_frame.h>
30#include <pcb_screen.h>
31#include <board.h>
33#include <pad.h>
34#include <zone.h>
35#include <string_utils.h>
36#include <math_for_graphics.h>
39#include <trigo.h>
40#include <i18n_utility.h>
41
42
43ZONE::ZONE( BOARD_ITEM_CONTAINER* aParent, bool aInFP ) :
44 BOARD_CONNECTED_ITEM( aParent, aInFP ? PCB_FP_ZONE_T : PCB_ZONE_T ),
45 m_area( 0.0 ),
46 m_outlinearea( 0.0 )
47{
48 m_Poly = new SHAPE_POLY_SET(); // Outlines
51 m_zoneName = wxEmptyString;
52 m_CornerSelection = nullptr; // no corner is selected
53 m_isFilled = false; // fill status : true when the zone is filled
58 m_priority = 0;
59 SetIsRuleArea( aInFP ); // Zones living in footprints have the rule area option
60 SetLocalFlags( 0 ); // flags temporary used in zone calculations
61 m_fillVersion = 5; // set the "old" way to build filled polygon areas (< 6.0.x)
62
63 aParent->GetZoneSettings().ExportSetting( *this );
64
68
69 m_needRefill = false; // True only after edits.
70}
71
72
73ZONE::ZONE( const ZONE& aZone ) :
74 BOARD_CONNECTED_ITEM( aZone ),
75 m_Poly( nullptr ),
76 m_CornerSelection( nullptr )
77{
79}
80
81
82ZONE& ZONE::operator=( const ZONE& aOther )
83{
85
87
88 return *this;
89}
90
91
93{
94 delete m_Poly;
95 delete m_CornerSelection;
96}
97
98
100{
101 // members are expected non initialize in this.
102 // InitDataFromSrcInCopyCtor() is expected to be called only from a copy constructor.
103
104 // Copy only useful EDA_ITEM flags:
105 m_flags = aZone.m_flags;
107
108 // Replace the outlines for aZone outlines.
109 delete m_Poly;
110 m_Poly = new SHAPE_POLY_SET( *aZone.m_Poly );
111
114 m_zoneName = aZone.m_zoneName;
115 m_priority = aZone.m_priority;
117 SetLayerSet( aZone.GetLayerSet() );
118
124
126 m_ZoneClearance = aZone.m_ZoneClearance; // clearance value
131
132 m_isFilled = aZone.m_isFilled;
135
138
139 m_fillMode = aZone.m_fillMode; // solid vs. hatched
141 m_hatchGap = aZone.m_hatchGap;
147
148 // For corner moving, corner index to drag, or nullptr if no selection
149 delete m_CornerSelection;
150 m_CornerSelection = nullptr;
151
152 for( PCB_LAYER_ID layer : aZone.GetLayerSet().Seq() )
153 {
154 std::shared_ptr<SHAPE_POLY_SET> fill = aZone.m_FilledPolysList.at( layer );
155
156 if( fill )
157 m_FilledPolysList[layer] = std::make_shared<SHAPE_POLY_SET>( *fill );
158 else
159 m_FilledPolysList[layer] = std::make_shared<SHAPE_POLY_SET>();
160
161 m_filledPolysHash[layer] = aZone.m_filledPolysHash.at( layer );
162 m_insulatedIslands[layer] = aZone.m_insulatedIslands.at( layer );
163 }
164
168
169 SetLocalFlags( aZone.GetLocalFlags() );
170
171 m_netinfo = aZone.m_netinfo;
172 m_area = aZone.m_area;
174}
175
176
178{
179 return new ZONE( *this );
180}
181
182
183bool ZONE::HigherPriority( const ZONE* aOther ) const
184{
185 // Teardrops are always higher priority than regular zones, so if one zone is a teardrop
186 // and the other is not, then return higher priority as the teardrop
188 ^ ( aOther->m_teardropType == TEARDROP_TYPE::TD_NONE ) )
189 {
190 return static_cast<int>( m_teardropType ) > static_cast<int>( aOther->m_teardropType );
191 }
192
193 if( m_priority != aOther->m_priority )
194 return m_priority > aOther->m_priority;
195
196 return m_Uuid > aOther->m_Uuid;
197}
198
199
200bool ZONE::SameNet( const ZONE* aOther ) const
201{
202 return GetNetCode() == aOther->GetNetCode();
203}
204
205
207{
208 bool change = false;
209
210 for( std::pair<const PCB_LAYER_ID, std::shared_ptr<SHAPE_POLY_SET>>& pair : m_FilledPolysList )
211 {
212 change |= !pair.second->IsEmpty();
213 m_insulatedIslands[pair.first].clear();
214 pair.second->RemoveAllContours();
215 }
216
217 m_isFilled = false;
218 m_fillFlags.reset();
219
220 return change;
221}
222
223
225{
226 return GetCornerPosition( 0 );
227}
228
229
231{
232 return BOARD_ITEM::GetLayer();
233}
234
235
237{
238 if( m_layerSet.size() )
239 return m_layerSet.UIOrder()[0];
240 else
241 return UNDEFINED_LAYER;
242}
243
244
246{
247 return ( m_layerSet & LSET::AllCuMask() ).count() > 0;
248}
249
250
252{
253 SetLayerSet( LSET( aLayer ) );
254}
255
256
257void ZONE::SetLayerSet( LSET aLayerSet )
258{
259 if( aLayerSet.count() == 0 )
260 return;
261
262 if( m_layerSet != aLayerSet )
263 {
264 SetNeedRefill( true );
265
266 UnFill();
267
268 m_FilledPolysList.clear();
269 m_filledPolysHash.clear();
270 m_insulatedIslands.clear();
271
272 for( PCB_LAYER_ID layer : aLayerSet.Seq() )
273 {
274 m_FilledPolysList[layer] = std::make_shared<SHAPE_POLY_SET>();
275 m_filledPolysHash[layer] = {};
276 m_insulatedIslands[layer] = {};
277 }
278 }
279
280 m_layerSet = aLayerSet;
281}
282
283
284void ZONE::ViewGetLayers( int aLayers[], int& aCount ) const
285{
286 LSEQ layers = m_layerSet.Seq();
287
288 for( unsigned int idx = 0; idx < layers.size(); idx++ )
289 aLayers[idx] = LAYER_ZONE_START + layers[idx];
290
291 aCount = layers.size();
292}
293
294
295double ZONE::ViewGetLOD( int aLayer, KIGFX::VIEW* aView ) const
296{
297 constexpr double HIDE = std::numeric_limits<double>::max();
298
299 return aView->IsLayerVisible( LAYER_ZONES ) ? 0.0 : HIDE;
300}
301
302
303bool ZONE::IsOnLayer( PCB_LAYER_ID aLayer ) const
304{
305 return m_layerSet.test( aLayer );
306}
307
308
310{
311 return m_Poly->BBox();
312}
313
314
315int ZONE::GetThermalReliefGap( PAD* aPad, wxString* aSource ) const
316{
317 if( aPad->GetLocalThermalGapOverride() == 0 )
318 {
319 if( aSource )
320 *aSource = _( "zone" );
321
322 return m_thermalReliefGap;
323 }
324
325 return aPad->GetLocalThermalGapOverride( aSource );
326
327}
328
329
330void ZONE::SetCornerRadius( unsigned int aRadius )
331{
332 if( m_cornerRadius != aRadius )
333 SetNeedRefill( true );
334
335 m_cornerRadius = aRadius;
336}
337
338
340
341
343{
344 if( !m_filledPolysHash.count( aLayer ) )
345 return g_nullPoly.GetHash();
346 else
347 return m_filledPolysHash.at( aLayer );
348}
349
350
352{
353 if( !m_FilledPolysList.count( aLayer ) )
355 else
356 m_filledPolysHash[aLayer] = m_FilledPolysList.at( aLayer )->GetHash();
357}
358
359
360bool ZONE::HitTest( const VECTOR2I& aPosition, int aAccuracy ) const
361{
362 // When looking for an "exact" hit aAccuracy will be 0 which works poorly for very thin
363 // lines. Give it a floor.
364 int accuracy = std::max( aAccuracy, pcbIUScale.mmToIU( 0.1 ) );
365
366 return HitTestForCorner( aPosition, accuracy * 2 ) || HitTestForEdge( aPosition, accuracy );
367}
368
369
370bool ZONE::HitTestForCorner( const VECTOR2I& refPos, int aAccuracy,
371 SHAPE_POLY_SET::VERTEX_INDEX* aCornerHit ) const
372{
373 return m_Poly->CollideVertex( VECTOR2I( refPos ), aCornerHit, aAccuracy );
374}
375
376
377bool ZONE::HitTestForEdge( const VECTOR2I& refPos, int aAccuracy,
378 SHAPE_POLY_SET::VERTEX_INDEX* aCornerHit ) const
379{
380 return m_Poly->CollideEdge( VECTOR2I( refPos ), aCornerHit, aAccuracy );
381}
382
383
384bool ZONE::HitTest( const BOX2I& aRect, bool aContained, int aAccuracy ) const
385{
386 // Calculate bounding box for zone
387 BOX2I bbox = GetBoundingBox();
388 bbox.Normalize();
389
390 BOX2I arect = aRect;
391 arect.Normalize();
392 arect.Inflate( aAccuracy );
393
394 if( aContained )
395 {
396 return arect.Contains( bbox );
397 }
398 else
399 {
400 // Fast test: if aBox is outside the polygon bounding box, rectangles cannot intersect
401 if( !arect.Intersects( bbox ) )
402 return false;
403
404 int count = m_Poly->TotalVertices();
405
406 for( int ii = 0; ii < count; ii++ )
407 {
408 VECTOR2I vertex = m_Poly->CVertex( ii );
409 VECTOR2I vertexNext = m_Poly->CVertex( ( ii + 1 ) % count );
410
411 // Test if the point is within the rect
412 if( arect.Contains( vertex ) )
413 return true;
414
415 // Test if this edge intersects the rect
416 if( arect.Intersects( vertex, vertexNext ) )
417 return true;
418 }
419
420 return false;
421 }
422}
423
424
425int ZONE::GetLocalClearance( wxString* aSource ) const
426{
427 if( m_isRuleArea )
428 return 0;
429
430 if( aSource )
431 *aSource = _( "zone" );
432
433 return m_ZoneClearance;
434}
435
436
437bool ZONE::HitTestFilledArea( PCB_LAYER_ID aLayer, const VECTOR2I& aRefPos, int aAccuracy ) const
438{
439 // Rule areas have no filled area, but it's generally nice to treat their interior as if it were
440 // filled so that people don't have to select them by their outline (which is min-width)
441 if( GetIsRuleArea() )
442 return m_Poly->Contains( aRefPos, -1, aAccuracy );
443
444 if( !m_FilledPolysList.count( aLayer ) )
445 return false;
446
447 return m_FilledPolysList.at( aLayer )->Contains( aRefPos, -1, aAccuracy );
448}
449
450
451bool ZONE::HitTestCutout( const VECTOR2I& aRefPos, int* aOutlineIdx, int* aHoleIdx ) const
452{
453 // Iterate over each outline polygon in the zone and then iterate over
454 // each hole it has to see if the point is in it.
455 for( int i = 0; i < m_Poly->OutlineCount(); i++ )
456 {
457 for( int j = 0; j < m_Poly->HoleCount( i ); j++ )
458 {
459 if( m_Poly->Hole( i, j ).PointInside( aRefPos ) )
460 {
461 if( aOutlineIdx )
462 *aOutlineIdx = i;
463
464 if( aHoleIdx )
465 *aHoleIdx = j;
466
467 return true;
468 }
469 }
470 }
471
472 return false;
473}
474
475
476void ZONE::GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_ITEM>& aList )
477{
478 wxString msg;
479
480 if( GetIsRuleArea() )
481 msg = _( "Rule Area" );
482 else if( IsTeardropArea() )
483 msg = _( "Teardrop Area" );
484 else if( IsOnCopperLayer() )
485 msg = _( "Copper Zone" );
486 else
487 msg = _( "Non-copper Zone" );
488
489 // Display Cutout instead of Outline for holes inside a zone (i.e. when num contour !=0).
490 // Check whether the selected corner is in a hole; i.e., in any contour but the first one.
491 if( m_CornerSelection != nullptr && m_CornerSelection->m_contour > 0 )
492 msg << wxT( " " ) << _( "Cutout" );
493
494 aList.emplace_back( _( "Type" ), msg );
495
496 if( GetIsRuleArea() )
497 {
498 msg.Empty();
499
500 if( GetDoNotAllowVias() )
501 AccumulateDescription( msg, _( "No vias" ) );
502
503 if( GetDoNotAllowTracks() )
504 AccumulateDescription( msg, _( "No tracks" ) );
505
506 if( GetDoNotAllowPads() )
507 AccumulateDescription( msg, _( "No pads" ) );
508
510 AccumulateDescription( msg, _( "No copper zones" ) );
511
513 AccumulateDescription( msg, _( "No footprints" ) );
514
515 if( !msg.IsEmpty() )
516 aList.emplace_back( _( "Restrictions" ), msg );
517 }
518 else if( IsOnCopperLayer() )
519 {
520 if( aFrame->GetName() == PCB_EDIT_FRAME_NAME )
521 {
522 aList.emplace_back( _( "Net" ), UnescapeString( GetNetname() ) );
523
524 aList.emplace_back( _( "Resolved Netclass" ),
525 UnescapeString( GetEffectiveNetClass()->GetName() ) );
526 }
527
528 // Display priority level
529 aList.emplace_back( _( "Priority" ),
530 wxString::Format( wxT( "%d" ), GetAssignedPriority() ) );
531 }
532
533 if( aFrame->GetName() == PCB_EDIT_FRAME_NAME )
534 {
535 if( IsLocked() )
536 aList.emplace_back( _( "Status" ), _( "Locked" ) );
537 }
538
539 wxString layerDesc;
540 int count = 0;
541
542 for( PCB_LAYER_ID layer : m_layerSet.Seq() )
543 {
544 if( count == 0 )
545 layerDesc = GetBoard()->GetLayerName( layer );
546
547 count++;
548 }
549
550 if( count > 1 )
551 layerDesc.Printf( _( "%s and %d more" ), layerDesc, count - 1 );
552
553 aList.emplace_back( _( "Layer" ), layerDesc );
554
555 if( !m_zoneName.empty() )
556 aList.emplace_back( _( "Name" ), m_zoneName );
557
558 switch( m_fillMode )
559 {
560 case ZONE_FILL_MODE::POLYGONS: msg = _( "Solid" ); break;
561 case ZONE_FILL_MODE::HATCH_PATTERN: msg = _( "Hatched" ); break;
562 default: msg = _( "Unknown" ); break;
563 }
564
565 aList.emplace_back( _( "Fill Mode" ), msg );
566
567 aList.emplace_back( _( "Filled Area" ),
569
570 wxString source;
571 int clearance = GetOwnClearance( UNDEFINED_LAYER, &source );
572
573 if( !source.IsEmpty() )
574 {
575 aList.emplace_back( wxString::Format( _( "Min Clearance: %s" ),
576 aFrame->MessageTextFromValue( clearance ) ),
577 wxString::Format( _( "(from %s)" ),
578 source ) );
579 }
580
581 if( !m_FilledPolysList.empty() )
582 {
583 count = 0;
584
585 for( std::pair<const PCB_LAYER_ID, std::shared_ptr<SHAPE_POLY_SET>>& ii: m_FilledPolysList )
586 count += ii.second->TotalVertices();
587
588 aList.emplace_back( _( "Corner Count" ), wxString::Format( wxT( "%d" ), count ) );
589 }
590}
591
592
593void ZONE::Move( const VECTOR2I& offset )
594{
595 /* move outlines */
596 m_Poly->Move( offset );
597
598 HatchBorder();
599
600 for( std::pair<const PCB_LAYER_ID, std::shared_ptr<SHAPE_POLY_SET>>& pair : m_FilledPolysList )
601 pair.second->Move( offset );
602}
603
604
605void ZONE::MoveEdge( const VECTOR2I& offset, int aEdge )
606{
607 int next_corner;
608
609 if( m_Poly->GetNeighbourIndexes( aEdge, nullptr, &next_corner ) )
610 {
611 m_Poly->SetVertex( aEdge, m_Poly->CVertex( aEdge ) + VECTOR2I( offset ) );
612 m_Poly->SetVertex( next_corner, m_Poly->CVertex( next_corner ) + VECTOR2I( offset ) );
613 HatchBorder();
614
615 SetNeedRefill( true );
616 }
617}
618
619
620void ZONE::Rotate( const VECTOR2I& aCentre, const EDA_ANGLE& aAngle )
621{
622 m_Poly->Rotate( aAngle, VECTOR2I( aCentre ) );
623 HatchBorder();
624
625 /* rotate filled areas: */
626 for( std::pair<const PCB_LAYER_ID, std::shared_ptr<SHAPE_POLY_SET>>& pair : m_FilledPolysList )
627 pair.second->Rotate( aAngle, aCentre );
628}
629
630
631void ZONE::Flip( const VECTOR2I& aCentre, bool aFlipLeftRight )
632{
633 Mirror( aCentre, aFlipLeftRight );
634
635 SetLayerSet( FlipLayerMask( GetLayerSet(), GetBoard()->GetCopperLayerCount() ) );
636}
637
638
639void ZONE::Mirror( const VECTOR2I& aMirrorRef, bool aMirrorLeftRight )
640{
641 m_Poly->Mirror( aMirrorLeftRight, !aMirrorLeftRight, aMirrorRef );
642
643 HatchBorder();
644
645 for( std::pair<const PCB_LAYER_ID, std::shared_ptr<SHAPE_POLY_SET>>& pair : m_FilledPolysList )
646 pair.second->Mirror( aMirrorLeftRight, !aMirrorLeftRight, aMirrorRef );
647}
648
649
650void ZONE::RemoveCutout( int aOutlineIdx, int aHoleIdx )
651{
652 // Ensure the requested cutout is valid
653 if( m_Poly->OutlineCount() < aOutlineIdx || m_Poly->HoleCount( aOutlineIdx ) < aHoleIdx )
654 return;
655
656 SHAPE_POLY_SET cutPoly( m_Poly->Hole( aOutlineIdx, aHoleIdx ) );
657
658 // Add the cutout back to the zone
660
661 SetNeedRefill( true );
662}
663
664
665void ZONE::AddPolygon( const SHAPE_LINE_CHAIN& aPolygon )
666{
667 wxASSERT( aPolygon.IsClosed() );
668
669 // Add the outline as a new polygon in the polygon set
670 if( m_Poly->OutlineCount() == 0 )
671 m_Poly->AddOutline( aPolygon );
672 else
673 m_Poly->AddHole( aPolygon );
674
675 SetNeedRefill( true );
676}
677
678
679void ZONE::AddPolygon( std::vector<VECTOR2I>& aPolygon )
680{
681 if( aPolygon.empty() )
682 return;
683
684 SHAPE_LINE_CHAIN outline;
685
686 // Create an outline and populate it with the points of aPolygon
687 for( const VECTOR2I& pt : aPolygon )
688 outline.Append( pt );
689
690 outline.SetClosed( true );
691
692 AddPolygon( outline );
693}
694
695
696bool ZONE::AppendCorner( VECTOR2I aPosition, int aHoleIdx, bool aAllowDuplication )
697{
698 // Ensure the main outline exists:
699 if( m_Poly->OutlineCount() == 0 )
701
702 // If aHoleIdx >= 0, the corner musty be added to the hole, index aHoleIdx.
703 // (remember: the index of the first hole is 0)
704 // Return error if it does not exist.
705 if( aHoleIdx >= m_Poly->HoleCount( 0 ) )
706 return false;
707
708 m_Poly->Append( aPosition.x, aPosition.y, -1, aHoleIdx, aAllowDuplication );
709
710 SetNeedRefill( true );
711
712 return true;
713}
714
715
716wxString ZONE::GetSelectMenuText( UNITS_PROVIDER* aUnitsProvider ) const
717{
718 wxString layerDesc;
719 int count = 0;
720
721 for( PCB_LAYER_ID layer : m_layerSet.Seq() )
722 {
723 if( count == 0 )
724 layerDesc = GetBoard()->GetLayerName( layer );
725
726 count++;
727 }
728
729 if( count > 1 )
730 layerDesc.Printf( _( "%s and %d more" ), layerDesc, count - 1 );
731
732 // Check whether the selected contour is a hole (contour index > 0)
733 if( m_CornerSelection != nullptr && m_CornerSelection->m_contour > 0 )
734 {
735 if( GetIsRuleArea() )
736 return wxString::Format( _( "Rule Area Cutout on %s" ), layerDesc );
737 else
738 return wxString::Format( _( "Zone Cutout on %s" ), layerDesc );
739 }
740 else
741 {
742 if( GetIsRuleArea() )
743 return wxString::Format( _( "Rule Area on %s" ), layerDesc );
744 else
745 return wxString::Format( _( "Zone %s on %s" ), GetNetnameMsg(), layerDesc );
746 }
747}
748
749
751{
752 return m_borderHatchPitch;
753}
754
755
757 int aBorderHatchPitch, bool aRebuildBorderHatch )
758{
759 aBorderHatchPitch = std::max( aBorderHatchPitch,
761 aBorderHatchPitch = std::min( aBorderHatchPitch,
763 SetBorderHatchPitch( aBorderHatchPitch );
764 m_borderStyle = aBorderHatchStyle;
765
766 if( aRebuildBorderHatch )
767 HatchBorder();
768}
769
770
772{
773 m_borderHatchPitch = aPitch;
774}
775
776
778{
779 m_borderHatchLines.clear();
780}
781
782
783// Creates hatch lines inside the outline of the complex polygon
784// sort function used in ::HatchBorder to sort points by descending VECTOR2I.x values
785bool sortEndsByDescendingX( const VECTOR2I& ref, const VECTOR2I& tst )
786{
787 return tst.x < ref.x;
788}
789
790
792{
794
796 || m_borderHatchPitch == 0
797 || m_Poly->IsEmpty() )
798 {
799 return;
800 }
801
802 // define range for hatch lines
803 int min_x = m_Poly->CVertex( 0 ).x;
804 int max_x = m_Poly->CVertex( 0 ).x;
805 int min_y = m_Poly->CVertex( 0 ).y;
806 int max_y = m_Poly->CVertex( 0 ).y;
807
808 for( auto iterator = m_Poly->IterateWithHoles(); iterator; iterator++ )
809 {
810 if( iterator->x < min_x )
811 min_x = iterator->x;
812
813 if( iterator->x > max_x )
814 max_x = iterator->x;
815
816 if( iterator->y < min_y )
817 min_y = iterator->y;
818
819 if( iterator->y > max_y )
820 max_y = iterator->y;
821 }
822
823 // Calculate spacing between 2 hatch lines
824 int spacing;
825
827 spacing = m_borderHatchPitch;
828 else
829 spacing = m_borderHatchPitch * 2;
830
831 // set the "length" of hatch lines (the length on horizontal axis)
832 int hatch_line_len = m_borderHatchPitch;
833
834 // To have a better look, give a slope depending on the layer
835 int layer = GetFirstLayer();
836 int slope_flag = (layer & 1) ? 1 : -1; // 1 or -1
837 double slope = 0.707106 * slope_flag; // 45 degrees slope
838 int max_a, min_a;
839
840 if( slope_flag == 1 )
841 {
842 max_a = KiROUND( max_y - slope * min_x );
843 min_a = KiROUND( min_y - slope * max_x );
844 }
845 else
846 {
847 max_a = KiROUND( max_y - slope * max_x );
848 min_a = KiROUND( min_y - slope * min_x );
849 }
850
851 min_a = (min_a / spacing) * spacing;
852
853 // calculate an offset depending on layer number,
854 // for a better look of hatches on a multilayer board
855 int offset = (layer * 7) / 8;
856 min_a += offset;
857
858 // loop through hatch lines
859 std::vector<VECTOR2I> pointbuffer;
860 pointbuffer.reserve( 256 );
861
862 for( int a = min_a; a < max_a; a += spacing )
863 {
864 pointbuffer.clear();
865
866 // Iterate through all vertices
867 for( auto iterator = m_Poly->IterateSegmentsWithHoles(); iterator; iterator++ )
868 {
869 double x, y;
870
871 SEG segment = *iterator;
872
873 if( FindLineSegmentIntersection( a, slope, segment.A.x, segment.A.y, segment.B.x,
874 segment.B.y, x, y ) )
875 pointbuffer.emplace_back( KiROUND( x ), KiROUND( y ) );
876 }
877
878 // sort points in order of descending x (if more than 2) to
879 // ensure the starting point and the ending point of the same segment
880 // are stored one just after the other.
881 if( pointbuffer.size() > 2 )
882 sort( pointbuffer.begin(), pointbuffer.end(), sortEndsByDescendingX );
883
884 // creates lines or short segments inside the complex polygon
885 for( size_t ip = 0; ip + 1 < pointbuffer.size(); ip += 2 )
886 {
887 int dx = pointbuffer[ip + 1].x - pointbuffer[ip].x;
888
889 // Push only one line for diagonal hatch,
890 // or for small lines < twice the line length
891 // else push 2 small lines
893 || std::abs( dx ) < 2 * hatch_line_len )
894 {
895 m_borderHatchLines.emplace_back( SEG( pointbuffer[ip], pointbuffer[ ip + 1] ) );
896 }
897 else
898 {
899 double dy = pointbuffer[ip + 1].y - pointbuffer[ip].y;
900 slope = dy / dx;
901
902 if( dx > 0 )
903 dx = hatch_line_len;
904 else
905 dx = -hatch_line_len;
906
907 int x1 = KiROUND( pointbuffer[ip].x + dx );
908 int x2 = KiROUND( pointbuffer[ip + 1].x - dx );
909 int y1 = KiROUND( pointbuffer[ip].y + dx * slope );
910 int y2 = KiROUND( pointbuffer[ip + 1].y - dx * slope );
911
912 m_borderHatchLines.emplace_back( SEG( pointbuffer[ip].x, pointbuffer[ip].y,
913 x1, y1 ) );
914
915 m_borderHatchLines.emplace_back( SEG( pointbuffer[ip+1].x, pointbuffer[ip+1].y,
916 x2, y2 ) );
917 }
918 }
919 }
920}
921
922
924{
926}
927
928
930{
931 return BITMAPS::add_zone;
932}
933
934
936{
937 assert( aImage->Type() == PCB_ZONE_T || aImage->Type() == PCB_FP_ZONE_T );
938
939 std::swap( *((ZONE*) this), *((ZONE*) aImage) );
940}
941
942
944{
945 if( aLayer == UNDEFINED_LAYER )
946 {
947 for( std::pair<const PCB_LAYER_ID, std::shared_ptr<SHAPE_POLY_SET>>& pair : m_FilledPolysList )
948 pair.second->CacheTriangulation();
949
950 m_Poly->CacheTriangulation( false );
951 }
952 else
953 {
954 if( m_FilledPolysList.count( aLayer ) )
955 m_FilledPolysList[ aLayer ]->CacheTriangulation();
956 }
957}
958
959
960bool ZONE::IsIsland( PCB_LAYER_ID aLayer, int aPolyIdx ) const
961{
962 if( GetNetCode() < 1 )
963 return true;
964
965 if( !m_insulatedIslands.count( aLayer ) )
966 return false;
967
968 return m_insulatedIslands.at( aLayer ).count( aPolyIdx );
969}
970
971
972void ZONE::GetInteractingZones( PCB_LAYER_ID aLayer, std::vector<ZONE*>* aZones ) const
973{
974 int epsilon = pcbIUScale.mmToIU( 0.001 );
976
977 bbox.Inflate( epsilon );
978
979 for( ZONE* candidate : GetBoard()->Zones() )
980 {
981 if( candidate == this )
982 continue;
983
984 if( !candidate->GetLayerSet().test( aLayer ) )
985 continue;
986
987 if( candidate->GetIsRuleArea() )
988 continue;
989
990 if( candidate->GetNetCode() != GetNetCode() )
991 continue;
992
993 if( !candidate->GetCachedBoundingBox().Intersects( bbox ) )
994 continue;
995
996 for( auto iter = m_Poly->CIterate(); iter; iter++ )
997 {
998 if( candidate->m_Poly->Collide( iter.Get(), epsilon ) )
999 {
1000 aZones->push_back( candidate );
1001 break;
1002 }
1003 }
1004 }
1005}
1006
1007
1009 SHAPE_POLY_SET* aBoardOutline,
1010 SHAPE_POLY_SET* aSmoothedPolyWithApron ) const
1011{
1012 if( GetNumCorners() <= 2 ) // malformed zone. polygon calculations will not like it ...
1013 return false;
1014
1015 // Processing of arc shapes in zones is not yet supported because Clipper can't do boolean
1016 // operations on them. The poly outline must be converted to segments first.
1018 flattened.ClearArcs();
1019
1020 if( GetIsRuleArea() )
1021 {
1022 // We like keepouts just the way they are....
1023 aSmoothedPoly = flattened;
1024 return true;
1025 }
1026
1027 const BOARD* board = GetBoard();
1028 int maxError = ARC_HIGH_DEF;
1029 bool keepExternalFillets = false;
1032
1033 if( IsTeardropArea() ) // We use teardrop shapes with no smoothing
1034 // these shapes are already optimized
1035 smooth_requested = false;
1036
1037 if( board )
1038 {
1040
1041 maxError = bds.m_MaxError;
1042 keepExternalFillets = bds.m_ZoneKeepExternalFillets;
1043 }
1044
1045 auto smooth = [&]( SHAPE_POLY_SET& aPoly )
1046 {
1047
1048 if( !smooth_requested )
1049 return;
1050
1051 switch( m_cornerSmoothingType )
1052 {
1054 aPoly = aPoly.Chamfer( (int) m_cornerRadius );
1055 break;
1056
1058 {
1059 aPoly = aPoly.Fillet( (int) m_cornerRadius, maxError );
1060 break;
1061 }
1062
1063 default:
1064 break;
1065 }
1066 };
1067
1068 std::vector<ZONE*> interactingZones;
1069 GetInteractingZones( aLayer, &interactingZones );
1070
1071 SHAPE_POLY_SET* maxExtents = &flattened;
1072 SHAPE_POLY_SET withFillets;
1073
1074 aSmoothedPoly = flattened;
1075
1076 // Should external fillets (that is, those applied to concave corners) be kept? While it
1077 // seems safer to never have copper extend outside the zone outline, 5.1.x and prior did
1078 // indeed fill them so we leave the mode available.
1079 if( keepExternalFillets && smooth_requested )
1080 {
1081 withFillets = flattened;
1082 smooth( withFillets );
1083 withFillets.BooleanAdd( flattened, SHAPE_POLY_SET::PM_FAST );
1084 maxExtents = &withFillets;
1085 }
1086
1087 for( ZONE* zone : interactingZones )
1088 {
1089 SHAPE_POLY_SET flattened_outline = zone->Outline()->CloneDropTriangulation();
1090 flattened_outline.ClearArcs();
1091 aSmoothedPoly.BooleanAdd( flattened_outline, SHAPE_POLY_SET::PM_FAST );
1092 }
1093
1094 if( aBoardOutline )
1095 aSmoothedPoly.BooleanIntersection( *aBoardOutline, SHAPE_POLY_SET::PM_STRICTLY_SIMPLE );
1096
1097 smooth( aSmoothedPoly );
1098
1099 if( aSmoothedPolyWithApron )
1100 {
1101 SHAPE_POLY_SET poly = maxExtents->CloneDropTriangulation();
1102 poly.Inflate( m_ZoneMinThickness, 64 );
1103 *aSmoothedPolyWithApron = aSmoothedPoly;
1104 aSmoothedPolyWithApron->BooleanIntersection( poly, SHAPE_POLY_SET::PM_FAST );
1105 }
1106
1107 aSmoothedPoly.BooleanIntersection( *maxExtents, SHAPE_POLY_SET::PM_FAST );
1108
1109 return true;
1110}
1111
1112
1114{
1115 m_area = 0.0;
1116
1117 // Iterate over each outline polygon in the zone and then iterate over
1118 // each hole it has to compute the total area.
1119 for( std::pair<const PCB_LAYER_ID, std::shared_ptr<SHAPE_POLY_SET>>& pair : m_FilledPolysList )
1120 {
1121 std::shared_ptr<SHAPE_POLY_SET>& poly = pair.second;
1122
1123 for( int i = 0; i < poly->OutlineCount(); i++ )
1124 {
1125 m_area += poly->Outline( i ).Area();
1126
1127 for( int j = 0; j < poly->HoleCount( i ); j++ )
1128 m_area -= poly->Hole( i, j ).Area();
1129 }
1130 }
1131
1132 return m_area;
1133}
1134
1135
1137{
1139 return m_outlinearea;
1140}
1141
1142
1143void ZONE::TransformSmoothedOutlineToPolygon( SHAPE_POLY_SET& aCornerBuffer, int aClearance,
1144 int aMaxError, ERROR_LOC aErrorLoc,
1145 SHAPE_POLY_SET* aBoardOutline ) const
1146{
1147 // Creates the zone outline polygon (with holes if any)
1148 SHAPE_POLY_SET polybuffer;
1149
1150 // TODO: using GetFirstLayer() means it only works for single-layer zones....
1151 BuildSmoothedPoly( polybuffer, GetFirstLayer(), aBoardOutline );
1152
1153 // Calculate the polygon with clearance
1154 // holes are linked to the main outline, so only one polygon is created.
1155 if( aClearance )
1156 {
1157 const BOARD* board = GetBoard();
1158 int maxError = ARC_HIGH_DEF;
1159
1160 if( board )
1161 maxError = board->GetDesignSettings().m_MaxError;
1162
1163 int segCount = GetArcToSegmentCount( aClearance, maxError, FULL_CIRCLE );
1164
1165 if( aErrorLoc == ERROR_OUTSIDE )
1166 aClearance += aMaxError;
1167
1168 polybuffer.Inflate( aClearance, segCount );
1169 }
1170
1171 polybuffer.Fracture( SHAPE_POLY_SET::PM_FAST );
1172 aCornerBuffer.Append( polybuffer );
1173}
1174
1175
1177 ZONE( aParent, true )
1178{
1179 // in a footprint, net classes are not managed.
1180 // so set the net to NETINFO_LIST::ORPHANED_ITEM
1181 SetNetCode( -1, true );
1182}
1183
1184
1185FP_ZONE::FP_ZONE( const FP_ZONE& aZone ) :
1186 ZONE( aZone )
1187{
1189}
1190
1191
1193{
1194 ZONE::operator=( aOther );
1195 return *this;
1196}
1197
1198
1200{
1201 return new FP_ZONE( *this );
1202}
1203
1204
1205double FP_ZONE::ViewGetLOD( int aLayer, KIGFX::VIEW* aView ) const
1206{
1207 constexpr double HIDE = (double)std::numeric_limits<double>::max();
1208
1209 if( !aView )
1210 return 0;
1211
1212 if( !aView->IsLayerVisible( LAYER_ZONES ) )
1213 return HIDE;
1214
1215 bool flipped = GetParent() && GetParent()->GetLayer() == B_Cu;
1216
1217 // Handle Render tab switches
1218 if( !flipped && !aView->IsLayerVisible( LAYER_MOD_FR ) )
1219 return HIDE;
1220
1221 if( flipped && !aView->IsLayerVisible( LAYER_MOD_BK ) )
1222 return HIDE;
1223
1224 // Other layers are shown without any conditions
1225 return 0.0;
1226}
1227
1228
1229std::shared_ptr<SHAPE> ZONE::GetEffectiveShape( PCB_LAYER_ID aLayer, FLASHING aFlash ) const
1230{
1231 if( m_FilledPolysList.find( aLayer ) == m_FilledPolysList.end() )
1232 return std::make_shared<SHAPE_NULL>();
1233 else
1234 return m_FilledPolysList.at( aLayer );
1235}
1236
1237
1239 PCB_LAYER_ID aLayer, int aClearance, int aError,
1240 ERROR_LOC aErrorLoc, bool aIgnoreLineWidth ) const
1241{
1242 wxASSERT_MSG( !aIgnoreLineWidth, wxT( "IgnoreLineWidth has no meaning for zones." ) );
1243
1244 if( !m_FilledPolysList.count( aLayer ) )
1245 return;
1246
1247 if( !aClearance )
1248 {
1249 aCornerBuffer.Append( *m_FilledPolysList.at( aLayer ) );
1250 return;
1251 }
1252
1253 SHAPE_POLY_SET temp_buf = m_FilledPolysList.at( aLayer )->CloneDropTriangulation();
1254
1255 // Rebuild filled areas only if clearance is not 0
1256 int numSegs = GetArcToSegmentCount( aClearance, aError, FULL_CIRCLE );
1257
1258 if( aErrorLoc == ERROR_OUTSIDE )
1259 aClearance += aError;
1260
1261 temp_buf.InflateWithLinkedHoles( aClearance, numSegs, SHAPE_POLY_SET::PM_FAST );
1262
1263 aCornerBuffer.Append( temp_buf );
1264}
1265
1266
1268 int aError ) const
1269{
1270 if( m_FilledPolysList.count( aLayer ) && !m_FilledPolysList.at( aLayer )->IsEmpty() )
1271 aCornerBuffer.Append( *m_FilledPolysList.at( aLayer ) );
1272}
1273
1274
1275static struct ZONE_DESC
1276{
1278 {
1280 .Map( ZONE_CONNECTION::INHERITED, _HKI( "Inherited" ) )
1281 .Map( ZONE_CONNECTION::NONE, _HKI( "None" ) )
1282 .Map( ZONE_CONNECTION::THERMAL, _HKI( "Thermal reliefs" ) )
1283 .Map( ZONE_CONNECTION::FULL, _HKI( "Solid" ) )
1284 .Map( ZONE_CONNECTION::THT_THERMAL, _HKI( "Thermal reliefs for PTH" ) );
1285
1289 propMgr.AddProperty( new PROPERTY<ZONE, unsigned>( _HKI( "Priority" ),
1291 //propMgr.AddProperty( new PROPERTY<ZONE, bool>( "Filled",
1292 //&ZONE::SetIsFilled, &ZONE::IsFilled ) );
1293 propMgr.AddProperty( new PROPERTY<ZONE, wxString>( _HKI( "Name" ),
1295 propMgr.AddProperty( new PROPERTY<ZONE, int>( _HKI( "Clearance Override" ),
1298 propMgr.AddProperty( new PROPERTY<ZONE, int>( _HKI( "Min Width" ),
1301 propMgr.AddProperty( new PROPERTY_ENUM<ZONE, ZONE_CONNECTION>( _HKI( "Pad Connections" ),
1303 propMgr.AddProperty( new PROPERTY<ZONE, int>( _HKI( "Thermal Relief Gap" ),
1306 propMgr.AddProperty( new PROPERTY<ZONE, int>( _HKI( "Thermal Relief Spoke Width" ),
1309 }
1311
constexpr int ARC_HIGH_DEF
Definition: base_units.h:121
constexpr EDA_IU_SCALE pcbIUScale
Definition: base_units.h:109
BITMAPS
A list of all bitmap identifiers.
Definition: bitmaps_list.h:33
A base class derived from BOARD_ITEM for items that can be connected and have a net,...
wxString GetNetnameMsg() const
virtual NETCLASS * GetEffectiveNetClass() const
Return the NETCLASS for this item.
bool SetNetCode(int aNetCode, bool aNoAssert)
Set net using a net code.
NETINFO_ITEM * m_netinfo
Store all information about the net that item belongs to.
virtual int GetOwnClearance(PCB_LAYER_ID aLayer, wxString *aSource=nullptr) const
Return an item's "own" clearance in internal units.
Container for design settings for a BOARD object.
Abstract interface for BOARD_ITEMs capable of storing other items inside.
virtual const ZONE_SETTINGS & GetZoneSettings() const
Fetch the zone settings for this container.
A base class for any item which can be embedded within the BOARD container class, and therefore insta...
Definition: board_item.h:50
virtual PCB_LAYER_ID GetLayer() const
Return the primary layer this item is on.
Definition: board_item.h:167
virtual const BOARD * GetBoard() const
Return the BOARD in which this BOARD_ITEM resides, or NULL if none.
Definition: board_item.cpp:37
virtual bool IsLocked() const
Definition: board_item.cpp:65
BOARD_ITEM_CONTAINER * GetParent() const
Definition: board_item.h:150
Information pertinent to a Pcbnew printed circuit board.
Definition: board.h:265
const wxString GetLayerName(PCB_LAYER_ID aLayer) const
Return the name of a aLayer.
Definition: board.cpp:399
BOARD_DESIGN_SETTINGS & GetDesignSettings() const
Definition: board.cpp:617
BOX2< Vec > & Normalize()
Ensure that the height and width are positive.
Definition: box2.h:119
bool Intersects(const BOX2< Vec > &aRect) const
Definition: box2.h:269
bool Contains(const Vec &aPoint) const
Definition: box2.h:141
BOX2< Vec > & Inflate(coord_type dx, coord_type dy)
Inflates the rectangle horizontally by dx and vertically by dy.
Definition: box2.h:506
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:85
EDA_ITEM & operator=(const EDA_ITEM &aItem)
Assign the members of aItem to another object.
Definition: eda_item.cpp:240
const KIID m_Uuid
Definition: eda_item.h:492
bool m_forceVisible
Definition: eda_item.h:497
KICAD_T Type() const
Returns the type of object.
Definition: eda_item.h:97
EDA_ITEM_FLAGS m_flags
Definition: eda_item.h:498
static ENUM_MAP< T > & Instance()
Definition: property.h:512
A specialization of ZONE for use in footprints.
Definition: zone.h:897
FP_ZONE(BOARD_ITEM_CONTAINER *aParent)
Definition: zone.cpp:1176
FP_ZONE & operator=(const FP_ZONE &aOther)
Definition: zone.cpp:1192
double ViewGetLOD(int aLayer, KIGFX::VIEW *aView) const override
Return the level of detail (LOD) of the item.
Definition: zone.cpp:1205
EDA_ITEM * Clone() const override
Create a duplicate of this item with linked list members set to NULL.
Definition: zone.cpp:1199
Hold a (potentially large) number of VIEW_ITEMs and renders them on a graphics device provided by the...
Definition: view.h:69
bool IsLayerVisible(int aLayer) const
Return information about visibility of a particular layer.
Definition: view.h:410
LSEQ is a sequence (and therefore also a set) of PCB_LAYER_IDs.
Definition: layer_ids.h:491
LSET is a set of PCB_LAYER_IDs.
Definition: layer_ids.h:530
LSEQ UIOrder() const
Definition: lset.cpp:916
LSEQ Seq(const PCB_LAYER_ID *aWishListSequence, unsigned aCount) const
Return an LSEQ from the union of this LSET and a desired sequence.
Definition: lset.cpp:411
static LSET AllCuMask(int aCuLayerCount=MAX_CU_LAYERS)
Return a mask holding the requested number of Cu PCB_LAYER_IDs.
Definition: lset.cpp:773
Definition: pad.h:58
int GetLocalThermalGapOverride(wxString *aSource=nullptr) const
Definition: pad.cpp:925
Provide class metadata.Helper macro to map type hashes to names.
Definition: property_mgr.h:63
void AddProperty(PROPERTY_BASE *aProperty)
Register a property.
void InheritsAfter(TYPE_ID aDerived, TYPE_ID aBase)
Declare an inheritance relationship between types.
static PROPERTY_MANAGER & Instance()
Definition: property_mgr.h:65
Definition: seg.h:42
VECTOR2I A
Definition: seg.h:49
VECTOR2I B
Definition: seg.h:50
bool PointInside(const VECTOR2I &aPt, int aAccuracy=0, bool aUseBBoxCache=false) const
Check if point aP lies inside a polygon (any type) defined by the line chain.
Represent a polyline containing arcs as well as line segments: A chain of connected line and/or arc s...
bool IsClosed() const override
void SetClosed(bool aClosed)
Mark the line chain as closed (i.e.
void Append(int aX, int aY, bool aAllowDuplication=false)
Append a new point at the end of the line chain.
Represent a set of closed polygons.
void Rotate(const EDA_ANGLE &aAngle, const VECTOR2I &aCenter={ 0, 0 }) override
Rotate all vertices by a given angle.
bool CollideEdge(const VECTOR2I &aPoint, VERTEX_INDEX *aClosestVertex=nullptr, int aClearance=0) const
Check whether aPoint collides with any edge of any of the contours of the polygon.
ITERATOR IterateWithHoles(int aOutline)
void Fracture(POLYGON_MODE aFastMode)
Convert a single outline slitted ("fractured") polygon into a set ouf outlines with holes.
void ClearArcs()
Appends a vertex at the end of the given outline/hole (default: the last outline)
int AddOutline(const SHAPE_LINE_CHAIN &aOutline)
Adds a new hole to the given outline (default: last) and returns its index.
double Area()
Count the number of arc shapes present.
void SetVertex(const VERTEX_INDEX &aIndex, const VECTOR2I &aPos)
Accessor function to set the position of a specific point.
bool IsEmpty() const
void BooleanAdd(const SHAPE_POLY_SET &b, POLYGON_MODE aFastMode)
Perform boolean polyset difference For aFastMode meaning, see function booleanOp.
CONST_ITERATOR CIterate(int aFirst, int aLast, bool aIterateHoles=false) const
int TotalVertices() const
Delete aIdx-th polygon from the set.
void Inflate(int aAmount, int aCircleSegCount, CORNER_STRATEGY aCornerStrategy=ROUND_ALL_CORNERS)
Perform outline inflation/deflation.
void BooleanIntersection(const SHAPE_POLY_SET &b, POLYGON_MODE aFastMode)
Perform boolean polyset union between a and b, store the result in it self For aFastMode meaning,...
void CacheTriangulation(bool aPartition=true)
Build a polygon triangulation, needed to draw a polygon on OpenGL and in some other calculations.
MD5_HASH GetHash() const
int HoleCount(int aOutline) const
Return the reference to aIndex-th outline in the set.
int Append(int x, int y, int aOutline=-1, int aHole=-1, bool aAllowDuplication=false)
Add a new vertex to the contour indexed by aOutline and aHole (defaults to the outline of the last po...
bool GetNeighbourIndexes(int aGlobalIndex, int *aPrevious, int *aNext)
Return the global indexes of the previous and the next corner of the aGlobalIndex-th corner of a cont...
int AddHole(const SHAPE_LINE_CHAIN &aHole, int aOutline=-1)
Return the area of this poly set.
void Mirror(bool aX=true, bool aY=false, const VECTOR2I &aRef={ 0, 0 })
Mirror the line points about y or x (or both)
SHAPE_LINE_CHAIN & Outline(int aIndex)
SHAPE_LINE_CHAIN & Hole(int aOutline, int aHole)
Return the aIndex-th subpolygon in the set.
int NewOutline()
Creates a new hole in a given outline.
bool CollideVertex(const VECTOR2I &aPoint, VERTEX_INDEX *aClosestVertex=nullptr, int aClearance=0) const
Check whether aPoint collides with any vertex of any of the contours of the polygon.
const VECTOR2I & CVertex(int aIndex, int aOutline, int aHole) const
Return the aGlobalIndex-th vertex in the poly set.
int OutlineCount() const
Return the number of vertices in a given outline/hole.
void Move(const VECTOR2I &aVector) override
bool Contains(const VECTOR2I &aP, int aSubpolyIndex=-1, int aAccuracy=0, bool aUseBBoxCaches=false) const
Return true if a given subpolygon contains the point aP.
SHAPE_POLY_SET CloneDropTriangulation() const
Creates a new empty polygon in the set and returns its index.
void InflateWithLinkedHoles(int aFactor, int aCircleSegmentsCount, POLYGON_MODE aFastMode)
Perform outline inflation/deflation, using round corners.
SEGMENT_ITERATOR IterateSegmentsWithHoles()
Return an iterator object, for the aOutline-th outline in the set (with holes).
const BOX2I BBox(int aClearance=0) const override
Compute a bounding box of the shape, with a margin of aClearance a collision.
wxString MessageTextFromValue(double aValue, bool aAddUnitLabel=true, EDA_DATA_TYPE aType=EDA_DATA_TYPE::DISTANCE)
A lower-precision version of StringFromValue().
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:57
SHAPE_POLY_SET::VERTEX_INDEX * m_CornerSelection
The index of the corner being moved or nullptr if no corner is selected.
Definition: zone.h:857
void SetNeedRefill(bool aNeedRefill)
Definition: zone.h:239
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:360
int m_borderHatchPitch
Definition: zone.h:879
bool m_isRuleArea
Definition: zone.h:793
ZONE & operator=(const ZONE &aOther)
Definition: zone.cpp:82
int m_cornerSmoothingType
Definition: zone.h:776
void Mirror(const VECTOR2I &aMirrorRef, bool aMirrorLeftRight)
Mirror the outlines relative to a given horizontal axis the layer is not changed.
Definition: zone.cpp:639
void TransformSmoothedOutlineToPolygon(SHAPE_POLY_SET &aCornerBuffer, 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:1143
bool GetIsRuleArea() const
Accessors to parameters used in Rule Area zones:
Definition: zone.h:691
bool m_doNotAllowVias
Definition: zone.h:805
bool UnFill()
Removes the zone filling.
Definition: zone.cpp:206
bool GetDoNotAllowVias() const
Definition: zone.h:693
void TransformSolidAreasShapesToPolygon(PCB_LAYER_ID aLayer, SHAPE_POLY_SET &aCornerBuffer, int aError=ARC_HIGH_DEF) const
Convert solid areas full shapes to polygon set (the full shape is the polygon area with a thick outli...
Definition: zone.cpp:1267
void TransformShapeWithClearanceToPolygon(SHAPE_POLY_SET &aCornerBuffer, PCB_LAYER_ID aLayer, int aClearanceValue, 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:1238
void SetCornerRadius(unsigned int aRadius)
Definition: zone.cpp:330
ZONE_FILL_MODE m_fillMode
How to fill areas:
Definition: zone.h:843
bool m_doNotAllowFootprints
Definition: zone.h:808
int m_ZoneMinThickness
Definition: zone.h:812
virtual void ViewGetLayers(int aLayers[], int &aCount) const override
Return the all the layers within the VIEW the object is painted on.
Definition: zone.cpp:284
void AddPolygon(std::vector< VECTOR2I > &aPolygon)
Add a polygon to the zone outline.
Definition: zone.cpp:679
double m_hatchSmoothingValue
Definition: zone.h:851
void SetLocalFlags(int aFlags)
Definition: zone.h:303
int m_thermalReliefSpokeWidth
Definition: zone.h:834
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:451
EDA_ANGLE m_hatchOrientation
Definition: zone.h:846
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:943
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:883
wxString m_zoneName
An optional unique name for this zone, used for identifying it in DRC checking.
Definition: zone.h:780
void HatchBorder()
Compute the hatch lines depending on the hatch parameters and stores it in the zone's attribute m_bor...
Definition: zone.cpp:791
std::map< PCB_LAYER_ID, std::shared_ptr< SHAPE_POLY_SET > > m_FilledPolysList
Definition: zone.h:869
void SetBorderDisplayStyle(ZONE_BORDER_DISPLAY_STYLE aBorderHatchStyle, int aBorderHatchPitch, bool aRebuilBorderdHatch)
Set all hatch parameters for the zone.
Definition: zone.cpp:756
MD5_HASH GetHashValue(PCB_LAYER_ID aLayer)
Definition: zone.cpp:342
bool GetDoNotAllowPads() const
Definition: zone.h:695
const BOX2I GetBoundingBox() const override
Definition: zone.cpp:309
void SetMinThickness(int aMinThickness)
Definition: zone.h:245
void GetInteractingZones(PCB_LAYER_ID aLayer, std::vector< ZONE * > *aZones) const
Some intersecting zones, despite being on the same layer with the same net, cannot be merged due to o...
Definition: zone.cpp:972
double m_outlinearea
Definition: zone.h:886
bool GetDoNotAllowTracks() const
Definition: zone.h:694
int GetLocalFlags() const
Definition: zone.h:302
EDA_ITEM * Clone() const override
Create a duplicate of this item with linked list members set to NULL.
Definition: zone.cpp:177
bool m_doNotAllowCopperPour
Definition: zone.h:804
bool m_needRefill
False when a zone was refilled, true after changes in zone params.
Definition: zone.h:831
virtual void Flip(const VECTOR2I &aCentre, bool aFlipLeftRight) override
Flip this object, i.e.
Definition: zone.cpp:631
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:370
bool m_doNotAllowTracks
Definition: zone.h:806
void SetThermalReliefSpokeWidth(int aThermalReliefSpokeWidth)
Definition: zone.h:180
virtual PCB_LAYER_ID GetLayer() const override
Return the primary layer this item is on.
Definition: zone.cpp:230
virtual void SetLayer(PCB_LAYER_ID aLayer) override
Set the layer this item is on.
Definition: zone.cpp:251
LSET m_fillFlags
Definition: zone.h:873
bool m_doNotAllowPads
Definition: zone.h:807
void Move(const VECTOR2I &offset) override
Move the outlines.
Definition: zone.cpp:593
bool IsIsland(PCB_LAYER_ID aLayer, int aPolyIdx) const
Check if a given filled polygon is an insulated island.
Definition: zone.cpp:960
SHAPE_POLY_SET * m_Poly
Outline of the zone.
Definition: zone.h:775
TEARDROP_TYPE m_teardropType
Definition: zone.h:799
~ZONE()
Definition: zone.cpp:92
int m_hatchSmoothingLevel
Definition: zone.h:847
int GetLocalClearance() const
Definition: zone.h:145
LSET m_layerSet
Definition: zone.h:782
void SetIsRuleArea(bool aEnable)
Definition: zone.h:698
int m_ZoneClearance
Definition: zone.h:811
wxString GetZoneName() const
Definition: zone.h:117
int GetMinThickness() const
Definition: zone.h:244
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:377
void RemoveCutout(int aOutlineIdx, int aHoleIdx)
Remove a cutout from the zone.
Definition: zone.cpp:650
void Rotate(const VECTOR2I &aCentre, const EDA_ANGLE &aAngle) override
Rotate the outlines.
Definition: zone.cpp:620
bool HigherPriority(const ZONE *aOther) const
Definition: zone.cpp:183
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:437
BITMAPS GetMenuImage() const override
Return a pointer to an image to be used in menus.
Definition: zone.cpp:929
int m_hatchGap
Definition: zone.h:845
ZONE_CONNECTION GetPadConnection() const
Definition: zone.h:241
void InitDataFromSrcInCopyCtor(const ZONE &aZone)
Copy aZone data to me.
Definition: zone.cpp:99
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:476
virtual bool IsOnLayer(PCB_LAYER_ID) const override
Test to see if this object is on the given layer.
Definition: zone.cpp:303
int m_hatchBorderAlgorithm
Definition: zone.h:853
const BOX2I GetCachedBoundingBox() const
ONLY TO BE USED BY CLIENTS WHICH SET UP THE CACHE!
Definition: zone.h:133
bool IsTeardropArea() const
Definition: zone.h:675
std::vector< SEG > m_borderHatchLines
Definition: zone.h:880
VECTOR2I GetPosition() const override
Definition: zone.cpp:224
int GetThermalReliefSpokeWidth() const
Definition: zone.h:188
int GetBorderHatchPitch() const
HatchBorder related methods.
Definition: zone.cpp:750
void SetLocalClearance(int aClearance)
Definition: zone.h:146
void BuildHashValue(PCB_LAYER_ID aLayer)
Build the hash value of m_FilledPolysList, and store it internally in m_filledPolysHash.
Definition: zone.cpp:351
void SetThermalReliefGap(int aThermalReliefGap)
Definition: zone.h:169
void SetLayerSet(LSET aLayerSet) override
Definition: zone.cpp:257
bool BuildSmoothedPoly(SHAPE_POLY_SET &aSmoothedPoly, PCB_LAYER_ID aLayer, SHAPE_POLY_SET *aBoardOutline, SHAPE_POLY_SET *aSmoothedPolyWithApron=nullptr) const
Definition: zone.cpp:1008
int m_fillVersion
Definition: zone.h:813
const VECTOR2I & GetCornerPosition(int aCornerIndex) const
Definition: zone.h:524
bool GetDoNotAllowFootprints() const
Definition: zone.h:696
double m_hatchHoleMinArea
Definition: zone.h:852
virtual LSET GetLayerSet() const override
Return a std::bitset of all layers on which the item physically resides.
Definition: zone.h:115
bool GetDoNotAllowCopperPour() const
Definition: zone.h:692
void SetBorderHatchPitch(int aPitch)
Set the hatch pitch parameter for the zone.
Definition: zone.cpp:771
double CalculateOutlineArea()
Compute the area of the zone outline (not the filled area).
Definition: zone.cpp:1136
unsigned m_priority
Definition: zone.h:788
std::map< PCB_LAYER_ID, MD5_HASH > m_filledPolysHash
A hash value used in zone filling calculations to see if the filled areas are up to date.
Definition: zone.h:876
ISLAND_REMOVAL_MODE m_islandRemovalMode
Definition: zone.h:815
bool m_isFilled
True when a zone was filled, false after deleting the filled areas.
Definition: zone.h:824
virtual void SwapData(BOARD_ITEM *aImage) override
Swap data between aItem and aImage.
Definition: zone.cpp:935
ZONE(BOARD_ITEM_CONTAINER *parent, bool aInFP=false)
The ctor to build ZONE, but compatible with FP_ZONE requirement.
Definition: zone.cpp:43
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:696
void MoveEdge(const VECTOR2I &offset, int aEdge)
Move the outline Edge.
Definition: zone.cpp:605
int m_thermalReliefGap
Definition: zone.h:833
double ViewGetLOD(int aLayer, KIGFX::VIEW *aView) const override
Return the level of detail (LOD) of the item.
Definition: zone.cpp:295
bool IsOnCopperLayer() const override
Definition: zone.cpp:245
double CalculateFilledArea()
Compute the area currently occupied by the zone fill.
Definition: zone.cpp:1113
int m_hatchThickness
Definition: zone.h:844
void SetAssignedPriority(unsigned aPriority)
Definition: zone.h:101
double m_area
Definition: zone.h:885
unsigned int m_cornerRadius
Definition: zone.h:777
void SetPadConnection(ZONE_CONNECTION aPadConnection)
Definition: zone.h:242
void SetZoneName(const wxString &aName)
Definition: zone.h:118
void UnHatchBorder()
Clear the zone's hatch.
Definition: zone.cpp:777
PCB_LAYER_ID GetFirstLayer() const
Definition: zone.cpp:236
ZONE_CONNECTION m_PadConnection
Definition: zone.h:810
int GetThermalReliefGap() const
Definition: zone.h:177
static int GetDefaultHatchPitch()
Definition: zone.cpp:923
unsigned GetAssignedPriority() const
Definition: zone.h:106
int GetNumCorners(void) const
Access to m_Poly parameters.
Definition: zone.h:484
bool SameNet(const ZONE *aOther) const
Definition: zone.cpp:200
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:1229
ZONE_BORDER_DISPLAY_STYLE m_borderStyle
Definition: zone.h:878
long long int m_minIslandArea
When island removal mode is set to AREA, islands below this area will be removed.
Definition: zone.h:821
wxString GetSelectMenuText(UNITS_PROVIDER *aUnitsProvider) const override
Return the text to display to be used in the selection clarification context menu when multiple items...
Definition: zone.cpp:716
#define _HKI(x)
#define _(s)
static constexpr EDA_ANGLE & FULL_CIRCLE
Definition: eda_angle.h:410
#define PCB_EDIT_FRAME_NAME
a few functions useful in geometry calculations.
ERROR_LOC
When approximating an arc or circle, should the error be placed on the outside or inside of the curve...
@ ERROR_OUTSIDE
int GetArcToSegmentCount(int aRadius, int aErrorMax, const EDA_ANGLE &aArcAngle)
Some functions to handle hotkeys in KiCad.
FLASHING
Enum used during connectivity building to ensure we do not query connectivity while building the data...
Definition: layer_ids.h:147
@ LAYER_ZONES
Control for copper zone opacity/visibility (color ignored)
Definition: layer_ids.h:231
@ LAYER_MOD_FR
show footprints on front
Definition: layer_ids.h:208
@ LAYER_ZONE_START
Virtual layers for stacking zones and tracks on a given copper layer.
Definition: layer_ids.h:253
@ LAYER_MOD_BK
show footprints on back
Definition: layer_ids.h:209
PCB_LAYER_ID
A quick note on layer IDs:
Definition: layer_ids.h:59
@ B_Cu
Definition: layer_ids.h:95
@ UNDEFINED_LAYER
Definition: layer_ids.h:60
LSET FlipLayerMask(LSET aMask, int aCopperLayersCount)
Calculate the mask layer when flipping a footprint.
Definition: lset.cpp:590
constexpr int Mils2IU(const EDA_IU_SCALE &aIuScale, int mils)
Definition: eda_units.h:123
EDA_ANGLE abs(const EDA_ANGLE &aAngle)
Definition: eda_angle.h:401
#define TYPE_HASH(x)
Definition: property.h:60
@ PT_SIZE
Size expressed in distance units (mm/inch)
Definition: property.h:53
#define REGISTER_TYPE(x)
Definition: property_mgr.h:248
void Format(OUTPUTFORMATTER *out, int aNestLevel, int aCtl, const CPTREE &aTree)
Output a PTREE into s-expression format via an OUTPUTFORMATTER derivative.
Definition: ptree.cpp:200
wxString UnescapeString(const wxString &aSource)
void AccumulateDescription(wxString &aDesc, const wxString &aItem)
Utility to build comma separated lists in messages.
Definition: string_utils.h:322
constexpr int mmToIU(double mm) const
Definition: base_units.h:89
Structure to hold the necessary information in order to index a vertex on a SHAPE_POLY_SET object: th...
ZONE_DESC()
Definition: zone.cpp:1277
@ PCB_ZONE_T
class ZONE, a copper pour area
Definition: typeinfo.h:112
@ PCB_FP_ZONE_T
class ZONE, managed by a footprint
Definition: typeinfo.h:100
constexpr ret_type KiROUND(fp_type v)
Round a floating point number to an integer using "round halfway cases away from zero".
Definition: util.h:80
VECTOR2< int > VECTOR2I
Definition: vector2d.h:618
static SHAPE_POLY_SET g_nullPoly
Definition: zone.cpp:339
bool sortEndsByDescendingX(const VECTOR2I &ref, const VECTOR2I &tst)
Definition: zone.cpp:785
ENUM_TO_WXANY(ZONE_CONNECTION)
static struct ZONE_DESC _ZONE_DESC
ZONE_BORDER_DISPLAY_STYLE
Zone border styles.
Definition: zone_settings.h:49
ZONE_CONNECTION
How pads are covered by copper in zone.
Definition: zones.h:50
@ THERMAL
Use thermal relief for pads.
@ THT_THERMAL
Thermal relief only for THT pads.
@ NONE
Pads are not covered.
@ FULL
pads are covered by copper
#define ZONE_BORDER_HATCH_MINDIST_MM
Definition: zones.h:40
#define ZONE_THICKNESS_MIL
Definition: zones.h:35
#define ZONE_THERMAL_RELIEF_GAP_MIL
Definition: zones.h:33
#define ZONE_BORDER_HATCH_DIST_MIL
Definition: zones.h:39
#define ZONE_THERMAL_RELIEF_COPPER_WIDTH_MIL
Definition: zones.h:34
#define ZONE_BORDER_HATCH_MAXDIST_MM
Definition: zones.h:41