55    virtual bool Run() 
override;
 
   57    virtual const wxString 
GetName()
 const override { 
return wxT( 
"diff_pair_coupling" ); };
 
 
 
   71    int64_t t_b = p.
TCoef( p.
B );
 
   73    int64_t tproj_a = p.
TCoef( n_proj_p.
A );
 
   74    int64_t tproj_b = p.
TCoef( n_proj_p.
B );
 
   77        std::swap( t_b, t_a );
 
   79    if( tproj_b < tproj_a )
 
   80        std::swap( tproj_b, tproj_a );
 
   89    std::vector<int64_t> tv( t, t + 4 );
 
   90    std::sort( tv.begin(), tv.end() ); 
 
   95    pClip.
A.
x = p.
A.
x + 
rescale( (int64_t)dp.
x, tv[1], pLenSq );
 
   96    pClip.
A.
y = p.
A.
y + 
rescale( (int64_t)dp.
y, tv[1], pLenSq );
 
   98    pClip.
B.
x = p.
A.
x + 
rescale( (int64_t)dp.
x, tv[2], pLenSq );
 
   99    pClip.
B.
y = p.
A.
y + 
rescale( (int64_t)dp.
y, tv[2], pLenSq );
 
 
  114    bool p_is_ccw = p.
IsCCW();
 
  115    bool n_is_ccw = n.
IsCCW();
 
  118    double radiusDiffRatio = 
std::abs(p_radius - n_radius) / std::max(p_radius, n_radius);
 
  119    double centerDistance = (p_center - n_center).EuclideanNorm();
 
  121    if (radiusDiffRatio > 0.5 || centerDistance > std::max(p_radius, n_radius) * 0.5)
 
  128        std::swap( p_start, p_end );
 
  134        std::swap( n_start, n_end );
 
  142    p_arc.
Rotate( p_start_angle, p_center );
 
  143    n_arc.
Rotate( p_start_angle, n_center );
 
  150    EDA_ANGLE clip_start_angle, clip_end_angle;
 
  153    if( n_start_angle >= p_end_angle || n_end_angle <= 
EDA_ANGLE(0) )
 
  157    clip_start_angle = std::max( 
EDA_ANGLE(0), n_start_angle );
 
  158    clip_end_angle = std::min( p_end_angle, n_end_angle );
 
  161    EDA_ANGLE clip_total_angle = clip_end_angle - clip_start_angle;
 
  165    clip_start_angle += p_start_angle;
 
  166    clip_end_angle += p_start_angle;
 
  176    VECTOR2I p_clip_point, n_clip_point;
 
  181                                            KiROUND( p_radius * clip_start_angle.
Sin() ) );
 
  182        pClip = 
SHAPE_ARC( p_center, p_clip_point, clip_total_angle );
 
  188        pClip = 
SHAPE_ARC( p_center, p_clip_point, -clip_total_angle );
 
  194                                            KiROUND( n_radius * clip_start_angle.
Sin() ) );
 
  195        nClip = 
SHAPE_ARC( n_center, n_clip_point, clip_total_angle );
 
  201        nClip = 
SHAPE_ARC( n_center, n_clip_point, -clip_total_angle );
 
 
  277    std::vector<DIFF_PAIR_COUPLED_SEGMENTS> 
coupled;
 
 
  286    auto isInTuningPattern =
 
  289                if( 
EDA_GROUP* parent = track->GetParentGroup() )
 
  293                        if( generator->GetGeneratorType() == wxS( 
"tuning_pattern" ) )
 
  303        if( !itemP || itemP->
Type() != 
PCB_TRACE_T || isInTuningPattern( itemP ) )
 
  307        std::vector<std::optional<DIFF_PAIR_COUPLED_SEGMENTS>> coupled_vec;
 
  311            if( !itemN || itemN->
Type() != 
PCB_TRACE_T || isInTuningPattern( itemN ) )
 
  338                    coupled_vec.push_back( cpair );
 
  344        for( 
const std::optional<DIFF_PAIR_COUPLED_SEGMENTS>& coupled : coupled_vec )
 
  349                        if( aItem == coupled->parentN || aItem == coupled->parentP )
 
  357                            if( bci->
HitTest( coupled->coupledN.A, 0 )
 
  358                                || bci->
HitTest( coupled->coupledN.B, 0 )
 
  359                                || bci->
HitTest( coupled->coupledP.A, 0 )
 
  360                                || bci->
HitTest( coupled->coupledP.B, 0 ) )
 
  369                            auto trackExitsPad = [&]( 
PCB_TRACK* track )
 
  371                                bool startIn = 
pad->HitTest( track->GetStart(), 0 );
 
  372                                bool endIn = 
pad->HitTest( track->GetEnd(), 0 );
 
  374                                return startIn ^ endIn;
 
  377                            if( trackExitsPad( 
static_cast<PCB_TRACK*
>( coupled->parentP ) )
 
  378                                    || trackExitsPad( 
static_cast<PCB_TRACK*
>( coupled->parentN ) ) )
 
  387            SHAPE_SEGMENT checkSeg( coupled->nearestN, coupled->nearestP );
 
  388            DRC_RTREE*    tree = coupled->parentP->GetBoard()->m_CopperItemRTreeCache.get();
 
  394                aDp.
coupled.push_back( *coupled );
 
  400        if( !itemP || itemP->
Type() != 
PCB_ARC_T || isInTuningPattern( itemP ) )
 
  404        std::vector<std::optional<DIFF_PAIR_COUPLED_SEGMENTS>> coupled_vec;
 
  408            if( !itemN || itemN->
Type() != 
PCB_ARC_T || isInTuningPattern( itemN ) )
 
  437                    coupled_vec.push_back( cpair );
 
  442        for( 
const std::optional<DIFF_PAIR_COUPLED_SEGMENTS>& coupled : coupled_vec )
 
  447                        if( aItem == coupled->parentN || aItem == coupled->parentP )
 
  454                            if( bci->
GetNetCode() == coupled->parentN->GetNetCode()
 
  455                                    ||  bci->
GetNetCode() == coupled->parentP->GetNetCode() )
 
  464                            auto arcExitsPad = [&]( 
PCB_ARC* arc )
 
  466                                bool startIn = 
pad->HitTest( arc->GetStart(), 0 );
 
  467                                bool endIn = 
pad->HitTest( arc->GetEnd(), 0 );
 
  469                                return startIn ^ endIn;
 
  472                            if( arcExitsPad( 
static_cast<PCB_ARC*
>( coupled->parentP ) )
 
  473                                    || arcExitsPad( 
static_cast<PCB_ARC*
>( coupled->parentN ) ) )
 
  482            SHAPE_SEGMENT checkArcMid( coupled->coupledArcN.GetArcMid(), coupled->coupledArcP.GetArcMid() );
 
  483            DRC_RTREE*    tree = coupled->parentP->GetBoard()->m_CopperItemRTreeCache.get();
 
  489                aDp.
coupled.push_back( *coupled );
 
 
  503    std::map<DIFF_PAIR_KEY, DIFF_PAIR_ITEMS> dpRuleMatches;
 
  505    auto evaluateDpConstraints =
 
  529                        wxString ruleName = parentRule ? parentRule->
m_Name : constraint.
GetName();
 
  531                        switch( constraintType )
 
  550                            dpRuleMatches[key].itemsN.insert( citem );
 
  552                            dpRuleMatches[key].itemsP.insert( citem );
 
  567    for( 
auto& [ key, itemSet ] : dpRuleMatches )
 
  578        REPORT_AUX( wxString::Format( wxT( 
"Rule '%s', DP: (+) %s - (-) %s" ),
 
  579                                      key.gapRuleName, nameP, nameN ) );
 
  583        itemSet.totalCoupled = 0;
 
  584        itemSet.totalLengthN = 0;
 
  585        itemSet.totalLengthP = 0;
 
  589        std::set<BOARD_CONNECTED_ITEM*> allItems;
 
  595                if( allItems.insert( item ).second)
 
  596                    itemSet.totalLengthN += track->GetLength();
 
  604                if( allItems.insert( item ).second)
 
  605                    itemSet.totalLengthP += track->GetLength();
 
  621                overlay->SetLineWidth( 100000 );
 
  632            if( key.gapConstraint )
 
  634                if( key.gapConstraint->HasMin()
 
  635                    && key.gapConstraint->Min() >= 0
 
  641                if( key.gapConstraint->HasMax()
 
  642                    && key.gapConstraint->Max() >= 0
 
  650                itemSet.totalCoupled += length;
 
  653        int totalLen = std::max( itemSet.totalLengthN, itemSet.totalLengthP );
 
  655        REPORT_AUX( wxString::Format( wxT( 
"   - coupled length: %s, total length: %s" ),
 
  659        int  totalUncoupled = totalLen - itemSet.totalCoupled;
 
  660        bool uncoupledViolation = 
false;
 
  662        if( key.uncoupledConstraint && ( !itemSet.itemsP.empty() || !itemSet.itemsN.empty() ) )
 
  666            if( val.
HasMax() && val.
Max() >= 0 && totalUncoupled > val.
Max() )
 
  669                wxString msg = 
formatMsg( 
_( 
"(%s maximum uncoupled length %s; actual %s)" ),
 
  670                                          key.uncoupledRuleName,
 
  674                drce->SetErrorMessage( drce->GetErrorText() + wxS( 
" " ) + msg );
 
  677                auto                  p_it = itemSet.itemsP.begin();
 
  678                auto                  n_it = itemSet.itemsN.begin();
 
  680                if( p_it != itemSet.itemsP.end() )
 
  683                    drce->AddItem( *p_it );
 
  687                if( n_it != itemSet.itemsN.end() )
 
  690                    drce->AddItem( *n_it );
 
  694                while( p_it != itemSet.itemsP.end() )
 
  695                    drce->AddItem( *p_it++ );
 
  697                while( n_it != itemSet.itemsN.end() )
 
  698                    drce->AddItem( *n_it++ );
 
  700                uncoupledViolation = 
true;
 
  702                drce->SetViolatingRule( key.uncoupledRule );
 
  708        if( key.gapConstraint && ( uncoupledViolation || !key.uncoupledConstraint ) )
 
  737                        msg = 
formatMsg( 
_( 
"(%s minimum gap %s; actual %s)" ),
 
  744                        msg = 
formatMsg( 
_( 
"(%s maximum gap %s; actual %s)" ),
 
  750                    drcItem->SetErrorMessage( drcItem->GetErrorText() + wxS( 
" " ) + msg );
 
  751                    drcItem->SetViolatingRule( key.gapRule );
 
  758                        drcItem->AddItem( dp.
parentP );
 
  764                        drcItem->AddItem( dp.
parentN );
 
 
constexpr BOX2I KiROUND(const BOX2D &aBoxD)
 
static const ADVANCED_CFG & GetCfg()
Get the singleton instance's config, which is shared by all consumers.
 
A base class derived from BOARD_ITEM for items that can be connected and have a net,...
 
NETINFO_ITEM * GetNet() const
Return #NET_INFO object for a given item.
 
A base class for any item which can be embedded within the BOARD container class, and therefore insta...
 
virtual PCB_LAYER_ID GetLayer() const
Return the primary layer this item is on.
 
Information pertinent to a Pcbnew printed circuit board.
 
SEVERITY GetSeverity() const
 
const MINOPTMAX< int > & GetValue() const
 
DRC_RULE * GetParentRule() const
 
static bool IsNetADiffPair(BOARD *aBoard, NETINFO_ITEM *aNet, int &aNetP, int &aNetN)
 
static std::shared_ptr< DRC_ITEM > Create(int aErrorCode)
Constructs a DRC_ITEM for the given error code.
 
Implement an R-tree for fast spatial and layer indexing of connectable items.
 
bool CheckColliding(SHAPE *aRefShape, PCB_LAYER_ID aTargetLayer, int aClearance=0, std::function< bool(BOARD_ITEM *)> aFilter=nullptr) const
 
int forEachGeometryItem(const std::vector< KICAD_T > &aTypes, const LSET &aLayers, const std::function< bool(BOARD_ITEM *)> &aFunc)
 
void reportViolation(std::shared_ptr< DRC_ITEM > &item, const VECTOR2I &aMarkerPos, int aMarkerLayer, const std::function< void(PCB_MARKER *)> &aPathGenerator=[](PCB_MARKER *){})
 
wxString formatMsg(const wxString &aFormatString, const wxString &aSource, double aConstraint, double aActual, EDA_DATA_TYPE aDataType=EDA_DATA_TYPE::DISTANCE)
 
A set of EDA_ITEMs (i.e., without duplicates).
 
virtual VECTOR2I GetPosition() const
 
virtual const VECTOR2I GetFocusPosition() const
Similar to GetPosition() but allows items to return their visual center rather than their anchor.
 
KICAD_T Type() const
Returns the type of object.
 
LSET is a set of PCB_LAYER_IDs.
 
static LSET AllCuMask()
return AllCuMask( MAX_CU_LAYERS );
 
Handle the data for a net.
 
const wxString & GetNetname() const
 
virtual double GetLength() const override
Return the length of the arc track.
 
const VECTOR2I & GetMid() const
 
virtual VECTOR2I GetCenter() const override
This defaults to the center of the bounding box if not overridden.
 
virtual LSET GetLayerSet() const override
Return a std::bitset of all layers on which the item physically resides.
 
const VECTOR2I & GetStart() const
 
bool HitTest(const VECTOR2I &aPosition, int aAccuracy=0) const override
Test if aPosition is inside or on the boundary of this item.
 
const VECTOR2I & GetEnd() const
 
virtual int GetWidth() const
 
int Length() const
Return the length (this).
 
OPT_VECTOR2I Intersect(const SEG &aSeg, bool aIgnoreEndpoints=false, bool aLines=false) const
Compute intersection point of segment (this) with segment aSeg.
 
ecoord TCoef(const VECTOR2I &aP) const
 
ecoord SquaredLength() const
 
bool NearestPoints(const SEG &aSeg, VECTOR2I &aPtA, VECTOR2I &aPtB, int64_t &aDistSq) const
Compute closest points between this segment and aSeg.
 
VECTOR2I LineProject(const VECTOR2I &aP) const
Compute the perpendicular projection point of aP on a line passing through ends of the segment.
 
EDA_ANGLE GetEndAngle() const
 
void Rotate(const EDA_ANGLE &aAngle, const VECTOR2I &aCenter) override
Rotate the arc by a given angle about a point.
 
EDA_ANGLE GetStartAngle() const
 
bool NearestPoints(const SHAPE_ARC &aArc, VECTOR2I &aPtA, VECTOR2I &aPtB, int64_t &aDistSq) const
Compute closest points between this arc and aArc.
 
wxString MessageTextFromValue(double aValue, bool aAddUnitLabel=true, EDA_DATA_TYPE aType=EDA_DATA_TYPE::DISTANCE) const
A lower-precision version of StringFromValue().
 
constexpr extended_type SquaredDistance(const VECTOR2< T > &aVector) const
Compute the squared distance between two vectors.
 
virtual ~DRC_TEST_PROVIDER_DIFF_PAIR_COUPLING()=default
 
DRC_TEST_PROVIDER_DIFF_PAIR_COUPLING()
 
virtual const wxString GetName() const override
 
virtual bool Run() override
Run this provider against the given PCB with configured options (if any).
 
@ DRCE_DIFF_PAIR_GAP_OUT_OF_RANGE
 
@ DRCE_DIFF_PAIR_UNCOUPLED_LENGTH_TOO_LONG
 
@ DIFF_PAIR_GAP_CONSTRAINT
 
@ MAX_UNCOUPLED_CONSTRAINT
 
static bool commonParallelProjection(SEG p, SEG n, SEG &pClip, SEG &nClip)
 
static void extractDiffPairCoupledItems(DIFF_PAIR_ITEMS &aDp)
 
PCB_LAYER_ID
A quick note on layer IDs:
 
static DRC_REGISTER_TEST_PROVIDER< DRC_TEST_PROVIDER_ANNULAR_WIDTH > dummy
 
EDA_ANGLE abs(const EDA_ANGLE &aAngle)
 
std::shared_ptr< PNS_LOG_VIEWER_OVERLAY > overlay
 
DIFF_PAIR_COUPLED_SEGMENTS()
 
std::set< BOARD_CONNECTED_ITEM * > itemsN
 
std::vector< DIFF_PAIR_COUPLED_SEGMENTS > coupled
 
std::set< BOARD_CONNECTED_ITEM * > itemsP
 
wxString uncoupledRuleName
 
std::optional< MINOPTMAX< int > > uncoupledConstraint
 
std::optional< MINOPTMAX< int > > gapConstraint
 
bool operator<(const DIFF_PAIR_KEY &b) const
 
@ PCB_VIA_T
class PCB_VIA, a via (like a track segment on a copper layer)
 
@ PCB_PAD_T
class PAD, a pad in a footprint
 
@ PCB_ARC_T
class PCB_ARC, an arc track segment on a copper layer
 
@ PCB_TRACE_T
class PCB_TRACK, a track segment (segment on a copper layer)
 
T rescale(T aNumerator, T aValue, T aDenominator)
Scale a number (value) by rational (numerator/denominator).
 
VECTOR2< int32_t > VECTOR2I