KiCad PCB EDA Suite
pns_kicad_iface.cpp
Go to the documentation of this file.
1 /*
2  * KiRouter - a push-and-(sometimes-)shove PCB router
3  *
4  * Copyright (C) 2013-2016 CERN
5  * Copyright (C) 2016 KiCad Developers, see AUTHORS.txt for contributors.
6  * Author: Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
7  *
8  * This program is free software: you can redistribute it and/or modify it
9  * under the terms of the GNU General Public License as published by the
10  * Free Software Foundation, either version 3 of the License, or (at your
11  * option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful, but
14  * WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16  * General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License along
19  * with this program. If not, see <http://www.gnu.org/licenses/>.
20  */
21 
23 #include <class_board.h>
25 #include <class_module.h>
26 #include <class_track.h>
27 #include <board_commit.h>
29 #include <geometry/convex_hull.h>
30 #include <wxPcbStruct.h>
31 
32 #include <unordered_set>
33 #include <unordered_map>
34 
35 #include <view/view.h>
36 #include <view/view_item.h>
37 #include <view/view_group.h>
39 
40 #include <pcb_painter.h>
41 
42 #include <geometry/shape.h>
44 #include <geometry/shape_rect.h>
45 #include <geometry/shape_circle.h>
46 #include <geometry/shape_convex.h>
47 #include <geometry/convex_hull.h>
48 
49 
50 #include "pns_kicad_iface.h"
51 #include "pns_routing_settings.h"
52 #include "pns_sizes_settings.h"
53 #include "pns_item.h"
54 #include "pns_solid.h"
55 #include "pns_segment.h"
56 #include "pns_solid.h"
57 #include "pns_itemset.h"
58 #include "pns_node.h"
59 #include "pns_topology.h"
60 #include "pns_router.h"
61 #include "pns_debug_decorator.h"
62 #include "router_preview_item.h"
63 
65 {
66 public:
67  PNS_PCBNEW_RULE_RESOLVER( BOARD* aBoard, PNS::ROUTER* aRouter );
68  virtual ~PNS_PCBNEW_RULE_RESOLVER();
69 
70  virtual int Clearance( const PNS::ITEM* aA, const PNS::ITEM* aB ) const override;
71  virtual int Clearance( int aNetCode ) const override;
72  virtual void OverrideClearance( bool aEnable, int aNetA = 0, int aNetB = 0, int aClearance = 0 ) override;
73  virtual void UseDpGap( bool aUseDpGap ) override { m_useDpGap = aUseDpGap; }
74  virtual int DpCoupledNet( int aNet ) override;
75  virtual int DpNetPolarity( int aNet ) override;
76  virtual bool DpNetPair( PNS::ITEM* aItem, int& aNetP, int& aNetN ) override;
77 
78 private:
80  {
82  int clearance;
83  };
84 
85  int localPadClearance( const PNS::ITEM* aItem ) const;
86  int matchDpSuffix( wxString aNetName, wxString& aComplementNet, wxString& aBaseDpName );
87 
90 
91  std::vector<CLEARANCE_ENT> m_netClearanceCache;
92  std::unordered_map<const D_PAD*, int> m_localClearanceCache;
97  bool m_useDpGap;
98 };
99 
100 
102  m_router( aRouter ),
103  m_board( aBoard )
104 {
105  PNS::NODE* world = m_router->GetWorld();
106 
107  PNS::TOPOLOGY topo( world );
109 
110  // Build clearance cache for net classes
111  for( unsigned int i = 0; i < m_board->GetNetCount(); i++ )
112  {
113  NETINFO_ITEM* ni = m_board->FindNet( i );
114 
115  if( ni == NULL )
116  continue;
117 
118  CLEARANCE_ENT ent;
119  ent.coupledNet = DpCoupledNet( i );
120 
121  wxString netClassName = ni->GetClassName();
122  NETCLASSPTR nc = m_board->GetDesignSettings().m_NetClasses.Find( netClassName );
123 
124  int clearance = nc->GetClearance();
125  ent.clearance = clearance;
126  m_netClearanceCache[i] = ent;
127 
128  wxLogTrace( "PNS", "Add net %u netclass %s clearance %d", i, netClassName.mb_str(), clearance );
129  }
130 
131  // Build clearance cache for pads
132  for( MODULE* mod = m_board->m_Modules; mod ; mod = mod->Next() )
133  {
134  auto moduleClearance = mod->GetLocalClearance();
135 
136  for( D_PAD* pad = mod->PadsList(); pad; pad = pad->Next() )
137  {
138  int padClearance = pad->GetLocalClearance();
139 
140  if( padClearance > 0 )
141  m_localClearanceCache[ pad ] = padClearance;
142 
143  else if( moduleClearance > 0 )
144  m_localClearanceCache[ pad ] = moduleClearance;
145  }
146  }
147 
148  //printf("DefaultCL : %d\n", m_board->GetDesignSettings().m_NetClasses.Find ("Default clearance")->GetClearance());
149 
150  m_overrideEnabled = false;
151  m_defaultClearance = Millimeter2iu( 0.254 ); // m_board->m_NetClasses.Find ("Default clearance")->GetClearance();
152  m_overrideNetA = 0;
153  m_overrideNetB = 0;
155  m_useDpGap = false;
156 }
157 
158 
160 {
161 }
162 
163 
165 {
166  if( !aItem->Parent() || aItem->Parent()->Type() != PCB_PAD_T )
167  return 0;
168 
169  const D_PAD* pad = static_cast<D_PAD*>( aItem->Parent() );
170 
171  auto i = m_localClearanceCache.find( pad );
172 
173  if( i == m_localClearanceCache.end() )
174  return 0;
175 
176  return i->second;
177 }
178 
179 
180 int PNS_PCBNEW_RULE_RESOLVER::Clearance( const PNS::ITEM* aA, const PNS::ITEM* aB ) const
181 {
182  int net_a = aA->Net();
183  int cl_a = ( net_a >= 0 ? m_netClearanceCache[net_a].clearance : m_defaultClearance );
184  int net_b = aB->Net();
185  int cl_b = ( net_b >= 0 ? m_netClearanceCache[net_b].clearance : m_defaultClearance );
186 
187  bool linesOnly = aA->OfKind( PNS::ITEM::SEGMENT_T | PNS::ITEM::LINE_T )
189 
190  if( linesOnly && net_a >= 0 && net_b >= 0 && m_netClearanceCache[net_a].coupledNet == net_b )
191  {
192  cl_a = cl_b = m_router->Sizes().DiffPairGap() - 2 * PNS_HULL_MARGIN;
193  }
194 
195  int pad_a = localPadClearance( aA );
196  int pad_b = localPadClearance( aB );
197 
198  if( pad_a > 0 )
199  cl_a = pad_a;
200 
201  if( pad_b > 0 )
202  cl_b = pad_b;
203 
204  return std::max( cl_a, cl_b );
205 }
206 
207 
208 int PNS_PCBNEW_RULE_RESOLVER::Clearance( int aNetCode ) const
209 {
210  if( aNetCode > 0 && aNetCode < (int) m_netClearanceCache.size() )
211  return m_netClearanceCache[aNetCode].clearance;
212 
213  return m_defaultClearance;
214 }
215 
216 
217 // fixme: ugly hack to make the optimizer respect gap width for currently routed differential pair.
218 void PNS_PCBNEW_RULE_RESOLVER::OverrideClearance( bool aEnable, int aNetA, int aNetB , int aClearance )
219 {
220  m_overrideEnabled = aEnable;
221  m_overrideNetA = aNetA;
222  m_overrideNetB = aNetB;
223  m_overrideClearance = aClearance;
224 }
225 
226 
227 int PNS_PCBNEW_RULE_RESOLVER::matchDpSuffix( wxString aNetName, wxString& aComplementNet, wxString& aBaseDpName )
228 {
229  int rv = 0;
230 
231  if( aNetName.EndsWith( "+" ) )
232  {
233  aComplementNet = "-";
234  rv = 1;
235  }
236  else if( aNetName.EndsWith( "P" ) )
237  {
238  aComplementNet = "N";
239  rv = 1;
240  }
241  else if( aNetName.EndsWith( "-" ) )
242  {
243  aComplementNet = "+";
244  rv = -1;
245  }
246  else if( aNetName.EndsWith( "N" ) )
247  {
248  aComplementNet = "P";
249  rv = -1;
250  }
251  // Match P followed by 2 digits
252  else if( aNetName.Right( 2 ).IsNumber() && aNetName.Right( 3 ).Left( 1 ) == "P" )
253  {
254  aComplementNet = "N" + aNetName.Right( 2 );
255  rv = 1;
256  }
257  // Match P followed by 1 digit
258  else if( aNetName.Right( 1 ).IsNumber() && aNetName.Right( 2 ).Left( 1 ) == "P" )
259  {
260  aComplementNet = "N" + aNetName.Right( 1 );
261  rv = 1;
262  }
263  // Match N followed by 2 digits
264  else if( aNetName.Right( 2 ).IsNumber() && aNetName.Right( 3 ).Left( 1 ) == "N" )
265  {
266  aComplementNet = "P" + aNetName.Right( 2 );
267  rv = -1;
268  }
269  // Match N followed by 1 digit
270  else if( aNetName.Right( 1 ).IsNumber() && aNetName.Right( 2 ).Left( 1 ) == "N" )
271  {
272  aComplementNet = "P" + aNetName.Right( 1 );
273  rv = -1;
274  }
275  if( rv != 0 )
276  {
277  aBaseDpName = aNetName.Left( aNetName.Length() - aComplementNet.Length() );
278  aComplementNet = aBaseDpName + aComplementNet;
279  }
280 
281  return rv;
282 }
283 
284 
286 {
287  wxString refName = m_board->FindNet( aNet )->GetNetname();
288  wxString dummy, coupledNetName;
289 
290  if( matchDpSuffix( refName, coupledNetName, dummy ) )
291  {
292  NETINFO_ITEM* net = m_board->FindNet( coupledNetName );
293 
294  if( !net )
295  return -1;
296 
297  return net->GetNet();
298  }
299 
300  return -1;
301 }
302 
303 
305 {
306  wxString refName = m_board->FindNet( aNet )->GetNetname();
307  wxString dummy1, dummy2;
308 
309  return matchDpSuffix( refName, dummy1, dummy2 );
310 }
311 
312 
313 bool PNS_PCBNEW_RULE_RESOLVER::DpNetPair( PNS::ITEM* aItem, int& aNetP, int& aNetN )
314 {
315  if( !aItem || !aItem->Parent() || !aItem->Parent()->GetNet() )
316  return false;
317 
318  wxString netNameP = aItem->Parent()->GetNet()->GetNetname();
319  wxString netNameN, netNameCoupled, netNameBase;
320 
321  int r = matchDpSuffix( netNameP, netNameCoupled, netNameBase );
322 
323  if( r == 0 )
324  return false;
325  else if( r == 1 )
326  {
327  netNameN = netNameCoupled;
328  }
329  else
330  {
331  netNameN = netNameP;
332  netNameP = netNameCoupled;
333  }
334 
335 // wxLogTrace( "PNS","p %s n %s base %s\n", (const char *)netNameP.c_str(), (const char *)netNameN.c_str(), (const char *)netNameBase.c_str() );
336 
337  NETINFO_ITEM* netInfoP = m_board->FindNet( netNameP );
338  NETINFO_ITEM* netInfoN = m_board->FindNet( netNameN );
339 
340  //wxLogTrace( "PNS","ip %p in %p\n", netInfoP, netInfoN);
341 
342  if( !netInfoP || !netInfoN )
343  return false;
344 
345  aNetP = netInfoP->GetNet();
346  aNetN = netInfoN->GetNet();
347 
348  return true;
349 }
350 
351 
353 {
354 public:
356  m_view( NULL ), m_items( NULL )
357  {
358  SetView( aView );
359  }
360 
362  {
363  Clear();
364  delete m_items;
365  }
366 
367  void SetView( KIGFX::VIEW* aView )
368  {
369  Clear();
370  delete m_items;
371  m_items = NULL;
372  m_view = aView;
373 
374  if( m_view == NULL )
375  return;
376 
379  m_view->Add( m_items );
380  }
381 
382  void AddPoint( VECTOR2I aP, int aColor ) override
383  {
385 
386  l.Append( aP - VECTOR2I( -50000, -50000 ) );
387  l.Append( aP + VECTOR2I( -50000, -50000 ) );
388 
389  AddLine( l, aColor, 10000 );
390 
391  l.Clear();
392  l.Append( aP - VECTOR2I( 50000, -50000 ) );
393  l.Append( aP + VECTOR2I( 50000, -50000 ) );
394 
395  AddLine( l, aColor, 10000 );
396  }
397 
398  void AddBox( BOX2I aB, int aColor ) override
399  {
401 
402  VECTOR2I o = aB.GetOrigin();
403  VECTOR2I s = aB.GetSize();
404 
405  l.Append( o );
406  l.Append( o.x + s.x, o.y );
407  l.Append( o.x + s.x, o.y + s.y );
408  l.Append( o.x, o.y + s.y );
409  l.Append( o );
410 
411  AddLine( l, aColor, 10000 );
412  }
413 
414  void AddSegment( SEG aS, int aColor ) override
415  {
417 
418  l.Append( aS.A );
419  l.Append( aS.B );
420 
421  AddLine( l, aColor, 10000 );
422  }
423 
424  void AddDirections( VECTOR2D aP, int aMask, int aColor ) override
425  {
426  BOX2I b( aP - VECTOR2I( 10000, 10000 ), VECTOR2I( 20000, 20000 ) );
427 
428  AddBox( b, aColor );
429  for( int i = 0; i < 8; i++ )
430  {
431  if( ( 1 << i ) & aMask )
432  {
433  VECTOR2I v = DIRECTION_45( ( DIRECTION_45::Directions ) i ).ToVector() * 100000;
434  AddSegment( SEG( aP, aP + v ), aColor );
435  }
436  }
437  }
438 
439  void AddLine( const SHAPE_LINE_CHAIN& aLine, int aType, int aWidth ) override
440  {
441  ROUTER_PREVIEW_ITEM* pitem = new ROUTER_PREVIEW_ITEM( NULL, m_view );
442 
443  pitem->Line( aLine, aWidth, aType );
444  m_items->Add( pitem ); // Should not be needed, as m_items has been passed as a parent group in alloc;
445  m_view->Update( m_items );
446  }
447 
448  void Clear() override
449  {
450  if( m_view && m_items )
451  {
452  m_items->FreeItems();
453  m_view->Update( m_items );
454  }
455  }
456 
457 private:
460 };
461 
462 
464 {
465  return m_debugDecorator;
466 }
467 
468 
470 {
471  m_ruleResolver = nullptr;
472  m_board = nullptr;
473  m_frame = nullptr;
474  m_view = nullptr;
475  m_previewItems = nullptr;
476  m_world = nullptr;
477  m_router = nullptr;
478  m_debugDecorator = nullptr;
479  m_dispOptions = nullptr;
480 }
481 
482 
484 {
485  delete m_ruleResolver;
486  delete m_debugDecorator;
487 
488  if( m_previewItems )
489  {
491  delete m_previewItems;
492  }
493 }
494 
495 
496 std::unique_ptr<PNS::SOLID> PNS_KICAD_IFACE::syncPad( D_PAD* aPad )
497 {
498  LAYER_RANGE layers( 0, MAX_CU_LAYERS - 1 );
499 
500  // ignore non-copper pads
501  if( ( aPad->GetLayerSet() & LSET::AllCuMask()).none() )
502  return NULL;
503 
504  switch( aPad->GetAttribute() )
505  {
506  case PAD_ATTRIB_STANDARD:
507  break;
508 
509  case PAD_ATTRIB_SMD:
511  case PAD_ATTRIB_CONN:
512  {
513  LSET lmsk = aPad->GetLayerSet();
514  bool is_copper = false;
515 
516  for( int i = 0; i < MAX_CU_LAYERS; i++ )
517  {
518  if( lmsk[i] )
519  {
520  is_copper = true;
521 
523  layers = LAYER_RANGE( i );
524 
525  break;
526  }
527  }
528 
529  if( !is_copper )
530  return NULL;
531  }
532  break;
533 
534  default:
535  wxLogTrace( "PNS", "unsupported pad type 0x%x", aPad->GetAttribute() );
536  return NULL;
537  }
538 
539  std::unique_ptr< PNS::SOLID > solid( new PNS::SOLID );
540 
541  solid->SetLayers( layers );
542  solid->SetNet( aPad->GetNetCode() );
543  solid->SetParent( aPad );
544 
545  wxPoint wx_c = aPad->ShapePos();
546  wxSize wx_sz = aPad->GetSize();
547  wxPoint offset = aPad->GetOffset();
548 
549  VECTOR2I c( wx_c.x, wx_c.y );
550  VECTOR2I sz( wx_sz.x, wx_sz.y );
551 
552  RotatePoint( &offset, aPad->GetOrientation() );
553 
554  solid->SetPos( VECTOR2I( c.x - offset.x, c.y - offset.y ) );
555  solid->SetOffset( VECTOR2I( offset.x, offset.y ) );
556 
557  double orient = aPad->GetOrientation() / 10.0;
558 
559  if( aPad->GetShape() == PAD_SHAPE_CIRCLE )
560  {
561  solid->SetShape( new SHAPE_CIRCLE( c, sz.x / 2 ) );
562  }
563  else
564  {
565  if( orient == 0.0 || orient == 90.0 || orient == 180.0 || orient == 270.0 )
566  {
567  if( orient == 90.0 || orient == 270.0 )
568  sz = VECTOR2I( sz.y, sz.x );
569 
570  switch( aPad->GetShape() )
571  {
572  case PAD_SHAPE_OVAL:
573  if( sz.x == sz.y )
574  solid->SetShape( new SHAPE_CIRCLE( c, sz.x / 2 ) );
575  else
576  {
577  VECTOR2I delta;
578 
579  if( sz.x > sz.y )
580  delta = VECTOR2I( ( sz.x - sz.y ) / 2, 0 );
581  else
582  delta = VECTOR2I( 0, ( sz.y - sz.x ) / 2 );
583 
584  SHAPE_SEGMENT* shape = new SHAPE_SEGMENT( c - delta, c + delta,
585  std::min( sz.x, sz.y ) );
586  solid->SetShape( shape );
587  }
588  break;
589 
590  case PAD_SHAPE_RECT:
591  solid->SetShape( new SHAPE_RECT( c - sz / 2, sz.x, sz.y ) );
592  break;
593 
594  case PAD_SHAPE_TRAPEZOID:
595  {
596  wxPoint coords[4];
597  aPad->BuildPadPolygon( coords, wxSize( 0, 0 ), aPad->GetOrientation() );
598  SHAPE_CONVEX* shape = new SHAPE_CONVEX();
599 
600  for( int ii = 0; ii < 4; ii++ )
601  {
602  shape->Append( wx_c + coords[ii] );
603  }
604 
605  solid->SetShape( shape );
606  break;
607  }
608 
609  case PAD_SHAPE_ROUNDRECT:
610  {
611  SHAPE_POLY_SET outline;
612  const int segmentToCircleCount = 64;
613 
614  aPad->BuildPadShapePolygon( outline, wxSize( 0, 0 ), segmentToCircleCount, 1.0 );
615 
616  // TransformRoundRectToPolygon creates only one convex polygon
617  SHAPE_LINE_CHAIN& poly = outline.Outline( 0 );
618  SHAPE_CONVEX* shape = new SHAPE_CONVEX();
619 
620  for( int ii = 0; ii < poly.PointCount(); ++ii )
621  {
622  shape->Append( wxPoint( poly.Point( ii ).x, poly.Point( ii ).y ) );
623  }
624 
625  solid->SetShape( shape );
626  }
627  break;
628 
629  default:
630  wxLogTrace( "PNS", "unsupported pad shape" );
631  return nullptr;
632  }
633  }
634  else
635  {
636  switch( aPad->GetShape() )
637  {
638  // PAD_SHAPE_CIRCLE already handled above
639 
640  case PAD_SHAPE_OVAL:
641  if( sz.x == sz.y )
642  solid->SetShape( new SHAPE_CIRCLE( c, sz.x / 2 ) );
643  else
644  {
645  wxPoint start;
646  wxPoint end;
647  wxPoint corner;
648 
649  SHAPE_CONVEX* shape = new SHAPE_CONVEX();
650 
651  int w = aPad->BuildSegmentFromOvalShape( start, end, 0.0, wxSize( 0, 0 ) );
652 
653  if( start.y == 0 )
654  corner = wxPoint( start.x, -( w / 2 ) );
655  else
656  corner = wxPoint( w / 2, start.y );
657 
658  RotatePoint( &start, aPad->GetOrientation() );
659  RotatePoint( &corner, aPad->GetOrientation() );
660  shape->Append( wx_c + corner );
661 
662  for( int rot = 100; rot <= 1800; rot += 100 )
663  {
664  wxPoint p( corner );
665  RotatePoint( &p, start, rot );
666  shape->Append( wx_c + p );
667  }
668 
669  if( end.y == 0 )
670  corner = wxPoint( end.x, w / 2 );
671  else
672  corner = wxPoint( -( w / 2 ), end.y );
673 
674  RotatePoint( &end, aPad->GetOrientation() );
675  RotatePoint( &corner, aPad->GetOrientation() );
676  shape->Append( wx_c + corner );
677 
678  for( int rot = 100; rot <= 1800; rot += 100 )
679  {
680  wxPoint p( corner );
681  RotatePoint( &p, end, rot );
682  shape->Append( wx_c + p );
683  }
684 
685  solid->SetShape( shape );
686  }
687  break;
688 
689  case PAD_SHAPE_RECT:
690  case PAD_SHAPE_TRAPEZOID:
691  {
692  wxPoint coords[4];
693  aPad->BuildPadPolygon( coords, wxSize( 0, 0 ), aPad->GetOrientation() );
694 
695  SHAPE_CONVEX* shape = new SHAPE_CONVEX();
696  for( int ii = 0; ii < 4; ii++ )
697  {
698  shape->Append( wx_c + coords[ii] );
699  }
700 
701  solid->SetShape( shape );
702  break;
703  }
704 
705  case PAD_SHAPE_ROUNDRECT:
706  {
707  SHAPE_POLY_SET outline;
708  const int segmentToCircleCount = 32;
709  aPad->BuildPadShapePolygon( outline, wxSize( 0, 0 ),
710  segmentToCircleCount, 1.0 );
711 
712  // TransformRoundRectToPolygon creates only one convex polygon
713  SHAPE_LINE_CHAIN& poly = outline.Outline( 0 );
714  SHAPE_CONVEX* shape = new SHAPE_CONVEX();
715 
716  for( int ii = 0; ii < poly.PointCount(); ++ii )
717  {
718  shape->Append( wxPoint( poly.Point( ii ).x, poly.Point( ii ).y ) );
719  }
720 
721  solid->SetShape( shape );
722  break;
723  }
724 
725  default:
726  wxLogTrace( "PNS", "unsupported pad shape" );
727  return nullptr;
728  }
729  }
730  }
731  return solid;
732 }
733 
734 
735 std::unique_ptr<PNS::SEGMENT> PNS_KICAD_IFACE::syncTrack( TRACK* aTrack )
736 {
737  std::unique_ptr< PNS::SEGMENT > segment(
738  new PNS::SEGMENT( SEG( aTrack->GetStart(), aTrack->GetEnd() ), aTrack->GetNetCode() )
739  );
740 
741  segment->SetWidth( aTrack->GetWidth() );
742  segment->SetLayers( LAYER_RANGE( aTrack->GetLayer() ) );
743  segment->SetParent( aTrack );
744 
745  if( aTrack->IsLocked() )
746  segment->Mark( PNS::MK_LOCKED );
747 
748  return segment;
749 }
750 
751 
752 std::unique_ptr<PNS::VIA> PNS_KICAD_IFACE::syncVia( VIA* aVia )
753 {
754  PCB_LAYER_ID top, bottom;
755  aVia->LayerPair( &top, &bottom );
756  std::unique_ptr<PNS::VIA> via( new PNS::VIA(
757  aVia->GetPosition(),
758  LAYER_RANGE( top, bottom ),
759  aVia->GetWidth(),
760  aVia->GetDrillValue(),
761  aVia->GetNetCode(),
762  aVia->GetViaType() )
763  );
764 
765  via->SetParent( aVia );
766 
767  if( aVia->IsLocked() )
768  via->Mark( PNS::MK_LOCKED );
769 
770  return via;
771 }
772 
773 
775 {
776  m_board = aBoard;
777  wxLogTrace( "PNS", "m_board = %p", m_board );
778 }
779 
780 
782 {
783  if( !m_board )
784  {
785  wxLogTrace( "PNS", "No board attached, aborting sync." );
786  return;
787  }
788 
789  for( MODULE* module = m_board->m_Modules; module; module = module->Next() )
790  {
791  for( D_PAD* pad = module->PadsList(); pad; pad = pad->Next() )
792  {
793  std::unique_ptr< PNS::SOLID > solid = syncPad( pad );
794 
795  if( solid )
796  aWorld->Add( std::move( solid ) );
797  }
798  }
799 
800  for( TRACK* t = m_board->m_Track; t; t = t->Next() )
801  {
802  KICAD_T type = t->Type();
803 
804  if( type == PCB_TRACE_T ) {
805  std::unique_ptr< PNS::SEGMENT > segment = syncTrack( t );
806  if( segment ) {
807  aWorld->Add( std::move( segment ) );
808  }
809  } else if( type == PCB_VIA_T ) {
810  std::unique_ptr< PNS::VIA > via = syncVia( static_cast<VIA*>( t ) );
811  if( via ) {
812  aWorld->Add( std::move( via ) );
813  }
814  }
815  }
816 
817  int worstClearance = m_board->GetDesignSettings().GetBiggestClearanceValue();
818 
819  delete m_ruleResolver;
821 
822  aWorld->SetRuleResolver( m_ruleResolver );
823  aWorld->SetMaxClearance( 4 * worstClearance );
824 }
825 
826 
828 {
829  for( auto item : m_hiddenItems )
830  m_view->SetVisible( item, true );
831 
832  m_hiddenItems.clear();
833 
834  if( m_previewItems )
835  {
838  }
839 
840  if( m_debugDecorator )
842 }
843 
844 
845 void PNS_KICAD_IFACE::DisplayItem( const PNS::ITEM* aItem, int aColor, int aClearance )
846 {
847  wxLogTrace( "PNS", "DisplayItem %p", aItem );
848 
849  ROUTER_PREVIEW_ITEM* pitem = new ROUTER_PREVIEW_ITEM( aItem, m_view );
850 
851  if( aColor >= 0 )
852  pitem->SetColor( KIGFX::COLOR4D( aColor ) );
853 
854  if( aClearance >= 0 )
855  {
856  pitem->SetClearance( aClearance );
857 
858  if( m_dispOptions )
859  {
860  auto clearanceDisp = m_dispOptions->m_ShowTrackClearanceMode;
861  pitem->ShowTrackClearance( clearanceDisp != DO_NOT_SHOW_CLEARANCE );
862  pitem->ShowViaClearance( clearanceDisp != DO_NOT_SHOW_CLEARANCE
863  && clearanceDisp != SHOW_CLEARANCE_NEW_TRACKS );
864  }
865  }
866 
867 
868  m_previewItems->Add( pitem );
870 }
871 
872 
874 {
875  BOARD_CONNECTED_ITEM* parent = aItem->Parent();
876 
877  if( parent )
878  {
879  if( m_view->IsVisible( parent ) )
880  m_hiddenItems.insert( parent );
881 
882  m_view->SetVisible( parent, false );
883  m_view->Update( parent, KIGFX::APPEARANCE );
884  }
885 }
886 
887 
889 {
890  BOARD_CONNECTED_ITEM* parent = aItem->Parent();
891 
892  if( parent )
893  {
894  m_commit->Remove( parent );
895  }
896 }
897 
898 
900 {
901  BOARD_CONNECTED_ITEM* newBI = NULL;
902 
903  switch( aItem->Kind() )
904  {
906  {
907  PNS::SEGMENT* seg = static_cast<PNS::SEGMENT*>( aItem );
908  TRACK* track = new TRACK( m_board );
909  const SEG& s = seg->Seg();
910  track->SetStart( wxPoint( s.A.x, s.A.y ) );
911  track->SetEnd( wxPoint( s.B.x, s.B.y ) );
912  track->SetWidth( seg->Width() );
913  track->SetLayer( ToLAYER_ID( seg->Layers().Start() ) );
914  track->SetNetCode( seg->Net() > 0 ? seg->Net() : 0 );
915  newBI = track;
916  break;
917  }
918 
919  case PNS::ITEM::VIA_T:
920  {
921  VIA* via_board = new VIA( m_board );
922  PNS::VIA* via = static_cast<PNS::VIA*>( aItem );
923  via_board->SetPosition( wxPoint( via->Pos().x, via->Pos().y ) );
924  via_board->SetWidth( via->Diameter() );
925  via_board->SetDrill( via->Drill() );
926  via_board->SetNetCode( via->Net() > 0 ? via->Net() : 0 );
927  via_board->SetViaType( via->ViaType() ); // MUST be before SetLayerPair()
928  via_board->SetLayerPair( ToLAYER_ID( via->Layers().Start() ),
929  ToLAYER_ID( via->Layers().End() ) );
930  newBI = via_board;
931  break;
932  }
933 
934  default:
935  break;
936  }
937 
938  if( newBI )
939  {
940  aItem->SetParent( newBI );
941  newBI->ClearFlags();
942 
943  m_commit->Add( newBI );
944  }
945 }
946 
947 
949 {
950  EraseView();
951  m_commit->Push( wxT( "Added a track" ) );
952  m_commit.reset( new BOARD_COMMIT( m_frame ) );
953 }
954 
955 
957 {
958  wxLogTrace( "PNS", "SetView %p", aView );
959 
960  if( m_previewItems )
961  {
963  delete m_previewItems;
964  }
965 
966  m_view = aView;
970 
971  delete m_debugDecorator;
974 }
975 
976 
977 void PNS_KICAD_IFACE::UpdateNet( int aNetCode )
978 {
979  wxLogTrace( "PNS", "Update-net %d", aNetCode );
980 }
981 
982 
984 {
985  return m_ruleResolver;
986 }
987 
988 
990 {
991  m_router = aRouter;
992 }
993 
994 
996 {
997  m_frame = aFrame;
998 
999  m_commit.reset( new BOARD_COMMIT( m_frame ) );
1001 }
bool IsLocked() const override
Function IsLocked.
Definition: class_track.h:136
const VECTOR2I ToVector() const
Function ToVector()
Definition: direction45.h:295
static LSET AllCuMask(int aCuLayerCount=MAX_CU_LAYERS)
Function AllCuMask returns a mask holding the requested number of Cu PCB_LAYER_IDs.
Definition: lset.cpp:639
const Vec & GetOrigin() const
Definition: box2.h:181
Class ITEM.
Definition: pns_item.h:53
KICAD_T Type() const
Function Type()
Definition: base_struct.h:198
int matchDpSuffix(wxString aNetName, wxString &aComplementNet, wxString &aBaseDpName)
Class BOARD_CONNECTED_ITEM.
void SetView(KIGFX::VIEW *aView)
virtual bool DpNetPair(PNS::ITEM *aItem, int &aNetP, int &aNetN) override
NETCLASSPTR Find(const wxString &aName) const
Function Find searches this container for a NETCLASS given by aName.
PNS_PCBNEW_DEBUG_DECORATOR * m_debugDecorator
Class NODE.
Definition: pns_node.h:137
PAD_ATTR_T GetAttribute() const
Definition: class_pad.h:238
void SetViaType(VIATYPE_T aViaType)
Definition: class_track.h:440
const LAYER_RANGE & Layers() const
Function Layers()
Definition: pns_item.h:207
like PAD_STANDARD, but not plated mechanical use only, no connection allowed
Definition: pad_shapes.h:63
void SetPosition(const wxPoint &aPoint) override
Definition: class_track.h:412
virtual void SetLayer(PCB_LAYER_ID aLayer)
Function SetLayer sets the layer this item is on.
void SetEnd(const wxPoint &aEnd)
Definition: class_track.h:117
PNS::NODE * m_world
int GetBiggestClearanceValue()
Function GetBiggestClearanceValue.
void BuildPadPolygon(wxPoint aCoord[4], wxSize aInflateValue, double aRotation) const
Function BuildPadPolygon Has meaning only for polygonal pads (trapezoid and rectangular) Build the Co...
int PointCount() const
Function PointCount()
void AddPoint(VECTOR2I aP, int aColor) override
int Drill() const
Definition: pns_via.h:120
Class BOARD to handle a board.
int Diameter() const
Definition: pns_via.h:109
std::unordered_set< BOARD_CONNECTED_ITEM * > m_hiddenItems
std::unique_ptr< PNS::SOLID > syncPad(D_PAD *aPad)
wxString GetClassName() const
Function GetClassName returns the class name.
void UpdateNet(int aNetCode) override
void AddBox(BOX2I aB, int aColor) override
MODULE * Next() const
Definition: class_module.h:100
void SetRouter(PNS::ROUTER *aRouter) override
Smd pad, appears on the solder paste layer (default)
Definition: pad_shapes.h:59
int localPadClearance(const PNS::ITEM *aItem) const
#define PNS_HULL_MARGIN
Class LINE.
Definition: pns_line.h:58
void SetClearance(int aClearance)
class D_PAD, a pad in a footprint
Definition: typeinfo.h:102
Class SHAPE_CONVEX.
Definition: shape_convex.h:42
No updates are required.
Definition: view_item.h:55
Class RULE_RESOLVER.
Definition: pns_node.h:56
PNS_PCBNEW_DEBUG_DECORATOR(KIGFX::VIEW *aView=NULL)
void Line(const SHAPE_LINE_CHAIN &aLine, int aWidth=0, int aStyle=0)
void RotatePoint(int *pX, int *pY, double angle)
Definition: trigo.cpp:317
void ShowTrackClearance(bool aEnabled)
std::unique_ptr< PNS::SEGMENT > syncTrack(TRACK *aTrack)
const VECTOR2I & Pos() const
Definition: pns_via.h:88
void SetRuleResolver(RULE_RESOLVER *aFunc)
Assigns a clerance resolution function object
Definition: pns_node.h:163
SIZES_SETTINGS & Sizes()
Definition: pns_router.h:206
const Vec & GetSize() const
Definition: box2.h:177
void HideItem(PNS::ITEM *aItem) override
VECTOR2< int > VECTOR2I
Definition: vector2d.h:590
PAD_SHAPE_T GetShape() const
Function GetShape.
Definition: class_pad.h:166
PNS::DEBUG_DECORATOR * GetDebugDecorator() override
Class BOARD_CONNECTED_ITEM is a base class derived from BOARD_ITEM for items that can be connected an...
static const int delta[8][2]
Definition: solve.cpp:112
const wxPoint & GetEnd() const
Definition: class_track.h:118
KICAD_T
Enum KICAD_T is the set of class identification values, stored in EDA_ITEM::m_StructType.
Definition: typeinfo.h:90
NODE * GetWorld() const
Definition: pns_router.h:143
Functions relatives to tracks, vias and segments used to fill zones.
class TRACK, a track segment (segment on a copper layer)
Definition: typeinfo.h:107
void * GetDisplayOptions() override
Function GetDisplayOptions returns the display options current in use Display options are relative to...
void Append(int aX, int aY, bool aAllowDuplication=false)
Function Append()
KIGFX::VIEW_GROUP * m_items
void SetWidth(int aWidth)
Definition: class_track.h:114
virtual int DpNetPolarity(int aNet) override
void SetMaxClearance(int aClearance)
Sets the worst-case clerance between any pair of items
Definition: pns_node.h:157
bool OfKind(int aKindMask) const
Function OfKind()
Definition: pns_item.h:130
VIATYPE_T ViaType() const
Definition: pns_via.h:99
void SetHostFrame(PCB_EDIT_FRAME *aFrame)
int End() const
Definition: pns_layerset.h:88
void SetParent(BOARD_CONNECTED_ITEM *aParent)
Function SetParent()
Definition: pns_item.h:147
PCB_LAYER_ID
A quick note on layer IDs:
void FreeItems()
Function FreeItems() Frees all the items that were added to the group.
Definition: view_group.cpp:141
void Append(int aX, int aY)
Function Append()
Definition: shape_convex.h:151
Class LSET is a set of PCB_LAYER_IDs.
VIEW_ITEM class definition.
VIATYPE_T GetViaType() const
Definition: class_track.h:439
Class SHAPE_POLY_SET.
SHAPE_LINE_CHAIN & Outline(int aIndex)
Returns the reference to aIndex-th outline in the set
std::unique_ptr< BOARD_COMMIT > m_commit
Class DIRECTION_45.
Definition: direction45.h:33
const wxPoint & GetStart() const
Definition: class_track.h:121
virtual int DpCoupledNet(int aNet) override
LSET GetLayerSet() const override
Function GetLayerSet returns a "layer mask", which is a bitmap of all layers on which the TRACK segme...
Definition: class_pad.h:235
PCB_EDIT_FRAME * m_frame
D_PAD * Next() const
Definition: class_pad.h:106
void ShowViaClearance(bool aEnabled)
std::vector< CLEARANCE_ENT > m_netClearanceCache
const wxSize & GetSize() const
Definition: class_pad.h:182
PNS_PCBNEW_RULE_RESOLVER * m_ruleResolver
BOARD_DESIGN_SETTINGS & GetDesignSettings() const
Function GetDesignSettings.
Definition: class_board.h:524
bool SetNetCode(int aNetCode, bool aNoAssert=false)
Function SetNetCode sets net using a net code.
VIEW_GROUP extends VIEW_ITEM by possibility of grouping items into a single object.
general purpose overlay
KIGFX::VIEW_GROUP * m_previewItems
void SetLayerPair(PCB_LAYER_ID aTopLayer, PCB_LAYER_ID aBottomLayer)
Function SetLayerPair For a via m_Layer contains the top layer, the other layer is in m_BottomLayer...
int Width() const
Definition: pns_segment.h:88
int Start() const
Definition: pns_layerset.h:83
int GetNet() const
Function GetNet.
virtual void Add(VIEW_ITEM *aItem)
Function Add() Adds an item to the group.
Definition: view_group.cpp:55
void Update(VIEW_ITEM *aItem, int aUpdateFlags)
For dynamic VIEWs, informs the associated VIEW that the graphical representation of this item has cha...
Definition: view.cpp:1389
Like smd, does not appear on the solder paste layer (default) note also has a special attribute in Ge...
Definition: pad_shapes.h:60
void SetColor(const KIGFX::COLOR4D &aColor)
PNS::ROUTER * m_router
virtual void SetLayer(int aLayer)
Function SetLayer() Sets layer used to draw the group.
Definition: view_group.h:115
void DisplayItem(const PNS::ITEM *aItem, int aColor=0, int aClearance=0) override
void Commit() override
void LayerPair(PCB_LAYER_ID *top_layer, PCB_LAYER_ID *bottom_layer) const
Function LayerPair Return the 2 layers used by the via (the via actually uses all layers between thes...
Class DISPLAY_OPTIONS handles display options like enable/disable some optional drawings.
Definition: pcbstruct.h:62
PNS::RULE_RESOLVER * GetRuleResolver() override
PnsKind Kind() const
Function Kind()
Definition: pns_item.h:120
void EraseView() override
int GetNetCode() const
Function GetNetCode.
Definition: seg.h:37
TRACE_CLEARANCE_DISPLAY_MODE_T m_ShowTrackClearanceMode
How trace clearances are displayed.
Definition: pcbstruct.h:74
KIGFX::VIEW * m_view
Class NETINFO_ITEM handles the data for a net.
Definition: class_netinfo.h:69
PCB_LAYER_ID GetLayer() const
Function GetLayer returns the primary layer this item is on.
int BuildSegmentFromOvalShape(wxPoint &aSegStart, wxPoint &aSegEnd, double aRotation, const wxSize &aMargin) const
Function BuildSegmentFromOvalShape Has meaning only for OVAL (and ROUND) pads Build an equivalent seg...
void SyncWorld(PNS::NODE *aWorld) override
TRACK * Next() const
Definition: class_track.h:98
Board layer functions and definitions.
DISPLAY_OPTIONS * m_dispOptions
int GetDrillValue() const
Function GetDrillValue "calculates" the drill value for vias (m-Drill if > 0, or default drill value ...
static LIB_PART * dummy()
Used when a LIB_PART is not found in library to draw a dummy shape This component is a 400 mils squar...
#define max(a, b)
Definition: auxiliary.h:86
Class BOARD holds information pertinent to a Pcbnew printed circuit board.
Definition: class_board.h:169
DLIST< MODULE > m_Modules
Definition: class_board.h:245
Class SHAPE_LINE_CHAIN.
void RemoveItem(PNS::ITEM *aItem) override
int GetWidth() const
Definition: class_track.h:115
std::unique_ptr< PNS::VIA > syncVia(VIA *aVia)
double GetOrientation() const
Function GetOrientation returns the rotation angle of the pad in tenths of degrees, but soon degrees.
Definition: class_pad.h:214
VECTOR2I A
Definition: seg.h:47
void AddItem(PNS::ITEM *aItem) override
void SetDrill(int aDrill)
Function SetDrill sets the drill value for vias.
Definition: class_track.h:447
void SetView(KIGFX::VIEW *aView)
Usual pad.
Definition: pad_shapes.h:58
NETINFO_ITEM * FindNet(int aNetcode) const
Function FindNet searches for a net with the given netcode.
int Net() const
Function Net()
Definition: pns_item.h:177
virtual void OverrideClearance(bool aEnable, int aNetA=0, int aNetB=0, int aClearance=0) override
void BuildPadShapePolygon(SHAPE_POLY_SET &aCornerBuffer, wxSize aInflateValue, int aSegmentsPerCircle, double aCorrectionFactor) const
Function BuildPadShapePolygon Build the Corner list of the polygonal shape, depending on shape...
const wxPoint & GetPosition() const override
Definition: class_track.h:411
wxPoint ShapePos() const
Definition: class_pad.cpp:418
void ClearFlags(STATUS_FLAGS aMask=EDA_ITEM_ALL_FLAGS)
Definition: base_struct.h:254
void SetVisible(VIEW_ITEM *aItem, bool aIsVisible=true)
Sets the item visibility.
Definition: view.cpp:1335
void Clear()
Function Clear() Removes all points from the line chain.
void SetStart(const wxPoint &aStart)
Definition: class_track.h:120
const SEG & Seg() const
Definition: pns_segment.h:93
VECTOR2I & Point(int aIndex)
Function Point()
class VIA, a via (like a track segment on a copper layer)
Definition: typeinfo.h:108
void Add(VIEW_ITEM *aItem, int aDrawPriority=-1)
Function Add() Adds a VIEW_ITEM to the view.
Definition: view.cpp:311
void AddLine(const SHAPE_LINE_CHAIN &aLine, int aType, int aWidth) override
DLIST< TRACK > m_Track
Definition: class_board.h:246
Module description (excepted pads)
const wxString & GetNetname() const
Function GetNetname.
void AddDirections(VECTOR2D aP, int aMask, int aColor) override
virtual int Clearance(const PNS::ITEM *aA, const PNS::ITEM *aB) const override
Class VIEW.
Definition: view.h:58
bool IsVisible(const VIEW_ITEM *aItem) const
Returns information if the item is visible (or not).
Definition: view.cpp:1375
virtual void UseDpGap(bool aUseDpGap) override
Directions
Enum Directions Represents available directions - there are 8 of them, as on a rectilinear map (north...
Definition: direction45.h:42
void AddSegment(SEG aS, int aColor) override
Push and Shove diff pair dimensions (gap) settings dialog.
void SetBoard(BOARD *aBoard)
void Add(std::unique_ptr< SEGMENT > aSegment, bool aAllowRedundant=false)
Function Add()
Definition: pns_node.cpp:596
std::unordered_map< const D_PAD *, int > m_localClearanceCache
PCB_LAYER_ID ToLAYER_ID(int aLayer)
Definition: lset.cpp:767
#define mod(a, n)
Definition: greymap.cpp:24
PNS_PCBNEW_RULE_RESOLVER(BOARD *aBoard, PNS::ROUTER *aRouter)
const wxPoint & GetOffset() const
Definition: class_pad.h:191
BOARD_CONNECTED_ITEM * Parent() const
Function Parent()
Definition: pns_item.h:157
NETINFO_ITEM * GetNet() const
Function GetNet Returns NET_INFO object for a given item.
Class LAYER_RANGE.
Definition: pns_layerset.h:32
NETCLASSES m_NetClasses
List of current netclasses. There is always the default netclass.
unsigned GetNetCount() const
Function GetNetCount.
Definition: class_board.h:764
#define min(a, b)
Definition: auxiliary.h:85
Class COLOR4D is the color representation with 4 components: red, green, blue, alpha.
Definition: color4d.h:39
VECTOR2I B
Definition: seg.h:48