DRC: Make the marker factory a separate class

This separates the "newMarker" functions from the DRC class. These
are moved to a new class, DRC_MARKER_FACTORY, which is now responsible for
constructing suitable markers from BOARD_ITEMS.

The reasons for this are:

1) Allow DRC related functions to access theese functions without having
   to bake these functions into the main DRC class.
2) Thereby simplify the DRC class interface
3) As DRC_MARKER is now a small class with public interfaces, it's
   possible to put unit tests on these functions.

The motivation here is to allow to start to split out pieces of DRC
into separate classes.
This commit is contained in:
John Beard 2019-01-11 13:21:38 +00:00 committed by Wayne Stambaugh
parent 4247e32cd6
commit e6edc1b670
6 changed files with 269 additions and 143 deletions

View File

@ -211,10 +211,15 @@ set( PCBNEW_MICROWAVE_SRCS
microwave/microwave_inductor.cpp
)
set( PCBNEW_DRC_SRCS
drc/drc_marker_factory.cpp
)
set( PCBNEW_CLASS_SRCS
${PCBNEW_DIALOGS}
${PCBNEW_EXPORTERS}
${PCBNEW_IMPORT_GFX}
${PCBNEW_DRC_SRCS}
autorouter/rect_placement/rect_placement.cpp
autorouter/spread_footprints.cpp
@ -238,7 +243,6 @@ set( PCBNEW_CLASS_SRCS
dragsegm.cpp
drc.cpp
drc_clearance_test_functions.cpp
drc_marker_functions.cpp
edgemod.cpp
edit.cpp
edit_pcb_text.cpp

View File

@ -155,6 +155,8 @@ DRC::DRC( PCB_EDIT_FRAME* aPcbWindow )
m_ycliplo = 0;
m_xcliphi = 0;
m_ycliphi = 0;
m_markerFactory.SetUnitsProvider( [=]() { return aPcbWindow->GetUserUnits(); } );
}
@ -283,7 +285,8 @@ int DRC::TestZoneToZoneOutline( ZONE_CONTAINER* aZone, bool aCreateMarkers )
if( smoothed_polys[ia2].Contains( currentVertex ) )
{
if( aCreateMarkers )
commit.Add( newMarker( pt, zoneRef, zoneToTest, DRCE_ZONES_INTERSECT ) );
commit.Add( m_markerFactory.NewMarker(
pt, zoneRef, zoneToTest, DRCE_ZONES_INTERSECT ) );
nerrors++;
}
@ -298,7 +301,8 @@ int DRC::TestZoneToZoneOutline( ZONE_CONTAINER* aZone, bool aCreateMarkers )
if( smoothed_polys[ia].Contains( currentVertex ) )
{
if( aCreateMarkers )
commit.Add( newMarker( pt, zoneToTest, zoneRef, DRCE_ZONES_INTERSECT ) );
commit.Add( m_markerFactory.NewMarker(
pt, zoneToTest, zoneRef, DRCE_ZONES_INTERSECT ) );
nerrors++;
}
@ -346,7 +350,8 @@ int DRC::TestZoneToZoneOutline( ZONE_CONTAINER* aZone, bool aCreateMarkers )
for( wxPoint pt : conflictPoints )
{
if( aCreateMarkers )
commit.Add( newMarker( pt, zoneRef, zoneToTest, DRCE_ZONES_TOO_CLOSE ) );
commit.Add( m_markerFactory.NewMarker(
pt, zoneRef, zoneToTest, DRCE_ZONES_TOO_CLOSE ) );
nerrors++;
}
@ -598,7 +603,7 @@ bool DRC::doNetClass( const NETCLASSPTR& nc, wxString& msg )
FmtVal( g.m_TrackMinWidth )
);
addMarkerToPcb( newMarker( DRCE_NETCLASS_TRACKWIDTH, msg ) );
addMarkerToPcb( m_markerFactory.NewMarker( DRCE_NETCLASS_TRACKWIDTH, msg ) );
ret = false;
}
@ -610,7 +615,7 @@ bool DRC::doNetClass( const NETCLASSPTR& nc, wxString& msg )
FmtVal( g.m_ViasMinSize )
);
addMarkerToPcb( newMarker( DRCE_NETCLASS_VIASIZE, msg ) );
addMarkerToPcb( m_markerFactory.NewMarker( DRCE_NETCLASS_VIASIZE, msg ) );
ret = false;
}
@ -622,7 +627,7 @@ bool DRC::doNetClass( const NETCLASSPTR& nc, wxString& msg )
FmtVal( g.m_ViasMinDrill )
);
addMarkerToPcb( newMarker( DRCE_NETCLASS_VIADRILLSIZE, msg ) );
addMarkerToPcb( m_markerFactory.NewMarker( DRCE_NETCLASS_VIADRILLSIZE, msg ) );
ret = false;
}
@ -633,7 +638,7 @@ bool DRC::doNetClass( const NETCLASSPTR& nc, wxString& msg )
FmtVal( nc->GetuViaDiameter() ),
FmtVal( g.m_MicroViasMinSize ) );
addMarkerToPcb( newMarker( DRCE_NETCLASS_uVIASIZE, msg ) );
addMarkerToPcb( m_markerFactory.NewMarker( DRCE_NETCLASS_uVIASIZE, msg ) );
ret = false;
}
@ -644,7 +649,7 @@ bool DRC::doNetClass( const NETCLASSPTR& nc, wxString& msg )
FmtVal( nc->GetuViaDrill() ),
FmtVal( g.m_MicroViasMinDrill ) );
addMarkerToPcb( newMarker( DRCE_NETCLASS_uVIADRILLSIZE, msg ) );
addMarkerToPcb( m_markerFactory.NewMarker( DRCE_NETCLASS_uVIADRILLSIZE, msg ) );
ret = false;
}
@ -905,7 +910,8 @@ void DRC::testZones()
if( ( netcode < 0 ) || pads_in_net == 0 )
{
wxPoint markerPos = zone->GetPosition();
addMarkerToPcb( newMarker( markerPos, zone, DRCE_SUSPICIOUS_NET_FOR_ZONE_OUTLINE ) );
addMarkerToPcb( m_markerFactory.NewMarker(
markerPos, zone, DRCE_SUSPICIOUS_NET_FOR_ZONE_OUTLINE ) );
}
}
@ -940,7 +946,8 @@ void DRC::testKeepoutAreas()
SEG trackSeg( segm->GetStart(), segm->GetEnd() );
if( area->Outline()->Distance( trackSeg, segm->GetWidth() ) == 0 )
addMarkerToPcb( newMarker( segm, area, DRCE_TRACK_INSIDE_KEEPOUT ) );
addMarkerToPcb(
m_markerFactory.NewMarker( segm, area, DRCE_TRACK_INSIDE_KEEPOUT ) );
}
else if( segm->Type() == PCB_VIA_T )
{
@ -953,7 +960,8 @@ void DRC::testKeepoutAreas()
continue;
if( area->Outline()->Distance( segm->GetPosition() ) < segm->GetWidth()/2 )
addMarkerToPcb( newMarker( segm, area, DRCE_VIA_INSIDE_KEEPOUT ) );
addMarkerToPcb(
m_markerFactory.NewMarker( segm, area, DRCE_VIA_INSIDE_KEEPOUT ) );
}
}
// Test pads: TODO
@ -1073,9 +1081,11 @@ void DRC::testCopperDrawItem( DRAWSEGMENT* aItem )
if( trackAsSeg.Distance( itemSeg ) < minDist )
{
if( track->Type() == PCB_VIA_T )
addMarkerToPcb( newMarker( track, aItem, itemSeg, DRCE_VIA_NEAR_COPPER ) );
addMarkerToPcb( m_markerFactory.NewMarker(
track, aItem, itemSeg, DRCE_VIA_NEAR_COPPER ) );
else
addMarkerToPcb( newMarker( track, aItem, itemSeg, DRCE_TRACK_NEAR_COPPER ) );
addMarkerToPcb( m_markerFactory.NewMarker(
track, aItem, itemSeg, DRCE_TRACK_NEAR_COPPER ) );
break;
}
}
@ -1099,7 +1109,7 @@ void DRC::testCopperDrawItem( DRAWSEGMENT* aItem )
{
if( padOutline.Distance( itemSeg, itemWidth ) == 0 )
{
addMarkerToPcb( newMarker( pad, aItem, DRCE_PAD_NEAR_COPPER ) );
addMarkerToPcb( m_markerFactory.NewMarker( pad, aItem, DRCE_PAD_NEAR_COPPER ) );
break;
}
}
@ -1139,9 +1149,11 @@ void DRC::testCopperTextItem( BOARD_ITEM* aTextItem )
if( trackAsSeg.Distance( textSeg ) < minDist )
{
if( track->Type() == PCB_VIA_T )
addMarkerToPcb( newMarker( track, aTextItem, textSeg, DRCE_VIA_NEAR_COPPER ) );
addMarkerToPcb( m_markerFactory.NewMarker(
track, aTextItem, textSeg, DRCE_VIA_NEAR_COPPER ) );
else
addMarkerToPcb( newMarker( track, aTextItem, textSeg, DRCE_TRACK_NEAR_COPPER ) );
addMarkerToPcb( m_markerFactory.NewMarker(
track, aTextItem, textSeg, DRCE_TRACK_NEAR_COPPER ) );
break;
}
}
@ -1167,7 +1179,7 @@ void DRC::testCopperTextItem( BOARD_ITEM* aTextItem )
if( padOutline.Distance( textSeg, textWidth ) == 0 )
{
addMarkerToPcb( newMarker( pad, aTextItem, DRCE_PAD_NEAR_COPPER ) );
addMarkerToPcb( m_markerFactory.NewMarker( pad, aTextItem, DRCE_PAD_NEAR_COPPER ) );
break;
}
}
@ -1180,7 +1192,7 @@ void DRC::testOutline()
wxPoint error_loc( m_pcb->GetBoardEdgesBoundingBox().GetPosition() );
if( !m_pcb->GetBoardPolygonOutlines( m_board_outlines, nullptr, &error_loc ) )
{
addMarkerToPcb( newMarker( error_loc, m_pcb, DRCE_INVALID_OUTLINE ) );
addMarkerToPcb( m_markerFactory.NewMarker( error_loc, m_pcb, DRCE_INVALID_OUTLINE ) );
return;
}
}
@ -1195,9 +1207,9 @@ void DRC::testDisabledLayers()
// Perform the test only for copper layers
disabledLayers &= LSET::AllCuMask();
auto createMarker = [&]( BOARD_ITEM* aItem )
{
addMarkerToPcb( newMarker( aItem->GetPosition(), aItem, DRCE_DISABLED_LAYER_ITEM ) );
auto createMarker = [&]( BOARD_ITEM* aItem ) {
addMarkerToPcb( m_markerFactory.NewMarker(
aItem->GetPosition(), aItem, DRCE_DISABLED_LAYER_ITEM ) );
};
for( auto track : board->Tracks() )
@ -1244,7 +1256,8 @@ bool DRC::doTrackKeepoutDrc( TRACK* aRefSeg )
if( area->Outline()->Distance( SEG( aRefSeg->GetStart(), aRefSeg->GetEnd() ),
aRefSeg->GetWidth() ) == 0 )
{
m_currentMarker = newMarker( aRefSeg, area, DRCE_TRACK_INSIDE_KEEPOUT );
m_currentMarker =
m_markerFactory.NewMarker( aRefSeg, area, DRCE_TRACK_INSIDE_KEEPOUT );
return false;
}
}
@ -1260,7 +1273,8 @@ bool DRC::doTrackKeepoutDrc( TRACK* aRefSeg )
if( area->Outline()->Distance( aRefSeg->GetPosition() ) < aRefSeg->GetWidth()/2 )
{
m_currentMarker = newMarker( aRefSeg, area, DRCE_VIA_INSIDE_KEEPOUT );
m_currentMarker =
m_markerFactory.NewMarker( aRefSeg, area, DRCE_VIA_INSIDE_KEEPOUT );
return false;
}
}
@ -1342,7 +1356,7 @@ bool DRC::doPadToPadsDrc( D_PAD* aRefPad, D_PAD** aStart, D_PAD** aEnd, int x_li
if( !checkClearancePadToPad( aRefPad, &dummypad ) )
{
// here we have a drc error on pad!
m_currentMarker = newMarker( pad, aRefPad, DRCE_HOLE_NEAR_PAD );
m_currentMarker = m_markerFactory.NewMarker( pad, aRefPad, DRCE_HOLE_NEAR_PAD );
return false;
}
}
@ -1358,7 +1372,7 @@ bool DRC::doPadToPadsDrc( D_PAD* aRefPad, D_PAD** aStart, D_PAD** aEnd, int x_li
if( !checkClearancePadToPad( pad, &dummypad ) )
{
// here we have a drc error on aRefPad!
m_currentMarker = newMarker( aRefPad, pad, DRCE_HOLE_NEAR_PAD );
m_currentMarker = m_markerFactory.NewMarker( aRefPad, pad, DRCE_HOLE_NEAR_PAD );
return false;
}
}
@ -1393,7 +1407,7 @@ bool DRC::doPadToPadsDrc( D_PAD* aRefPad, D_PAD** aStart, D_PAD** aEnd, int x_li
if( !checkClearancePadToPad( aRefPad, pad ) )
{
// here we have a drc error!
m_currentMarker = newMarker( aRefPad, pad, DRCE_PAD_NEAR_PAD1 );
m_currentMarker = m_markerFactory.NewMarker( aRefPad, pad, DRCE_PAD_NEAR_PAD1 );
return false;
}
}
@ -1417,7 +1431,8 @@ bool DRC::doFootprintOverlappingDrc()
if( !is_ok && m_pcb->GetDesignSettings().m_ProhibitOverlappingCourtyards )
{
addMarkerToPcb( newMarker( pos, footprint, DRCE_MALFORMED_COURTYARD_IN_FOOTPRINT ) );
addMarkerToPcb( m_markerFactory.NewMarker(
pos, footprint, DRCE_MALFORMED_COURTYARD_IN_FOOTPRINT ) );
success = false;
}
@ -1428,7 +1443,8 @@ bool DRC::doFootprintOverlappingDrc()
footprint->GetPolyCourtyardBack().OutlineCount() == 0 &&
is_ok )
{
addMarkerToPcb( newMarker( pos, footprint, DRCE_MISSING_COURTYARD_IN_FOOTPRINT ) );
addMarkerToPcb( m_markerFactory.NewMarker(
pos, footprint, DRCE_MISSING_COURTYARD_IN_FOOTPRINT ) );
success = false;
}
}
@ -1462,8 +1478,8 @@ bool DRC::doFootprintOverlappingDrc()
{
//Overlap between footprint and candidate
VECTOR2I& pos = courtyard.Vertex( 0, 0, -1 );
addMarkerToPcb( newMarker( wxPoint( pos.x, pos.y ), footprint, candidate,
DRCE_OVERLAPPING_FOOTPRINTS ) );
addMarkerToPcb( m_markerFactory.NewMarker( wxPoint( pos.x, pos.y ), footprint,
candidate, DRCE_OVERLAPPING_FOOTPRINTS ) );
success = false;
}
}
@ -1493,8 +1509,8 @@ bool DRC::doFootprintOverlappingDrc()
{
//Overlap between footprint and candidate
VECTOR2I& pos = courtyard.Vertex( 0, 0, -1 );
addMarkerToPcb( newMarker( wxPoint( pos.x, pos.y ), footprint, candidate,
DRCE_OVERLAPPING_FOOTPRINTS ) );
addMarkerToPcb( m_markerFactory.NewMarker( wxPoint( pos.x, pos.y ), footprint,
candidate, DRCE_OVERLAPPING_FOOTPRINTS ) );
success = false;
}
}

View File

@ -34,6 +34,8 @@
#include <geometry/seg.h>
#include <geometry/shape_poly_set.h>
#include <drc/drc_marker_factory.h>
#define OK_DRC 0
#define BAD_DRC 1
@ -225,6 +227,7 @@ private:
BOARD* m_pcb;
SHAPE_POLY_SET m_board_outlines; ///< The board outline including cutouts
DIALOG_DRC_CONTROL* m_drcDialog;
DRC_MARKER_FACTORY m_markerFactory; ///< Class that generates markers
DRC_LIST m_unconnected; ///< list of unconnected pads, as DRC_ITEMs
@ -234,42 +237,6 @@ private:
*/
void updatePointers();
/**
* Function newMarker
* Creates a marker on a track, via or pad.
*
* @param aTrack/aPad The reference item.
* @param aConflitItem Another item on the board which is in conflict with the
* reference item.
* @param aErrorCode An ID for the particular type of error that is being reported.
*/
MARKER_PCB* newMarker( TRACK* aTrack, BOARD_ITEM* aConflitItem, const SEG& aConflictSeg,
int aErrorCode );
MARKER_PCB* newMarker( TRACK* aTrack, ZONE_CONTAINER* aConflictZone, int aErrorCode );
MARKER_PCB* newMarker( D_PAD* aPad, BOARD_ITEM* aConflictItem, int aErrorCode );
/**
* Function newMarker
* Creates a marker at a given location.
*
* @param aItem The reference item.
* @param aPos Usually the position of the item, but could be more specific for a zone.
* @param aErrorCode An ID for the particular type of error that is being reported.
*/
MARKER_PCB* newMarker( const wxPoint& aPos, BOARD_ITEM* aItem, int aErrorCode );
MARKER_PCB* newMarker( const wxPoint& aPos, BOARD_ITEM* aItem, BOARD_ITEM* bItem,
int aErrorCode );
/**
* Create a MARKER which will report on a generic problem with the board which is
* not geographically locatable.
*/
MARKER_PCB* newMarker( int aErrorCode, const wxString& aMessage );
/**
* Adds a DRC marker to the PCB through the COMMIT mechanism.
*/

View File

@ -1,7 +1,3 @@
/**
* @file drc_marker_functions.cpp
*/
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
@ -27,32 +23,48 @@
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include "drc_marker_factory.h"
/* Methods of class DRC to initialize drc markers with messages
* according to items and error code
*/
#include <fctsys.h>
#include <common.h>
#include <pcbnew.h>
#include <board_design_settings.h>
#include <geometry/geometry_utils.h>
#include <pcb_edit_frame.h>
#include <drc.h>
#include <class_pad.h>
#include <class_track.h>
#include <class_zone.h>
#include <class_board_item.h>
#include <class_edge_mod.h>
#include <class_marker_pcb.h>
#include <class_pad.h>
#include <class_pcb_text.h>
#include <class_text_mod.h>
#include <class_edge_mod.h>
#include <class_board_item.h>
#include <class_track.h>
#include <class_zone.h>
#include <common.h>
#include <drc.h>
#include <fctsys.h>
#include <geometry/geometry_utils.h>
#include <pcb_edit_frame.h>
#include <pcbnew.h>
const int EPSILON = Mils2iu( 5 );
MARKER_PCB* DRC::newMarker( TRACK* aTrack, ZONE_CONTAINER* aConflictZone, int aErrorCode )
DRC_MARKER_FACTORY::DRC_MARKER_FACTORY()
{
SetUnits( EDA_UNITS_T::MILLIMETRES );
}
void DRC_MARKER_FACTORY::SetUnitsProvider( UNITS_PROVIDER aUnitsProvider )
{
m_units_provider = aUnitsProvider;
}
void DRC_MARKER_FACTORY::SetUnits( EDA_UNITS_T aUnits )
{
m_units_provider = [=]() { return aUnits; };
}
MARKER_PCB* DRC_MARKER_FACTORY::NewMarker(
TRACK* aTrack, ZONE_CONTAINER* aConflictZone, int aErrorCode ) const
{
SHAPE_POLY_SET* conflictOutline;
@ -84,16 +96,15 @@ MARKER_PCB* DRC::newMarker( TRACK* aTrack, ZONE_CONTAINER* aConflictZone, int aE
markerPos = pt1;
}
return new MARKER_PCB( m_pcbEditorFrame->GetUserUnits(), aErrorCode, markerPos,
aTrack, aTrack->GetPosition(),
aConflictZone, aConflictZone->GetPosition() );
return new MARKER_PCB( getCurrentUnits(), aErrorCode, markerPos, aTrack, aTrack->GetPosition(),
aConflictZone, aConflictZone->GetPosition() );
}
MARKER_PCB* DRC::newMarker( TRACK* aTrack, BOARD_ITEM* aConflitItem, const SEG& aConflictSeg,
int aErrorCode )
MARKER_PCB* DRC_MARKER_FACTORY::NewMarker(
TRACK* aTrack, BOARD_ITEM* aConflitItem, const SEG& aConflictSeg, int aErrorCode ) const
{
wxPoint markerPos;
wxPoint markerPos;
wxPoint pt1 = aTrack->GetPosition();
wxPoint pt2 = aTrack->GetEnd();
@ -109,36 +120,36 @@ MARKER_PCB* DRC::newMarker( TRACK* aTrack, BOARD_ITEM* aConflitItem, const SEG&
// Once we're within EPSILON pt1 and pt2 are "equivalent"
markerPos = pt1;
return new MARKER_PCB( m_pcbEditorFrame->GetUserUnits(), aErrorCode, markerPos,
aTrack, aTrack->GetPosition(),
aConflitItem, aConflitItem->GetPosition() );
return new MARKER_PCB( getCurrentUnits(), aErrorCode, markerPos, aTrack, aTrack->GetPosition(),
aConflitItem, aConflitItem->GetPosition() );
}
MARKER_PCB* DRC::newMarker( D_PAD* aPad, BOARD_ITEM* aConflictItem, int aErrorCode )
MARKER_PCB* DRC_MARKER_FACTORY::NewMarker(
D_PAD* aPad, BOARD_ITEM* aConflictItem, int aErrorCode ) const
{
return new MARKER_PCB( m_pcbEditorFrame->GetUserUnits(), aErrorCode, aPad->GetPosition(),
aPad, aPad->GetPosition(),
aConflictItem, aConflictItem->GetPosition() );
return new MARKER_PCB( getCurrentUnits(), aErrorCode, aPad->GetPosition(), aPad,
aPad->GetPosition(), aConflictItem, aConflictItem->GetPosition() );
}
MARKER_PCB* DRC::newMarker(const wxPoint &aPos, BOARD_ITEM *aItem, int aErrorCode )
MARKER_PCB* DRC_MARKER_FACTORY::NewMarker(
const wxPoint& aPos, BOARD_ITEM* aItem, int aErrorCode ) const
{
return new MARKER_PCB( m_pcbEditorFrame->GetUserUnits(), aErrorCode, aPos,
aItem, aItem->GetPosition(), nullptr, wxPoint() );
return new MARKER_PCB(
getCurrentUnits(), aErrorCode, aPos, aItem, aItem->GetPosition(), nullptr, wxPoint() );
}
MARKER_PCB* DRC::newMarker( const wxPoint &aPos, BOARD_ITEM* aItem, BOARD_ITEM* bItem,
int aErrorCode )
MARKER_PCB* DRC_MARKER_FACTORY::NewMarker(
const wxPoint& aPos, BOARD_ITEM* aItem, BOARD_ITEM* bItem, int aErrorCode ) const
{
return new MARKER_PCB( m_pcbEditorFrame->GetUserUnits(), aErrorCode, aPos,
aItem, aItem->GetPosition(), bItem, bItem->GetPosition() );
return new MARKER_PCB( getCurrentUnits(), aErrorCode, aPos, aItem, aItem->GetPosition(), bItem,
bItem->GetPosition() );
}
MARKER_PCB* DRC::newMarker( int aErrorCode, const wxString& aMessage )
MARKER_PCB* DRC_MARKER_FACTORY::NewMarker( int aErrorCode, const wxString& aMessage ) const
{
MARKER_PCB* marker = new MARKER_PCB( aErrorCode, wxPoint(), aMessage, wxPoint() );
@ -146,5 +157,3 @@ MARKER_PCB* DRC::newMarker( int aErrorCode, const wxString& aMessage )
return marker;
}

View File

@ -0,0 +1,104 @@
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2018 KiCad Developers, see AUTHORS.txt for contributors.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, you may find one here:
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
* or you may search the http://www.gnu.org website for the version 2 license,
* or you may write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
#ifndef DRC_DRC_MARKER_FACTORY__H
#define DRC_DRC_MARKER_FACTORY__H
#include <class_marker_pcb.h>
#include <common.h> // for EDA_UNITS_T
class ZONE_CONTAINER;
class TRACK;
class D_PAD;
class SEG;
/**
* Class that constructs DRC markers of various kinds
* with messages according to items and error code
*/
class DRC_MARKER_FACTORY
{
public:
using UNITS_PROVIDER = std::function<EDA_UNITS_T()>;
DRC_MARKER_FACTORY();
/**
* Set the provider for the units (this will be called for each new
* marker constructed)
* @param aUnitsProvider a callable that returns the current units to use
*/
void SetUnitsProvider( UNITS_PROVIDER aUnitsProvider );
/**
* Set the units provider to a function returning a constant value.
* This is a shorthand for #SetUnitProvider.
*/
void SetUnits( EDA_UNITS_T aUnits );
/**
* Creates a marker on a track, via or pad.
*
* @param aTrack/aPad The reference item.
* @param aConflitItem Another item on the board which is in conflict with the
* reference item.
* @param aErrorCode An ID for the particular type of error that is being reported.
*/
MARKER_PCB* NewMarker( TRACK* aTrack, BOARD_ITEM* aConflitItem, const SEG& aConflictSeg,
int aErrorCode ) const;
MARKER_PCB* NewMarker( TRACK* aTrack, ZONE_CONTAINER* aConflictZone, int aErrorCode ) const;
MARKER_PCB* NewMarker( D_PAD* aPad, BOARD_ITEM* aConflictItem, int aErrorCode ) const;
/**
* Creates a marker at a given location.
*
* @param aItem The reference item.
* @param aPos Usually the position of the item, but could be more specific for a zone.
* @param aErrorCode An ID for the particular type of error that is being reported.
*/
MARKER_PCB* NewMarker( const wxPoint& aPos, BOARD_ITEM* aItem, int aErrorCode ) const;
MARKER_PCB* NewMarker(
const wxPoint& aPos, BOARD_ITEM* aItem, BOARD_ITEM* bItem, int aErrorCode ) const;
/**
* Create a MARKER which will report on a generic problem with the board which is
* not geographically locatable.
*/
MARKER_PCB* NewMarker( int aErrorCode, const wxString& aMessage ) const;
private:
EDA_UNITS_T getCurrentUnits() const
{
return m_units_provider();
}
UNITS_PROVIDER m_units_provider;
};
#endif // DRC_DRC_MARKER_FACTORY__H

View File

@ -211,7 +211,8 @@ bool DRC::doTrackDrc( TRACK* aRefSeg, TRACK* aStart, bool testPads )
{
if( refvia->GetWidth() < dsnSettings.m_MicroViasMinSize )
{
markers.push_back( newMarker( refviaPos, refvia, DRCE_TOO_SMALL_MICROVIA ) );
markers.push_back(
m_markerFactory.NewMarker( refviaPos, refvia, DRCE_TOO_SMALL_MICROVIA ) );
if( !handleNewMarker() )
return false;
@ -219,7 +220,8 @@ bool DRC::doTrackDrc( TRACK* aRefSeg, TRACK* aStart, bool testPads )
if( refvia->GetDrillValue() < dsnSettings.m_MicroViasMinDrill )
{
markers.push_back( newMarker( refviaPos, refvia, DRCE_TOO_SMALL_MICROVIA_DRILL ) );
markers.push_back( m_markerFactory.NewMarker(
refviaPos, refvia, DRCE_TOO_SMALL_MICROVIA_DRILL ) );
if( !handleNewMarker() )
return false;
@ -229,7 +231,8 @@ bool DRC::doTrackDrc( TRACK* aRefSeg, TRACK* aStart, bool testPads )
{
if( refvia->GetWidth() < dsnSettings.m_ViasMinSize )
{
markers.push_back( newMarker( refviaPos, refvia, DRCE_TOO_SMALL_VIA ) );
markers.push_back(
m_markerFactory.NewMarker( refviaPos, refvia, DRCE_TOO_SMALL_VIA ) );
if( !handleNewMarker() )
return false;
@ -237,7 +240,8 @@ bool DRC::doTrackDrc( TRACK* aRefSeg, TRACK* aStart, bool testPads )
if( refvia->GetDrillValue() < dsnSettings.m_ViasMinDrill )
{
markers.push_back( newMarker( refviaPos, refvia, DRCE_TOO_SMALL_VIA_DRILL ) );
markers.push_back(
m_markerFactory.NewMarker( refviaPos, refvia, DRCE_TOO_SMALL_VIA_DRILL ) );
if( !handleNewMarker() )
return false;
@ -249,7 +253,8 @@ bool DRC::doTrackDrc( TRACK* aRefSeg, TRACK* aStart, bool testPads )
// and a default via hole can be bigger than some vias sizes
if( refvia->GetDrillValue() > refvia->GetWidth() )
{
markers.push_back( newMarker( refviaPos, refvia, DRCE_VIA_HOLE_BIGGER ) );
markers.push_back(
m_markerFactory.NewMarker( refviaPos, refvia, DRCE_VIA_HOLE_BIGGER ) );
if( !handleNewMarker() )
return false;
@ -258,7 +263,8 @@ bool DRC::doTrackDrc( TRACK* aRefSeg, TRACK* aStart, bool testPads )
// test if the type of via is allowed due to design rules
if( refvia->GetViaType() == VIA_MICROVIA && !dsnSettings.m_MicroViasAllowed )
{
markers.push_back( newMarker( refviaPos, refvia, DRCE_MICRO_VIA_NOT_ALLOWED ) );
markers.push_back(
m_markerFactory.NewMarker( refviaPos, refvia, DRCE_MICRO_VIA_NOT_ALLOWED ) );
if( !handleNewMarker() )
return false;
}
@ -266,7 +272,8 @@ bool DRC::doTrackDrc( TRACK* aRefSeg, TRACK* aStart, bool testPads )
// test if the type of via is allowed due to design rules
if( refvia->GetViaType() == VIA_BLIND_BURIED && !dsnSettings.m_BlindBuriedViaAllowed )
{
markers.push_back( newMarker( refviaPos, refvia, DRCE_BURIED_VIA_NOT_ALLOWED ) );
markers.push_back(
m_markerFactory.NewMarker( refviaPos, refvia, DRCE_BURIED_VIA_NOT_ALLOWED ) );
if( !handleNewMarker() )
return false;
@ -292,7 +299,8 @@ bool DRC::doTrackDrc( TRACK* aRefSeg, TRACK* aStart, bool testPads )
if( err )
{
markers.push_back( newMarker( refviaPos, refvia, DRCE_MICRO_VIA_INCORRECT_LAYER_PAIR ) );
markers.push_back( m_markerFactory.NewMarker(
refviaPos, refvia, DRCE_MICRO_VIA_INCORRECT_LAYER_PAIR ) );
if( !handleNewMarker() )
return false;
@ -306,7 +314,8 @@ bool DRC::doTrackDrc( TRACK* aRefSeg, TRACK* aStart, bool testPads )
{
wxPoint refsegMiddle = ( aRefSeg->GetStart() + aRefSeg->GetEnd() ) / 2;
markers.push_back( newMarker( refsegMiddle, aRefSeg, DRCE_TOO_SMALL_TRACK_WIDTH ) );
markers.push_back( m_markerFactory.NewMarker(
refsegMiddle, aRefSeg, DRCE_TOO_SMALL_TRACK_WIDTH ) );
if( !handleNewMarker() )
return false;
@ -381,8 +390,8 @@ bool DRC::doTrackDrc( TRACK* aRefSeg, TRACK* aStart, bool testPads )
if( !checkClearanceSegmToPad( &dummypad, aRefSeg->GetWidth(),
netclass->GetClearance() ) )
{
markers.push_back( newMarker( aRefSeg, pad, padSeg,
DRCE_TRACK_NEAR_THROUGH_HOLE ) );
markers.push_back( m_markerFactory.NewMarker(
aRefSeg, pad, padSeg, DRCE_TRACK_NEAR_THROUGH_HOLE ) );
if( !handleNewMarker() )
return false;
@ -403,7 +412,8 @@ bool DRC::doTrackDrc( TRACK* aRefSeg, TRACK* aStart, bool testPads )
if( !checkClearanceSegmToPad( pad, aRefSeg->GetWidth(), aRefSeg->GetClearance( pad ) ) )
{
markers.push_back( newMarker( aRefSeg, pad, padSeg, DRCE_TRACK_NEAR_PAD ) );
markers.push_back(
m_markerFactory.NewMarker( aRefSeg, pad, padSeg, DRCE_TRACK_NEAR_PAD ) );
if( !handleNewMarker() )
return false;
@ -455,7 +465,8 @@ bool DRC::doTrackDrc( TRACK* aRefSeg, TRACK* aStart, bool testPads )
// Test distance between two vias, i.e. two circles, trivial case
if( EuclideanNorm( segStartPoint ) < w_dist )
{
markers.push_back( newMarker( pos, aRefSeg, track, DRCE_VIA_NEAR_VIA ) );
markers.push_back(
m_markerFactory.NewMarker( pos, aRefSeg, track, DRCE_VIA_NEAR_VIA ) );
if( !handleNewMarker() )
return false;
@ -472,7 +483,8 @@ bool DRC::doTrackDrc( TRACK* aRefSeg, TRACK* aStart, bool testPads )
if( !checkMarginToCircle( segStartPoint, w_dist, delta.x ) )
{
markers.push_back( newMarker( pos, aRefSeg, track, DRCE_VIA_NEAR_TRACK ) );
markers.push_back(
m_markerFactory.NewMarker( pos, aRefSeg, track, DRCE_VIA_NEAR_TRACK ) );
if( !handleNewMarker() )
return false;
@ -498,7 +510,8 @@ bool DRC::doTrackDrc( TRACK* aRefSeg, TRACK* aStart, bool testPads )
if( checkMarginToCircle( segStartPoint, w_dist, m_segmLength ) )
continue;
markers.push_back( newMarker( aRefSeg, track, seg, DRCE_TRACK_NEAR_VIA ) );
markers.push_back(
m_markerFactory.NewMarker( aRefSeg, track, seg, DRCE_TRACK_NEAR_VIA ) );
if( !handleNewMarker() )
return false;
@ -526,7 +539,8 @@ bool DRC::doTrackDrc( TRACK* aRefSeg, TRACK* aStart, bool testPads )
// Fine test : we consider the rounded shape of each end of the track segment:
if( segStartPoint.x >= 0 && segStartPoint.x <= m_segmLength )
{
markers.push_back( newMarker( aRefSeg, track, seg, DRCE_TRACK_ENDS1 ) );
markers.push_back(
m_markerFactory.NewMarker( aRefSeg, track, seg, DRCE_TRACK_ENDS1 ) );
if( !handleNewMarker() )
return false;
@ -534,7 +548,8 @@ bool DRC::doTrackDrc( TRACK* aRefSeg, TRACK* aStart, bool testPads )
if( !checkMarginToCircle( segStartPoint, w_dist, m_segmLength ) )
{
markers.push_back( newMarker( aRefSeg, track, seg, DRCE_TRACK_ENDS2 ) );
markers.push_back(
m_markerFactory.NewMarker( aRefSeg, track, seg, DRCE_TRACK_ENDS2 ) );
if( !handleNewMarker() )
return false;
@ -549,7 +564,8 @@ bool DRC::doTrackDrc( TRACK* aRefSeg, TRACK* aStart, bool testPads )
// Fine test : we consider the rounded shape of the ends
if( segEndPoint.x >= 0 && segEndPoint.x <= m_segmLength )
{
markers.push_back( newMarker( aRefSeg, track, seg, DRCE_TRACK_ENDS3 ) );
markers.push_back(
m_markerFactory.NewMarker( aRefSeg, track, seg, DRCE_TRACK_ENDS3 ) );
if( !handleNewMarker() )
return false;
@ -557,7 +573,8 @@ bool DRC::doTrackDrc( TRACK* aRefSeg, TRACK* aStart, bool testPads )
if( !checkMarginToCircle( segEndPoint, w_dist, m_segmLength ) )
{
markers.push_back( newMarker( aRefSeg, track, seg, DRCE_TRACK_ENDS4 ) );
markers.push_back(
m_markerFactory.NewMarker( aRefSeg, track, seg, DRCE_TRACK_ENDS4 ) );
if( !handleNewMarker() )
return false;
@ -571,7 +588,8 @@ bool DRC::doTrackDrc( TRACK* aRefSeg, TRACK* aStart, bool testPads )
// handled)
// X.............X
// O--REF--+
markers.push_back( newMarker( aRefSeg, track, seg, DRCE_TRACK_SEGMENTS_TOO_CLOSE ) );
markers.push_back( m_markerFactory.NewMarker(
aRefSeg, track, seg, DRCE_TRACK_SEGMENTS_TOO_CLOSE ) );
if( !handleNewMarker() )
return false;
@ -588,7 +606,8 @@ bool DRC::doTrackDrc( TRACK* aRefSeg, TRACK* aStart, bool testPads )
if( ( segStartPoint.y < 0 ) && ( segEndPoint.y > 0 ) )
{
markers.push_back( newMarker( aRefSeg, track, seg, DRCE_TRACKS_CROSSING ) );
markers.push_back(
m_markerFactory.NewMarker( aRefSeg, track, seg, DRCE_TRACKS_CROSSING ) );
if( !handleNewMarker() )
return false;
@ -597,14 +616,16 @@ bool DRC::doTrackDrc( TRACK* aRefSeg, TRACK* aStart, bool testPads )
// At this point the drc error is due to an end near a reference segm end
if( !checkMarginToCircle( segStartPoint, w_dist, m_segmLength ) )
{
markers.push_back( newMarker( aRefSeg, track, seg, DRCE_ENDS_PROBLEM1 ) );
markers.push_back(
m_markerFactory.NewMarker( aRefSeg, track, seg, DRCE_ENDS_PROBLEM1 ) );
if( !handleNewMarker() )
return false;
}
if( !checkMarginToCircle( segEndPoint, w_dist, m_segmLength ) )
{
markers.push_back( newMarker( aRefSeg, track, seg, DRCE_ENDS_PROBLEM2 ) );
markers.push_back(
m_markerFactory.NewMarker( aRefSeg, track, seg, DRCE_ENDS_PROBLEM2 ) );
if( !handleNewMarker() )
return false;
@ -633,7 +654,8 @@ bool DRC::doTrackDrc( TRACK* aRefSeg, TRACK* aStart, bool testPads )
if( !checkLine( segStartPoint, segEndPoint ) )
{
markers.push_back( newMarker( aRefSeg, track, seg, DRCE_ENDS_PROBLEM3 ) );
markers.push_back(
m_markerFactory.NewMarker( aRefSeg, track, seg, DRCE_ENDS_PROBLEM3 ) );
if( !handleNewMarker() )
return false;
@ -662,7 +684,8 @@ bool DRC::doTrackDrc( TRACK* aRefSeg, TRACK* aStart, bool testPads )
if( !checkMarginToCircle( relStartPos, w_dist, delta.x ) )
{
markers.push_back( newMarker( aRefSeg, track, seg, DRCE_ENDS_PROBLEM4 ) );
markers.push_back( m_markerFactory.NewMarker(
aRefSeg, track, seg, DRCE_ENDS_PROBLEM4 ) );
if( !handleNewMarker() )
return false;
@ -670,7 +693,8 @@ bool DRC::doTrackDrc( TRACK* aRefSeg, TRACK* aStart, bool testPads )
if( !checkMarginToCircle( relEndPos, w_dist, delta.x ) )
{
markers.push_back( newMarker( aRefSeg, track, seg, DRCE_ENDS_PROBLEM5 ) );
markers.push_back( m_markerFactory.NewMarker(
aRefSeg, track, seg, DRCE_ENDS_PROBLEM5 ) );
if( !handleNewMarker() )
return false;
@ -701,7 +725,7 @@ bool DRC::doTrackDrc( TRACK* aRefSeg, TRACK* aStart, bool testPads )
SHAPE_POLY_SET* outline = const_cast<SHAPE_POLY_SET*>( &zone->GetFilledPolysList() );
if( outline->Distance( refSeg, aRefSeg->GetWidth() ) < clearance )
addMarkerToPcb( newMarker( aRefSeg, zone, DRCE_TRACK_NEAR_ZONE ) );
addMarkerToPcb( m_markerFactory.NewMarker( aRefSeg, zone, DRCE_TRACK_NEAR_ZONE ) );
}
/***********************************************/
@ -721,7 +745,8 @@ bool DRC::doTrackDrc( TRACK* aRefSeg, TRACK* aStart, bool testPads )
if( test_seg.SquaredDistance( *it ) < w_dist )
{
auto pt = test_seg.NearestPoint( *it );
markers.push_back( newMarker( wxPoint( pt.x, pt.y ), aRefSeg, DRCE_TRACK_NEAR_EDGE ) );
markers.push_back( m_markerFactory.NewMarker(
wxPoint( pt.x, pt.y ), aRefSeg, DRCE_TRACK_NEAR_EDGE ) );
if( !handleNewMarker() )
return false;
@ -793,7 +818,8 @@ bool DRC::doEdgeZoneDrc( ZONE_CONTAINER* aArea, int aCornerIndex )
if( area_to_test->Outline()->Contains( end ) )
{
wxPoint pos( end.x, end.y );
m_currentMarker = newMarker( pos, aArea, area_to_test, DRCE_ZONES_INTERSECT );
m_currentMarker =
m_markerFactory.NewMarker( pos, aArea, area_to_test, DRCE_ZONES_INTERSECT );
return false;
}
@ -825,8 +851,8 @@ bool DRC::doEdgeZoneDrc( ZONE_CONTAINER* aArea, int aCornerIndex )
if( d < zone_clearance )
{
// COPPERAREA_COPPERAREA error : edge intersect or too close
m_currentMarker = newMarker( wxPoint( x, y ), aArea, area_to_test,
DRCE_ZONES_TOO_CLOSE );
m_currentMarker = m_markerFactory.NewMarker(
wxPoint( x, y ), aArea, area_to_test, DRCE_ZONES_TOO_CLOSE );
return false;
}