KiCad PCB EDA Suite
courtyard_overlap.cpp
Go to the documentation of this file.
1 
5 /*
6  * This program source code file is part of KiCad, a free EDA CAD application.
7  *
8  * Copyright (C) 2010 Dick Hollenbeck, dick@softplc.com
9  * Copyright (C) 2004-2017 Jean-Pierre Charras, jp.charras at wanadoo.fr
10  * Copyright (C) 2018 KiCad Developers, see AUTHORS.txt for contributors.
11  *
12  * This program is free software; you can redistribute it and/or
13  * modify it under the terms of the GNU General Public License
14  * as published by the Free Software Foundation; either version 2
15  * of the License, or (at your option) any later version.
16  *
17  * This program is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20  * GNU General Public License for more details.
21  *
22  * You should have received a copy of the GNU General Public License
23  * along with this program; if not, you may find one here:
24  * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
25  * or you may search the http://www.gnu.org website for the version 2 license,
26  * or you may write to the Free Software Foundation, Inc.,
27  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
28  */
29 
30 
31 #include <drc/courtyard_overlap.h>
32 
33 #include <class_module.h>
34 #include <tools/drc.h>
35 
36 #include <drc/drc_marker_factory.h>
37 
38 
46 static const wxChar* DRC_COURTYARD_TRACE = wxT( "KICAD_DRC_COURTYARD" );
47 
48 
50  const DRC_MARKER_FACTORY& aMarkerFactory, MARKER_HANDLER aMarkerHandler )
51  : DRC_PROVIDER( aMarkerFactory, aMarkerHandler )
52 {
53 }
54 
55 
56 bool DRC_COURTYARD_OVERLAP::RunDRC( BOARD& aBoard ) const
57 {
58  wxLogTrace( DRC_COURTYARD_TRACE, "Running DRC: Courtyard" );
59 
60  // Detects missing (or malformed) footprint courtyard,
61  // and for footprint with courtyard, courtyards overlap.
62  wxString msg;
63  bool success = true;
64 
65  const DRC_MARKER_FACTORY& marker_factory = GetMarkerFactory();
66 
67  // Update courtyard polygons, and test for missing courtyard definition:
68  for( auto footprint : aBoard.Modules() )
69  {
70  wxPoint pos = footprint->GetPosition();
71  bool is_ok = footprint->BuildPolyCourtyard();
72 
73  if( !is_ok && aBoard.GetDesignSettings().m_ProhibitOverlappingCourtyards )
74  {
75  auto marker = std::unique_ptr<MARKER_PCB>( marker_factory.NewMarker(
76  pos, footprint, DRCE_MALFORMED_COURTYARD_IN_FOOTPRINT ) );
77  HandleMarker( std::move( marker ) );
78  success = false;
79  }
80 
82  continue;
83 
84  if( footprint->GetPolyCourtyardFront().OutlineCount() == 0
85  && footprint->GetPolyCourtyardBack().OutlineCount() == 0 && is_ok )
86  {
87  auto marker = std::unique_ptr<MARKER_PCB>( marker_factory.NewMarker(
88  pos, footprint, DRCE_MISSING_COURTYARD_IN_FOOTPRINT ) );
89  HandleMarker( std::move( marker ) );
90  success = false;
91  }
92  }
93 
95  return success;
96 
97  wxLogTrace( DRC_COURTYARD_TRACE, "Checking for courtyard overlap" );
98 
99  // Now test for overlapping on top layer:
100  SHAPE_POLY_SET courtyard; // temporary storage of the courtyard of current footprint
101 
102  for( auto it1 = aBoard.Modules().begin(); it1 != aBoard.Modules().end(); it1++ )
103  {
104  auto footprint = *it1;
105 
106  if( footprint->GetPolyCourtyardFront().OutlineCount() == 0 )
107  continue; // No courtyard defined
108 
109  for( auto it2 = it1 + 1; it2 != aBoard.Modules().end(); it2++ )
110  {
111  auto candidate = *it2;
112 
113  if( candidate->GetPolyCourtyardFront().OutlineCount() == 0 )
114  continue; // No courtyard defined
115 
116  courtyard.RemoveAllContours();
117  courtyard.Append( footprint->GetPolyCourtyardFront() );
118 
119  // Build the common area between footprint and the candidate:
120  courtyard.BooleanIntersection(
121  candidate->GetPolyCourtyardFront(), SHAPE_POLY_SET::PM_FAST );
122 
123  // If no overlap, courtyard is empty (no common area).
124  // Therefore if a common polygon exists, this is a DRC error
125  if( courtyard.OutlineCount() )
126  {
127  //Overlap between footprint and candidate
128  VECTOR2I& pos = courtyard.Vertex( 0, 0, -1 );
129  auto marker = std::unique_ptr<MARKER_PCB>(
130  marker_factory.NewMarker( wxPoint( pos.x, pos.y ), footprint, candidate,
132  HandleMarker( std::move( marker ) );
133  success = false;
134  }
135  }
136  }
137 
138  // Test for overlapping on bottom layer:
139  for( auto it1 = aBoard.Modules().begin(); it1 != aBoard.Modules().end(); it1++ )
140  {
141  auto footprint = *it1;
142 
143  if( footprint->GetPolyCourtyardBack().OutlineCount() == 0 )
144  continue; // No courtyard defined
145 
146  for( auto it2 = it1 + 1; it2 != aBoard.Modules().end(); it2++ )
147  {
148  auto candidate = *it2;
149 
150  if( candidate->GetPolyCourtyardBack().OutlineCount() == 0 )
151  continue; // No courtyard defined
152 
153  courtyard.RemoveAllContours();
154  courtyard.Append( footprint->GetPolyCourtyardBack() );
155 
156  // Build the common area between footprint and the candidate:
157  courtyard.BooleanIntersection(
158  candidate->GetPolyCourtyardBack(), SHAPE_POLY_SET::PM_FAST );
159 
160  // If no overlap, courtyard is empty (no common area).
161  // Therefore if a common polygon exists, this is a DRC error
162  if( courtyard.OutlineCount() )
163  {
164  //Overlap between footprint and candidate
165  VECTOR2I& pos = courtyard.Vertex( 0, 0, -1 );
166  auto marker = std::unique_ptr<MARKER_PCB>(
167  marker_factory.NewMarker( wxPoint( pos.x, pos.y ), footprint, candidate,
169  HandleMarker( std::move( marker ) );
170  success = false;
171  }
172  }
173  }
174 
175  return success;
176 }
int OutlineCount() const
Returns the number of outlines in the set
const DRC_MARKER_FACTORY & GetMarkerFactory() const
Access to the stored reference to a marker constructor.
void HandleMarker(std::unique_ptr< MARKER_PCB > aMarker) const
Pass a given marker to the marker handler.
bool m_ProhibitOverlappingCourtyards
check for overlapping courtyards in DRC
BOARD_DESIGN_SETTINGS & GetDesignSettings() const
Function GetDesignSettings.
Definition: class_board.h:531
#define DRCE_MALFORMED_COURTYARD_IN_FOOTPRINT
footprint has a courtyard but malformed
Definition: drc.h:92
#define DRCE_MISSING_COURTYARD_IN_FOOTPRINT
footprint has no courtyard defined
Definition: drc.h:91
VECTOR2I & Vertex(int aIndex, int aOutline, int aHole)
Returns the index-th vertex in a given hole outline within a given outline
DRC_COURTYARD_OVERLAP(const DRC_MARKER_FACTORY &aMarkerFactory, MARKER_HANDLER aMarkerHandler)
Class that constructs DRC markers of various kinds with messages according to items and error code.
MODULES & Modules()
Definition: class_board.h:227
Class SHAPE_POLY_SET.
MARKER_PCB * NewMarker(TRACK *aTrack, BOARD_ITEM *aConflitItem, const SEG &aConflictSeg, int aErrorCode) const
Creates a marker on a track, via or pad.
Class that represents a DRC "provider" which runs some DRC functions over a BOARD and spits out #PCB_...
Definition: drc_provider.h:40
#define DRCE_OVERLAPPING_FOOTPRINTS
footprint courtyards overlap
Definition: drc.h:90
bool RunDRC(BOARD &aBoard) const override
Runs this provider against the given PCB with configured options (if any).
void BooleanIntersection(const SHAPE_POLY_SET &b, POLYGON_MODE aFastMode)
Performs boolean polyset intersection For aFastMode meaning, see function booleanOp
bool m_RequireCourtyards
require courtyard definitions in footprints
Class BOARD holds information pertinent to a Pcbnew printed circuit board.
Definition: class_board.h:161
std::function< void(MARKER_PCB *)> MARKER_HANDLER
A callable that can handle a single generated PCB_MARKER.
Definition: drc_provider.h:46
void RemoveAllContours()
Removes all outlines & holes (clears) the polygon set.
Module description (excepted pads)
static const wxChar * DRC_COURTYARD_TRACE
Flag to enable courtyard DRC debug tracing.
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)