KiCad PCB EDA Suite
Loading...
Searching...
No Matches
pns_log_viewer_frame.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 The 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#include <string>
28
29#include <confirm.h>
30#include <common.h>
31#include <wx/clipbrd.h>
32#include <pgm_base.h>
33#include <core/profile.h>
34#include <reporter.h>
35#include <trace_helpers.h>
36#include <view/view_overlay.h>
37#include <view/view_controls.h>
39#include <kiplatform/ui.h>
40
41
42#include "label_manager.h"
43
44#include "pns_log_file.h"
45#include "pns_log_player.h"
47
49#include "router/pns_utils.h"
51
53
54class WX_SHAPE_TREE_ITEM_DATA : public wxClientData
55{
56public:
57 WX_SHAPE_TREE_ITEM_DATA( PNS_DEBUG_SHAPE* item, int level = 0 ) : m_item( item ), m_level( level ) {};
58
61};
62
63
68
69
70void PNS_LOG_VIEWER_OVERLAY::AnnotatedPolyset( const SHAPE_POLY_SET& aPolyset, std::string aName,
71 bool aShowVertexNumbers )
72{
73 for( int i = 0; i < aPolyset.OutlineCount(); i++ )
74 {
75 if( i == 0 && !aName.empty() )
76 AnnotatedPolyline( aPolyset.COutline( i ), aName );
77 else
78 AnnotatedPolyline( aPolyset.COutline( i ), "" );
79
80 for( int j = 0; j < aPolyset.HoleCount( i ); j++ )
81 AnnotatedPolyline( aPolyset.CHole( i, j ), "" );
82 }
83}
84
85
87 bool aShowVertexNumbers )
88{
89 Polyline( aL );
90
91 if( name.length() > 0 && aL.PointCount() > 0 )
93
94 if( aShowVertexNumbers )
95 {
96 for( int i = 0; i < aL.PointCount(); i++ )
97 m_labelMgr->Add( aL.CPoint(i), wxString::Format("%d", i ), GetStrokeColor() );
98 }
99}
100
101
102void PNS_LOG_VIEWER_OVERLAY::AnnotatedPoint( const VECTOR2I p, int size, std::string name, bool aShowVertexNumbers )
103{
104 Line( p + VECTOR2D( size, size ), p - VECTOR2D( size, size ) );
105 Line( p + VECTOR2D( -size, size ), p - VECTOR2D( -size, size ) );
106
107 if( name.length() > 0 )
108 m_labelMgr->Add( p, name, GetStrokeColor() );
109}
110
111
113{
114 double radius = arc.GetRadius();
115 EDA_ANGLE start_angle = arc.GetStartAngle();
116 EDA_ANGLE angle = arc.GetCentralAngle();
117
119 KIGFX::VIEW_OVERLAY::Arc( arc.GetCenter(), radius, start_angle, start_angle + angle );
120
122 COLOR4D lightStrokeCol = prevStrokeCol.WithAlpha(0.5);
123 KIGFX::VIEW_OVERLAY::SetStrokeColor( lightStrokeCol );
124
126 KIGFX::VIEW_OVERLAY::Arc( arc.GetCenter(), radius, start_angle, start_angle + angle );
127
129}
130
132{
133 m_labelMgr->Redraw( this );
134}
135
136
139{
140 LoadSettings();
142
144 m_galPanel->SetParent( m_mainSplitter );
145 m_mainSplitter->SplitHorizontally( m_galPanel.get(), m_panelProps );
146
147 Layout();
148
149 Show( true );
150 Maximize();
151 Raise();
152
153 auto settings = static_cast<KIGFX::PCB_RENDER_SETTINGS*>(
154 m_galPanel->GetView()->GetPainter()->GetSettings() );
155
156
158
160
161 double opacity = 0.5;
162
163 opts.m_TrackOpacity = opacity;
164 opts.m_ViaOpacity = opacity;
165 opts.m_PadOpacity = opacity;
166 opts.m_ZoneOpacity = opacity;
167
168 settings->LoadDisplayOptions( opts );
169
170
171 m_listPopupMenu = new wxMenu( wxT( "" ) );
172 m_listPopupMenu->Append( ID_LIST_COPY, wxT( "Copy selected geometry" ), wxT( "" ),
173 wxITEM_NORMAL );
174 m_listPopupMenu->Append( ID_LIST_SHOW_ALL, wxT( "Show all" ), wxT( "" ), wxITEM_NORMAL );
175 m_listPopupMenu->Append( ID_LIST_SHOW_NONE, wxT( "Show none" ), wxT( "" ), wxITEM_NORMAL );
176 m_listPopupMenu->Append( ID_LIST_DISPLAY_LINE, wxT( "Go to line in IDE" ), wxT( "" ), wxITEM_NORMAL );
177
178 m_itemList->Connect( m_itemList->GetId(), wxEVT_TREELIST_ITEM_CONTEXT_MENU,
179 wxMouseEventHandler( PNS_LOG_VIEWER_FRAME::onListRightClick ), nullptr,
180 this );
181 //m_itemList->Connect(m_itemList->GetId(),wxEVT_LISTBOX,wxCommandEventHandler(PNS_LOG_VIEWER_FRAME::onListSelect),nullptr,this);
182 m_itemList->Connect( m_itemList->GetId(), wxEVT_TREELIST_SELECTION_CHANGED,
183 wxCommandEventHandler( PNS_LOG_VIEWER_FRAME::onListSelect ),
184 nullptr, this );
185 m_itemList->Connect( m_itemList->GetId(), wxEVT_TREELIST_ITEM_CHECKED,
186 wxCommandEventHandler( PNS_LOG_VIEWER_FRAME::onListChecked ),
187 nullptr, this );
188
189 m_itemList->AppendColumn( "Type" );
190 m_itemList->AppendColumn( "Value" );
191 m_itemList->AppendColumn( "File" );
192 m_itemList->AppendColumn( "Method" );
193 m_itemList->AppendColumn( "Line" );
194 m_itemList->AppendColumn( "VCount" );
195 m_itemList->AppendColumn( "Non-45" );
196
197 m_overlay.reset( new PNS_LOG_VIEWER_OVERLAY ( m_galPanel->GetGAL() ) );
198 m_galPanel->GetView()->Add( m_overlay.get() );
199 m_galPanel->GetViewControls()->EnableCursorWarping(false);
200
201 for( PCB_LAYER_ID layer : LSET::AllNonCuMask().Seq() )
202 m_galPanel->GetView()->SetLayerVisible( layer, false );
203}
204
205
207{
208 m_board = nullptr;
209 m_logPlayer = nullptr;
210 m_logFile = nullptr;
211 m_overlay = nullptr;
212}
213
214
219
220
222{
223 PNS_TEST_DEBUG_DECORATOR* dbgd = m_logPlayer->GetDebugDecorator();
224 int count = dbgd->GetStageCount();
225
226 int iter = m_rewindIter;
227
228 if( count <= 0 )
229 return nullptr;
230
231 if( iter < 0 )
232 iter = 0;
233
234 if( iter >= count )
235 iter = count - 1;
236
237 return dbgd->GetStage( iter );
238}
239
240
241void PNS_LOG_VIEWER_FRAME::drawSimpleShape( SHAPE* aShape, bool aIsSelected, const std::string& aName )
242{
243 switch( aShape->Type() )
244 {
245 case SH_CIRCLE:
246 {
247 auto cir = static_cast<SHAPE_CIRCLE*>( aShape );
248 m_overlay->Circle( cir->GetCenter(), cir->GetRadius() );
249
250 break;
251 }
252 case SH_SEGMENT:
253 {
254 auto seg = static_cast<SHAPE_SEGMENT*>( aShape );
255 m_overlay->Line( seg->GetSeg().A, seg->GetSeg().B );
256
257 break;
258 }
259 case SH_RECT:
260 {
261 auto rect = static_cast<SHAPE_RECT*>( aShape );
262 m_overlay->Rectangle( rect->GetPosition(), rect->GetPosition() + rect->GetSize() );
263
264 break;
265 }
266 case SH_LINE_CHAIN:
267 {
268 auto lc = static_cast<SHAPE_LINE_CHAIN*>( aShape );
269 m_overlay->AnnotatedPolyline( *lc, aName, m_showVertices || aIsSelected );
270
271 break;
272 }
273 default: break;
274 }
275}
276
277
279{
280 if( !m_logPlayer )
281 return;
282
284
285 if( !st )
286 return;
287
288 m_overlay.reset( new PNS_LOG_VIEWER_OVERLAY ( m_galPanel->GetGAL() ) );
289 m_galPanel->GetView()->Add( m_overlay.get() );
290 //m_galPanel->GetGAL()->EnableDepthTest( false );
291
292 auto drawShapes = [&]( PNS_DEBUG_SHAPE* ent ) -> bool
293 {
294 bool isEnabled = ent->IsVisible();
295 bool isSelected = ent->m_selected;
296
297 if( m_searchString.Length() > 0 )
298 isEnabled = ent->m_filterMatch;
299
300 if( !isEnabled )
301 return true;
302
303 for( auto& sh : ent->m_shapes )
304 {
305 COLOR4D color = ent->m_color;
306 int lineWidth = ent->m_width;
307
308 m_overlay->SetIsStroke( true );
309 m_overlay->SetIsFill( false );
310
311 if( isSelected )
312 {
313 color.Brighten( 0.5 );
314 }
315
316 color.a = 1.0;
317
318 m_overlay->SetStrokeColor( color );
319 m_overlay->SetLineWidth( m_showThinLines ? 10000 : ent->m_width );
320
321 if( sh->Type() == SH_COMPOUND )
322 {
323 auto cmpnd = static_cast<SHAPE_COMPOUND*>( sh );
324
325 for( auto subshape : cmpnd->Shapes() )
326 {
327 drawSimpleShape( subshape, isSelected, ent->m_name.ToStdString() );
328 }
329 }
330 else
331 {
332 drawSimpleShape( sh, isSelected, ent->m_name.ToStdString() );
333 }
334 }
335
336 return true;
337 };
338
340
341 m_overlay->DrawAnnotations();
342
343 m_galPanel->GetView()->MarkDirty();
344 m_galPanel->GetParent()->Refresh();
345}
346
347
348void PNS_LOG_VIEWER_FRAME::LoadLogFile( const wxString& aFile )
349{
350 std::unique_ptr<PNS_LOG_FILE> logFile( new PNS_LOG_FILE );
351
352 wxFileName logFn( aFile );
353 logFn.MakeAbsolute();
354
355 if( logFile->Load( logFn, m_reporter.get() ) )
356 SetLogFile( logFile.release() );
357}
358
359
361{
362 m_viewerIface = std::make_shared<PNS_VIEWER_IFACE>( m_board );
363}
364
365
367{
368 m_logPlayer.reset( new PNS_LOG_PLAYER );
369 m_board = nullptr;
370 m_logFile.reset( aLog );
371
372 SetBoard( m_logFile->GetBoard() );
374 m_logPlayer->ReplayLog( m_logFile.get(), 0, 0, -1, true );
375
376 auto dbgd = m_logPlayer->GetDebugDecorator();
377 int n_stages = dbgd->GetStageCount();
378 m_rewindSlider->SetMax( n_stages - 1 );
379 m_rewindSlider->SetValue( n_stages - 1 );
380 m_rewindIter = n_stages - 1;
381
382 auto extents = m_board->GetBoundingBox();
383
384
385 BOX2D bbd;
386 bbd.SetOrigin( extents.GetOrigin() );
387 bbd.SetWidth( extents.GetWidth() );
388 bbd.SetHeight( extents.GetHeight() );
389 bbd.Inflate( std::min( bbd.GetWidth(), bbd.GetHeight() ) / 5 );
390
391 m_galPanel->GetView()->SetViewport( bbd );
392
396
397}
398
399
400void PNS_LOG_VIEWER_FRAME::SetBoard2( std::shared_ptr<BOARD> aBoard )
401{
402 SetBoard( aBoard );
404 auto extents = m_board->GetBoundingBox();
405
406 BOX2D bbd;
407 bbd.SetOrigin( extents.GetOrigin() );
408 bbd.SetWidth( extents.GetWidth() );
409 bbd.SetHeight( extents.GetHeight() );
410 bbd.Inflate( std::min( bbd.GetWidth(), bbd.GetHeight() ) / 5 );
411
412 m_galPanel->GetView()->SetViewport( bbd );
413}
414
415
416void PNS_LOG_VIEWER_FRAME::onOpen( wxCommandEvent& event )
417{
418 wxFileDialog dlg( this, "Select Log File", m_mruPath, wxEmptyString,
419 "PNS log files" + AddFileExtListToFilter( { "log" } ),
420 wxFD_OPEN | wxFD_FILE_MUST_EXIST );
421
423
424 if( dlg.ShowModal() != wxID_CANCEL )
425 {
426 wxString logPath = dlg.GetPath();
427 LoadLogFile( logPath );
428 m_mruPath = wxFileName( logPath ).GetPath();
429 }
430}
431
432
433void PNS_LOG_VIEWER_FRAME::onSaveAs( wxCommandEvent& event )
434{
435 if( !m_logFile )
436 {
437 DisplayErrorMessage( this, wxT( "No log file Loaded!" ) );
438 return;
439 }
440
441 wxFileDialog dlg( this, "New log file", m_mruPath, wxEmptyString,
442 "PNS log files" + AddFileExtListToFilter( { "log" } ),
443 wxFD_SAVE | wxFD_OVERWRITE_PROMPT );
444
446
447 if( dlg.ShowModal() != wxID_CANCEL )
448 {
449 // Enforce the extension, wxFileDialog is inept.
450 wxFileName create_me = EnsureFileExtension( dlg.GetPath(), "log" );
451
452 wxASSERT_MSG( create_me.IsAbsolute(), wxS( "wxFileDialog returned non-absolute path" ) );
453
454 m_logFile->SaveLog( create_me, m_reporter.get() );
455 m_mruPath = create_me.GetPath();
456 }
457
458}
459
460
461void PNS_LOG_VIEWER_FRAME::onExit( wxCommandEvent& event )
462{
463 Close();
464}
465
466
467void PNS_LOG_VIEWER_FRAME::onListChecked( wxCommandEvent& event )
468{
469 syncModel();
471}
472
474{
475 m_showThinLines = event.GetInt();
478}
479
480void PNS_LOG_VIEWER_FRAME::onShowRPIsChecked( wxCommandEvent& event )
481{
482 m_showRPIs = event.GetInt();
485}
486
488{
489 m_showVertices = event.GetInt();
492}
493
494
495void PNS_LOG_VIEWER_FRAME::onRewindScroll( wxScrollEvent& event )
496{
497 m_rewindIter = event.GetPosition();
501 m_rewindPos->SetValue( std::to_string( m_rewindIter ) );
502 event.Skip();
503}
504
505
506void PNS_LOG_VIEWER_FRAME::onBtnRewindLeft( wxCommandEvent& event )
507{
508 if( m_rewindIter > 0 )
509 {
510 m_rewindIter--;
514 m_rewindPos->SetValue( std::to_string( m_rewindIter ) );
515 m_rewindSlider->SetValue( m_rewindIter );
516 }
517}
518
519
520void PNS_LOG_VIEWER_FRAME::onBtnRewindRight( wxCommandEvent& event )
521{
522 auto dbgd = m_logPlayer->GetDebugDecorator();
523 int count = dbgd->GetStageCount();
524
525 if( m_rewindIter < count )
526 {
527 m_rewindIter++;
531 m_rewindPos->SetValue( std::to_string( m_rewindIter ) );
532 m_rewindSlider->SetValue( m_rewindIter );
533 }
534}
535
536void PNS_LOG_VIEWER_FRAME::onFilterText( wxCommandEvent& event )
537{
538 m_searchString = m_filterString->GetValue();
540}
541
542
543void PNS_LOG_VIEWER_FRAME::onRewindCountText( wxCommandEvent& event )
544{
545 if( !m_logPlayer )
546 return;
547
548 int val = wxAtoi( m_rewindPos->GetValue() );
549
550 auto dbgd = m_logPlayer->GetDebugDecorator();
551 int count = dbgd->GetStageCount();
552
553 if( val < 0 )
554 val = 0;
555
556 if( val >= count )
557 val = count - 1;
558
559 m_rewindIter = val;
560 m_rewindSlider->SetValue( m_rewindIter );
564
565 event.Skip();
566}
567
568
570{
571 for( wxTreeListItem item = m_itemList->GetFirstItem(); item.IsOk();
572 item = m_itemList->GetNextItem( item ) )
573 {
575 static_cast<WX_SHAPE_TREE_ITEM_DATA*>( m_itemList->GetItemData( item ) );
576
577 if( idata )
578 {
579 bool checked = m_itemList->GetCheckedState( item ) == wxCHK_CHECKED;
580 bool selected = m_itemList->IsSelected( item );
581 idata->m_item->m_visible = checked || selected;
582 idata->m_item->m_selected = selected;
583 }
584 }
585}
586
587
588void runCommand( const wxString& aCommand )
589{
590#ifdef __WXMSW__
591 wxShell( aCommand ); // on windows we need to launch a shell in order to run the command
592#else
593 wxExecute( aCommand );
594#endif /* __WXMSW__ */
595}
596
597
598void PNS_LOG_VIEWER_FRAME::onListRightClick( wxMouseEvent& event )
599{
600 auto sel = m_itemList->GetPopupMenuSelectionFromUser( *m_listPopupMenu );
601
602 switch( sel )
603 {
605 m_itemList->CheckItemRecursively( m_itemList->GetRootItem(), wxCHK_UNCHECKED );
606 syncModel();
608 break;
609 case ID_LIST_SHOW_ALL:
610 m_itemList->CheckItemRecursively( m_itemList->GetRootItem(), wxCHK_CHECKED );
611 syncModel();
613 break;
614 case ID_LIST_COPY:
615 {
616 wxString s;
617
619
620 if( !st )
621 return;
622
623 auto formatShapes = [&]( PNS_DEBUG_SHAPE* ent ) -> bool
624 {
625 if( ent->m_selected )
626 {
627 for( auto sh : ent->m_shapes )
628 {
629 s += "// " + ent->m_name + "\n " + sh->Format() + "; \n";
630 }
631 }
632
633 return true;
634 };
635
636 st->m_entries->IterateTree( formatShapes );
637
638 if( wxTheClipboard->Open() )
639 {
640 // This data objects are held by the clipboard,
641 // so do not delete them in the app.
642 wxTheClipboard->SetData( new wxTextDataObject( s ) );
643 wxTheClipboard->Flush(); // Allow data to be available after closing KiCad
644 wxTheClipboard->Close();
645 }
646
647 return;
648 }
650 {
651 wxVector<wxTreeListItem> selectedItems;
652
653 if( m_itemList->GetSelections( selectedItems ) == 1 )
654 {
655 wxString filename = m_itemList->GetItemText(selectedItems.back(), 2);
656 wxString line = m_itemList->GetItemText(selectedItems.back(), 4);
657
658
659 if( !filename.empty() && !line.empty() )
660 {
661 wxString filepath = m_filenameToPathMap[filename];
662
663 switch( m_ideChoice->GetCurrentSelection() )
664 {
665 case 0: runCommand( wxString::Format( "code --goto %s:%s", filepath, line ) ); return;
666 case 1: runCommand( wxString::Format( "start devenv /edit %s /command \"Gotoln %s\"", filepath, line ) ); return; // fixme
667 case 2: runCommand( wxString::Format( "clion --line %s %s", line, filepath ) ); return;
668 case 3: runCommand( wxString::Format( "emacsclient +%s %s", line, filepath ) ); return;
669 default: return;
670 }
671 }
672 }
673 break;
674 }
675 }
676 return;
677}
678
679
680void PNS_LOG_VIEWER_FRAME::onListSelect( wxCommandEvent& event )
681{
682 syncModel();
684}
685
686
687
688static bool isLine45Degree( const SHAPE_LINE_CHAIN* lc )
689{
690 for( int i = 0; i < lc->SegmentCount(); i++ )
691 {
692 const SEG& s = lc->CSegment( i );
693
694 if( lc->IsArcSegment( i ) )
695 continue;
696
697 if( s.Length() < 10 )
698 continue;
699
700 double angle = 180.0 / M_PI *
701 atan2( (double) s.B.y - (double) s.A.y,
702 (double) s.B.x - (double) s.A.x );
703
704 if( angle < 0 )
705 angle += 360.0;
706
707 double angle_a = fabs( fmod( angle, 45.0 ) );
708
709 if( angle_a > 1.0 && angle_a < 44.0 )
710 return false;
711 }
712
713 return true;
714}
715
716
718{
719
720 std::set<PNS_DEBUG_SHAPE*> processed;
721 std::deque<PNS_DEBUG_SHAPE*> q;
722
723 q.push_back(ent);
724 int total = 0;
725 while ( q.size() > 0 )
726 {
727 PNS_DEBUG_SHAPE* top = q.front();
728
729 q.pop_front();
730
731 for ( auto chld : top->m_children )
732 {
733 bool match = m_searchString.Length() == 0 ? true : false;
734 //printf("CHK %s\n", (const char *) chld->m_name.c_str() );
735 chld->m_filterMatch = false;
736 if ( chld->m_name.Contains( m_searchString ) )
737 match = true;
738 if ( chld->m_msg.Contains( m_searchString ) )
739 match = true;
740
741 if( match )
742 {
743 for ( PNS_DEBUG_SHAPE *cur = chld; cur; cur = cur->m_parent )
744 cur->m_filterMatch = match;
745 }
746
747 if( processed.find(chld) == processed.end() )
748 {
749 q.push_back( chld );
750 processed.insert( chld );
751 }
752 }
753 total++;
754 }
755
756 printf("total: %d\n", total );
757
758 return false;
759}
760
761
762void PNS_LOG_VIEWER_FRAME::buildListTree( wxTreeListItem item,
763 PNS_DEBUG_SHAPE* ent, int depth )
764{
765#ifdef EXTRA_VERBOSE
766 for( int i = 0; i < depth * 2; i++ )
767 printf( " " );
768
769 if( ent->m_msg.length() )
770 printf( "MSG: %s\n", ent->m_msg.c_str() );
771 else
772 printf( "SHAPES: %s [%d]\n", ent->m_name.c_str(), ent->m_children.size() );
773#endif
774
775 wxTreeListItem ritem;
776
777 if( !ent->m_filterMatch )
778 return;
779
780 if( ent->m_msg.length() )
781 {
782 ritem = m_itemList->AppendItem( item, "Child" );
783 m_itemList->SetItemText( ritem, 0, "Message" );
784 m_itemList->SetItemText( ritem, 1, ent->m_msg );
785 }
786 else
787 {
788 ritem = m_itemList->AppendItem( item, "Child" );
789 int n_verts = 0;
790 for(auto sh : ent->m_shapes )
791 {
792 if ( sh->Type() == SH_LINE_CHAIN )
793 {
794 n_verts += static_cast<const SHAPE_LINE_CHAIN*>( sh )->PointCount();
795 }
796 }
797 m_itemList->SetItemText( ritem, 0, wxString::Format( "Shapes [%d verts]", n_verts ) );
798 m_itemList->SetItemText( ritem, 1, ent->m_name );
799 }
800
801 wxString fullfilepath = ent->m_srcLoc.fileName;
802 wxString filename = wxFileNameFromPath( fullfilepath );
803
804 if( !filename.empty() )
805 m_filenameToPathMap.insert( { filename, fullfilepath } );
806
807 m_itemList->SetItemText( ritem, 2, filename );
808 m_itemList->SetItemText( ritem, 3, ent->m_srcLoc.funcName );
809 m_itemList->SetItemText( ritem, 4, wxString::Format("%d", ent->m_srcLoc.line ) );
810
811 int totalVC = 0, totalVCSimplified = 0;
812 bool is45Degree = true;
813
814 for( SHAPE* sh : ent->m_shapes )
815 {
816 if( sh->Type() == SH_LINE_CHAIN )
817 {
818 auto lc = static_cast<SHAPE_LINE_CHAIN*>( sh );
819
820 totalVC += lc->PointCount();
821
822 SHAPE_LINE_CHAIN simp(*lc);
823
824 simp.Simplify();
825
826 totalVCSimplified += simp.PointCount();
827
828 if( !isLine45Degree( lc ) )
829 is45Degree = false;
830 }
831 }
832
833 if( totalVC > 0 )
834 m_itemList->SetItemText( ritem, 5, wxString::Format( "%d [%d]", totalVC, totalVCSimplified ) );
835
836 if( !is45Degree )
837 m_itemList->SetItemText( ritem, 6, wxT("") );
838
839 m_itemList->SetItemData( ritem, new WX_SHAPE_TREE_ITEM_DATA( ent, depth ) );
840
841 if( !ent->m_children.size() )
842 return;
843
844 for( auto child : ent->m_children )
845 {
846 buildListTree( ritem, child, depth + 1 );
847 }
848}
849
850
851static void expandAllChildren( wxTreeListCtrl* tree, int maxLevel = -1 )
852{
853 wxTreeListItem child = tree->GetFirstItem ();
854
855 while( child.IsOk() )
856 {
858 static_cast<WX_SHAPE_TREE_ITEM_DATA*>( tree->GetItemData( child ) );
859
860 if( maxLevel < 0 || idata->m_level <= maxLevel )
861 tree->Expand ( child );
862 else
863 tree->Collapse ( child );
864 child = tree->GetNextItem( child );
865 }
866}
867
868static void collapseAllChildren( wxTreeListCtrl* tree )
869{
870 wxTreeListItem child = tree->GetFirstItem ();
871
872 while( child.IsOk() )
873 {
874 tree->Collapse ( child );
875 child = tree->GetNextItem( child );
876 }
877}
878
879
881{
882 printf("UpdateDUmp %d\n", iter );
883 if( !m_logPlayer )
884 return;
885
886 auto dbgd = m_logPlayer->GetDebugDecorator();
887 int count = dbgd->GetStageCount();
888
889 wxArrayString dumpStrings;
890
891 if( count <= 0 )
892 return;
893
894 if( iter < 0 )
895 iter = 0;
896
897 if( iter >= count )
898 iter = count - 1;
899
900 auto st = dbgd->GetStage( iter );
901
902 if( st->m_status )
903 {
904 m_algoStatus->SetLabel("OK");
905 m_algoStatus->SetForegroundColour( wxColor(*wxGREEN));
906 }
907 else
908 {
909 m_algoStatus->SetLabel("FAIL");
910 m_algoStatus->SetForegroundColour( wxColor(*wxRED));
911 }
912
913 auto rootItem = m_itemList->GetRootItem();
914
915 m_itemList->DeleteAllItems();
916 filterStringMatches( st->m_entries );
917 buildListTree( rootItem, st->m_entries );
918 m_itemList->CheckItemRecursively( rootItem, wxCHK_UNCHECKED );
919
921
922 m_itemList->Refresh();
923}
924
926{
927 auto viewTracker = m_logPlayer->GetViewTracker();
928 PNS_LOG_VIEW_TRACKER::VIEW_ENTRIES& entries = viewTracker->GetEntriesForStage( iter );
929 auto view = m_galPanel->GetView();
930 printf("DBG updatePnsPreviewItems: %zu items\n", entries.size() );
931
932 m_previewItems.reset( new KIGFX::VIEW_GROUP( m_galPanel->GetView() ) );
933 m_galPanel->GetView()->Add( m_previewItems.get() );
935 m_galPanel->GetView()->SetLayerVisible( LAYER_SELECT_OVERLAY );
936
937 if( !m_showRPIs )
938 return;
939
940 for( auto& ent : entries )
941 {
942 if ( ent.m_isHideOp )
943 {
944
945 auto parent = ent.m_item->Parent();
946 if( parent )
947 {
948
949 view->Hide( parent );
950 }
951 }
952 else
953 {
954 ROUTER_PREVIEW_ITEM* pitem = new ROUTER_PREVIEW_ITEM( ent.m_item, m_viewerIface.get(), view );
955 pitem->Update( ent.m_item );
956 m_previewItems->Add(pitem);
957 // printf("DBG vadd %p total %d\n", pitem, m_previewItems->GetSize() );
958 }
959 }
960
961 view->SetVisible( m_previewItems.get(), true );
962
963 view->Update( m_previewItems.get() );
964 printf("DBG vgrp %p total %d\n", m_previewItems.get(), m_previewItems->GetSize() );
965
966
967 //view->UpdateAllItems( KIGFX::ALL );
968}
969
974
975
976#if 0
977
978static BOARD* loadBoard( const std::string& filename )
979{
981 BOARD* brd = nullptr;
982
983 try
984 {
985 brd = pi->LoadBoard( wxString( filename.c_str() ), nullptr, nullptr );
986 }
987 catch( const IO_ERROR& )
988 {
989 return nullptr;
990 }
991
992 return brd;
993}
994
995
996
997
998
999int render_perftest_main_func( int argc, char* argv[] )
1000{
1001 auto frame = new PNS_LOG_VIEWER_FRAME( nullptr );
1002
1003 // drcCreateTestsProviderClearance();
1004 // drcCreateTestsProviderEdgeClearance();
1005
1006 if( argc >= 2 && std::string( argv[1] ) == "-h" )
1007 {
1008 printf( "PCB render performance test. Just renders a board without UI update overhead.\n" );
1009 return 0;
1010 }
1011
1012 if( argc < 2 )
1013 {
1014 printf( "Expected parameters: board_file\n" );
1015 return 0;
1016 }
1017
1018 PROF_TIMER cnt("load-board");
1019 std::shared_ptr<BOARD> brd ( loadBoard( argv[1] ) );
1020 cnt.Stop();
1021
1022 KI_TRACE( traceGalProfile, "%s\n", cnt.to_string() );
1023
1024 frame->SetBoard2( brd );
1025
1026 return 0;
1027}
1028
1029
1030static bool registered3 = UTILITY_REGISTRY::Register( {
1031 "render_perftest",
1032 "Renderer performance test",
1033 render_perftest_main_func,
1034} );
1035
1036
1037VECTOR2I NearestPointFixpt( SEG seg, const VECTOR2I& aP )
1038{
1039 VECTOR2I d = seg.B - seg.A;
1040 SEG::ecoord l_squared = d.Dot( d );
1041
1042 if( l_squared == 0 )
1043 return seg.A;
1044
1045 SEG::ecoord t = d.Dot( aP - seg.A );
1046
1047 if( t < 0 )
1048 return seg.A;
1049 else if( t > l_squared )
1050 return seg.B;
1051
1052 int xp = rescale( t, (SEG::ecoord) d.x, l_squared );
1053 int yp = rescale( t, (SEG::ecoord) d.y, l_squared );
1054
1055 return seg.A + VECTOR2I( xp, yp );
1056}
1057
1058
1059VECTOR2D NearestPointDbl( SEG seg, const VECTOR2I& aP )
1060{
1061 VECTOR2D d = seg.B - seg.A;
1062 double l_squared = d.Dot(d);
1063
1064 if( l_squared == 0 )
1065 return seg.A;
1066
1067 double t = d.Dot(VECTOR2D( aP - seg.A ) );
1068
1069 if( t < 0 )
1070 return seg.A;
1071 else if( t > l_squared )
1072 return seg.B;
1073
1074 double xp = t * d.x / l_squared;
1075 double yp = t * d.y / l_squared;
1076
1077 return VECTOR2D(seg.A) + VECTOR2D( xp, yp );
1078}
1079
1080int ttt_main_func( int argc, char* argv[] )
1081{
1082 int n = 1000000;
1083 std::vector<VECTOR2I> pts;
1084 std::vector<SEG> segs;
1085 std::vector<VECTOR2D> rv;
1086 std::vector<VECTOR2I> rvi;
1087
1088
1089 rv.resize(n);
1090 rvi.resize(n);
1091
1092 for (int i = 0; i < n ;i++)
1093 {
1094 pts.push_back(VECTOR2I(random()%100000000, random()%100000000));
1095 segs.push_back(SEG( VECTOR2I(random()%100000000, random()%100000000), VECTOR2I(random()%100000000, random()%100000000) ) );
1096 }
1097
1098 PROF_TIMER tmrFix("nearest-fixpt");
1099 for(int i = 0; i < n ; i++)
1100 {
1101 rvi[i] = NearestPointFixpt( segs[i], pts[i]);
1102 }
1103 tmrFix.Show();
1104
1105 PROF_TIMER tmrDbl("nearest-double");
1106 for(int i = 0; i < n ; i++)
1107 {
1108 rv[i] = NearestPointDbl( segs[i], pts[i]);
1109 }
1110 tmrDbl.Show();
1111 return 0;
1112}
1113
1114
1115
1116static bool registered4 = UTILITY_REGISTRY::Register( {
1117 "ttt",
1118 "Renderer performance test",
1119 ttt_main_func,
1120} );
1121
1122#endif
const char * name
BOX2< VECTOR2D > BOX2D
Definition box2.h:923
Information pertinent to a Pcbnew printed circuit board.
Definition board.h:322
constexpr BOX2< Vec > & Inflate(coord_type dx, coord_type dy)
Inflates the rectangle horizontally by dx and vertically by dy.
Definition box2.h:558
constexpr void SetHeight(size_type val)
Definition box2.h:292
constexpr void SetOrigin(const Vec &pos)
Definition box2.h:237
constexpr size_type GetWidth() const
Definition box2.h:214
constexpr size_type GetHeight() const
Definition box2.h:215
constexpr void SetWidth(size_type val)
Definition box2.h:287
@ GAL_TYPE_OPENGL
OpenGL implementation.
Hold an error message and may be used when throwing exceptions containing meaningful error messages.
A color representation with 4 components: red, green, blue, alpha.
Definition color4d.h:105
COLOR4D WithAlpha(double aAlpha) const
Return a color with the same color, but the given alpha.
Definition color4d.h:312
COLOR4D & Brighten(double aFactor)
Makes the color brighter by a given factor.
Definition color4d.h:210
double a
Alpha component.
Definition color4d.h:396
Abstract interface for drawing on a 2D-surface.
PCB specific render settings.
Definition pcb_painter.h:82
Extend VIEW_ITEM by possibility of grouping items into a single object.
Definition view_group.h:43
void SetLineWidth(double aLineWidth)
void Polyline(const SHAPE_LINE_CHAIN &aPolyLine)
const COLOR4D & GetStrokeColor() const
void Line(const VECTOR2D &aStartPoint, const VECTOR2D &aEndPoint)
void Arc(const VECTOR2D &aCenterPoint, double aRadius, const EDA_ANGLE &aStartAngle, const EDA_ANGLE &aEndAngle)
void SetStrokeColor(const COLOR4D &aColor)
static LSET AllNonCuMask()
Return a mask holding all layer minus CU layers.
Definition lset.cpp:627
double m_TrackOpacity
Opacity override for all tracks.
double m_ZoneOpacity
Opacity override for filled zone areas.
double m_PadOpacity
Opacity override for SMD pads and PTHs.
double m_ViaOpacity
Opacity override for all types of via.
ZONE_DISPLAY_MODE m_ZoneDisplayMode
A #PLUGIN derivation for saving and loading Pcbnew s-expression formatted files.
std::shared_ptr< BOARD > m_board
std::shared_ptr< PCB_DRAW_PANEL_GAL > m_galPanel
void createView(wxWindow *aParent, PCB_DRAW_PANEL_GAL::GAL_TYPE aGalType=PCB_DRAW_PANEL_GAL::GAL_TYPE_OPENGL)
virtual void SetBoard(std::shared_ptr< BOARD > b)
std::vector< SHAPE * > m_shapes
void IterateTree(std::function< bool(PNS_DEBUG_SHAPE *)> visitor, int depth=0)
PNS_DEBUG_SHAPE * m_parent
PNS::DEBUG_DECORATOR::SRC_LOCATION_INFO m_srcLoc
std::vector< PNS_DEBUG_SHAPE * > m_children
PNS_LOG_VIEWER_FRAME_BASE(wxWindow *parent, wxWindowID id=wxID_ANY, const wxString &title=wxT("P&S Log Viewer"), const wxPoint &pos=wxDefaultPosition, const wxSize &size=wxSize(1045, 574), long style=wxDEFAULT_FRAME_STYLE|wxTAB_TRAVERSAL)
std::shared_ptr< WX_TEXT_CTRL_REPORTER > m_reporter
std::shared_ptr< PNS_LOG_FILE > m_logFile
virtual void onListRightClick(wxMouseEvent &event)
std::shared_ptr< PNS_LOG_PLAYER > m_logPlayer
std::map< wxString, wxString > m_filenameToPathMap
void drawSimpleShape(SHAPE *aShape, bool aIsSelected, const std::string &aName)
virtual void onRewindCountText(wxCommandEvent &event) override
std::shared_ptr< KIGFX::VIEW_GROUP > m_previewItems
PNS_DEBUG_STAGE * getCurrentStage()
bool filterStringMatches(PNS_DEBUG_SHAPE *ent)
void SetBoard2(std::shared_ptr< BOARD > aBoard)
virtual void createUserTools() override
void buildListTree(wxTreeListItem item, PNS_DEBUG_SHAPE *ent, int depth=0)
virtual void onShowVerticesChecked(wxCommandEvent &event) override
void SetLogFile(PNS_LOG_FILE *aLog)
virtual void onShowThinLinesChecked(wxCommandEvent &event) override
std::shared_ptr< PNS_LOG_VIEWER_OVERLAY > m_overlay
void LoadLogFile(const wxString &aFile)
virtual void onListChecked(wxCommandEvent &event)
std::shared_ptr< PNS_VIEWER_IFACE > m_viewerIface
virtual void onListSelect(wxCommandEvent &event)
virtual void onSaveAs(wxCommandEvent &event) override
virtual void onRewindScroll(wxScrollEvent &event) override
virtual void onShowRPIsChecked(wxCommandEvent &event) override
virtual void onBtnRewindRight(wxCommandEvent &event) override
virtual void onFilterText(wxCommandEvent &event) override
PNS_LOG_VIEWER_FRAME(wxFrame *frame)
virtual void onOpen(wxCommandEvent &event) override
virtual void onBtnRewindLeft(wxCommandEvent &event) override
virtual void onExit(wxCommandEvent &event) override
void AnnotatedPoint(const VECTOR2I p, int size, std::string name="", bool aShowVertexNumbers=false)
void AnnotatedPolyset(const SHAPE_POLY_SET &aL, std::string name="", bool aShowVertexNumbers=false)
void AnnotatedPolyline(const SHAPE_LINE_CHAIN &aL, std::string name, bool aShowVertexNumbers=false)
PNS_LOG_VIEWER_OVERLAY(KIGFX::GAL *aGal)
std::unique_ptr< LABEL_MANAGER > m_labelMgr
void Arc(const SHAPE_ARC &arc)
std::vector< ENTRY > VIEW_ENTRIES
PNS_DEBUG_STAGE * GetStage(int index)
A small class to help profiling.
Definition profile.h:49
A pure virtual class used to derive REPORTER objects from.
Definition reporter.h:73
void Update(const PNS::ITEM *aItem)
Definition seg.h:42
VECTOR2I A
Definition seg.h:49
VECTOR2I::extended_type ecoord
Definition seg.h:44
VECTOR2I B
Definition seg.h:50
int Length() const
Return the length (this).
Definition seg.h:343
EDA_ANGLE GetCentralAngle() const
Get the "central angle" of the arc - this is the angle at the point of the "pie slice".
int GetWidth() const override
Definition shape_arc.h:215
double GetRadius() const
EDA_ANGLE GetStartAngle() const
const VECTOR2I & GetCenter() const
SHAPE_TYPE Type() const
Return the type of the shape.
Definition shape.h:98
Represent a polyline containing arcs as well as line segments: A chain of connected line and/or arc s...
int PointCount() const
Return the number of points (vertices) in this line chain.
void Simplify(int aTolerance=0)
Simplify the line chain by removing colinear adjacent segments and duplicate vertices.
const VECTOR2I & CPoint(int aIndex) const
Return a reference to a given point in the line chain.
int SegmentCount() const
Return the number of segments in this line chain.
const VECTOR2I & CLastPoint() const
Return the last point in the line chain.
const SEG CSegment(int aIndex) const
Return a constant copy of the aIndex segment in the line chain.
bool IsArcSegment(size_t aSegment) const
Represent a set of closed polygons.
int HoleCount(int aOutline) const
Returns the number of holes in a given outline.
const SHAPE_LINE_CHAIN & CHole(int aOutline, int aHole) const
int OutlineCount() const
Return the number of outlines in the set.
const SHAPE_LINE_CHAIN & COutline(int aIndex) const
An abstract shape on 2D plane.
Definition shape.h:126
static bool Register(const KI_TEST::UTILITY_PROGRAM &aProgInfo)
Register a utility program factory function against an ID string.
constexpr extended_type Dot(const VECTOR2< T > &aVector) const
Compute dot product of self with aVector.
Definition vector2d.h:554
WX_SHAPE_TREE_ITEM_DATA(PNS_DEBUG_SHAPE *item, int level=0)
A wrapper for reporting to a wxTextCtrl object.
Definition reporter.h:167
wxString EnsureFileExtension(const wxString &aFilename, const wxString &aExtension)
It's annoying to throw up nag dialogs when the extension isn't right.
Definition common.cpp:629
The common library.
void DisplayErrorMessage(wxWindow *aParent, const wxString &aText, const wxString &aExtraInfo)
Display an error message with aMessage.
Definition confirm.cpp:202
This file is part of the common library.
const wxChar *const traceGalProfile
Flag to enable debug output of GAL performance profiling.
std::unique_ptr< T > IO_RELEASER
Helper to hold and release an IO_BASE object when exceptions are thrown.
Definition io_mgr.h:33
@ LAYER_SELECT_OVERLAY
Selected items overlay.
Definition layer_ids.h:280
PCB_LAYER_ID
A quick note on layer IDs:
Definition layer_ids.h:60
void AllowNetworkFileSystems(wxDialog *aDialog)
Configure a file dialog to show network and virtual file systems.
Definition wxgtk/ui.cpp:435
see class PGM_BASE
int drawShapes(int argc, char *argv[])
static bool isLine45Degree(const SHAPE_LINE_CHAIN *lc)
static void collapseAllChildren(wxTreeListCtrl *tree)
static void expandAllChildren(wxTreeListCtrl *tree, int maxLevel=-1)
void runCommand(const wxString &aCommand)
#define ID_LIST_COPY
#define ID_LIST_DISPLAY_LINE
#define ID_LIST_SHOW_ALL
#define ID_LIST_SHOW_NONE
@ SH_RECT
axis-aligned rectangle
Definition shape.h:47
@ SH_CIRCLE
circle
Definition shape.h:50
@ SH_SEGMENT
line segment
Definition shape.h:48
@ SH_LINE_CHAIN
line chain (polyline)
Definition shape.h:49
@ SH_COMPOUND
compound shape, consisting of multiple simple shapes
Definition shape.h:53
PNS_DEBUG_SHAPE * m_entries
KIBIS top(path, &reporter)
int radius
#define M_PI
wxLogTrace helper definitions.
#define KI_TRACE(aWhat,...)
T rescale(T aNumerator, T aValue, T aDenominator)
Scale a number (value) by rational (numerator/denominator).
Definition util.h:139
VECTOR2< int32_t > VECTOR2I
Definition vector2d.h:695
VECTOR2< double > VECTOR2D
Definition vector2d.h:694
wxString AddFileExtListToFilter(const std::vector< std::string > &aExts)
Build the wildcard extension file dialog wildcard filter to add to the base message dialog.
Definition of file extensions used in Kicad.