KiCad PCB EDA Suite
pns_log_viewer.cpp
Go to the documentation of this file.
1 /*
2  * This program source code file is part of KiCad, a free EDA CAD application.
3  *
4  * Copyright (C) 2020 KiCad Developers.
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, you may find one here:
18  * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
19  * or you may search the http://www.gnu.org website for the version 2 license,
20  * or you may write to the Free Software Foundation, Inc.,
21  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
22  */
23 
24 
25 // WARNING - this Tom's crappy PNS hack tool code. Please don't complain about its quality
26 // (unless you want to improve it).
27 
28 #include <wx/clipbrd.h>
29 
30 #include <pcb_painter.h>
31 #include <pcb_test_frame.h>
33 #include <pgm_base.h>
34 
35 #include <profile.h>
36 
37 #include <view/view_overlay.h>
38 
39 #include "pns_log.h"
40 #include "router/pns_diff_pair.h"
42 
43 #include "qa/drc_proto/drc_proto.h"
44 
45 #define ID_LIST_COPY 10001
46 #define ID_LIST_SHOW_ALL 10002
47 #define ID_LIST_SHOW_NONE 10003
48 
50 {
51 public:
52  PNS_LOG_VIEWER_FRAME( wxFrame* frame ) : PNS_LOG_VIEWER_FRAME_BASE( frame )
53  {
54  LoadSettings();
56 
57  m_viewSizer->Add( m_galPanel.get(), 1, wxEXPAND, 5 );
58 
59  Layout();
60 
61  Show( true );
62  Maximize();
63  Raise();
64 
65  auto settings = static_cast<KIGFX::PCB_RENDER_SETTINGS*>(
66  m_galPanel->GetView()->GetPainter()->GetSettings() );
67 
68  settings->SetZoneDisplayMode( ZONE_DISPLAY_MODE::SHOW_ZONE_OUTLINE );
69 
70  m_listPopupMenu = new wxMenu(wxT(""));
71  m_listPopupMenu->Append(ID_LIST_COPY, wxT("Copy selected geometry"), wxT(""), wxITEM_NORMAL);
72  m_listPopupMenu->Append(ID_LIST_SHOW_ALL, wxT("Show all"), wxT (""), wxITEM_NORMAL);
73  m_listPopupMenu->Append(ID_LIST_SHOW_NONE, wxT("Show none"), wxT (""), wxITEM_NORMAL);
74 
75  m_itemList->Connect(m_itemList->GetId(),wxEVT_TREELIST_ITEM_CONTEXT_MENU,wxMouseEventHandler(PNS_LOG_VIEWER_FRAME::onListRightClick),NULL,this);
76  //m_itemList->Connect(m_itemList->GetId(),wxEVT_LISTBOX,wxCommandEventHandler(PNS_LOG_VIEWER_FRAME::onListSelect),NULL,this);
77  m_itemList->Connect(m_itemList->GetId(),wxEVT_TREELIST_SELECTION_CHANGED,wxCommandEventHandler(PNS_LOG_VIEWER_FRAME::onListSelect),NULL,this);
78  m_itemList->Connect(m_itemList->GetId(),wxEVT_TREELIST_ITEM_CHECKED,wxCommandEventHandler(PNS_LOG_VIEWER_FRAME::onListChecked),NULL,this);
79 
80  //Connect(ID_LIST_COPY,wxEVT_COMMAND_MENU_SELECTED,wxCommandEventHandler(PNS_LOG_VIEWER_FRAME::onListCopy),NULL,this);
81  //Connect(ID_LIST_SHOW_ALL,wxEVT_COMMAND_MENU_SELECTED,wxCommandEventHandler(PNS_LOG_VIEWER_FRAME::onListShowAll),NULL,this);
82  //Connect(ID_LIST_SHOW_NONE,wxEVT_COMMAND_MENU_SELECTED,wxCommandEventHandler(PNS_LOG_VIEWER_FRAME::onListShowNone),NULL,this);
83  m_itemList->AppendColumn ( "Type" );
84  m_itemList->AppendColumn ( "Value" );
85  }
86 
88  {
89  }
90 
91  void SetLogFile( PNS_LOG_FILE* aLog );
92 
93 private:
94  void drawLoggedItems( int iter );
95  void updateDumpPanel( int iter );
96  virtual void createUserTools() override;
97  void buildListTree( wxTreeListItem item, PNS_TEST_DEBUG_DECORATOR::DEBUG_ENT* ent );
98  void syncModel();
100 
101  virtual void onReload( wxCommandEvent& event ) override;
102  virtual void onExit( wxCommandEvent& event ) override;
103  virtual void onRewindScroll( wxScrollEvent& event ) override;
104  virtual void onRewindCountText( wxCommandEvent& event ) override;
105  virtual void onListRightClick(wxMouseEvent& event);
106  virtual void onListShowAll( wxCommandEvent& event );
107  virtual void onListShowNone( wxCommandEvent& event );
108  virtual void onListCopy( wxCommandEvent& event );
109  virtual void onListSelect( wxCommandEvent& event );
110  virtual void onBtnRewindLeft( wxCommandEvent& event ) override;
111  virtual void onBtnRewindRight( wxCommandEvent& event ) override;
112  virtual void onListChecked( wxCommandEvent& event );
113 
114  std::shared_ptr<KIGFX::VIEW_OVERLAY> m_overlay;
115  std::shared_ptr<PNS_LOG_FILE> m_logFile;
116  std::shared_ptr<PNS_TEST_ENVIRONMENT> m_env;
119 };
120 
121 
122 class WX_SHAPE_TREE_ITEM_DATA : public wxClientData
123 {
124  public:
126  m_item(item) {};
127 
129 };
130 
132 {
133 
134 }
135 
136 
137 static const COLOR4D assignColor( int aStyle )
138 {
139  COLOR4D color;
140 
141  switch( aStyle )
142  {
143  case 0:
144  color = COLOR4D( 0, 1, 0, 1 );
145  break;
146 
147  case 1:
148  color = COLOR4D( 1, 0, 0, 1 );
149  break;
150 
151  case 2:
152  color = COLOR4D( 1, 1, 0, 1 );
153  break;
154 
155  case 3:
156  color = COLOR4D( 0, 0, 1, 1 );
157  break;
158 
159  case 4:
160  color = COLOR4D( 1, 1, 1, 1 );
161  break;
162 
163  case 5:
164  color = COLOR4D( 1, 1, 0, 1 );
165  break;
166 
167  case 6:
168  color = COLOR4D( 0, 1, 1, 1 );
169  break;
170 
171  case 32:
172  color = COLOR4D( 0, 0, 1, 1 );
173  break;
174 
175  default:
176  color = COLOR4D( 0.4, 0.4, 0.4, 1 );
177  break;
178  }
179 
180  return color;
181 }
182 
184 {
185  PNS_TEST_DEBUG_DECORATOR* dbgd = m_env->GetDebugDecorator();
186  int count = dbgd->GetStageCount();
187 
188  int iter = m_rewindIter;
189 
190  if( count <= 0 )
191  return nullptr;
192 
193  if( iter < 0 )
194  iter = 0;
195 
196  if( iter >= count )
197  iter = count - 1;
198 
199  return dbgd->GetStage( iter );
200 }
201 
203 {
204  if( !m_env )
205  return;
206 
207  m_overlay = m_galPanel->DebugOverlay();
208  m_overlay->Clear();
209 
211 
212  if( !st )
213  return;
214 
215  auto drawShapes = [ & ] ( PNS_TEST_DEBUG_DECORATOR::DEBUG_ENT *ent ) -> bool
216  {
217  bool isEnabled = ent->IsVisible();
218  bool isSelected = false;
219  if (! isEnabled )
220  return true;
221 
222  for( auto& sh : ent->m_shapes )
223  {
224  m_overlay->SetIsStroke( true );
225  m_overlay->SetIsFill( false );
226  m_overlay->SetStrokeColor( assignColor( ent->m_color ) );
227  m_overlay->SetLineWidth( ent->m_width );
228 
229  switch( sh->Type() )
230  {
231  case SH_CIRCLE:
232  {
233  auto cir = static_cast<SHAPE_CIRCLE*>( sh );
234  m_overlay->Circle( cir->GetCenter(), cir->GetRadius() );
235 
236  break;
237  }
238  case SH_RECT:
239  {
240  auto rect = static_cast<SHAPE_RECT*>( sh );
241  m_overlay->Rectangle( rect->GetPosition(), rect->GetPosition() + rect->GetSize() );
242 
243  break;
244  }
245  case SH_LINE_CHAIN:
246  {
247  auto lc = static_cast<SHAPE_LINE_CHAIN*>( sh );
248 
249  if( isSelected )
250  {
251  m_overlay->SetLineWidth( ent->m_width * 2 );
252  m_overlay->SetStrokeColor( COLOR4D(1.0, 1.0, 1.0, 1.0) );
253  }
254 
255  for( int i = 0; i < lc->SegmentCount(); i++ )
256  {
257  auto s = lc->CSegment( i );
258  m_overlay->Line( s.A, s.B );
259  }
260  break;
261  }
262  default:
263  break;
264  }
265  }
266 
267 
268  return true;
269  };
270 
271  st->m_entries->IterateTree( drawShapes );
272 
273 /* if ( !m_itemList->IsChecked(itemID) || !ent.m_shapes.size() )
274  {
275  if( itemID != m_selectedItem )
276  {
277  itemID++;
278  continue;
279  }
280  }*/
281 
282  //m_galPanel->ForceRefresh();
283 
284  m_galPanel->GetView()->MarkDirty();
285  m_galPanel->GetParent()->Refresh();
286 }
287 
288 
289 static BOARD* loadBoard( const std::string& filename )
290 {
291  PLUGIN::RELEASER pi( new PCB_IO );
292  BOARD* brd = nullptr;
293 
294  try
295  {
296  brd = pi->Load( wxString( filename.c_str() ), NULL, NULL );
297  }
298  catch( const IO_ERROR& ioe )
299  {
300  wxString msg = wxString::Format( _( "Error loading board.\n%s" ),
301  ioe.Problem() );
302 
303  printf( "Board Loading Error: '%s'\n", (const char*) msg.mb_str() );
304  return nullptr;
305  }
306 
307  return brd;
308 }
309 
310 
312 {
313  m_logFile.reset( aLog );
314 
315  SetBoard( m_logFile->GetBoard() );
316 
317  m_env.reset( new PNS_TEST_ENVIRONMENT );
318 
319  m_env->SetMode( PNS::PNS_MODE_ROUTE_SINGLE );
320  m_env->ReplayLog( m_logFile.get() );
321 
322  auto dbgd = m_env->GetDebugDecorator();
323  int n_stages = dbgd->GetStageCount();
324  m_rewindSlider->SetMax( n_stages - 1 );
325  m_rewindSlider->SetValue( n_stages - 1 );
326  m_rewindIter = n_stages - 1;
327 
328  auto extents = m_board->GetBoundingBox();
329 
330 
331  BOX2D bbd;
332  bbd.SetOrigin( extents.GetOrigin() );
333  bbd.SetWidth( extents.GetWidth() );
334  bbd.SetHeight( extents.GetHeight() );
335  bbd.Inflate( std::min( bbd.GetWidth(), bbd.GetHeight() )/ 5);
336 
337  m_galPanel->GetView()->SetViewport( bbd );
338 
341 }
342 
343 void PNS_LOG_VIEWER_FRAME::onReload( wxCommandEvent& event )
344 {
345  event.Skip();
346 }
347 
348 void PNS_LOG_VIEWER_FRAME::onExit( wxCommandEvent& event )
349 {
350  event.Skip();
351 }
352 
353 void PNS_LOG_VIEWER_FRAME::onListChecked( wxCommandEvent& event )
354 {
355  printf("On-list-checked\n");
356  syncModel();
358 }
359 
360 
361 void PNS_LOG_VIEWER_FRAME::onRewindScroll( wxScrollEvent& event )
362 {
363  m_rewindIter = event.GetPosition();
366  char str[128];
367  sprintf(str,"%d",m_rewindIter);
368  m_rewindPos->SetValue( str );
369  event.Skip();
370 }
371 
372 void PNS_LOG_VIEWER_FRAME::onBtnRewindLeft( wxCommandEvent& event )
373 {
374  if(m_rewindIter > 0)
375  {
376  m_rewindIter--;
379  char str[128];
380  sprintf(str,"%d",m_rewindIter);
381  m_rewindPos->SetValue( str );
382  }
383 }
384 
385 void PNS_LOG_VIEWER_FRAME::onBtnRewindRight( wxCommandEvent& event )
386 {
387  auto dbgd = m_env->GetDebugDecorator();
388  int count = dbgd->GetStageCount();
389 
390  if(m_rewindIter < count)
391  {
392  m_rewindIter++;
395  char str[128];
396  sprintf(str,"%d",m_rewindIter);
397  m_rewindPos->SetValue( str );
398  }
399 }
400 
401 void PNS_LOG_VIEWER_FRAME::onRewindCountText( wxCommandEvent& event )
402 {
403  if( !m_env )
404  return;
405 
406  int val = wxAtoi( m_rewindPos->GetValue() );
407 
408  auto dbgd = m_env->GetDebugDecorator();
409  int count = dbgd->GetStageCount();
410 
411  if( val < 0 )
412  val = 0;
413 
414  if( val >= count )
415  val = count - 1;
416 
417  m_rewindIter = val;
418  m_rewindSlider->SetValue( m_rewindIter );
421 
422  event.Skip();
423 }
424 
426 {
427  printf("SyncModel\n");
428 
429  for( wxTreeListItem item = m_itemList->GetFirstItem();
430  item.IsOk();
431  item = m_itemList->GetNextItem( item )
432  )
433  {
434  WX_SHAPE_TREE_ITEM_DATA* idata = static_cast<WX_SHAPE_TREE_ITEM_DATA*> ( m_itemList->GetItemData( item ) );
435  printf("IDATA %p\n", idata);
436  if( idata )
437  {
438  idata->m_item->m_visible = m_itemList->GetCheckedState( item ) == wxCHK_CHECKED;
439  }
440  }
441 
442 }
443 
444 void PNS_LOG_VIEWER_FRAME::onListRightClick(wxMouseEvent& event)
445 {
446  fprintf(stderr,"OnListMenu\n");
447  //m_itemList->PopupMenu(m_listPopupMenu);
448  auto sel = m_itemList->GetPopupMenuSelectionFromUser( *m_listPopupMenu );
449 
450  switch( sel )
451  {
452  case ID_LIST_SHOW_NONE:
453  m_itemList->CheckItemRecursively( m_itemList->GetRootItem(), wxCHK_UNCHECKED );
454  syncModel();
456  break;
457  case ID_LIST_SHOW_ALL:
458  m_itemList->CheckItemRecursively( m_itemList->GetRootItem(), wxCHK_CHECKED );
459  syncModel();
461  break;
462  }
463 }
464 
465 void PNS_LOG_VIEWER_FRAME::onListShowAll( wxCommandEvent& event )
466 {
467 
468 }
469 
470 void PNS_LOG_VIEWER_FRAME::onListShowNone( wxCommandEvent& event )
471 {
472  m_itemList->CheckItemRecursively( m_itemList->GetRootItem(), wxCHK_UNCHECKED );
473 
475 }
476 
477 void PNS_LOG_VIEWER_FRAME::onListCopy( wxCommandEvent& event )
478 {
479  wxString s;
480 
481  int sel = 0; //m_itemList->GetSelection();
482  auto dbgd = m_env->GetDebugDecorator();
483  int count = dbgd->GetStageCount();
484 
485  if( count <= 0 )
486  return;
487 
488  int iter = m_rewindIter;
489 
490  if( iter < 0 )
491  iter = 0;
492 
493  if( iter >= count )
494  iter = count - 1;
495 
496  const PNS_TEST_DEBUG_DECORATOR::STAGE* st = dbgd->GetStage( iter );
497 
498 // if ( st->m_entries.size() < sel )
499  // return;
500 
501  const PNS_TEST_DEBUG_DECORATOR::DEBUG_ENT& ent = st->m_entries[sel];
502 
503  for( auto& sh : ent.m_shapes )
504  {
505  s += sh->Format() + " ";
506  }
507 
508  if (wxTheClipboard->Open())
509  {
510  // This data objects are held by the clipboard,
511  // so do not delete them in the app.
512  wxTheClipboard->SetData( new wxTextDataObject(s) );
513  wxTheClipboard->Close();
514  }
515 }
516 
517 void PNS_LOG_VIEWER_FRAME::onListSelect( wxCommandEvent& event )
518 {
519  printf("OnListSelect!\n");
521 }
522 
523 
525 {
526  printf("LOG append %p\n", ent );
527 
528  wxTreeListItem ritem;
529 
530  if( ent->m_children.size() )
531  ritem = m_itemList->AppendItem( item, "Child" );
532  else
533  ritem = item;
534 
535  //ent->m_item = ritem;
536 
537  if( ent->m_msg.length() )
538  {
539  m_itemList->SetItemText( ritem, 0, "Message" );
540  m_itemList->SetItemText( ritem, 1, ent->m_msg );
541  }
542  else
543  {
544  m_itemList->SetItemText( ritem, 0, "Shapes" );
545  m_itemList->SetItemText( ritem, 1, ent->m_name );
546  }
547 
548  m_itemList->SetItemData( ritem, new WX_SHAPE_TREE_ITEM_DATA( ent ) );
549 
550  for( auto child : ent->m_children )
551  {
552  auto citem = m_itemList->AppendItem( ritem, "" );
553  buildListTree( citem, child );
554  }
555 
556 
557 
558 
559 
560 }
561 
562 
563 
564 static void expandAllChildren( wxTreeListCtrl* tree, const wxTreeListItem& item)
565 {
566  tree->Freeze();
567  // expand this item first, this might result in its children being added on
568  // the fly
569  if ( item != tree->GetRootItem() )
570  tree->Expand(item);
571  //else: expanding hidden root item is unsupported and unnecessary
572 
573  // then (recursively) expand all the children
574  for ( auto idCurr = tree->GetFirstChild(item);
575  idCurr.IsOk();
576  idCurr = tree->GetNextSibling(item) )
577  {
578  expandAllChildren(tree, idCurr);
579  }
580  tree->Thaw();
581 }
582 
584 {
585  if ( !m_env )
586  return;
587 
588  auto dbgd = m_env->GetDebugDecorator();
589  int count = dbgd->GetStageCount();
590 
591  wxArrayString dumpStrings;
592 
593  if( count <= 0 )
594  return;
595 
596  if( iter < 0 )
597  iter = 0;
598 
599  if( iter >= count )
600  iter = count - 1;
601 
602 
603  auto st = dbgd->GetStage( iter );
604 
605  auto rootItem = m_itemList->GetRootItem();
606 
607  printf("ItemList: %p\n", m_itemList );
608 
609  m_itemList->DeleteAllItems();
610  buildListTree( rootItem, st->m_entries );
611  m_itemList->CheckItemRecursively ( rootItem, wxCHK_CHECKED );
612  //m_itemList->Expand( List->GetRootItem() );
613 
614  //expandAllChildren( m_itemList, m_itemList->GetRootItem() );
615  m_itemList->Refresh();
616 }
617 
618 static bool commonParallelProjection( SEG p, SEG n, SEG &pClip, SEG& nClip )
619 {
620  SEG n_proj_p( p.LineProject( n.A ), p.LineProject( n.B ) );
621 
622  int64_t t_a = 0;
623  int64_t t_b = p.TCoef( p.B );
624 
625  int64_t tproj_a = p.TCoef( n_proj_p.A );
626  int64_t tproj_b = p.TCoef( n_proj_p.B );
627 
628  if( t_b < t_a )
629  std::swap( t_b, t_a );
630 
631  if( tproj_b < tproj_a )
632  std::swap( tproj_b, tproj_a );
633 
634  if( t_b <= tproj_a )
635  return false;
636 
637  if( t_a >= tproj_b )
638  return false;
639 
640  int64_t t[4] = { 0, p.TCoef( p.B ), p.TCoef( n_proj_p.A ), p.TCoef( n_proj_p.B ) };
641  std::vector<int64_t> tv( t, t + 4 );
642  std::sort( tv.begin(), tv.end() ); // fixme: awful and disgusting way of finding 2 midpoints
643 
644  int64_t pLenSq = p.SquaredLength();
645 
646  VECTOR2I dp = p.B - p.A;
647  pClip.A.x = p.A.x + rescale( (int64_t)dp.x, tv[1], pLenSq );
648  pClip.A.y = p.A.y + rescale( (int64_t)dp.y, tv[1], pLenSq );
649 
650  pClip.B.x = p.A.x + rescale( (int64_t)dp.x, tv[2], pLenSq );
651  pClip.B.y = p.A.y + rescale( (int64_t)dp.y, tv[2], pLenSq );
652 
653  nClip.A = n.LineProject( pClip.A );
654  nClip.B = n.LineProject( pClip.B );
655 
656  return true;
657 }
658 
659 #if 0
660 
661 using namespace PNS;
662 
663 
664 
665 template <typename T1, typename T2>
666 typename std::map<T1, T2>::iterator findClosestKey( std::map<T1, T2> & data, T1 key)
667 {
668  if (data.size() == 0) {
669  return data.end();
670  }
671 
672  auto lower = data.lower_bound(key);
673 
674  if (lower == data.end()) // If none found, return the last one.
675  return std::prev(lower);
676 
677  if (lower == data.begin())
678  return lower;
679 
680  // Check which one is closest.
681  auto previous = std::prev(lower);
682  if ((key - previous->first) < (lower->first - key))
683  return previous;
684 
685  return lower;
686 }
687 
688 void extractDiffPairItems ( PNS::NODE* node, int net_p, int net_n )
689 {
690  std::set<PNS::ITEM*> pendingItems, complementItems;
691  node->AllItemsInNet( net_p, pendingItems, PNS::ITEM::SEGMENT_T | PNS::ITEM::ARC_T );
692  node->AllItemsInNet( net_n, complementItems, PNS::ITEM::SEGMENT_T | PNS::ITEM::ARC_T );
693 
694  while( pendingItems.size() )
695  {
696  PNS::LINE l = node->AssembleLine( static_cast<PNS::LINKED_ITEM*>( *pendingItems.begin() ) );
697 
698  printf("l net %d segs %d layer %d\n", net_p, l.SegmentCount(), l.Layer() );
699 
700  std::map<int, int> gapMap;
701  std::map<PNS::LINKED_ITEM*, int> coupledCandidates;
702 
703  for( auto li : l.Links() )
704  {
705  pendingItems.erase( li );
706  auto sp = dyn_cast<PNS::SEGMENT*> ( li );
707 
708  if(!sp)
709  continue;
710 
711  for ( auto ci : complementItems )
712  {
713  auto sn = dyn_cast<PNS::SEGMENT*> ( ci );
714 
715  if( !sn->Layers().Overlaps( sp->Layers() ))
716  continue;
717 
718 
719  auto ssp = sp->Seg();
720  auto ssn = sn->Seg();
721 
722  if( ssp.ApproxParallel(ssn) )
723  {
724  SEG ca, cb;
725  bool coupled = commonParallelProjection( ssp, ssn, ca, cb );
726 
727  if( coupled )
728  {
729  /* g_overlay->SetStrokeColor( KIGFX::COLOR4D( 1.0, 0.8, 0.8, 1.0 ) );
730  g_overlay->SetIsFill(false);
731  g_overlay->SetIsStroke(true );
732  g_overlay->SetLineWidth( 10000 );
733  g_overlay->Line( ca );
734  g_overlay->SetStrokeColor( KIGFX::COLOR4D( 0.8, 0.8, 1.0, 1.0 ) );
735  g_overlay->Line( cb );*/
736 
737  int len = ca.Length();
738  int gap = (int)(ca.A - cb.A).EuclideanNorm() - (sp->Width()+sn->Width()) / 2;
739 
740  auto closestGap = findClosestKey( gapMap, gap );
741 
742  coupledCandidates[sn] = gap;
743 
744  if( closestGap == gapMap.end() || std::abs(closestGap->first - gap) > 50 )
745  {
746  gapMap[gap] = len;
747  } else {
748  closestGap->second += len;
749  }
750 
751  printf("Seg %p %p gap %d dist %d\n", sp, sn, gap, len );
752  }
753  }
754  }
755  }
756 
757  int bestGap = -1;
758  int maxLength = 0;
759  for( auto i : gapMap )
760  {
761  if( i.second > maxLength )
762  {
763  maxLength = i.second;
764  bestGap = i.first;
765  }
766  }
767 
768  printf("Best gap: %d\n", bestGap);
769 
770  bool pendingCandidates = true;
771 
772  while ( pendingCandidates )
773  {
774  pendingCandidates = false;
775 
776  for ( auto c : coupledCandidates )
777  {
778  if( std::abs(c.second - bestGap ) < 50 )
779  {
780  PNS::LINE l_coupled = node->AssembleLine( c.first );
781 
782  PNS::DIFF_PAIR pair(l, l_coupled, bestGap );
783  pair.SetNets( l.Net(), l_coupled.Net() );
784 
785 /* g_overlay->SetStrokeColor( KIGFX::COLOR4D( 1.0, 0.8, 0.8, 1.0 ) );
786  g_overlay->SetIsFill(true);
787  g_overlay->SetIsStroke(true );
788  g_overlay->SetLineWidth( 10000 );
789  g_overlay->Polyline( l.CLine() );
790  g_overlay->SetStrokeColor( KIGFX::COLOR4D( 0.8, 0.8, 1.0, 1.0 ) );
791  g_overlay->Polyline( l_coupled.CLine() );
792 */
793  for( auto li : l_coupled.Links() )
794  coupledCandidates.erase( li );
795 
796  printf("Orig line : %d segs, coupled line: %d segs\n", l.SegmentCount(), l_coupled.SegmentCount() );
797 
798  pendingCandidates = true;
799  break;
800  }
801  }
802  }
803  }
804 }
805 
806 
807 
808 int pns1_main_func( int argc, char* argv[] )
809 {
810  auto frame = new PNS_LOG_VIEWER_FRAME(nullptr);
811  std::shared_ptr<BOARD> board;
812 
813  board.reset( loadBoard ( argv[1] ) );
814 
815  frame->SetBoard( board );
816 
817  Pgm().App().SetTopWindow( frame ); // wxApp gets a face.
818  frame->Show();
819 
820  PNS_KICAD_IFACE_BASE iface;
821  PNS::NODE *world = new PNS::NODE;
822 
823  iface.SetBoard( board.get() );
824  iface.SyncWorld( world );
825 
826  #if 0
827  std::map<int, int> diffPairs;
828 
829  // FIXMe: GetNetInfo copies f***ing pointers...
830  const auto& netinfo = board->GetNetInfo();
831 
832  int n_nets = netinfo.GetNetCount();
833 
834  for (int net = 0 ; net < n_nets; net++ )
835  {
836  int coupled = iface.GetRuleResolver()->DpCoupledNet( net );
837  if( coupled > 0 && diffPairs.find( coupled ) == diffPairs.end() )
838  {
839  printf("net %d coupled %d\n", net, coupled );
840  diffPairs[net] = coupled;
841  }
842  }
843 
844  for( auto p : diffPairs )
845  {
846  extractDiffPairItems ( world, p.first, p.second );
847  }
848  #endif
849 
850  return 0;
851 }
852 
853 static bool registered = UTILITY_REGISTRY::Register( {
854  "pns1",
855  "PNS Dumb Test (Tom's hacks)",
856  pns1_main_func,
857 } );
858 
859 #endif
860 
861 //extern "C" void drcCreateTestsProviderClearance();
862 //extern "C" void drcCreateTestsProviderEdgeClearance();
863 
864 int replay_main_func( int argc, char* argv[] )
865 {
866  auto frame = new PNS_LOG_VIEWER_FRAME(nullptr);
867 
868  // drcCreateTestsProviderClearance();
869 // drcCreateTestsProviderEdgeClearance();
870 
871 
872  if( argc >= 2 && std::string(argv[1]) == "-h")
873  {
874  printf("PNS Log (Re)player. Allows to step through the log written by the ROUTER_TOOL in debug Kicad builds. ");
875  printf("Requires a board file with UUIDs and a matching log file. Both are written to /tmp when you press '0' during routing.");
876  return 0;
877  }
878 
879  if(argc < 3)
880  {
881  printf("Expected parameters: log_file.log board_file.dump\n");
882  return 0;
883  }
884 
885  PNS_LOG_FILE* logFile = new PNS_LOG_FILE;
886  logFile->Load( argv[1], argv[2] );
887 
888  frame->SetLogFile( logFile );
889  //SetTopFrame( frame ); // wxApp gets a face.
890 
891  return 0;
892 }
893 
895  "replay",
896  "PNS Log Player",
898 } );
899 
900 
901 
902 
903 bool commonParallelProjection( SEG p, SEG n, SEG &pClip, SEG& nClip );
904 
905 
906 template <typename T1, typename T2>
907 typename std::map<T1, T2>::iterator findClosestKey( std::map<T1, T2> & data, T1 key)
908 {
909  if (data.size() == 0) {
910  return data.end();
911  }
912 
913  auto lower = data.lower_bound(key);
914 
915  if (lower == data.end()) // If none found, return the last one.
916  return std::prev(lower);
917 
918  if (lower == data.begin())
919  return lower;
920 
921  // Check which one is closest.
922  auto previous = std::prev(lower);
923  if ((key - previous->first) < (lower->first - key))
924  return previous;
925 
926  return lower;
927 }
928 
929 
930 
931 void extractDiffPair( BOARD* aBoard, int net_p, int net_n )
932 {
933  std::set<TRACK*> pendingItems, complementItems;
934 
935  struct DP_COUPLED_SEGMENTS
936  {
937  TRACK* itemP, *itemN;
938  };
939 
940  for( auto trk: aBoard->Tracks() )
941  {
942  if( trk->Type() == PCB_TRACE_T || trk->Type() == PCB_ARC_T )
943  {
944  if( trk->GetNetCode() == net_p )
945  pendingItems.insert( trk );
946  else if( trk->GetNetCode() == net_n )
947  complementItems.insert( trk );
948  }
949  }
950 
951  while( pendingItems.size() )
952  {
953  auto li = *pendingItems.begin();
954  pendingItems.erase( li );
955  auto sp = dyn_cast<TRACK*>(li);
956 
957  if(!sp)
958  continue;
959 
960  for ( auto ci : complementItems )
961  {
962  auto sn = dyn_cast<TRACK*> ( ci );
963 
964  if( ( sn->GetLayerSet() & sp->GetLayerSet() ).none() )
965  continue;
966 
967  SEG ssp ( sp->GetStart(), sp->GetEnd() );
968  SEG ssn ( sn->GetStart(), sn->GetEnd() );
969 
970  if( ssp.ApproxParallel(ssn) )
971  {
972  SEG ca, cb;
973  bool coupled = commonParallelProjection( ssp, ssn, ca, cb );
974 
975  }
976  }
977  }
978 
979 }
980 
981 static int matchDpSuffix( const wxString& aNetName, wxString& aComplementNet,
982  wxString& aBaseDpName )
983 {
984  int rv = 0;
985 
986  if( aNetName.EndsWith( "+" ) )
987  {
988  aComplementNet = "-";
989  rv = 1;
990  }
991  else if( aNetName.EndsWith( "P" ) )
992  {
993  aComplementNet = "N";
994  rv = 1;
995  }
996  else if( aNetName.EndsWith( "-" ) )
997  {
998  aComplementNet = "+";
999  rv = -1;
1000  }
1001  else if( aNetName.EndsWith( "N" ) )
1002  {
1003  aComplementNet = "P";
1004  rv = -1;
1005  }
1006  // Match P followed by 2 digits
1007  else if( aNetName.Right( 2 ).IsNumber() && aNetName.Right( 3 ).Left( 1 ) == "P" )
1008  {
1009  aComplementNet = "N" + aNetName.Right( 2 );
1010  rv = 1;
1011  }
1012  // Match P followed by 1 digit
1013  else if( aNetName.Right( 1 ).IsNumber() && aNetName.Right( 2 ).Left( 1 ) == "P" )
1014  {
1015  aComplementNet = "N" + aNetName.Right( 1 );
1016  rv = 1;
1017  }
1018  // Match N followed by 2 digits
1019  else if( aNetName.Right( 2 ).IsNumber() && aNetName.Right( 3 ).Left( 1 ) == "N" )
1020  {
1021  aComplementNet = "P" + aNetName.Right( 2 );
1022  rv = -1;
1023  }
1024  // Match N followed by 1 digit
1025  else if( aNetName.Right( 1 ).IsNumber() && aNetName.Right( 2 ).Left( 1 ) == "N" )
1026  {
1027  aComplementNet = "P" + aNetName.Right( 1 );
1028  rv = -1;
1029  }
1030  if( rv != 0 )
1031  {
1032  aBaseDpName = aNetName.Left( aNetName.Length() - aComplementNet.Length() );
1033  aComplementNet = aBaseDpName + aComplementNet;
1034  }
1035 
1036  return rv;
1037 }
1038 
1039 
1040 static int dpCoupledNet( BOARD* aBoard, int aNet )
1041 {
1042  wxString refName = aBoard->FindNet( aNet )->GetNetname();
1043  wxString dummy, coupledNetName;
1044 
1045  if( matchDpSuffix( refName, coupledNetName, dummy ) )
1046  {
1047  NETINFO_ITEM* net = aBoard->FindNet( coupledNetName );
1048 
1049  if( !net )
1050  return -1;
1051 
1052  return net->GetNetCode();
1053  }
1054 
1055  return -1;
1056 }
1057 
1058 
1060 {
1061  std::map<int, int> diffPairs;
1062 
1063  // FIXMe: GetNetInfo copies f***ing pointers...
1064  const auto& netinfo = aBoard->GetNetInfo();
1065 
1066  int n_nets = netinfo.GetNetCount();
1067 
1068  for (int net = 0 ; net < n_nets; net++ )
1069  {
1070  int coupled = dpCoupledNet(aBoard, net );
1071 
1072  if( coupled > 0 && diffPairs.find( coupled ) == diffPairs.end() )
1073  {
1074  diffPairs[net] = coupled;
1075  }
1076  }
1077 
1078  for( auto p : diffPairs )
1079  {
1080  printf("Extract DP: %s/%s\n", (const char*) aBoard->FindNet( p.first )->GetNetname(),
1081  (const char*) aBoard->FindNet( p.second )->GetNetname() );
1082 
1083  extractDiffPair ( aBoard, p.first, p.second );
1084  }
1085 }
1086 
1087 #if 0
1088 int test1_main_func( int argc, char* argv[] )
1089 {
1090  auto frame = new PNS_LOG_VIEWER_FRAME(nullptr);
1091 
1093 
1094  frame->SetBoard( project.board);
1095 
1096  Pgm().App().SetTopWindow( frame ); // wxApp gets a face.
1097  frame->Show();
1098 
1099  auto view = frame->GetPanel()->GetView();
1100  //auto settings = static_cast<KIGFX::PCB_RENDER_SETTINGS*>( view->GetPainter()->GetSettings() );
1101  //settings->SetZoneDisplayMode( ZONE_DISPLAY_MODE:: );
1102 
1103 /* view->SetLayerVisible( LAYER_TRACKS, false );
1104  view->SetLayerVisible( LAYER_PADS, false );
1105  view->SetLayerVisible( LAYER_MOD_TEXT_BK, false );
1106  view->SetLayerVisible( LAYER_MOD_TEXT_FR, false );
1107  view->SetLayerVisible( LAYER_MOD_REFERENCES, false );
1108  view->SetLayerVisible( LAYER_MOD_VALUES, false );
1109  view->SetLayerVisible( LAYER_MOD_BK, false );
1110  view->SetLayerVisible( LAYER_MOD_FR, false );*/
1111 
1112  runDRCProto( project, frame->GetPanel()->DebugOverlay() );
1113 
1114  return 0;
1115 }
1116 #endif
1117 
1118 //std::shared_ptr<KIGFX::VIEW_OVERLAY> g_overlay;
1119 static std::shared_ptr<KIGFX::VIEW_OVERLAY> overlay;
1120 
1121 bool segmentCrossesHullBoundary( const SHAPE_LINE_CHAIN& hull, const SEG& seg)
1122 {
1123  for( int j = 0; j < hull.SegmentCount(); j++ )
1124  {
1125  auto sr = hull.CSegment(j);
1126  }
1127 
1128 
1129 }
1130 
1132  SHAPE_LINE_CHAIN& aWalk, SHAPE_LINE_CHAIN& aPost, bool aCw )
1133 {
1134  const SHAPE_LINE_CHAIN& line( aLine );
1135 
1136  if( line.SegmentCount() < 1 )
1137  return false;
1138 
1139  const auto pFirst = line.CPoint(0);
1140  const auto pLast = line.CPoint(-1);
1141 
1142  bool inFirst = aObstacle.PointInside( pFirst ) && !aObstacle.PointOnEdge( pFirst );
1143  bool inLast = aObstacle.PointInside( pLast ) && !aObstacle.PointOnEdge( pLast );
1144 
1145  if( inFirst || inLast )
1146  {
1147  return false;
1148  }
1149 
1150  enum VERTEX_TYPE { INSIDE = 0, OUTSIDE, ON_EDGE };
1151 
1152  struct VERTEX
1153  {
1154  VERTEX_TYPE type;
1155  bool isHull;
1156  VECTOR2I pos;
1157  std::vector<VERTEX*> neighbours;
1158  int indexp, indexh;
1159  bool visited = false;
1160  };
1161 
1163 
1164  line.Intersect( aObstacle, ips );
1165 
1166  SHAPE_LINE_CHAIN pnew(aLine), hnew(aObstacle);
1167 
1168  std::vector<VERTEX> vts;
1169 
1170  auto findVertex = [&]( VECTOR2I pos) -> VERTEX*
1171  {
1172  for(auto& v : vts)
1173  if(v.pos == pos )
1174  return &v;
1175 
1176  return nullptr;
1177  };
1178 
1179  for( auto ip : ips )
1180  {
1181  bool isNewP, isNewH;
1182 
1183  if( pnew.Find( ip.p ) < 0 )
1184  {
1185  pnew.Split(ip.p);
1186  //overlay->SetStrokeColor( YELLOW );
1187  //overlay->Circle( ip.p, 200000 );
1188  }
1189 
1190  if( hnew.Find( ip.p ) < 0 )
1191  {
1192  hnew.Split(ip.p);
1193  //overlay->SetStrokeColor( CYAN );
1194  //overlay->Circle( ip.p, 250000 );
1195  }
1196  }
1197 
1198  if ( !aCw )
1199  hnew = hnew.Reverse();
1200 
1201  for( int i = 0; i < pnew.PointCount(); i++ )
1202  {
1203  auto p = pnew.CPoint(i);
1204  VERTEX v;
1205  v.indexp = i;
1206  v.isHull = false;
1207  v.pos = p;
1208  v.type = hnew.PointInside( p ) && !hnew.PointOnEdge( p ) ? INSIDE : hnew.PointOnEdge( p ) ? ON_EDGE : OUTSIDE;
1209  vts.push_back(v);
1210  overlay->SetStrokeColor( WHITE );
1211  overlay->SetFillColor( WHITE );
1212  overlay->SetGlyphSize( VECTOR2D( 200000, 200000 ));
1213  overlay->BitmapText( wxString::Format("%d", i), v.pos, 0 );
1214  }
1215 
1216  for( int i = 0; i < pnew.PointCount() - 1; i++ )
1217  {
1218  vts[i].neighbours.push_back(&vts[i+1]);
1219  }
1220 
1221  for( int i = 0; i < hnew.PointCount(); i++ )
1222  {
1223  auto hp = hnew.CPoint(i);
1224  bool found = false;
1225  auto vn = findVertex( hp );
1226 
1227  if( vn )
1228  {
1229  vn->isHull = true;
1230  vn->indexh = i;
1231  } else {
1232  VERTEX v;
1233  v.pos = hp;
1234  v.type = ON_EDGE;
1235  v.indexh = i;
1236  v.isHull = true;
1237  vts.push_back( v );
1238  }
1239 
1240  overlay->SetStrokeColor( WHITE );
1241  overlay->SetFillColor( WHITE );
1242  overlay->SetGlyphSize( VECTOR2D( 200000, 200000 ));
1243  // overlay->BitmapText( wxString::Format("%d", i), hp, 0 );
1244  }
1245 
1246 
1247  for( int i = 0; i < hnew.PointCount(); i++ )
1248  {
1249  auto vc = findVertex( hnew.CPoint(i ) );
1250  auto vnext = findVertex( hnew.CPoint(i+1) );
1251 
1252 
1253 
1254  if(vc && vnext)
1255  vc->neighbours.push_back(vnext);
1256  }
1257 
1258  for( auto& v : vts )
1259  {
1260  printf(" ip %d ih %d t %d ishull %d\n", v.indexp, v.indexh, v.type, v.isHull?1:0);
1261  }
1262 
1263 
1264  VERTEX* v = &vts[0];
1265 
1266  SHAPE_LINE_CHAIN out;
1267 
1268  int n = 0;
1269  while (v->indexp != pnew.PointCount() )
1270  {
1271  printf("SCAN ip %d ih %d t %d ishull %d\n", v->indexp, v->indexh, v->type, v->isHull?1:0);
1272 
1273  out.Append( v->pos );
1274  if(v->visited)
1275  break;
1276 
1277  overlay->SetStrokeColor( v->isHull ? RED : WHITE );
1278  overlay->SetFillColor( v->isHull ? RED : WHITE );
1279  overlay->SetGlyphSize( VECTOR2D( 200000, 200000 ));
1280  //overlay->BitmapText( wxString::Format("%d", v->isHull ? v->indexh : v->indexp), v->pos, 0 );
1281 
1282 
1283  v->visited = true;
1284 
1285  if ( (n++) == 2000 ) // sanity check
1286  break;
1287 
1288  for( auto vn : v->neighbours )
1289  {
1290  printf(" ---> next ip %d ih %d t %d ishull %d\n",vn->indexp, vn->indexh, vn->type, vn->isHull?1:0);
1291  }
1292 
1293 
1294  if (v->type == OUTSIDE)
1295  {
1296  out.Append(v->pos);
1297  for( auto vn : v->neighbours )
1298  if( (vn->indexp > v->indexp) && vn->type != INSIDE )
1299  {
1300  v = vn;
1301  break;
1302  }
1303  }
1304  else if (v->type == ON_EDGE)
1305  {
1306  VERTEX* v_next = nullptr;
1307  int best_dist = INT_MAX;
1308 
1309  for( auto vn: v->neighbours)
1310  {
1311  if( vn->type == ON_EDGE && (vn->indexp == (v->indexp + 1) ) )
1312  {
1313  v_next = vn;
1314  break;
1315  }
1316  }
1317 
1318  if( !v_next )
1319  {
1320  for( auto vn: v->neighbours)
1321  {
1322  if( vn->type == OUTSIDE )
1323  {
1324  v_next = vn;
1325  break;
1326  }
1327  }
1328  }
1329 
1330  if( !v_next )
1331  {
1332  for( auto vn: v->neighbours)
1333  {
1334  if ( v->type == ON_EDGE )
1335  {
1336  if( vn->indexh == ( (v->indexh + 1) % hnew.PointCount() ) )
1337  {
1338  v_next = vn;
1339  //printf("E2\n");
1340 
1341 
1342  break;
1343  }
1344  }
1345  }
1346  }
1347 
1348  v = v_next;
1349 
1350 
1351  }
1352  }
1353 
1354  out.Append( v->pos );
1355 
1356  aWalk = out;
1357 
1358  return true;
1359 }
1360 
1361 int test2_main_func( int argc, char* argv[] )
1362 {
1363  auto frame = new PNS_LOG_VIEWER_FRAME(nullptr);
1364  Pgm().App().SetTopWindow( frame ); // wxApp gets a face.
1365  frame->Show();
1366 
1367  overlay = frame->GetPanel()->DebugOverlay();
1368 
1369 
1370  overlay->SetIsFill(false);
1371  overlay->SetLineWidth(10000);
1372 
1373  // auto hull = SHAPE_LINE_CHAIN( { VECTOR2I( 155977520, 128439216), VECTOR2I( 155639216, 128777520), VECTOR2I( 155160784, 128777520), VECTOR2I( 154822480, 128439216), VECTOR2I( 154822480, 97960784), VECTOR2I( 155160784, 97622480), VECTOR2I( 155639216, 97622480), VECTOR2I( 155977520, 97960784)}, true );
1374  //auto path = SHAPE_LINE_CHAIN( { VECTOR2I( 148981200, 102320000), VECTOR2I( 154822480, 102320000), VECTOR2I( 154822480, 98777520), VECTOR2I( 60977520, 98777520), VECTOR2I( 60977520, 127622480), VECTOR2I( 155639216, 127622480), VECTOR2I( 155977520, 127960784), VECTOR2I( 155977520, 128439216), VECTOR2I( 155639216, 128777520), VECTOR2I( 60160784, 128777520), VECTOR2I( 59822480, 128439216), VECTOR2I( 59822480, 97960784), VECTOR2I( 60160784, 97622480), VECTOR2I( 155639216, 97622480), VECTOR2I( 155977520, 97960784), VECTOR2I( 155977520, 102320000), VECTOR2I( 160208000, 102320000), VECTOR2I( 160462000, 102574000)}, false );
1375 
1376  //auto path = SHAPE_LINE_CHAIN( { VECTOR2I( 112456000, 102726400), VECTOR2I( 112456000, 98560800), VECTOR2I( 112456000, 98827020)}, false );
1377  //auto hull = SHAPE_LINE_CHAIN( { VECTOR2I( 155659720, 97572980), VECTOR2I( 156027020, 97940280), VECTOR2I( 156027020, 98459720), VECTOR2I( 155659720, 98827020), VECTOR2I( 60140280, 98827020), VECTOR2I( 59772980, 98459720), VECTOR2I( 59772980, 97940280), VECTOR2I( 60140280, 97572980)}, true );
1378 
1379  //auto path = SHAPE_LINE_CHAIN( { VECTOR2I( 119364800, 100288000), VECTOR2I( 119364800, 97697200), VECTOR2I( 119364800, 97572980)}, false );
1380  //auto hull = SHAPE_LINE_CHAIN( { VECTOR2I( 155659720, 97572980), VECTOR2I( 156027020, 97940280), VECTOR2I( 156027020, 98459720), VECTOR2I( 155659720, 98827020), VECTOR2I( 60140280, 98827020), VECTOR2I( 59772980, 98459720), VECTOR2I( 59772980, 97940280), VECTOR2I( 60140280, 97572980)}, true );
1381 
1382  //auto path = SHAPE_LINE_CHAIN( { VECTOR2I( 119263200, 101253200), VECTOR2I( 119263200, 98827020), VECTOR2I( 61027020, 98827020), VECTOR2I( 61027020, 127572980), VECTOR2I( 154772980, 127572980), VECTOR2I( 154772980, 97940280), VECTOR2I( 155140280, 97572980), VECTOR2I( 155659720, 97572980), VECTOR2I( 156027020, 97940280), VECTOR2I( 156027020, 128459720), VECTOR2I( 155659720, 128827020), VECTOR2I( 60140280, 128827020), VECTOR2I( 59772980, 128459720), VECTOR2I( 59772980, 97940280), VECTOR2I( 60140280, 97572980), VECTOR2I( 119641420, 97572980), VECTOR2I( 121650800, 95563600)}, false );
1383  //auto hull = SHAPE_LINE_CHAIN( { VECTOR2I( 155659720, 97572980), VECTOR2I( 156027020, 97940280), VECTOR2I( 156027020, 98459720), VECTOR2I( 155659720, 98827020), VECTOR2I( 60140280, 98827020), VECTOR2I( 59772980, 98459720), VECTOR2I( 59772980, 97940280), VECTOR2I( 60140280, 97572980)}, true );
1384 
1385 // auto hull = SHAPE_LINE_CHAIN( { VECTOR2I( 96722489, 117694794), VECTOR2I( 97594794, 116822489), VECTOR2I( 99205206, 116822489), VECTOR2I( 100077511, 117694794), VECTOR2I( 100077511, 119305206), VECTOR2I( 99205206, 120177511), VECTOR2I( 97594794, 120177511), VECTOR2I( 96722489, 119305206)}, true );
1386  // auto path = SHAPE_LINE_CHAIN( { VECTOR2I( 103400000, 118500000), VECTOR2I( 93400000, 118500000)}, false );
1387 
1388  auto hull = SHAPE_LINE_CHAIN( { VECTOR2I( 66280505, 107710033), VECTOR2I( 65914967, 107344495), VECTOR2I( 65914967, 106827549), VECTOR2I( 66280505, 106462011), VECTOR2I( 74810033, 106462009), VECTOR2I( 75175571, 106827547), VECTOR2I( 75175571, 107344493), VECTOR2I( 74810033, 107710031)}, true );
1389  auto path = SHAPE_LINE_CHAIN( { /*VECTOR2I( 143928480, 109445996), VECTOR2I( 111066480, 109445996), VECTOR2I( 106254391, 104633907), VECTOR2I( 105909001, 104633907), VECTOR2I( 105775094, 104500000),*/ VECTOR2I( 76250000, 104500000), VECTOR2I( 74287991, 106462009), VECTOR2I( 66280505, 106462011), VECTOR2I( 66012989, 106462011)}, false );
1390 
1391 
1392  BOX2D bb ( path.BBox().GetPosition(), path.BBox().GetSize() );
1393 
1394  frame->GetPanel()->GetView()->SetViewport(bb);
1395 
1396  PNS::LINE l;
1397  SHAPE_LINE_CHAIN path_pre, path_walk, path_post;
1398  l.SetShape( path );
1399 
1400  auto status = l.Walkaround( hull, path_walk, false );
1401  printf("Stat: %d\n", status );
1402 
1403  //printf("status: %d\n", walkaround2( path, hull, path_pre, path_walk,
1404  // path_post, false ) );
1405 
1406  overlay->SetLineWidth(200000.0);
1407  overlay->SetStrokeColor( BLUE );
1408  //overlay->Polyline( path_pre );
1409  overlay->Polyline( path_walk );
1410  //overlay->Polyline( path_post );
1411 
1412  overlay->SetStrokeColor( WHITE );
1413  overlay->SetLineWidth( 100000.0 );
1414  overlay->Polyline( path );
1415 
1416  overlay->SetStrokeColor( RED );
1417  overlay->Polyline( hull );
1418 
1419 
1420  return 0;
1421 }
1422 
1423 #if 0
1424 static bool registered3 = UTILITY_REGISTRY::Register( {
1425  "test1",
1426  "Test1",
1427  test1_main_func,
1428 } );
1429 
1430 #endif
1431 
1433  "test2",
1434  "Test2",
1436 } );
1437 
1438 
int Length() const
Return the length (this).
Definition: seg.h:355
int Find(const VECTOR2I &aP) const
Function Find()
bool Load(const std::string &logName, const std::string boardName)
Definition: pns_log.cpp:45
std::shared_ptr< PNS_LOG_FILE > m_logFile
NETINFO_ITEM * FindNet(int aNetcode) const
Search for a net with the given netcode.
Definition: board.cpp:1289
STAGE * GetStage(int index)
Definition: pns_log.h:230
int Split(const VECTOR2I &aP)
Function Split()
int Intersect(const SEG &aSeg, INTERSECTIONS &aIp) const
Function Intersect()
std::vector< INTERSECTION > INTERSECTIONS
virtual int Layer() const
Definition: pns_item.h:154
PNS::RULE_RESOLVER * GetRuleResolver() override
A PLUGIN derivation for saving and loading Pcbnew s-expression formatted files.
Keep the router "world" - i.e.
Definition: pns_node.h:145
Class PNS_LOG_VIEWER_FRAME_BASE.
bool Walkaround(SHAPE_LINE_CHAIN aObstacle, SHAPE_LINE_CHAIN &aPre, SHAPE_LINE_CHAIN &aWalk, SHAPE_LINE_CHAIN &aPost, bool aCw) const
Calculate a line tightly wrapping a convex hull of an obstacle object (aObstacle).
ecoord SquaredLength() const
Definition: seg.h:360
int SegmentCount() const
Definition: pns_line.h:139
virtual void onBtnRewindRight(wxCommandEvent &event) override
virtual int DpCoupledNet(int aNet)=0
std::vector< SHAPE * > m_shapes
Definition: pns_log.h:172
int color
Definition: DXF_plotter.cpp:60
static bool registered
Definition: coroutines.cpp:128
class ARC, an arc track segment on a copper layer
Definition: typeinfo.h:97
virtual void onListShowNone(wxCommandEvent &event)
static LIB_PART * dummy()
Used to draw a dummy shape when a LIB_PART is not found in library.
Definition: sch_symbol.cpp:69
PNS_TEST_DEBUG_DECORATOR::DEBUG_ENT * m_item
const NETINFO_LIST & GetNetInfo() const
Definition: board.h:754
bool PointOnEdge(const VECTOR2I &aP, int aAccuracy=0) const
Check if point aP lies on an edge or vertex of the line chain.
static std::pair< bool, SHAPE_POLY_SET::VERTEX_INDEX > findVertex(SHAPE_POLY_SET &aPolySet, const EDIT_POINT &aPoint)
void extractDiffPair(BOARD *aBoard, int net_p, int net_n)
Represents a track on a PCB, connecting two non-trivial joints (that is, vias, pads,...
Definition: pns_line.h:60
const SHAPE_LINE_CHAIN Reverse() const
Function Reverse()
void createView(wxWindow *aParent, PCB_DRAW_PANEL_GAL::GAL_TYPE aGalType=PCB_DRAW_PANEL_GAL::GAL_TYPE_OPENGL)
VECTOR2< int > VECTOR2I
Definition: vector2d.h:623
int PointCount() const
Function PointCount()
KIWAY Kiway & Pgm(), KFCTL_STANDALONE
The global Program "get" accessor.
Definition: single_top.cpp:106
virtual const wxString Problem() const
what was the problem?
Definition: exceptions.cpp:45
class TRACK, a track segment (segment on a copper layer)
Definition: typeinfo.h:95
void Append(int aX, int aY, bool aAllowDuplication=false)
Function Append()
int GetStageCount() const
Definition: pns_log.h:228
void SetShape(const SHAPE_LINE_CHAIN &aLine)
Return the shape of the line.
Definition: pns_line.h:126
Releases a PLUGIN in the context of a potential thrown exception through its destructor.
Definition: io_mgr.h:550
virtual void onExit(wxCommandEvent &event) override
const VECTOR2I & CPoint(int aIndex) const
Function Point()
PNS_TEST_DEBUG_DECORATOR::STAGE * getCurrentStage()
VECTOR2I LineProject(const VECTOR2I &aP) const
Compute the perpendicular projection point of aP on a line passing through ends of the segment.
Definition: seg.h:404
std::shared_ptr< KIGFX::VIEW_OVERLAY > m_overlay
const LINE AssembleLine(LINKED_ITEM *aSeg, int *aOriginSegmentIndex=NULL, bool aStopAtLockedJoints=false)
Follow the joint map to assemble a line connecting two non-trivial joints starting from segment aSeg.
Definition: pns_node.cpp:912
#define NULL
VECTOR2< double > VECTOR2D
Definition: vector2d.h:622
ecoord TCoef(const VECTOR2I &aP) const
Definition: seg.h:431
virtual void onRewindCountText(wxCommandEvent &event) override
static bool Register(const KI_TEST::UTILITY_PROGRAM &aProgInfo)
Register a utility program factory function against an ID string.
void updateDumpPanel(int iter)
#define ID_LIST_SHOW_NONE
int Net() const
Definition: pns_item.h:148
void extractAllDiffPairs(BOARD *aBoard)
static int matchDpSuffix(const wxString &aNetName, wxString &aComplementNet, wxString &aBaseDpName)
coord_type GetWidth() const
Definition: box2.h:197
int test2_main_func(int argc, char *argv[])
bool segmentCrossesHullBoundary(const SHAPE_LINE_CHAIN &hull, const SEG &seg)
virtual void onBtnRewindLeft(wxCommandEvent &event) override
bool PointInside(const VECTOR2I &aPt, int aAccuracy=0, bool aUseBBoxCache=false) const
Check if point aP lies inside a polygon (any type) defined by the line chain.
virtual void createUserTools() override
std::map< T1, T2 >::iterator findClosestKey(std::map< T1, T2 > &data, T1 key)
static bool registered2
const wxString & GetNetname() const
Definition: netinfo.h:119
#define ID_LIST_SHOW_ALL
Text appears outside the dimension line (default)
void SyncWorld(PNS::NODE *aWorld) override
PNS_LOG_VIEWER_FRAME(wxFrame *frame)
Definition: color4d.h:59
virtual void onReload(wxCommandEvent &event) override
int SegmentCount() const
Function SegmentCount()
#define ID_LIST_COPY
circle
Definition: shape.h:46
static void expandAllChildren(wxTreeListCtrl *tree, const wxTreeListItem &item)
void SetBoard(BOARD *aBoard)
std::vector< DEBUG_ENT * > m_children
Definition: pns_log.h:173
Definition: color4d.h:48
void Format(OUTPUTFORMATTER *out, int aNestLevel, int aCtl, const CPTREE &aTree)
Output a PTREE into s-expression format via an OUTPUTFORMATTER derivative.
Definition: ptree.cpp:200
Definition: seg.h:41
void IterateTree(std::function< bool(DEBUG_ENT *)> visitor, int depth=0)
Definition: pns_log.cpp:380
DIFF_PAIR.
std::shared_ptr< PCB_DRAW_PANEL_GAL > m_galPanel
virtual void onListShowAll(wxCommandEvent &event)
std::shared_ptr< BOARD > m_board
void SetHeight(coord_type val)
Definition: box2.h:224
static int dpCoupledNet(BOARD *aBoard, int aNet)
virtual void onListCopy(wxCommandEvent &event)
Handle the data for a net.
Definition: netinfo.h:64
BOX2< Vec > & Inflate(coord_type dx, coord_type dy)
Function Inflate inflates the rectangle horizontally by dx and vertically by dy.
Definition: box2.h:302
virtual ~PNS_LOG_VIEWER_FRAME()
Definition: color4d.h:56
see class PGM_BASE
int runDRCProto(PROJECT_CONTEXT project, std::shared_ptr< KIGFX::VIEW_OVERLAY > aDebugOverlay)
Definition: drc_proto.cpp:105
Only the zone outline is shown.
const SEG CSegment(int aIndex) const
Function CSegment()
Information pertinent to a Pcbnew printed circuit board.
Definition: board.h:190
#define _(s)
Definition: 3d_actions.cpp:33
SHAPE_LINE_CHAIN.
bool walkaround2(SHAPE_LINE_CHAIN &aLine, SHAPE_LINE_CHAIN aObstacle, SHAPE_LINE_CHAIN &aPre, SHAPE_LINE_CHAIN &aWalk, SHAPE_LINE_CHAIN &aPost, bool aCw)
bool commonParallelProjection(SEG p, SEG n, SEG &pClip, SEG &nClip)
void AllItemsInNet(int aNet, std::set< ITEM * > &aItems, int aKindMask=-1)
Definition: pns_node.cpp:1317
virtual void onListRightClick(wxMouseEvent &event)
static std::shared_ptr< KIGFX::VIEW_OVERLAY > overlay
std::shared_ptr< PNS_TEST_ENVIRONMENT > m_env
virtual void SetBoard(std::shared_ptr< BOARD > b)
VECTOR2I A
Definition: seg.h:49
void SetOrigin(const Vec &pos)
Definition: box2.h:210
T rescale(T aNumerator, T aValue, T aDenominator)
Function rescale()
Definition: util.h:95
void buildListTree(wxTreeListItem item, PNS_TEST_DEBUG_DECORATOR::DEBUG_ENT *ent)
line chain (polyline)
Definition: shape.h:45
coord_type GetHeight() const
Definition: box2.h:198
static bool registered4
boost::optional< T > OPT
Definition: optional.h:7
unsigned GetNetCount() const
Definition: netinfo.h:339
virtual void onListSelect(wxCommandEvent &event)
void drawLoggedItems(int iter)
virtual void onRewindScroll(wxScrollEvent &event) override
static bool commonParallelProjection(SEG p, SEG n, SEG &pClip, SEG &nClip)
axis-aligned rectangle
Definition: shape.h:43
int replay_main_func(int argc, char *argv[])
static BOARD * loadBoard(const std::string &filename)
PROJECT_CONTEXT loadKicadProject(wxString filename, OPT< wxString > rulesFilePath)
Definition: drc_proto.cpp:58
virtual void onListChecked(wxCommandEvent &event)
Push and Shove diff pair dimensions (gap) settings dialog.
static const COLOR4D assignColor(int aStyle)
Hold an error message and may be used when throwing exceptions containing meaningful error messages.
Definition: ki_exception.h:75
TRACKS & Tracks()
Definition: board.h:302
Definition: track.h:83
WX_SHAPE_TREE_ITEM_DATA(PNS_TEST_DEBUG_DECORATOR::DEBUG_ENT *item)
void SetLogFile(PNS_LOG_FILE *aLog)
void SetWidth(coord_type val)
Definition: box2.h:223
A color representation with 4 components: red, green, blue, alpha.
Definition: color4d.h:98
int GetNetCode() const
Definition: netinfo.h:113
VECTOR2I B
Definition: seg.h:50