24#include <wx/filename.h>
26#include <wx/stdstream.h>
27#include <wx/wfstream.h>
48 std::vector<BOARD_CONNECTED_ITEM*> parents;
50 parents.resize( evt.
uuids.size() );
54 for(
int i = 0; i < evt.
uuids.size(); i++ )
56 if( item->m_Uuid == evt.
uuids[i] )
70 if ( parents.size() > 0 )
80 fgets( str,
sizeof( str ) - 1, f );
81 return wxString( str );
86 m_mode(
PNS::ROUTER_MODE::PNS_MODE_ROUTE_SINGLE )
94 const wxString type =
static_cast<wxString
>( aJSON.at(
"type" ).get<wxString>() );
96 if( type == wxT(
"segment") )
99 sh->SetSeg(
SEG( aJSON.at(
"start" ).get<
VECTOR2I>(), aJSON.at(
"end" ).get<
VECTOR2I>() ) );
100 sh->SetWidth( aJSON.at(
"width" ).get<
int>() );
103 else if( type == wxT(
"circle") )
106 sh->SetCenter( aJSON.at(
"center" ).get<
VECTOR2I>() );
107 sh->SetRadius( aJSON.at(
"radius" ).get<
int>() );
110 else if( type == wxT(
"arc") )
115 int width = aJSON.at(
"width" ).get<
int>();
117 std::shared_ptr<SHAPE_ARC> sh(
new SHAPE_ARC( start, mid,
end, width ) );
120 else if( type == wxT(
"line_chain") )
123 for(
const nlohmann::json& p : aJSON.at(
"points" ) )
124 sh->Append( p.get<
VECTOR2I>(),
true );
141 a.
x = wxAtoi( aTokens.GetNextToken() );
142 a.
y = wxAtoi( aTokens.GetNextToken() );
143 b.
x = wxAtoi( aTokens.GetNextToken() );
144 b.
y = wxAtoi( aTokens.GetNextToken() );
145 int width = wxAtoi( aTokens.GetNextToken() );
146 sh->SetSeg(
SEG( a, b ));
147 sh->SetWidth( width );
154 a.
x = wxAtoi( aTokens.GetNextToken() );
155 a.
y = wxAtoi( aTokens.GetNextToken() );
156 int radius = wxAtoi( aTokens.GetNextToken() );
166 wxStringTokenizer& aTokens )
168 if( cmd == wxS(
"net" ) )
170 aItem->
SetNet(
m_board->FindNet( wxAtoi( aTokens.GetNextToken() ) ) );
173 else if( cmd == wxS(
"layers" ) )
175 int start = wxAtoi( aTokens.GetNextToken() );
176 int end = wxAtoi( aTokens.GetNextToken() );
186 aItem->
SetNet(
m_board->FindNet( aJSON.at(
"net" ).get<wxString>() ) );
188 PNS_LAYER_RANGE( aJSON.at(
"layers" ).at( 0 ).get<
int>(), aJSON.at(
"layers" ).at( 1 ).get<
int>() ) );
195 std::unique_ptr<PNS::SEGMENT> seg(
new PNS::SEGMENT() );
197 while( aTokens.CountTokens() )
199 wxString cmd = aTokens.GetNextToken();
203 if( cmd == wxS(
"shape" ) )
223 while( aTokens.CountTokens() )
225 wxString cmd = aTokens.GetNextToken();
229 if( cmd == wxS(
"shape" ) )
241 else if( cmd == wxS(
"drill" ) )
243 via->SetDrill( wxAtoi( aTokens.GetNextToken() ) );
253 wxString kind = aJSON.at(
"kind").get<wxString>();
255 if( kind == wxT(
"segment") )
257 auto parsedShape =
parseShape( aJSON.at(
"shape") );
262 auto shape =
static_cast<const SHAPE_SEGMENT*
>( parsedShape.get() );
263 std::unique_ptr<PNS::SEGMENT> seg(
new PNS::SEGMENT( *shape,
nullptr ) );
265 return std::move( seg );
267 else if ( kind == wxT(
"arc" ) )
269 auto parsedShape =
parseShape( aJSON.at(
"shape") );
274 auto shape =
static_cast<const SHAPE_ARC*
>( parsedShape.get() );
275 std::unique_ptr<PNS::ARC> arc(
new PNS::ARC( *shape,
nullptr ) );
277 return std::move( arc );
279 else if ( kind == wxT(
"via" ) )
281 auto parsedShape =
parseShape( aJSON.at(
"shape") );
286 auto shape =
static_cast<const SHAPE_CIRCLE*
>( parsedShape.get() );
289 via->SetPos( shape->Centre() );
290 via->SetDiameter(
via->Layers().Start(), shape->GetRadius() * 2 );
291 via->SetDrill( aJSON.at(
"drill").get<
int>() );
292 return std::move(
via);
294 else if ( kind == wxT(
"hole" ) )
296 auto parsedShape =
parseShape( aJSON.at(
"shape") );
303 auto shape =
static_cast<const SHAPE_CIRCLE*
>( parsedShape.get() );
304 std::unique_ptr<PNS::HOLE> hole(
new PNS::HOLE( parsedShape->Clone() ) );
306 hole->SetCenter( shape->GetCenter() );
307 hole->SetRadius( shape->GetRadius() );
308 return std::move( hole );
311 else if( kind == wxT(
"line") )
313 auto parsedShape =
parseShape( aJSON.at(
"shape") );
319 std::unique_ptr<PNS::LINE> line(
new PNS::LINE() );
320 line->SetShape( *shape );
321 line->SetWidth( aJSON.at(
"width").get<
int>() );
325 return std::move( line );
333 wxString type = aTokens.GetNextToken();
335 if( type == wxS(
"segment" ) )
337 else if( type == wxS(
"via" ) )
369 if( va->
Pos() != vb->
Pos() )
378 if( sa->
Seg() != sb->
Seg() )
409const std::set<PNS::ITEM*>
deduplicate(
const std::vector<PNS::ITEM*>& items )
411 std::set<PNS::ITEM*> rv;
415 bool isDuplicate =
false;
452 bool matched =
false;
458 chkAddedItems.erase( chk );
473 for(
int headIdx = 0; headIdx <
m_heads.size(); headIdx ++)
482 if( chkAddedItems.empty() && check.
m_removedIds.empty() )
503 wxFFileOutputStream fp( logFileName.GetFullPath(), wxT(
"wt" ) );
509 aRpt->
Report( wxString::Format( wxT(
"Failed to write log file: %s"), logFileName.GetFullPath() ),
RPT_SEVERITY_ERROR );
514 wxScopedCharBuffer utf8 = logString.ToUTF8();
515 fp.Write( utf8.data(), utf8.length() );
524 wxFileName fname_log( logFileName );
525 fname_log.SetExt( wxT(
"log" ) );
527 wxFileName fname_dump( logFileName );
528 fname_dump.SetExt( wxT(
"dump" ) );
530 if( !boardFileName.IsEmpty() )
532 fname_dump = boardFileName;
535 if( !fname_dump.IsFileReadable() )
541 wxFileName fname_project( logFileName );
542 fname_project.SetExt( wxT(
"kicad_pro" ) );
543 fname_project.MakeAbsolute();
545 wxFileName fname_settings( logFileName );
546 fname_settings.SetExt( wxT(
"settings" ) );
548 aRpt->
Report( wxString::Format( wxT(
"Loading router settings from '%s'" ),
549 fname_settings.GetFullPath() ) );
551 bool ok =
m_routerSettings->LoadFromRawFile( fname_settings.GetFullPath() );
555 aRpt->
Report( wxT(
"Failed to load routing settings. Using defaults." ),
559 aRpt->
Report( wxString::Format( wxT(
"Loading project settings from '%s'" ),
560 fname_settings.GetFullPath() ) );
570 aRpt->
Report( wxString::Format( wxT(
"Loading board snapshot from '%s'"),
571 fname_dump.GetFullPath() ) );
576 std::shared_ptr<DRC_ENGINE> drcEngine(
new DRC_ENGINE );
583 m_board->SynchronizeNetsAndNetClasses(
true );
585 drcEngine->SetBoard(
m_board.get() );
586 drcEngine->SetDesignSettings( &bds );
587 drcEngine->SetLogReporter( aRpt );
590 wxFileName fname_rules( logFileName );
593 if( fname_rules.FileExists() )
594 drcEngine->InitEngine( fname_rules );
596 drcEngine->InitEngine( wxFileName() );
600 aRpt->
Report( wxString::Format(
"parse error : %s (%s)\n",
602 parse_error.
What() ),
609 ok =
loadJsonLog( logFileName.GetFullPath(), aRpt,
false );
610 if( !ok && logFileName.FileExists() )
622 wxFFileInputStream fp( aFilename, wxT(
"rt" ) );
623 wxStdInputStream fstream( fp );
628 aRpt->
Report( wxString::Format(
"Loading log from: %s", aFilename ) );
641 nlohmann::json logJson = nlohmann::json::parse( fstream,
nullptr,
645 if( logJson.contains(
"board_hash") )
647 m_boardHash = logJson.at(
"board_hash").get<wxString>();
650 if( logJson.contains(
"test_case_type") )
660 for(
const nlohmann::json& event : logJson.at(
"events" ) )
665 for(
const nlohmann::json& addedItem : logJson.at(
"addedItems" ) )
673 for(
const nlohmann::json& addedItem : logJson.at(
"removedItems" ) )
679 for(
const nlohmann::json& headItem : logJson.at(
"headItems" ) )
686 aRpt->
Report( wxString::Format(
"JSON log load: %zu events, %zu added, %zu removed\n",
m_events.size(),
693 catch(
const std::exception& exc )
708 FILE* f = fopen( aFilename.c_str(),
"rb" );
710 aRpt->
Report( wxString::Format(
"Loading log from '%s'", aFilename ) );
723 wxStringTokenizer tokens( line );
725 if( !tokens.CountTokens() )
728 wxString cmd = tokens.GetNextToken();
730 if( cmd == wxT(
"mode" ) )
734 else if( cmd == wxT(
"event" ) )
738 else if( cmd == wxT(
"added" ) )
745 else if( cmd == wxT(
"removed" ) )
A base class derived from BOARD_ITEM for items that can be connected and have a net,...
Container for design settings for a BOARD object.
std::shared_ptr< DRC_ENGINE > m_DRCEngine
bool m_UseConnectedTrackWidth
Design Rule Checker object that performs all the DRC tests.
virtual const wxString What() const
A composite of Problem() and Where()
virtual const wxString Problem() const
what was the problem?
A #PLUGIN derivation for saving and loading Pcbnew s-expression formatted files.
std::unique_ptr< BOARD > LoadBoard(const wxString &aFileName, const std::map< std::string, UTF8 > *aProperties=nullptr, PROJECT *aProject=nullptr)
Load information from some input file format that this PCB_IO implementation knows about into new BOA...
const SHAPE * Shape(int aLayer) const override
Return the geometrical shape of the item.
Base class for PNS router board items.
void SetLayers(const PNS_LAYER_RANGE &aLayers)
const PNS_LAYER_RANGE & Layers() const
virtual NET_HANDLE Net() const
PnsKind Kind() const
Return the type (kind) of the item.
void SetNet(NET_HANDLE aNet)
Represents a track on a PCB, connecting two non-trivial joints (that is, vias, pads,...
static wxString FormatLogFileAsJSON(const LOG_DATA &aLogData)
static EVENT_ENTRY ParseEventFromJSON(const nlohmann::json &aJSON)
static EVENT_ENTRY ParseEvent(const wxString &aLine)
Contain all persistent settings of the router, such as the mode, optimization effort,...
int Width() const override
int Diameter(int aLayer) const
const VECTOR2I & Pos() const
static constexpr int ALL_LAYERS
Represent a contiguous set of PCB layers.
bool parseCommonPnsProps(const nlohmann::json &aJSON, PNS::ITEM *aItem)
BOARD_CONNECTED_ITEM * ItemById(const PNS::LOGGER::EVENT_ENTRY &evt)
std::unique_ptr< PNS::VIA > parseLegacyPnsViaFromString(wxStringTokenizer &aTokens)
const std::optional< wxString > GetLogBoardHash(const wxString &logFileName)
bool SaveLog(const wxFileName &logFileName, REPORTER *aRpt)
bool loadLegacyLog(const wxString &aFilename, REPORTER *aRpt)
std::shared_ptr< BOARD > m_board
bool parseLegacyCommonPnsProps(PNS::ITEM *aItem, const wxString &cmd, wxStringTokenizer &aTokens)
std::shared_ptr< SETTINGS_MANAGER > m_settingsMgr
std::shared_ptr< SHAPE > parseShape(const nlohmann::json &aJSON)
std::unique_ptr< PNS::ITEM > parseItem(const nlohmann::json &aJSON)
std::shared_ptr< SHAPE > parseLegacyShape(SHAPE_TYPE expectedType, wxStringTokenizer &aTokens)
std::vector< std::unique_ptr< PNS::ITEM > > m_parsed_items
std::optional< wxString > m_boardHash
COMMIT_STATE m_commitState
bool loadJsonLog(const wxString &aFilename, REPORTER *aRpt, bool aHashOnly=false)
std::vector< PNS::LOGGER::EVENT_ENTRY > m_events
std::vector< BOARD_CONNECTED_ITEM * > ItemsById(const PNS::LOGGER::EVENT_ENTRY &evt)
std::unique_ptr< PNS::SEGMENT > parseLegacyPnsSegmentFromString(wxStringTokenizer &aTokens)
std::optional< PNS::LOGGER::TEST_CASE_TYPE > m_testCaseType
std::unique_ptr< PNS::ROUTING_SETTINGS > m_routerSettings
bool Load(const wxFileName &logFileName, REPORTER *aRpt, const wxString boardFileName=wxT(""))
std::unique_ptr< PNS::ITEM > parseLegacyItemFromString(wxStringTokenizer &aTokens)
Container for project specific data.
A pure virtual class used to derive REPORTER objects from.
virtual REPORTER & Report(const wxString &aText, SEVERITY aSeverity=RPT_SEVERITY_UNDEFINED)
Report a string with a given severity.
SHAPE_TYPE Type() const
Return the type of the shape.
const VECTOR2I GetCenter() const
Represent a polyline containing arcs as well as line segments: A chain of connected line and/or arc s...
bool CompareGeometry(const SHAPE_LINE_CHAIN &aOther, bool aCyclicalCompare=false, int aEpsilon=0) const
Compare this line chain with another one.
An abstract shape on 2D plane.
static const std::string DesignRulesFileExtension
Push and Shove diff pair dimensions (gap) settings dialog.
bool comparePnsItems(const PNS::ITEM *a, const PNS::ITEM *b)
static const wxString readLine(FILE *f)
const std::set< PNS::ITEM * > deduplicate(const std::vector< PNS::ITEM * > &items)
SHAPE_TYPE
Lists all supported shapes.
A filename or source description, a problem input line, a line number, a byte offset,...
std::vector< KIID > uuids
std::optional< wxString > m_BoardHash
std::optional< TEST_CASE_TYPE > m_TestCaseType
std::vector< ITEM * > m_AddedItems
std::vector< EVENT_ENTRY > m_Events
std::set< KIID > m_RemovedItems
std::vector< ITEM * > m_Heads
std::set< KIID > m_removedIds
bool Compare(const COMMIT_STATE &aOther, bool aSkipHeads=false)
std::vector< PNS::ITEM * > m_addedItems
std::vector< PNS::ITEM * > m_heads
VECTOR2< int32_t > VECTOR2I
Definition of file extensions used in Kicad.