← Back to team overview

kicad-developers team mailing list archive

Re: [update] [PATCH] Differential pair DRC Errors

 

On 13.02.2017 18:04, Tomasz Wlostowski wrote:
> On 13.02.2017 17:26, Jon Evans wrote:
>> I verified using Novak's test case on the Launchpad bug report.  DRC
>> error is generated if the distance between the tracks is exactly equal
>> to the clearance. 
>> If you increase the spacing by the minimum distance recognized by the
>> software's precision, the DRC passes.
>> So, I think it's an issue of DRC specification -- The code currently
>> requires that the clearance be *larger* than the minimum in the design
>> rules.
>> The diff pair router is setting the spacing to the minimum (exactly)
>> which causes this bug.
>>
>> IMHO, the DRC code should be changed to "larger or equal to", but I am
>> not sure if there is some subtle reason why it is implemented this way.
>> If you tell KiCad that you can go down to 2mm clearance, you should be
>> able to design something with *exactly* 2mm clearance :-)
> 
> Hi guys,
> 
> The issue is a bit more complex: it's a mix of DRC's floating point
> inaccuracies as well as ill-defined (rounding-error-wise) fixed point
> calculations in the 'gateway' computation part of the diff pair code.
> I'll fix it when my time permits (certainly before v5.0).
> 

Hi again,

I've fixed the rounding issues in the P&S code (patch attached), now the
diff pair gap should always equal the specified value. The DRC checker
still produces some errors, though. I've identified their source is the
DRC::checkMarginToCircle() function. The current clearance test
algorithm is quite complex for me to understand, so I couldn't see any
obvious rounding/comparison issues...

@Jean-Pierre: could you have a look at the attached PCB file and the DRC
errors it produces? A trivial clearance check (see code below) finds no
clearance errors.

Cheers,
Tom

-- snip --

void DRC::testTracks2( wxWindow *aActiveWindow, bool aShowProgressBar )
{
    for( TRACK* segm1 = m_pcb->m_Track; segm1; segm1 = segm1->Next() )
    {
        for( TRACK* segm2 = m_pcb->m_Track; segm2; segm2 = segm2->Next() )
        {
            if ( segm1 == segm2 )
                continue;

            if( segm1->Type() == PCB_VIA_T )
                continue;

            if( segm2->Type() == PCB_VIA_T )
                continue;

            if (segm1->GetNetCode() == segm2->GetNetCode() )
                continue;

            if (segm1->GetLayer() != segm2->GetLayer() )
                continue;

            NETCLASSPTR netclass = segm1->GetNetClass();

            SEG s1 ( VECTOR2I( segm1->GetStart() ), VECTOR2I (
segm1->GetEnd() ) );
            SEG s2 ( VECTOR2I( segm2->GetStart() ), VECTOR2I (
segm2->GetEnd() ) );

            int dist = s1.Distance ( s2 );
            int min_dist  = netclass->GetClearance() +
(segm1->GetWidth() + 1) / 2 + (segm2->GetWidth() + 1 ) / 2;

            if ( dist < min_dist )
            {
                printf("segment/segment clearance failure %p %p dist %d
min_dist %d w1 %d w2 %d cl %d\n",segm1, segm2, dist, min_dist,
segm1->GetWidth(), segm2->GetWidth(), netclass->GetClearance() );
            }
        }
    }
}


(kicad_pcb (version 20170123) (host pcbnew "(2017-02-28 revision fd4e2b0)-master")

  (general
    (links 20)
    (no_connects 11)
    (area 61.477825 45.17296 219.825668 128.460501)
    (thickness 1.6002)
    (drawings 0)
    (tracks 12)
    (zones 0)
    (modules 1)
    (nets 29)
  )

  (page A4)
  (title_block
    (date "27 mar 2013")
  )

  (layers
    (0 Front signal)
    (1 Inner3 signal)
    (2 Inner2 signal)
    (31 Back signal)
    (32 B.Adhes user)
    (33 F.Adhes user)
    (34 B.Paste user)
    (35 F.Paste user)
    (36 B.SilkS user)
    (37 F.SilkS user)
    (38 B.Mask user)
    (39 F.Mask user)
    (44 Edge.Cuts user)
  )

  (setup
    (last_trace_width 0.1)
    (user_trace_width 0.1)
    (user_trace_width 0.1524)
    (user_trace_width 0.2032)
    (user_trace_width 0.254)
    (user_trace_width 0.3048)
    (user_trace_width 0.4572)
    (user_trace_width 0.508)
    (user_trace_width 1.27)
    (trace_clearance 0.1)
    (zone_clearance 0.3048)
    (zone_45_only no)
    (trace_min 0.1)
    (segment_width 0.2032)
    (edge_width 0.381)
    (via_size 0.6858)
    (via_drill 0.3302)
    (via_min_size 0.35)
    (via_min_drill 0.25)
    (user_via 0.4 0.25)
    (user_via 0.7874 0.4064)
    (user_via 0.9398 0.508)
    (user_via 1.0668 0.635)
    (uvia_size 0.508)
    (uvia_drill 0.127)
    (uvias_allowed no)
    (uvia_min_size 0.508)
    (uvia_min_drill 0.127)
    (pcb_text_width 0.1905)
    (pcb_text_size 0.762 1.016)
    (mod_edge_width 0.2032)
    (mod_text_size 1.524 1.524)
    (mod_text_width 0.3048)
    (pad_size 4.52882 4.52882)
    (pad_drill 0)
    (pad_to_mask_clearance 0.1524)
    (pad_to_paste_clearance_ratio -0.12)
    (aux_axis_origin 0 0)
    (grid_origin 134.7 62.1)
    (visible_elements FFFFFFFF)
    (pcbplotparams
      (layerselection 0x00030_80000001)
      (usegerberextensions true)
      (excludeedgelayer true)
      (linewidth 0.150000)
      (plotframeref false)
      (viasonmask false)
      (mode 1)
      (useauxorigin false)
      (hpglpennumber 1)
      (hpglpenspeed 20)
      (hpglpendiameter 15)
      (psnegative false)
      (psa4output false)
      (plotreference false)
      (plotvalue false)
      (plotinvisibletext false)
      (padsonsilk false)
      (subtractmaskfromsilk false)
      (outputformat 1)
      (mirror false)
      (drillshape 1)
      (scaleselection 1)
      (outputdirectory ""))
  )

  (net 0 "")
  (net 1 /baseband/CPOUT+)
  (net 2 /baseband/CPOUT-)
  (net 3 /baseband/RXBBI+)
  (net 4 /baseband/RXBBI-)
  (net 5 /baseband/RXBBQ+)
  (net 6 /baseband/RXBBQ-)
  (net 7 /baseband/TXBBI+)
  (net 8 /baseband/TXBBI-)
  (net 9 /baseband/TXBBQ+)
  (net 10 /baseband/TXBBQ-)
  (net 11 /baseband/XCVR_CLKOUT)
  (net 12 /baseband/XTAL2)
  (net 13 CS_XCVR)
  (net 14 GND)
  (net 15 N-000247)
  (net 16 N-000252)
  (net 17 N-000262)
  (net 18 N-000280)
  (net 19 N-000281)
  (net 20 RSSI)
  (net 21 RXENABLE)
  (net 22 SSP1_MISO)
  (net 23 SSP1_MOSI)
  (net 24 SSP1_SCK)
  (net 25 TXENABLE)
  (net 26 VAA)
  (net 27 VCC)
  (net 28 XCVR_EN)

  (net_class Default "This is the default net class."
    (clearance 0.1)
    (trace_width 0.1)
    (via_dia 0.6858)
    (via_drill 0.3302)
    (uvia_dia 0.508)
    (uvia_drill 0.127)
    (diff_pair_gap 0.1)
    (diff_pair_width 0.1)
    (add_net /baseband/CPOUT+)
    (add_net /baseband/CPOUT-)
    (add_net /baseband/RXBBI+)
    (add_net /baseband/RXBBI-)
    (add_net /baseband/RXBBQ+)
    (add_net /baseband/RXBBQ-)
    (add_net /baseband/TXBBI+)
    (add_net /baseband/TXBBI-)
    (add_net /baseband/TXBBQ+)
    (add_net /baseband/TXBBQ-)
    (add_net /baseband/XCVR_CLKOUT)
    (add_net /baseband/XTAL2)
    (add_net CS_XCVR)
    (add_net GND)
    (add_net N-000247)
    (add_net N-000252)
    (add_net N-000262)
    (add_net N-000280)
    (add_net N-000281)
    (add_net RSSI)
    (add_net RXENABLE)
    (add_net SSP1_MISO)
    (add_net SSP1_MOSI)
    (add_net SSP1_SCK)
    (add_net TXENABLE)
    (add_net VAA)
    (add_net VCC)
    (add_net XCVR_EN)
  )

  (module GSG-QFN48-6 placed (layer Front) (tedit 4F5D8918) (tstamp 50465D79)
    (at 130.1115 68.6435 270)
    (path /50370666/4F5BBC9D)
    (solder_mask_margin 0.0508)
    (clearance 0.1524)
    (fp_text reference U17 (at 0 0 270) (layer F.SilkS)
      (effects (font (size 1.00076 1.00076) (thickness 0.2032)))
    )
    (fp_text value MAX2837 (at 0 0 270) (layer F.SilkS) hide
      (effects (font (size 1.00076 1.00076) (thickness 0.2032)))
    )
    (fp_line (start -2.99974 -2.60096) (end -2.60096 -2.99974) (layer F.SilkS) (width 0.2032))
    (fp_line (start -2.60096 2.99974) (end -2.99974 2.99974) (layer F.SilkS) (width 0.2032))
    (fp_line (start -2.99974 2.99974) (end -2.99974 2.60096) (layer F.SilkS) (width 0.2032))
    (fp_line (start 2.99974 2.60096) (end 2.99974 2.99974) (layer F.SilkS) (width 0.2032))
    (fp_line (start 2.99974 2.99974) (end 2.60096 2.99974) (layer F.SilkS) (width 0.2032))
    (fp_line (start 2.60096 -2.99974) (end 2.99974 -2.99974) (layer F.SilkS) (width 0.2032))
    (fp_line (start 2.99974 -2.99974) (end 2.99974 -2.60096) (layer F.SilkS) (width 0.2032))
    (pad 1 smd oval (at -2.99974 -2.19964 270) (size 0.87122 0.24638) (layers Front F.Paste F.Mask)
      (net 26 VAA) (die_length 0.00254))
    (pad 2 smd oval (at -2.99974 -1.80086 270) (size 0.87122 0.24638) (layers Front F.Paste F.Mask)
      (net 14 GND) (die_length 0.28702))
    (pad 3 smd oval (at -2.99974 -1.39954 270) (size 0.87122 0.24638) (layers Front F.Paste F.Mask)
      (die_length -2147.483648))
    (pad 4 smd oval (at -2.99974 -1.00076 270) (size 0.87122 0.24638) (layers Front F.Paste F.Mask)
      (net 17 N-000262) (die_length -2147.483648))
    (pad 5 smd oval (at -2.99974 -0.59944 270) (size 0.87122 0.24638) (layers Front F.Paste F.Mask)
      (net 15 N-000247) (die_length 0.0508))
    (pad 6 smd oval (at -2.99974 -0.20066 270) (size 0.87122 0.24638) (layers Front F.Paste F.Mask)
      (die_length -2147.483648))
    (pad 7 smd oval (at -2.99974 0.20066 270) (size 0.87122 0.24638) (layers Front F.Paste F.Mask)
      (net 26 VAA) (die_length -2147.483648))
    (pad 8 smd oval (at -2.99974 0.59944 270) (size 0.87122 0.24638) (layers Front F.Paste F.Mask)
      (die_length 0.59436))
    (pad 9 smd oval (at -2.99974 1.00076 270) (size 0.87122 0.24638) (layers Front F.Paste F.Mask)
      (die_length 0.00254))
    (pad 10 smd oval (at -2.99974 1.39954 270) (size 0.87122 0.24638) (layers Front F.Paste F.Mask)
      (net 19 N-000281) (die_length 0.08382))
    (pad 11 smd oval (at -2.99974 1.80086 270) (size 0.87122 0.24638) (layers Front F.Paste F.Mask)
      (net 18 N-000280) (die_length -2147.483648))
    (pad 12 smd oval (at -2.99974 2.19964 270) (size 0.87122 0.24638) (layers Front F.Paste F.Mask)
      (die_length 0.16256))
    (pad 13 smd oval (at -2.19964 2.99974) (size 0.87122 0.24638) (layers Front F.Paste F.Mask)
      (net 26 VAA) (die_length 0.09906))
    (pad 14 smd oval (at -1.80086 2.99974) (size 0.87122 0.24638) (layers Front F.Paste F.Mask)
      (die_length 0.0889))
    (pad 15 smd oval (at -1.39954 2.99974) (size 0.87122 0.24638) (layers Front F.Paste F.Mask)
      (net 24 SSP1_SCK) (die_length -2147.483648))
    (pad 16 smd oval (at -1.00076 2.99974) (size 0.87122 0.24638) (layers Front F.Paste F.Mask)
      (net 11 /baseband/XCVR_CLKOUT) (die_length 0.27178))
    (pad 17 smd oval (at -0.59944 2.99974) (size 0.87122 0.24638) (layers Front F.Paste F.Mask)
      (net 12 /baseband/XTAL2) (die_length 0.12192))
    (pad 18 smd oval (at -0.20066 2.99974) (size 0.87122 0.24638) (layers Front F.Paste F.Mask)
      (die_length 0.16256))
    (pad 19 smd oval (at 0.20066 2.99974) (size 0.87122 0.24638) (layers Front F.Paste F.Mask)
      (net 26 VAA) (die_length -2147.483648))
    (pad 20 smd oval (at 0.59944 2.99974) (size 0.87122 0.24638) (layers Front F.Paste F.Mask)
      (net 27 VCC) (die_length -2147.483648))
    (pad 21 smd oval (at 1.00076 2.99974) (size 0.87122 0.24638) (layers Front F.Paste F.Mask)
      (net 26 VAA) (die_length -2147.483648))
    (pad 22 smd oval (at 1.39954 2.99974) (size 0.87122 0.24638) (layers Front F.Paste F.Mask)
      (net 14 GND) (die_length 0.32766))
    (pad 23 smd oval (at 1.80086 2.99974) (size 0.87122 0.24638) (layers Front F.Paste F.Mask)
      (net 1 /baseband/CPOUT+) (die_length 0.3683))
    (pad 24 smd oval (at 2.19964 2.99974) (size 0.87122 0.24638) (layers Front F.Paste F.Mask)
      (net 2 /baseband/CPOUT-) (die_length -2147.483648))
    (pad 25 smd oval (at 2.99974 2.19964 270) (size 0.87122 0.24638) (layers Front F.Paste F.Mask)
      (net 28 XCVR_EN) (die_length 0.7239))
    (pad 26 smd oval (at 2.99974 1.80086 270) (size 0.87122 0.24638) (layers Front F.Paste F.Mask)
      (net 14 GND) (die_length -2147.483648))
    (pad 27 smd oval (at 2.99974 1.39954 270) (size 0.87122 0.24638) (layers Front F.Paste F.Mask)
      (net 16 N-000252) (die_length 21.41728))
    (pad 28 smd oval (at 2.99974 1.00076 270) (size 0.87122 0.24638) (layers Front F.Paste F.Mask)
      (net 26 VAA) (die_length -2147.483648))
    (pad 29 smd oval (at 2.99974 0.59944 270) (size 0.87122 0.24638) (layers Front F.Paste F.Mask)
      (net 22 SSP1_MISO) (die_length 0.00254))
    (pad 30 smd oval (at 2.99974 0.20066 270) (size 0.87122 0.24638) (layers Front F.Paste F.Mask)
      (net 13 CS_XCVR) (die_length 0.00762))
    (pad 31 smd oval (at 2.99974 -0.20066 270) (size 0.87122 0.24638) (layers Front F.Paste F.Mask)
      (net 23 SSP1_MOSI) (die_length 0.2159))
    (pad 32 smd oval (at 2.99974 -0.59944 270) (size 0.87122 0.24638) (layers Front F.Paste F.Mask)
      (net 20 RSSI) (die_length 0.9779))
    (pad 33 smd oval (at 2.99974 -1.00076 270) (size 0.87122 0.24638) (layers Front F.Paste F.Mask)
      (die_length 0.28448))
    (pad 34 smd oval (at 2.99974 -1.39954 270) (size 0.87122 0.24638) (layers Front F.Paste F.Mask)
      (die_length 1.30302))
    (pad 35 smd oval (at 2.99974 -1.80086 270) (size 0.87122 0.24638) (layers Front F.Paste F.Mask)
      (net 6 /baseband/RXBBQ-) (die_length 0.7747))
    (pad 36 smd oval (at 2.99974 -2.19964 270) (size 0.87122 0.24638) (layers Front F.Paste F.Mask)
      (net 5 /baseband/RXBBQ+) (die_length 0.08382))
    (pad 37 smd oval (at 2.19964 -2.99974) (size 0.87122 0.24638) (layers Front F.Paste F.Mask)
      (net 4 /baseband/RXBBI-) (die_length -2147.483648))
    (pad 38 smd oval (at 1.80086 -2.99974) (size 0.87122 0.24638) (layers Front F.Paste F.Mask)
      (net 3 /baseband/RXBBI+) (die_length -2147.483648))
    (pad 39 smd oval (at 1.39954 -2.99974) (size 0.87122 0.24638) (layers Front F.Paste F.Mask)
      (net 26 VAA) (die_length 0.0889))
    (pad 40 smd oval (at 1.00076 -2.99974) (size 0.87122 0.24638) (layers Front F.Paste F.Mask)
      (die_length 0.72898))
    (pad 41 smd oval (at 0.59944 -2.99974) (size 0.87122 0.24638) (layers Front F.Paste F.Mask)
      (net 26 VAA) (die_length -2147.483648))
    (pad 42 smd oval (at 0.20066 -2.99974) (size 0.87122 0.24638) (layers Front F.Paste F.Mask)
      (net 8 /baseband/TXBBI-) (die_length 0.27432))
    (pad 43 smd oval (at -0.20066 -2.99974) (size 0.87122 0.24638) (layers Front F.Paste F.Mask)
      (net 7 /baseband/TXBBI+) (die_length 152.8064))
    (pad 44 smd oval (at -0.59944 -2.99974) (size 0.87122 0.24638) (layers Front F.Paste F.Mask)
      (net 9 /baseband/TXBBQ+) (die_length 165.8112))
    (pad 45 smd oval (at -1.00076 -2.99974) (size 0.87122 0.24638) (layers Front F.Paste F.Mask)
      (net 10 /baseband/TXBBQ-) (die_length 178.816))
    (pad 46 smd oval (at -1.39954 -2.99974) (size 0.87122 0.24638) (layers Front F.Paste F.Mask)
      (net 26 VAA) (die_length -2147.483648))
    (pad 47 smd oval (at -1.80086 -2.99974) (size 0.87122 0.24638) (layers Front F.Paste F.Mask)
      (net 25 TXENABLE) (die_length -2147.483648))
    (pad 48 smd oval (at -2.19964 -2.99974) (size 0.87122 0.24638) (layers Front F.Paste F.Mask)
      (net 21 RXENABLE) (die_length 0.2159))
    (pad 0 smd rect (at 0 0 270) (size 4.52882 4.52882) (layers Front F.Mask)
      (net 14 GND) (die_length -2147.483648) (solder_mask_margin -0.09906))
    (pad 0 thru_hole circle (at 0 0 270) (size 0.635 0.635) (drill 0.381) (layers *.Cu B.Mask)
      (net 14 GND) (die_length 0.5461) (clearance -0.09906))
    (pad 0 thru_hole circle (at -1.50876 0 270) (size 0.635 0.635) (drill 0.381) (layers *.Cu B.Mask)
      (net 14 GND) (die_length 0.85598) (clearance -0.09906))
    (pad 0 thru_hole circle (at -1.50876 -1.50876 270) (size 0.635 0.635) (drill 0.381) (layers *.Cu B.Mask)
      (net 14 GND) (die_length -2147.483648) (clearance -0.09906))
    (pad 0 thru_hole circle (at 0 -1.50876 270) (size 0.635 0.635) (drill 0.381) (layers *.Cu B.Mask)
      (net 14 GND) (die_length 0.08128) (clearance -0.09906))
    (pad 0 thru_hole circle (at 1.50876 -1.50876 270) (size 0.635 0.635) (drill 0.381) (layers *.Cu B.Mask)
      (net 14 GND) (die_length 0.43942) (clearance -0.09906))
    (pad 0 thru_hole circle (at 1.50876 0 270) (size 0.635 0.635) (drill 0.381) (layers *.Cu B.Mask)
      (net 14 GND) (die_length 0.28448) (clearance -0.09906))
    (pad 0 thru_hole circle (at 1.50876 1.50876 270) (size 0.635 0.635) (drill 0.381) (layers *.Cu B.Mask)
      (net 14 GND) (die_length 0.27432) (clearance -0.09906))
    (pad 0 thru_hole circle (at 0 1.50876 270) (size 0.635 0.635) (drill 0.381) (layers *.Cu B.Mask)
      (net 14 GND) (die_length -0.7493) (clearance -0.09906))
    (pad 0 thru_hole circle (at -1.50876 1.50876 270) (size 0.635 0.635) (drill 0.381) (layers *.Cu B.Mask)
      (net 14 GND) (die_length 0.08382) (clearance -0.09906))
    (pad "" smd rect (at -1.50876 -1.50876 270) (size 1.50876 1.50876) (layers F.Paste)
      (die_length -2147.483648))
    (pad "" smd rect (at 0 -1.50876 270) (size 1.50876 1.50876) (layers F.Paste)
      (die_length -2147.483648))
    (pad "" smd rect (at 1.50876 -1.50876 270) (size 1.50876 1.50876) (layers F.Paste)
      (die_length 0.12192))
    (pad "" smd rect (at -1.50876 0 270) (size 1.50876 1.50876) (layers F.Paste)
      (die_length -2147.483648))
    (pad "" smd rect (at 0 0 270) (size 1.50876 1.50876) (layers F.Paste)
      (die_length 0.72898))
    (pad "" smd rect (at 1.50876 0 270) (size 1.50876 1.50876) (layers F.Paste)
      (die_length -2147.483648))
    (pad "" smd rect (at -1.50876 1.50876 270) (size 1.50876 1.50876) (layers F.Paste)
      (die_length 0.2921))
    (pad "" smd rect (at 0 1.50876 270) (size 1.50876 1.50876) (layers F.Paste)
      (die_length 0.08382))
    (pad "" smd rect (at 1.50876 1.50876 270) (size 1.50876 1.50876) (layers F.Paste)
      (die_length -2147.483648))
  )

  (segment (start 140.241422 69.5) (end 140.770711 70.029289) (width 0.1) (layer Front) (net 7))
  (segment (start 133.64751 68.5435) (end 134.784922 68.5435) (width 0.1) (layer Front) (net 7))
  (segment (start 134.784922 68.5435) (end 135.741422 69.5) (width 0.1) (layer Front) (net 7))
  (segment (start 135.741422 69.5) (end 140.241422 69.5) (width 0.1) (layer Front) (net 7))
  (segment (start 133.11124 68.44284) (end 133.54685 68.44284) (width 0.1) (layer Front) (net 7))
  (segment (start 133.54685 68.44284) (end 133.64751 68.5435) (width 0.1) (layer Front) (net 7))
  (segment (start 140.158578 69.7) (end 140.629289 70.170711) (width 0.1) (layer Front) (net 8))
  (segment (start 135.658578 69.7) (end 140.158578 69.7) (width 0.1) (layer Front) (net 8))
  (segment (start 133.64751 68.7435) (end 134.702078 68.7435) (width 0.1) (layer Front) (net 8))
  (segment (start 134.702078 68.7435) (end 135.658578 69.7) (width 0.1) (layer Front) (net 8))
  (segment (start 133.54685 68.84416) (end 133.64751 68.7435) (width 0.1) (layer Front) (net 8))
  (segment (start 133.11124 68.84416) (end 133.54685 68.84416) (width 0.1) (layer Front) (net 8))

)
>From d8c4f6be00a4cb924c889054871df0d4064b43f3 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Tomasz=20W=C5=82ostowski?= <tomasz.wlostowski@xxxxxxx>
Date: Wed, 1 Mar 2017 16:37:03 +0100
Subject: [PATCH] Fixed differential pair gap clearance error when gap equaled
 minimum clearance.

---
 pcbnew/router/pns_diff_pair.cpp | 69 ++++++++++++++++++++++++-----------------
 pcbnew/router/pns_kicad_iface.h |  1 -
 2 files changed, 41 insertions(+), 29 deletions(-)

diff --git a/pcbnew/router/pns_diff_pair.cpp b/pcbnew/router/pns_diff_pair.cpp
index 4b2d586..8581464 100644
--- a/pcbnew/router/pns_diff_pair.cpp
+++ b/pcbnew/router/pns_diff_pair.cpp
@@ -406,6 +406,18 @@ void DP_GATEWAYS::FilterByOrientation ( int aAngleMask, DIRECTION_45 aRefOrienta
     } );
 }
 
+static VECTOR2I makeGapVector( VECTOR2I dir, int length )
+{
+    int l = length / 2;
+    VECTOR2I rv;
+    do
+	{
+        rv = dir.Resize( l );
+        l++;
+    } while( ( rv * 2 ).EuclideanNorm() < length );
+
+    return rv;
+}
 
 void DP_GATEWAYS::BuildFromPrimitivePair( DP_PRIMITIVE_PAIR aPair, bool aPreferDiagonal )
 {
@@ -452,8 +464,8 @@ void DP_GATEWAYS::BuildFromPrimitivePair( DP_PRIMITIVE_PAIR aPair, bool aPreferD
         if( w < h )
             std::swap( w, h );
 
-        orthoFanDistance = w * 3/4;
-        diagFanDistance = ( w - h ) / 2;
+        orthoFanDistance = ( w + 1 )* 3 / 2;
+        diagFanDistance = ( w - h );
         break;
     }
 
@@ -462,8 +474,8 @@ void DP_GATEWAYS::BuildFromPrimitivePair( DP_PRIMITIVE_PAIR aPair, bool aPreferD
         int w = static_cast<const SHAPE_SEGMENT*>( shP )->GetWidth();
         SEG s = static_cast<const SHAPE_SEGMENT*>( shP )->GetSeg();
 
-        orthoFanDistance = w + ( s.B - s.A ).EuclideanNorm() / 2;
-        diagFanDistance = ( s.B - s.A ).EuclideanNorm() / 2;
+        orthoFanDistance = w + ( s.B - s.A ).EuclideanNorm();
+        diagFanDistance = ( s.B - s.A ).EuclideanNorm();
         break;
     }
 
@@ -482,18 +494,17 @@ void DP_GATEWAYS::BuildFromPrimitivePair( DP_PRIMITIVE_PAIR aPair, bool aPreferD
 
             if( k == 0 )
             {
-                dir = majorDirection.Resize( orthoFanDistance );
-                int d = ( padDist - m_gap ) / 2;
-
-                dp = dir.Resize( d );
-                dv = ( p0_n - p0_p ).Resize( d );
+                dir = makeGapVector( majorDirection, orthoFanDistance );
+                int d = ( padDist - m_gap );
+                dp = makeGapVector( dir, d );
+                dv = makeGapVector( p0_n - p0_p, d );
             }
             else
             {
-                dir = majorDirection.Resize( diagFanDistance );
-                int d = ( padDist - m_gap ) / 2;
-                dp = dir.Resize( d );
-                dv = ( p0_n - p0_p ).Resize( d );
+                dir = makeGapVector( majorDirection, diagFanDistance );
+                int d = ( padDist - m_gap );
+                dp = makeGapVector( dir, d );
+                dv = makeGapVector( p0_n - p0_p, d );
             }
 
             for( int i = 0; i < 2; i++ )
@@ -531,7 +542,7 @@ void DP_GATEWAYS::BuildForCursor( const VECTOR2I& aCursorPos )
 
             if( !attempt )
             {
-                dir = VECTOR2I( gap, gap ).Resize( gap / 2 );
+                dir = makeGapVector( VECTOR2I( gap, gap ), gap );
 
                 if( i % 2 == 0 )
                     dir.x = -dir.x;
@@ -542,9 +553,9 @@ void DP_GATEWAYS::BuildForCursor( const VECTOR2I& aCursorPos )
             else
             {
                 if( i /2 == 0 )
-                    dir = VECTOR2I( gap / 2 * ( ( i % 2 ) ? -1 : 1 ), 0 );
+                    dir = VECTOR2I( (gap + 1) / 2 * ( ( i % 2 ) ? -1 : 1 ), 0 );
                 else
-                    dir = VECTOR2I( 0, gap / 2 * ( ( i % 2 ) ? -1 : 1) );
+                    dir = VECTOR2I( 0, (gap + 1) / 2 * ( ( i % 2 ) ? -1 : 1) );
             }
 
             if( m_fitVias )
@@ -593,20 +604,22 @@ void DP_GATEWAYS::buildDpContinuation( DP_PRIMITIVE_PAIR aPair, bool aIsDiagonal
 
     VECTOR2I t1, t2;
 
+    auto vL = makeGapVector( dP.Left().ToVector(), ( gap + 1 ) / 2 );
+    auto vR = makeGapVector( dP.Right().ToVector(), ( gap + 1 ) / 2 );
+
     if( sP->Seg().Side( vdP ) == sP->Seg().Side( vdN ) )
     {
-        t1 = aPair.AnchorP() + dP.Left().ToVector().Resize( gap );
-        t2 = aPair.AnchorN() + dP.Right().ToVector().Resize( gap );
+        t1 = aPair.AnchorP() + vL;
+        t2 = aPair.AnchorN() + vR;
     }
     else
     {
-        t1 = aPair.AnchorP() + dP.Right().ToVector().Resize( gap );
-        t2 = aPair.AnchorN() + dP.Left().ToVector().Resize( gap );
+        t1 = aPair.AnchorP() + vR;
+        t2 = aPair.AnchorN() + vL;
     }
 
     DP_GATEWAY gwL( t2, aPair.AnchorN(), !aIsDiagonal );
     SHAPE_LINE_CHAIN ep = dP.BuildInitialTrace( aPair.AnchorP(), t2, !aIsDiagonal );
-
     gwL.SetPriority( 10 );
     gwL.SetEntryLines( ep , SHAPE_LINE_CHAIN() );
 
@@ -646,7 +659,7 @@ void DP_GATEWAYS::BuildGeneric( const VECTOR2I& p0_p, const VECTOR2I& p0_n, bool
 
         if( straightColl || diagColl )
         {
-            VECTOR2I dir = ( p0_n - p0_p ).Resize( m_gap / 2 );
+            VECTOR2I dir = makeGapVector( p0_n - p0_p, m_gap / 2 );
             VECTOR2I m = ( p0_p + p0_n ) / 2;
             int prio = ( padDist > padToGapThreshold * m_gap ? 2 : 1);
 
@@ -654,7 +667,7 @@ void DP_GATEWAYS::BuildGeneric( const VECTOR2I& p0_p, const VECTOR2I& p0_n, bool
             {
                 m_gateways.push_back( DP_GATEWAY( m - dir, m + dir, diagColl, DIRECTION_45::ANG_RIGHT, prio ) );
 
-                dir = ( p0_n - p0_p ).Resize( m_gap );
+                dir = makeGapVector( p0_n - p0_p, 2 * m_gap );
                 m_gateways.push_back( DP_GATEWAY( p0_p - dir, p0_p - dir + dir.Perpendicular(), diagColl ) );
                 m_gateways.push_back( DP_GATEWAY( p0_p - dir, p0_p - dir - dir.Perpendicular(), diagColl ) );
                 m_gateways.push_back( DP_GATEWAY( p0_n + dir + dir.Perpendicular(), p0_n + dir, diagColl ) );
@@ -688,8 +701,8 @@ void DP_GATEWAYS::BuildGeneric( const VECTOR2I& p0_p, const VECTOR2I& p0_n, bool
                     if( m != p0_p && m != p0_n )
                     {
                         int prio = ( padDist > padToGapThreshold * m_gap ? 10 : 20 );
-                        VECTOR2I g_p( ( p0_p - m ).Resize( (double) m_gap * M_SQRT1_2 ) );
-                        VECTOR2I g_n( ( p0_n - m ).Resize( (double) m_gap * M_SQRT1_2 ) );
+                        VECTOR2I g_p( ( p0_p - m ).Resize( ceil( (double) m_gap * M_SQRT1_2 ) ) );
+                        VECTOR2I g_n( ( p0_n - m ).Resize( ceil( (double) m_gap * M_SQRT1_2 ) ) );
 
                         m_gateways.push_back( DP_GATEWAY( m + g_p, m + g_n, k == 0 ? true : false, DIRECTION_45::ANG_OBTUSE, prio ) );
                     }
@@ -710,14 +723,14 @@ void DP_GATEWAYS::BuildGeneric( const VECTOR2I& p0_p, const VECTOR2I& p0_n, bool
                     {
                         VECTOR2I g_p, g_n;
 
-                        g_p = ( p0_p - m ).Resize( (double) m_gap * M_SQRT2 );
-                        g_n = ( p0_n - m ).Resize( (double) m_gap );
+                        g_p = ( p0_p - m ).Resize( ceil( (double) m_gap * M_SQRT2 ) );
+                        g_n = ( p0_n - m ).Resize( ceil( (double) m_gap ) );
 
                         if( angle( g_p, g_n ) != DIRECTION_45::ANG_ACUTE )
                             m_gateways.push_back( DP_GATEWAY( m + g_p, m + g_n, true ) );
 
                         g_p = ( p0_p - m ).Resize( m_gap );
-                        g_n = ( p0_n - m ).Resize( (double) m_gap * M_SQRT2 );
+                        g_n = ( p0_n - m ).Resize( ceil( (double) m_gap * M_SQRT2 ) );
 
                         if( angle( g_p, g_n ) != DIRECTION_45::ANG_ACUTE )
                             m_gateways.push_back( DP_GATEWAY( m + g_p, m + g_n, true ) );
diff --git a/pcbnew/router/pns_kicad_iface.h b/pcbnew/router/pns_kicad_iface.h
index 0d65847..361f579 100644
--- a/pcbnew/router/pns_kicad_iface.h
+++ b/pcbnew/router/pns_kicad_iface.h
@@ -76,7 +76,6 @@ private:
     PNS::NODE* m_world;
     PNS::ROUTER* m_router;
     BOARD* m_board;
-    PICKED_ITEMS_LIST m_undoBuffer;
     PCB_EDIT_FRAME* m_frame;
     std::unique_ptr<BOARD_COMMIT> m_commit;
     DISPLAY_OPTIONS* m_dispOptions;
-- 
1.9.1


Follow ups

References