diff --git a/CMakeLists.txt b/CMakeLists.txt index 968a0a37a7..4a923759cf 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -149,6 +149,13 @@ if( CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang" ) set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fvisibility-inlines-hidden" ) endif() + find_package( OpenMP QUIET ) + if( OPENMP_FOUND ) + set( CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${OpenMP_C_FLAGS}" ) + set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${OpenMP_CXX_FLAGS}" ) + add_definitions( -DUSE_OPENMP ) + endif() + if( MINGW ) set( CMAKE_EXE_LINKER_FLAGS_RELEASE "-s" ) diff --git a/common/CMakeLists.txt b/common/CMakeLists.txt index 01455b7df0..ea5c2b3144 100644 --- a/common/CMakeLists.txt +++ b/common/CMakeLists.txt @@ -219,6 +219,8 @@ set( PCB_COMMON_SRCS ../pcbnew/class_zone.cpp ../pcbnew/class_zone_settings.cpp ../pcbnew/classpcb.cpp + ../pcbnew/ratsnest_data.cpp + ../pcbnew/ratsnest_viewitem.cpp ../pcbnew/collectors.cpp ../pcbnew/netlist_reader.cpp ../pcbnew/legacy_netlist_reader.cpp diff --git a/common/class_undoredo_container.cpp b/common/class_undoredo_container.cpp index e56d765139..2dd862ef01 100644 --- a/common/class_undoredo_container.cpp +++ b/common/class_undoredo_container.cpp @@ -50,7 +50,7 @@ PICKED_ITEMS_LIST::~PICKED_ITEMS_LIST() } -void PICKED_ITEMS_LIST::PushItem( ITEM_PICKER& aItem ) +void PICKED_ITEMS_LIST::PushItem( const ITEM_PICKER& aItem ) { m_ItemsList.push_back( aItem ); } @@ -70,7 +70,7 @@ ITEM_PICKER PICKED_ITEMS_LIST::PopItem() } -bool PICKED_ITEMS_LIST::ContainsItem( EDA_ITEM* aItem ) const +bool PICKED_ITEMS_LIST::ContainsItem( const EDA_ITEM* aItem ) const { for( size_t i = 0; i < m_ItemsList.size(); i++ ) { @@ -82,6 +82,18 @@ bool PICKED_ITEMS_LIST::ContainsItem( EDA_ITEM* aItem ) const } +int PICKED_ITEMS_LIST::FindItem( const EDA_ITEM* aItem ) const +{ + for( size_t i = 0; i < m_ItemsList.size(); i++ ) + { + if( m_ItemsList[i].GetItem() == aItem ) + return i; + } + + return -1; +} + + void PICKED_ITEMS_LIST::ClearItemsList() { m_ItemsList.clear(); @@ -157,7 +169,7 @@ void PICKED_ITEMS_LIST::ClearListAndDeleteItems() } -ITEM_PICKER PICKED_ITEMS_LIST::GetItemWrapper( unsigned int aIdx ) +ITEM_PICKER PICKED_ITEMS_LIST::GetItemWrapper( unsigned int aIdx ) const { ITEM_PICKER picker; @@ -168,7 +180,7 @@ ITEM_PICKER PICKED_ITEMS_LIST::GetItemWrapper( unsigned int aIdx ) } -EDA_ITEM* PICKED_ITEMS_LIST::GetPickedItem( unsigned int aIdx ) +EDA_ITEM* PICKED_ITEMS_LIST::GetPickedItem( unsigned int aIdx ) const { if( aIdx < m_ItemsList.size() ) return m_ItemsList[aIdx].GetItem(); @@ -177,7 +189,7 @@ EDA_ITEM* PICKED_ITEMS_LIST::GetPickedItem( unsigned int aIdx ) } -EDA_ITEM* PICKED_ITEMS_LIST::GetPickedItemLink( unsigned int aIdx ) +EDA_ITEM* PICKED_ITEMS_LIST::GetPickedItemLink( unsigned int aIdx ) const { if( aIdx < m_ItemsList.size() ) return m_ItemsList[aIdx].GetLink(); @@ -186,7 +198,7 @@ EDA_ITEM* PICKED_ITEMS_LIST::GetPickedItemLink( unsigned int aIdx ) } -UNDO_REDO_T PICKED_ITEMS_LIST::GetPickedItemStatus( unsigned int aIdx ) +UNDO_REDO_T PICKED_ITEMS_LIST::GetPickedItemStatus( unsigned int aIdx ) const { if( aIdx < m_ItemsList.size() ) return m_ItemsList[aIdx].GetStatus(); @@ -195,7 +207,7 @@ UNDO_REDO_T PICKED_ITEMS_LIST::GetPickedItemStatus( unsigned int aIdx ) } -STATUS_FLAGS PICKED_ITEMS_LIST::GetPickerFlags( unsigned aIdx ) +STATUS_FLAGS PICKED_ITEMS_LIST::GetPickerFlags( unsigned aIdx ) const { if( aIdx < m_ItemsList.size() ) return m_ItemsList[aIdx].GetFlags(); diff --git a/common/drawpanel_gal.cpp b/common/drawpanel_gal.cpp index aa30b5ba92..e0d9dcdf89 100644 --- a/common/drawpanel_gal.cpp +++ b/common/drawpanel_gal.cpp @@ -78,18 +78,21 @@ EDA_DRAW_PANEL_GAL::EDA_DRAW_PANEL_GAL( wxWindow* aParentWindow, wxWindowID aWin Connect( wxEVT_SIZE, wxSizeEventHandler( EDA_DRAW_PANEL_GAL::onSize ), NULL, this ); /* Generic events for the Tool Dispatcher */ - Connect( wxEVT_MOTION, wxEventHandler( EDA_DRAW_PANEL_GAL::onEvent ), NULL, this ); - Connect( wxEVT_LEFT_UP, wxEventHandler( EDA_DRAW_PANEL_GAL::onEvent ), NULL, this ); - Connect( wxEVT_LEFT_DOWN, wxEventHandler( EDA_DRAW_PANEL_GAL::onEvent ), NULL, this ); - Connect( wxEVT_RIGHT_UP, wxEventHandler( EDA_DRAW_PANEL_GAL::onEvent ), NULL, this ); - Connect( wxEVT_RIGHT_DOWN, wxEventHandler( EDA_DRAW_PANEL_GAL::onEvent ), NULL, this ); - Connect( wxEVT_MIDDLE_UP, wxEventHandler( EDA_DRAW_PANEL_GAL::onEvent ), NULL, this ); - Connect( wxEVT_MIDDLE_DOWN, wxEventHandler( EDA_DRAW_PANEL_GAL::onEvent ), NULL, this ); - Connect( wxEVT_MOUSEWHEEL, wxEventHandler( EDA_DRAW_PANEL_GAL::onEvent ), NULL, this ); - Connect( wxEVT_CHAR_HOOK, wxEventHandler( EDA_DRAW_PANEL_GAL::skipEvent ) ); - Connect( wxEVT_KEY_UP, wxEventHandler( EDA_DRAW_PANEL_GAL::onEvent ), NULL, this ); - Connect( wxEVT_KEY_DOWN, wxEventHandler( EDA_DRAW_PANEL_GAL::onEvent ), NULL, this ); - Connect( wxEVT_ENTER_WINDOW, wxEventHandler( EDA_DRAW_PANEL_GAL::onEnter ), NULL, this ); + Connect( wxEVT_MOTION, wxEventHandler( EDA_DRAW_PANEL_GAL::onEvent ), NULL, this ); + Connect( wxEVT_LEFT_UP, wxEventHandler( EDA_DRAW_PANEL_GAL::onEvent ), NULL, this ); + Connect( wxEVT_LEFT_DOWN, wxEventHandler( EDA_DRAW_PANEL_GAL::onEvent ), NULL, this ); + Connect( wxEVT_LEFT_DCLICK, wxEventHandler( EDA_DRAW_PANEL_GAL::onEvent ), NULL, this ); + Connect( wxEVT_RIGHT_UP, wxEventHandler( EDA_DRAW_PANEL_GAL::onEvent ), NULL, this ); + Connect( wxEVT_RIGHT_DOWN, wxEventHandler( EDA_DRAW_PANEL_GAL::onEvent ), NULL, this ); + Connect( wxEVT_RIGHT_DCLICK, wxEventHandler( EDA_DRAW_PANEL_GAL::onEvent ), NULL, this ); + Connect( wxEVT_MIDDLE_UP, wxEventHandler( EDA_DRAW_PANEL_GAL::onEvent ), NULL, this ); + Connect( wxEVT_MIDDLE_DOWN, wxEventHandler( EDA_DRAW_PANEL_GAL::onEvent ), NULL, this ); + Connect( wxEVT_MIDDLE_DCLICK, wxEventHandler( EDA_DRAW_PANEL_GAL::onEvent ), NULL, this ); + Connect( wxEVT_MOUSEWHEEL, wxEventHandler( EDA_DRAW_PANEL_GAL::onEvent ), NULL, this ); + Connect( wxEVT_CHAR_HOOK, wxEventHandler( EDA_DRAW_PANEL_GAL::skipEvent ) ); + Connect( wxEVT_KEY_UP, wxEventHandler( EDA_DRAW_PANEL_GAL::onEvent ), NULL, this ); + Connect( wxEVT_KEY_DOWN, wxEventHandler( EDA_DRAW_PANEL_GAL::onEvent ), NULL, this ); + Connect( wxEVT_ENTER_WINDOW, wxEventHandler( EDA_DRAW_PANEL_GAL::onEnter ), NULL, this ); Connect( KIGFX::WX_VIEW_CONTROLS::EVT_REFRESH_MOUSE, wxEventHandler( EDA_DRAW_PANEL_GAL::onEvent ), NULL, this ); diff --git a/common/gal/cairo/cairo_gal.cpp b/common/gal/cairo/cairo_gal.cpp index 110f647146..5f180d7338 100644 --- a/common/gal/cairo/cairo_gal.cpp +++ b/common/gal/cairo/cairo_gal.cpp @@ -57,15 +57,18 @@ CAIRO_GAL::CAIRO_GAL( wxWindow* aParent, wxEvtHandler* aMouseListener, Connect( wxEVT_PAINT, wxPaintEventHandler( CAIRO_GAL::onPaint ) ); // Mouse events are skipped to the parent - Connect( wxEVT_MOTION, wxMouseEventHandler( CAIRO_GAL::skipMouseEvent ) ); - Connect( wxEVT_LEFT_DOWN, wxMouseEventHandler( CAIRO_GAL::skipMouseEvent ) ); - Connect( wxEVT_LEFT_UP, wxMouseEventHandler( CAIRO_GAL::skipMouseEvent ) ); - Connect( wxEVT_MIDDLE_DOWN, wxMouseEventHandler( CAIRO_GAL::skipMouseEvent ) ); - Connect( wxEVT_MIDDLE_UP, wxMouseEventHandler( CAIRO_GAL::skipMouseEvent ) ); - Connect( wxEVT_RIGHT_DOWN, wxMouseEventHandler( CAIRO_GAL::skipMouseEvent ) ); - Connect( wxEVT_RIGHT_UP, wxMouseEventHandler( CAIRO_GAL::skipMouseEvent ) ); + Connect( wxEVT_MOTION, wxMouseEventHandler( CAIRO_GAL::skipMouseEvent ) ); + Connect( wxEVT_LEFT_DOWN, wxMouseEventHandler( CAIRO_GAL::skipMouseEvent ) ); + Connect( wxEVT_LEFT_UP, wxMouseEventHandler( CAIRO_GAL::skipMouseEvent ) ); + Connect( wxEVT_LEFT_DCLICK, wxMouseEventHandler( CAIRO_GAL::skipMouseEvent ) ); + Connect( wxEVT_MIDDLE_DOWN, wxMouseEventHandler( CAIRO_GAL::skipMouseEvent ) ); + Connect( wxEVT_MIDDLE_UP, wxMouseEventHandler( CAIRO_GAL::skipMouseEvent ) ); + Connect( wxEVT_MIDDLE_DCLICK, wxMouseEventHandler( CAIRO_GAL::skipMouseEvent ) ); + Connect( wxEVT_RIGHT_DOWN, wxMouseEventHandler( CAIRO_GAL::skipMouseEvent ) ); + Connect( wxEVT_RIGHT_UP, wxMouseEventHandler( CAIRO_GAL::skipMouseEvent ) ); + Connect( wxEVT_RIGHT_DCLICK, wxMouseEventHandler( CAIRO_GAL::skipMouseEvent ) ); #if defined _WIN32 || defined _WIN64 - Connect( wxEVT_ENTER_WINDOW, wxMouseEventHandler( CAIRO_GAL::skipMouseEvent ) ); + Connect( wxEVT_ENTER_WINDOW, wxMouseEventHandler( CAIRO_GAL::skipMouseEvent ) ); #endif SetSize( aParent->GetSize() ); diff --git a/common/gal/opengl/gpu_manager.cpp b/common/gal/opengl/gpu_manager.cpp index 8b556b32ce..25cd5fa418 100644 --- a/common/gal/opengl/gpu_manager.cpp +++ b/common/gal/opengl/gpu_manager.cpp @@ -34,11 +34,11 @@ #include #include #include -#ifdef __WXDEBUG__ +#ifdef PROFILE #include #include #include -#endif +#endif /* PROFILE */ using namespace KIGFX; @@ -187,10 +187,10 @@ void GPU_CACHED_MANAGER::EndDrawing() void GPU_CACHED_MANAGER::uploadToGpu() { -#ifdef __WXDEBUG__ +#ifdef PROFILE prof_counter totalTime; prof_start( &totalTime ); -#endif /* __WXDEBUG__ */ +#endif /* PROFILE */ if( !m_buffersInitialized ) Initialize(); @@ -207,15 +207,13 @@ void GPU_CACHED_MANAGER::uploadToGpu() m_indices.reset( new GLuint[bufferSize] ); if( glGetError() != GL_NO_ERROR ) - { DisplayError( NULL, wxT( "Error during data upload to the GPU memory" ) ); - } -#ifdef __WXDEBUG__ +#ifdef PROFILE prof_end( &totalTime ); wxLogDebug( wxT( "Uploading %d vertices to GPU / %.1f ms" ), bufferSize, totalTime.msecs() ); -#endif /* __WXDEBUG__ */ +#endif /* PROFILE */ } diff --git a/common/gal/opengl/opengl_gal.cpp b/common/gal/opengl/opengl_gal.cpp index 970cc32d16..f9cccbd365 100644 --- a/common/gal/opengl/opengl_gal.cpp +++ b/common/gal/opengl/opengl_gal.cpp @@ -70,15 +70,18 @@ OPENGL_GAL::OPENGL_GAL( wxWindow* aParent, wxEvtHandler* aMouseListener, Connect( wxEVT_PAINT, wxPaintEventHandler( OPENGL_GAL::onPaint ) ); // Mouse events are skipped to the parent - Connect( wxEVT_MOTION, wxMouseEventHandler( OPENGL_GAL::skipMouseEvent ) ); - Connect( wxEVT_LEFT_DOWN, wxMouseEventHandler( OPENGL_GAL::skipMouseEvent ) ); - Connect( wxEVT_LEFT_UP, wxMouseEventHandler( OPENGL_GAL::skipMouseEvent ) ); - Connect( wxEVT_MIDDLE_DOWN, wxMouseEventHandler( OPENGL_GAL::skipMouseEvent ) ); - Connect( wxEVT_MIDDLE_UP, wxMouseEventHandler( OPENGL_GAL::skipMouseEvent ) ); - Connect( wxEVT_RIGHT_DOWN, wxMouseEventHandler( OPENGL_GAL::skipMouseEvent ) ); - Connect( wxEVT_RIGHT_UP, wxMouseEventHandler( OPENGL_GAL::skipMouseEvent ) ); + Connect( wxEVT_MOTION, wxMouseEventHandler( OPENGL_GAL::skipMouseEvent ) ); + Connect( wxEVT_LEFT_DOWN, wxMouseEventHandler( OPENGL_GAL::skipMouseEvent ) ); + Connect( wxEVT_LEFT_UP, wxMouseEventHandler( OPENGL_GAL::skipMouseEvent ) ); + Connect( wxEVT_LEFT_DCLICK, wxMouseEventHandler( OPENGL_GAL::skipMouseEvent ) ); + Connect( wxEVT_MIDDLE_DOWN, wxMouseEventHandler( OPENGL_GAL::skipMouseEvent ) ); + Connect( wxEVT_MIDDLE_UP, wxMouseEventHandler( OPENGL_GAL::skipMouseEvent ) ); + Connect( wxEVT_MIDDLE_DCLICK, wxMouseEventHandler( OPENGL_GAL::skipMouseEvent ) ); + Connect( wxEVT_RIGHT_DOWN, wxMouseEventHandler( OPENGL_GAL::skipMouseEvent ) ); + Connect( wxEVT_RIGHT_UP, wxMouseEventHandler( OPENGL_GAL::skipMouseEvent ) ); + Connect( wxEVT_RIGHT_DCLICK, wxMouseEventHandler( OPENGL_GAL::skipMouseEvent ) ); #if defined _WIN32 || defined _WIN64 - Connect( wxEVT_ENTER_WINDOW, wxMouseEventHandler( OPENGL_GAL::skipMouseEvent ) ); + Connect( wxEVT_ENTER_WINDOW, wxMouseEventHandler( OPENGL_GAL::skipMouseEvent ) ); #endif SetSize( aParent->GetSize() ); diff --git a/common/geometry/hetriang.cpp b/common/geometry/hetriang.cpp index c1523ac347..eb5e59ecf7 100644 --- a/common/geometry/hetriang.cpp +++ b/common/geometry/hetriang.cpp @@ -45,14 +45,14 @@ #include #include #include +#include +#include using namespace hed; using namespace std; -Triangulation* TTLtraits::triang_ = NULL; - #ifdef TTL_USE_NODE_ID int Node::id_count = 0; #endif @@ -117,28 +117,27 @@ EdgePtr Triangulation::initTwoEnclosingTriangles(NodesContainer::iterator first, double dx = (xmax-xmin)/fac; double dy = (ymax-ymin)/fac; - NodePtr n1(new Node(xmin-dx,ymin-dy)); - NodePtr n2(new Node(xmax+dx,ymin-dy)); - NodePtr n3(new Node(xmax+dx,ymax+dy)); - NodePtr n4(new Node(xmin-dx,ymax+dy)); + NodePtr n1 = boost::make_shared(xmin-dx, ymin-dy); + NodePtr n2 = boost::make_shared(xmax+dx, ymin-dy); + NodePtr n3 = boost::make_shared(xmax+dx, ymax+dy); + NodePtr n4 = boost::make_shared(xmin-dx, ymax+dy); // diagonal - EdgePtr e1d(new Edge); // lower - EdgePtr e2d(new Edge); // upper, the twin edge + EdgePtr e1d = boost::make_shared(); + EdgePtr e2d = boost::make_shared(); // lower triangle - EdgePtr e11(new Edge); - EdgePtr e12(new Edge); + EdgePtr e11 = boost::make_shared(); + EdgePtr e12 = boost::make_shared(); // upper triangle - EdgePtr e21(new Edge); // upper upper - EdgePtr e22(new Edge); + EdgePtr e21 = boost::make_shared(); + EdgePtr e22 = boost::make_shared(); // lower triangle e1d->setSourceNode(n3); e1d->setNextEdgeInFace(e11); e1d->setTwinEdge(e2d); - e1d->setAsLeadingEdge(); addLeadingEdge(e1d); e11->setSourceNode(n1); @@ -151,7 +150,6 @@ EdgePtr Triangulation::initTwoEnclosingTriangles(NodesContainer::iterator first, e2d->setSourceNode(n1); e2d->setNextEdgeInFace(e21); e2d->setTwinEdge(e1d); - e2d->setAsLeadingEdge(); addLeadingEdge(e2d); e21->setSourceNode(n3); @@ -164,11 +162,30 @@ EdgePtr Triangulation::initTwoEnclosingTriangles(NodesContainer::iterator first, } +//-------------------------------------------------------------------------------------------------- +Triangulation::Triangulation() { + helper = new ttl::TriangulationHelper( *this ); +} + + +//-------------------------------------------------------------------------------------------------- +Triangulation::Triangulation(const Triangulation& tr) { + std::cout << "Triangulation: Copy constructor not present - EXIT."; + exit(-1); +} + + +//-------------------------------------------------------------------------------------------------- +Triangulation::~Triangulation() { + cleanAll(); + delete helper; +} + + //-------------------------------------------------------------------------------------------------- void Triangulation::createDelaunay(NodesContainer::iterator first, NodesContainer::iterator last) { - - TTLtraits::triang_ = this; + cleanAll(); EdgePtr bedge = initTwoEnclosingTriangles(first, last); @@ -178,7 +195,7 @@ void Triangulation::createDelaunay(NodesContainer::iterator first, NodesContainer::iterator it; for (it = first; it != last; ++it) { - ttl::insertNode(d_iter, *it); + helper->insertNode(d_iter, *it); } // In general (e.g. for the triangle based data structure), the initial dart @@ -189,7 +206,7 @@ void Triangulation::createDelaunay(NodesContainer::iterator first, // triangle "outside" the triangulation.) // Assumes rectangular domain - ttl::removeRectangularBoundary(dc); + helper->removeRectangularBoundary(dc); } @@ -206,15 +223,12 @@ void Triangulation::removeTriangle(EdgePtr& edge) { removeLeadingEdgeFromList(e1); // cout << "No leading edges = " << leadingEdges_.size() << endl; // Remove the triangle - EdgePtr e2 = e1->getNextEdgeInFace(); - EdgePtr e3 = e2->getNextEdgeInFace(); - - if (e1->getTwinEdge()) - e1->getTwinEdge()->setTwinEdge(EdgePtr()); - if (e2->getTwinEdge()) - e2->getTwinEdge()->setTwinEdge(EdgePtr()); - if (e3->getTwinEdge()) - e3->getTwinEdge()->setTwinEdge(EdgePtr()); + EdgePtr e2(e1->getNextEdgeInFace()); + EdgePtr e3(e2->getNextEdgeInFace()); + + e1->clear(); + e2->clear(); + e3->clear(); } @@ -223,15 +237,15 @@ void Triangulation::reverse_splitTriangle(EdgePtr& edge) { // Reverse operation of splitTriangle - EdgePtr e1 = edge->getNextEdgeInFace(); - EdgePtr le = getLeadingEdgeInTriangle(e1); + EdgePtr e1(edge->getNextEdgeInFace()); + EdgePtr le(getLeadingEdgeInTriangle(e1)); #ifdef DEBUG_HE if (!le) errorAndExit("Triangulation::removeTriangle: could not find leading edge"); #endif removeLeadingEdgeFromList(le); - EdgePtr e2 = e1->getNextEdgeInFace()->getTwinEdge()->getNextEdgeInFace(); + EdgePtr e2(e1->getNextEdgeInFace()->getTwinEdge()->getNextEdgeInFace()); le = getLeadingEdgeInTriangle(e2); #ifdef DEBUG_HE if (!le) @@ -239,7 +253,7 @@ void Triangulation::reverse_splitTriangle(EdgePtr& edge) { #endif removeLeadingEdgeFromList(le); - EdgePtr e3 = edge->getTwinEdge()->getNextEdgeInFace()->getNextEdgeInFace(); + EdgePtr e3(edge->getTwinEdge()->getNextEdgeInFace()->getNextEdgeInFace()); le = getLeadingEdgeInTriangle(e3); #ifdef DEBUG_HE if (!le) @@ -251,6 +265,19 @@ void Triangulation::reverse_splitTriangle(EdgePtr& edge) { // from the triangulation, but the arcs have not been deleted. // Next delete the 6 half edges radiating from the node // The node is maintained by handle and need not be deleted explicitly + EdgePtr estar = edge; + EdgePtr enext = estar->getTwinEdge()->getNextEdgeInFace(); + estar->getTwinEdge()->clear(); + estar->clear(); + + estar = enext; + enext = estar->getTwinEdge()->getNextEdgeInFace(); + estar->getTwinEdge()->clear(); + estar->clear(); + + enext->getTwinEdge()->clear(); + enext->clear(); + // Create the new triangle e1->setNextEdgeInFace(e2); @@ -260,25 +287,6 @@ void Triangulation::reverse_splitTriangle(EdgePtr& edge) { } -//-------------------------------------------------------------------------------------------------- -// This is a "template" for iterating the boundary -/* -static void iterateBoundary(const Dart& dart) { -cout << "Iterate boundary 2" << endl; -// input is a dart at the boundary - - Dart dart_iter = dart; - do { - if (ttl::isBoundaryEdge(dart_iter)) - dart_iter.alpha0().alpha1(); - else - dart_iter.alpha2().alpha1(); - - } while(dart_iter != dart); -} -*/ - - //-------------------------------------------------------------------------------------------------- Dart Triangulation::createDart() { @@ -305,20 +313,43 @@ bool Triangulation::removeLeadingEdgeFromList(EdgePtr& leadingEdge) { edge->setAsLeadingEdge(false); it = leadingEdges_.erase(it); - break; + return true; } } - if (it == leadingEdges_.end()) - return false; - - return true; + return false; } //-------------------------------------------------------------------------------------------------- void Triangulation::cleanAll() { - leadingEdges_.clear(); + BOOST_FOREACH(EdgePtr& edge, leadingEdges_) + edge->setNextEdgeInFace(EdgePtr()); +} + + +//-------------------------------------------------------------------------------------------------- +void Triangulation::swapEdge(Dart& dart) { + swapEdge(dart.getEdge()); +} + + +//-------------------------------------------------------------------------------------------------- +void Triangulation::splitTriangle(Dart& dart, const NodePtr& point) { + EdgePtr edge = splitTriangle(dart.getEdge(), point); + dart.init(edge); +} + + +//-------------------------------------------------------------------------------------------------- +void Triangulation::reverse_splitTriangle(Dart& dart) { + reverse_splitTriangle(dart.getEdge()); +} + + +//-------------------------------------------------------------------------------------------------- +void Triangulation::removeBoundaryTriangle(Dart& d) { + removeTriangle(d.getEdge()); } @@ -390,7 +421,7 @@ list* Triangulation::getEdges(bool skip_boundary_edges) const { //-------------------------------------------------------------------------------------------------- -EdgePtr Triangulation::splitTriangle(EdgePtr& edge, NodePtr& point) { +EdgePtr Triangulation::splitTriangle(EdgePtr& edge, const NodePtr& point) { // Add a node by just splitting a triangle into three triangles // Assumes the half edge is located in the triangle @@ -409,21 +440,21 @@ EdgePtr Triangulation::splitTriangle(EdgePtr& edge, NodePtr& point) { // Add the node to the structure //NodePtr new_node(new Node(x,y,z)); - NodePtr n1 = edge->getSourceNode(); - EdgePtr e1 = edge; + NodePtr n1(edge->getSourceNode()); + EdgePtr e1(edge); - EdgePtr e2 = edge->getNextEdgeInFace(); - NodePtr n2 = e2->getSourceNode(); + EdgePtr e2(edge->getNextEdgeInFace()); + NodePtr n2(e2->getSourceNode()); - EdgePtr e3 = e2->getNextEdgeInFace(); - NodePtr n3 = e3->getSourceNode(); + EdgePtr e3(e2->getNextEdgeInFace()); + NodePtr n3(e3->getSourceNode()); - EdgePtr e1_n(new Edge); - EdgePtr e11_n(new Edge); - EdgePtr e2_n(new Edge); - EdgePtr e22_n(new Edge); - EdgePtr e3_n(new Edge); - EdgePtr e33_n(new Edge); + EdgePtr e1_n = boost::make_shared(); + EdgePtr e11_n = boost::make_shared(); + EdgePtr e2_n = boost::make_shared(); + EdgePtr e22_n = boost::make_shared(); + EdgePtr e3_n = boost::make_shared(); + EdgePtr e33_n = boost::make_shared(); e1_n->setSourceNode(n1); e11_n->setSourceNode(point); @@ -447,7 +478,6 @@ EdgePtr Triangulation::splitTriangle(EdgePtr& edge, NodePtr& point) { e22_n->setNextEdgeInFace(e2); e33_n->setNextEdgeInFace(e3); - // and update old's next edge e1->setNextEdgeInFace(e2_n); e2->setNextEdgeInFace(e3_n); @@ -458,18 +488,14 @@ EdgePtr Triangulation::splitTriangle(EdgePtr& edge, NodePtr& point) { // Use the field telling if an edge is a leading edge // NOTE: Must search in the list!!! - - EdgePtr leadingEdge; if (e1->isLeadingEdge()) - leadingEdge = e1; + removeLeadingEdgeFromList(e1); else if (e2->isLeadingEdge()) - leadingEdge = e2; + removeLeadingEdgeFromList(e2); else if(e3->isLeadingEdge()) - leadingEdge = e3; + removeLeadingEdgeFromList(e3); else - return EdgePtr(); - - removeLeadingEdgeFromList(leadingEdge); + assert( false ); // one of the edges should be leading addLeadingEdge(e1_n); addLeadingEdge(e2_n); @@ -486,20 +512,20 @@ void Triangulation::swapEdge(EdgePtr& diagonal) { // Note that diagonal is both input and output and it is always // kept in counterclockwise direction (this is not required by all - // finctions in ttl:: now) + // functions in TriangulationHelper now) // Swap by rotating counterclockwise // Use the same objects - no deletion or new objects - EdgePtr eL = diagonal; - EdgePtr eR = eL->getTwinEdge(); - EdgePtr eL_1 = eL->getNextEdgeInFace(); - EdgePtr eL_2 = eL_1->getNextEdgeInFace(); - EdgePtr eR_1 = eR->getNextEdgeInFace(); - EdgePtr eR_2 = eR_1->getNextEdgeInFace(); + EdgePtr eL(diagonal); + EdgePtr eR(eL->getTwinEdge()); + EdgePtr eL_1(eL->getNextEdgeInFace()); + EdgePtr eL_2(eL_1->getNextEdgeInFace()); + EdgePtr eR_1(eR->getNextEdgeInFace()); + EdgePtr eR_2(eR_1->getNextEdgeInFace()); // avoid node to be dereferenced to zero and deleted - NodePtr nR = eR_2->getSourceNode(); - NodePtr nL = eL_2->getSourceNode(); + NodePtr nR(eR_2->getSourceNode()); + NodePtr nL(eL_2->getSourceNode()); eL->setSourceNode(nR); eR->setSourceNode(nL); @@ -513,24 +539,20 @@ void Triangulation::swapEdge(EdgePtr& diagonal) { eR_2->setNextEdgeInFace(eL_1); eL_1->setNextEdgeInFace(eR); - EdgePtr leL; if (eL->isLeadingEdge()) - leL = eL; + removeLeadingEdgeFromList(eL); else if (eL_1->isLeadingEdge()) - leL = eL_1; + removeLeadingEdgeFromList(eL_1); else if (eL_2->isLeadingEdge()) - leL = eL_2; + removeLeadingEdgeFromList(eL_2); - EdgePtr leR; if (eR->isLeadingEdge()) - leR = eR; + removeLeadingEdgeFromList(eR); else if (eR_1->isLeadingEdge()) - leR = eR_1; + removeLeadingEdgeFromList(eR_1); else if (eR_2->isLeadingEdge()) - leR = eR_2; + removeLeadingEdgeFromList(eR_2); - removeLeadingEdgeFromList(leL); - removeLeadingEdgeFromList(leR); addLeadingEdge(eL); addLeadingEdge(eR); } @@ -567,7 +589,7 @@ bool Triangulation::checkDelaunay() const { // only one of the half-edges if (!twinedge || (size_t)edge.get() > (size_t)twinedge.get()) { Dart dart(edge); - if (ttl::swapTestDelaunay(dart)) { + if (helper->swapTestDelaunay(dart)) { noNotDelaunay++; //printEdge(dart,os); os << "\n"; @@ -610,7 +632,7 @@ void Triangulation::optimizeDelaunay() { Dart dart(edge); // Constrained edges should not be swapped - if (!edge->isConstrained() && ttl::swapTestDelaunay(dart, cycling_check)) { + if (helper->swapTestDelaunay(dart, cycling_check)) { optimal = false; swapEdge(edge); } @@ -632,7 +654,7 @@ EdgePtr Triangulation::getInteriorNode() const { for (int i = 0; i < 3; ++i) { if (edge->getTwinEdge()) { - if (!ttl::isBoundaryNode(Dart(edge))) + if (!helper->isBoundaryNode(Dart(edge))) return edge; } edge = edge->getNextEdgeInFace(); @@ -643,18 +665,18 @@ EdgePtr Triangulation::getInteriorNode() const { //-------------------------------------------------------------------------------------------------- -static EdgePtr getBoundaryEdgeInTriangle(const EdgePtr& e) { +EdgePtr Triangulation::getBoundaryEdgeInTriangle(const EdgePtr& e) const { EdgePtr edge = e; - if (ttl::isBoundaryEdge(Dart(edge))) + if (helper->isBoundaryEdge(Dart(edge))) return edge; edge = edge->getNextEdgeInFace(); - if (ttl::isBoundaryEdge(Dart(edge))) + if (helper->isBoundaryEdge(Dart(edge))) return edge; edge = edge->getNextEdgeInFace(); - if (ttl::isBoundaryEdge(Dart(edge))) + if (helper->isBoundaryEdge(Dart(edge))) return edge; return EdgePtr(); diff --git a/common/tool/action_manager.cpp b/common/tool/action_manager.cpp index be90ef055f..a00d4d08cc 100644 --- a/common/tool/action_manager.cpp +++ b/common/tool/action_manager.cpp @@ -34,9 +34,18 @@ ACTION_MANAGER::ACTION_MANAGER( TOOL_MANAGER* aToolManager ) : } +ACTION_MANAGER::~ACTION_MANAGER() +{ + while( !m_actionIdIndex.empty() ) + UnregisterAction( m_actionIdIndex.begin()->second ); +} + + void ACTION_MANAGER::RegisterAction( TOOL_ACTION* aAction ) { assert( aAction->GetId() == -1 ); // Check if the TOOL_ACTION was not registered before + assert( m_actionNameIndex.find( aAction->m_name ) == m_actionNameIndex.end() ); + assert( m_actionIdIndex.find( aAction->m_id ) == m_actionIdIndex.end() ); aAction->setId( MakeActionId( aAction->m_name ) ); @@ -44,7 +53,13 @@ void ACTION_MANAGER::RegisterAction( TOOL_ACTION* aAction ) m_actionIdIndex[aAction->m_id] = aAction; if( aAction->HasHotKey() ) + { + // Duplication of hot keys leads to unexpected behaviour + // The right way to change a hotkey is to use ACTION_MANAGER::ClearHotKey() first + assert( m_actionHotKeys.find( aAction->m_currentHotKey ) == m_actionHotKeys.end() ); + m_actionHotKeys[aAction->m_currentHotKey] = aAction; + } aAction->setActionMgr( this ); } @@ -52,13 +67,13 @@ void ACTION_MANAGER::RegisterAction( TOOL_ACTION* aAction ) void ACTION_MANAGER::UnregisterAction( TOOL_ACTION* aAction ) { + m_actionNameIndex.erase( aAction->m_name ); + m_actionIdIndex.erase( aAction->m_id ); + // Indicate that the ACTION_MANAGER no longer care about the object aAction->setActionMgr( NULL ); aAction->setId( -1 ); - m_actionNameIndex.erase( aAction->m_name ); - m_actionIdIndex.erase( aAction->m_id ); - if( aAction->HasHotKey() ) m_actionHotKeys.erase( aAction->m_currentHotKey ); } @@ -98,6 +113,12 @@ bool ACTION_MANAGER::RunHotKey( int aHotKey ) const } +void ACTION_MANAGER::ClearHotKey( int aHotKey ) +{ + m_actionHotKeys.erase( aHotKey ); +} + + void ACTION_MANAGER::runAction( const TOOL_ACTION* aAction ) const { TOOL_EVENT event = aAction->MakeEvent(); diff --git a/common/tool/context_menu.cpp b/common/tool/context_menu.cpp index e20dfdf115..6dfab27e58 100644 --- a/common/tool/context_menu.cpp +++ b/common/tool/context_menu.cpp @@ -29,7 +29,7 @@ #include CONTEXT_MENU::CONTEXT_MENU() : - m_titleSet( false ), m_handler( this ), m_tool( NULL ) + m_titleSet( false ), m_selected( -1 ), m_handler( this ), m_tool( NULL ) { m_menu.Connect( wxEVT_MENU_HIGHLIGHT, wxEventHandler( CMEventHandler::onEvent ), NULL, &m_handler ); @@ -43,7 +43,7 @@ CONTEXT_MENU::CONTEXT_MENU() : CONTEXT_MENU::CONTEXT_MENU( const CONTEXT_MENU& aMenu ) : - m_titleSet( aMenu.m_titleSet ), m_handler( this ), m_tool( aMenu.m_tool ) + m_titleSet( aMenu.m_titleSet ), m_selected( -1 ), m_handler( this ), m_tool( aMenu.m_tool ) { m_menu.Connect( wxEVT_MENU_HIGHLIGHT, wxEventHandler( CMEventHandler::onEvent ), NULL, &m_handler ); @@ -164,6 +164,9 @@ void CONTEXT_MENU::CMEventHandler::onEvent( wxEvent& aEvent ) // One of menu entries was selected.. else if( type == wxEVT_COMMAND_MENU_SELECTED ) { + // Store the selected position + m_menu->m_selected = aEvent.GetId(); + // Check if there is a TOOL_ACTION for the given ID if( m_menu->m_toolActions.count( aEvent.GetId() ) == 1 ) { diff --git a/common/tool/tool_dispatcher.cpp b/common/tool/tool_dispatcher.cpp index 49ab4382ac..f35689c97f 100644 --- a/common/tool/tool_dispatcher.cpp +++ b/common/tool/tool_dispatcher.cpp @@ -43,10 +43,11 @@ using boost::optional; struct TOOL_DISPATCHER::BUTTON_STATE { BUTTON_STATE( TOOL_MOUSE_BUTTONS aButton, const wxEventType& aDownEvent, - const wxEventType& aUpEvent ) : + const wxEventType& aUpEvent, const wxEventType& aDblClickEvent ) : button( aButton ), downEvent( aDownEvent ), - upEvent( aUpEvent ) + upEvent( aUpEvent ), + dblClickEvent( aDblClickEvent ) {}; ///> Flag indicating that dragging is active for the given button. @@ -74,6 +75,9 @@ struct TOOL_DISPATCHER::BUTTON_STATE ///> The type of wxEvent that determines mouse button release. wxEventType upEvent; + ///> The type of wxEvent that determines mouse button double click. + wxEventType dblClickEvent; + ///> Time stamp for the last mouse button press event. wxLongLong downTimestamp; @@ -89,9 +93,12 @@ struct TOOL_DISPATCHER::BUTTON_STATE TOOL_DISPATCHER::TOOL_DISPATCHER( TOOL_MANAGER* aToolMgr, PCB_BASE_FRAME* aEditFrame ) : m_toolMgr( aToolMgr ), m_editFrame( aEditFrame ) { - m_buttons.push_back( new BUTTON_STATE( BUT_LEFT, wxEVT_LEFT_DOWN, wxEVT_LEFT_UP ) ); - m_buttons.push_back( new BUTTON_STATE( BUT_RIGHT, wxEVT_RIGHT_DOWN, wxEVT_RIGHT_UP ) ); - m_buttons.push_back( new BUTTON_STATE( BUT_MIDDLE, wxEVT_MIDDLE_DOWN, wxEVT_MIDDLE_UP ) ); + m_buttons.push_back( new BUTTON_STATE( BUT_LEFT, wxEVT_LEFT_DOWN, + wxEVT_LEFT_UP, wxEVT_LEFT_DCLICK ) ); + m_buttons.push_back( new BUTTON_STATE( BUT_RIGHT, wxEVT_RIGHT_DOWN, + wxEVT_RIGHT_UP, wxEVT_RIGHT_DCLICK ) ); + m_buttons.push_back( new BUTTON_STATE( BUT_MIDDLE, wxEVT_MIDDLE_DOWN, + wxEVT_MIDDLE_UP, wxEVT_MIDDLE_DCLICK ) ); ResetState(); } @@ -126,6 +133,7 @@ bool TOOL_DISPATCHER::handleMouseButton( wxEvent& aEvent, int aIndex, bool aMoti bool up = type == st->upEvent; bool down = type == st->downEvent; + bool dblClick = type == st->dblClickEvent; int mods = decodeModifiers( static_cast( &aEvent ) ); int args = st->button | mods; @@ -139,7 +147,7 @@ bool TOOL_DISPATCHER::handleMouseButton( wxEvent& aEvent, int aIndex, bool aMoti st->pressed = true; evt = TOOL_EVENT( TC_MOUSE, TA_MOUSE_DOWN, args ); } - else if( up ) // Handle mouse button release + else if( up ) // Handle mouse button release { st->pressed = false; @@ -162,6 +170,10 @@ bool TOOL_DISPATCHER::handleMouseButton( wxEvent& aEvent, int aIndex, bool aMoti st->dragging = false; } + else if( dblClick ) + { + evt = TOOL_EVENT( TC_MOUSE, TA_MOUSE_DBLCLICK, args ); + } if( st->pressed && aMotion ) { @@ -204,14 +216,15 @@ void TOOL_DISPATCHER::DispatchWxEvent( wxEvent& aEvent ) type == wxEVT_LEFT_DOWN || type == wxEVT_LEFT_UP || type == wxEVT_MIDDLE_DOWN || type == wxEVT_MIDDLE_UP || type == wxEVT_RIGHT_DOWN || type == wxEVT_RIGHT_UP || + type == wxEVT_LEFT_DCLICK || type == wxEVT_MIDDLE_DCLICK || type == wxEVT_RIGHT_DCLICK || // Event issued whem mouse retains position in screen coordinates, - // but changes in world coordinates (eg. autopanning) + // but changes in world coordinates (e.g. autopanning) type == KIGFX::WX_VIEW_CONTROLS::EVT_REFRESH_MOUSE ) { - VECTOR2D screenPos = m_toolMgr->GetViewControls()->GetCursorPosition(); + VECTOR2D screenPos = m_toolMgr->GetViewControls()->GetMousePosition(); VECTOR2D pos = getView()->ToWorld( screenPos ); - if( pos != m_lastMousePos || type == KIGFX::WX_VIEW_CONTROLS::EVT_REFRESH_MOUSE ) + if( pos != m_lastMousePos ) { motion = true; m_lastMousePos = pos; @@ -267,11 +280,6 @@ void TOOL_DISPATCHER::DispatchWxCommand( const wxCommandEvent& aEvent ) toolName = "pcbnew.InteractiveRouter"; activateTool = true; break; - - case ID_SELECTION_TOOL: - toolName = "pcbnew.InteractiveSelection"; - activateTool = true; - break; } // do nothing if the legacy view is active diff --git a/common/tool/tool_event.cpp b/common/tool/tool_event.cpp index 402f9798f2..07460f3571 100644 --- a/common/tool/tool_event.cpp +++ b/common/tool/tool_event.cpp @@ -75,6 +75,7 @@ const std::string TOOL_EVENT::Format() const const FlagString actions[] = { { TA_MOUSE_CLICK, "click" }, + { TA_MOUSE_DBLCLICK, "double click" }, { TA_MOUSE_UP, "button-up" }, { TA_MOUSE_DOWN, "button-down" }, { TA_MOUSE_DRAG, "drag" }, @@ -90,6 +91,7 @@ const std::string TOOL_EVENT::Format() const { TA_CANCEL_TOOL, "cancel-tool" }, { TA_CONTEXT_MENU_UPDATE, "context-menu-update" }, { TA_CONTEXT_MENU_CHOICE, "context-menu-choice" }, + { TA_UNDO_REDO, "undo-redo" }, { TA_ACTION, "action" }, { 0, "" } }; @@ -100,7 +102,7 @@ const std::string TOOL_EVENT::Format() const { BUT_LEFT, "left" }, { BUT_RIGHT, "right" }, { BUT_MIDDLE, "middle" }, - { 0, "" } + { 0, "" } }; const FlagString modifiers[] = diff --git a/common/tool/tool_manager.cpp b/common/tool/tool_manager.cpp index 6d887a291c..f36d0cb343 100644 --- a/common/tool/tool_manager.cpp +++ b/common/tool/tool_manager.cpp @@ -96,7 +96,7 @@ struct TOOL_MANAGER::TOOL_STATE TOOL_MANAGER::TOOL_MANAGER() : - m_model( NULL ), m_view( NULL ) + m_model( NULL ), m_view( NULL ), m_viewControls( NULL ), m_editFrame( NULL ) { m_actionMgr = new ACTION_MANAGER( this ); } @@ -119,10 +119,14 @@ TOOL_MANAGER::~TOOL_MANAGER() void TOOL_MANAGER::RegisterTool( TOOL_BASE* aTool ) { + wxASSERT_MSG( m_toolNameIndex.find( aTool->GetName() ) == m_toolNameIndex.end(), + wxT( "Adding two tools with the same name may result in unexpected behaviour.") ); + wxASSERT_MSG( m_toolIdIndex.find( aTool->GetId() ) == m_toolIdIndex.end(), + wxT( "Adding two tools with the same ID may result in unexpected behaviour.") ); + TOOL_STATE* st = new TOOL_STATE; st->theTool = aTool; - st->idle = true; st->pendingWait = false; st->pendingContextMenu = false; st->cofunc = NULL; @@ -134,22 +138,20 @@ void TOOL_MANAGER::RegisterTool( TOOL_BASE* aTool ) aTool->m_toolMgr = this; - if( aTool->GetType() == INTERACTIVE ) + if( !aTool->Init() ) { - if( !static_cast( aTool )->Init() ) - { - std::string msg = StrPrintf( "Initialization of the %s tool failed", aTool->GetName().c_str() ); + std::string msg = StrPrintf( "Initialization of the %s tool failed", + aTool->GetName().c_str() ); - DisplayError( NULL, wxString::FromUTF8( msg.c_str() ) ); + DisplayError( NULL, wxString::FromUTF8( msg.c_str() ) ); - // Unregister the tool - m_toolState.erase( aTool ); - m_toolNameIndex.erase( aTool->GetName() ); - m_toolIdIndex.erase( aTool->GetId() ); + // Unregister the tool + m_toolState.erase( aTool ); + m_toolNameIndex.erase( aTool->GetName() ); + m_toolIdIndex.erase( aTool->GetId() ); - delete st; - delete aTool; - } + delete st; + delete aTool; } } @@ -188,6 +190,12 @@ void TOOL_MANAGER::UnregisterAction( TOOL_ACTION* aAction ) } +bool TOOL_MANAGER::RunAction( const std::string& aActionName ) +{ + return m_actionMgr->RunAction( aActionName ); +} + + bool TOOL_MANAGER::invokeTool( TOOL_BASE* aTool ) { wxASSERT( aTool != NULL ); @@ -226,17 +234,16 @@ bool TOOL_MANAGER::runTool( TOOL_BASE* aTool ) wxASSERT( aTool != NULL ); if( !isRegistered( aTool ) ) + { + wxASSERT_MSG( false, wxT( "You cannot run unregistered tools" ) ); return false; - - TOOL_STATE* state = m_toolState[aTool]; + } // If the tool is already active, do not invoke it again - if( state->idle == false ) + if( isActive( aTool ) ) return false; - state->idle = false; - - static_cast( aTool )->Reset(); + aTool->Reset( TOOL_INTERACTIVE::RUN ); // Add the tool on the front of the processing queue (it gets events first) m_activeTools.push_front( aTool->GetId() ); @@ -267,6 +274,13 @@ TOOL_BASE* TOOL_MANAGER::FindTool( const std::string& aName ) const } +void TOOL_MANAGER::ResetTools( TOOL_BASE::RESET_REASON aReason ) +{ + BOOST_FOREACH( TOOL_BASE* tool, m_toolState | boost::adaptors::map_keys ) + tool->Reset( aReason ); +} + + void TOOL_MANAGER::ScheduleNextState( TOOL_BASE* aTool, TOOL_STATE_FUNC& aHandler, const TOOL_EVENT_LIST& aConditions ) { @@ -333,10 +347,11 @@ void TOOL_MANAGER::dispatchInternal( TOOL_EVENT& aEvent ) // Go() method that match the event. if( st->transitions.size() ) { - BOOST_FOREACH( TRANSITION tr, st->transitions ) + BOOST_FOREACH( TRANSITION& tr, st->transitions ) { if( tr.first.Matches( aEvent ) ) { + // as the state changes, the transition table has to be set up again st->transitions.clear(); // no tool context allocated yet? Create one. @@ -350,6 +365,9 @@ void TOOL_MANAGER::dispatchInternal( TOOL_EVENT& aEvent ) if( !st->cofunc->Running() ) finishTool( st ); // The couroutine has finished immediately? + + // there is no point in further checking, as transitions got cleared + break; } } } @@ -394,21 +412,18 @@ bool TOOL_MANAGER::dispatchActivation( TOOL_EVENT& aEvent ) void TOOL_MANAGER::finishTool( TOOL_STATE* aState ) { - // Find the tool to be deactivated - std::deque::iterator it, it_end; + std::deque::iterator it, itEnd; - for( it = m_activeTools.begin(), it_end = m_activeTools.end(); it != it_end; ++it ) + // Find the tool and deactivate it + for( it = m_activeTools.begin(), itEnd = m_activeTools.end(); it != itEnd; ++it ) { if( aState == m_toolIdIndex[*it] ) + { + m_activeTools.erase( it ); break; + } } - if( it != m_activeTools.end() ) - m_activeTools.erase( it ); - else - wxLogWarning( wxT( "Tried to finish inactive tool" ) ); - - aState->idle = true; delete aState->cofunc; aState->cofunc = NULL; } @@ -445,9 +460,12 @@ bool TOOL_MANAGER::ProcessEvent( TOOL_EVENT& aEvent ) boost::scoped_ptr menu( new CONTEXT_MENU( *st->contextMenu ) ); GetEditFrame()->PopupMenu( menu->GetMenu() ); - // - TOOL_EVENT evt( TC_COMMAND, TA_CONTEXT_MENU_CHOICE ); - dispatchInternal( evt ); + // If nothing was chosen from the context menu, we must notify the tool as well + if( menu->GetSelected() < 0 ) + { + TOOL_EVENT evt( TC_COMMAND, TA_CONTEXT_MENU_CHOICE ); + dispatchInternal( evt ); + } break; } @@ -456,7 +474,8 @@ bool TOOL_MANAGER::ProcessEvent( TOOL_EVENT& aEvent ) if( m_view->IsDirty() ) { PCB_EDIT_FRAME* f = static_cast( GetEditFrame() ); - f->GetGalCanvas()->Refresh(); // fixme: ugly hack, provide a method in TOOL_DISPATCHER. + if( f->IsGalCanvasActive() ) + f->GetGalCanvas()->Refresh(); // fixme: ugly hack, provide a method in TOOL_DISPATCHER. } return false; @@ -492,15 +511,6 @@ void TOOL_MANAGER::SetEnvironment( EDA_ITEM* aModel, KIGFX::VIEW* aView, m_view = aView; m_viewControls = aViewControls; m_editFrame = aFrame; - - // Reset state of the registered tools - BOOST_FOREACH( TOOL_ID toolId, m_activeTools ) - { - TOOL_BASE* tool = m_toolIdIndex[toolId]->theTool; - - if( tool->GetType() == INTERACTIVE ) - static_cast( tool )->Reset(); - } } @@ -509,5 +519,6 @@ bool TOOL_MANAGER::isActive( TOOL_BASE* aTool ) if( !isRegistered( aTool ) ) return false; - return !m_toolState[aTool]->idle; + // Just check if the tool is on the active tools stack + return std::find( m_activeTools.begin(), m_activeTools.end(), aTool->GetId() ) != m_activeTools.end(); } diff --git a/common/view/view.cpp b/common/view/view.cpp index 8bde0d5aca..e27751bb76 100644 --- a/common/view/view.cpp +++ b/common/view/view.cpp @@ -34,9 +34,9 @@ #include #include -#ifdef __WXDEBUG__ +#ifdef PROFILE #include -#endif /* __WXDEBUG__ */ +#endif /* PROFILE */ using namespace KIGFX; @@ -122,6 +122,12 @@ void VIEW::Remove( VIEW_ITEM* aItem ) { VIEW_LAYER& l = m_layers[layers[i]]; l.items->Remove( aItem ); + MarkTargetDirty( l.target ); + + // Clear the GAL cache + int prevGroup = aItem->getGroup( layers[i] ); + if( prevGroup >= 0 ) + m_gal->DeleteGroup( prevGroup ); } } @@ -833,7 +839,7 @@ void VIEW::clearGroupCache() } -void VIEW::invalidateItem( VIEW_ITEM* aItem, int aUpdateFlags ) +void VIEW::InvalidateItem( VIEW_ITEM* aItem, int aUpdateFlags ) { // updateLayers updates geometry too, so we do not have to update both of them at the same time if( aUpdateFlags & VIEW_ITEM::LAYERS ) @@ -944,6 +950,12 @@ void VIEW::updateLayers( VIEW_ITEM* aItem ) VIEW_LAYER& l = m_layers[layers[i]]; l.items->Remove( aItem ); MarkTargetDirty( l.target ); + + // Redraw the item from scratch + int prevGroup = aItem->getGroup( layers[i] ); + + if( prevGroup >= 0 ) + m_gal->DeleteGroup( prevGroup ); } // Add the item to new layer set @@ -983,10 +995,10 @@ void VIEW::RecacheAllItems( bool aImmediately ) r.SetMaximum(); -#ifdef __WXDEBUG__ +#ifdef PROFILE prof_counter totalRealTime; prof_start( &totalRealTime ); -#endif /* __WXDEBUG__ */ +#endif /* PROFILE */ for( LAYER_MAP_ITER i = m_layers.begin(); i != m_layers.end(); ++i ) { @@ -1002,12 +1014,12 @@ void VIEW::RecacheAllItems( bool aImmediately ) } } -#ifdef __WXDEBUG__ +#ifdef PROFILE prof_end( &totalRealTime ); wxLogDebug( wxT( "RecacheAllItems::immediately: %u %.1f ms" ), aImmediately, totalRealTime.msecs() ); -#endif /* __WXDEBUG__ */ +#endif /* PROFILE */ } diff --git a/common/view/view_item.cpp b/common/view/view_item.cpp index 1521c88a9e..305ab68579 100644 --- a/common/view/view_item.cpp +++ b/common/view/view_item.cpp @@ -34,17 +34,13 @@ void VIEW_ITEM::ViewSetVisible( bool aIsVisible ) bool update = false; if( m_visible != aIsVisible ) - { update = true; - } m_visible = aIsVisible; // update only if the visibility has really changed if( update ) - { ViewUpdate( APPEARANCE ); - } } @@ -53,16 +49,14 @@ void VIEW_ITEM::ViewUpdate( int aUpdateFlags ) if( !m_view ) return; - m_view->invalidateItem( this, aUpdateFlags ); + m_view->InvalidateItem( this, aUpdateFlags ); } void VIEW_ITEM::ViewRelease() { if( m_view && m_view->IsDynamic() ) - { m_view->Remove( this ); - } } diff --git a/common/view/wx_view_controls.cpp b/common/view/wx_view_controls.cpp index 7f7308d935..48107911d2 100644 --- a/common/view/wx_view_controls.cpp +++ b/common/view/wx_view_controls.cpp @@ -73,19 +73,12 @@ void WX_VIEW_CONTROLS::onMotion( wxMouseEvent& aEvent ) m_mousePosition.x = aEvent.GetX(); m_mousePosition.y = aEvent.GetY(); - if( m_forceCursorPosition ) - m_cursorPosition = m_view->ToScreen( m_forcedPosition ); - else if( m_snappingEnabled ) - m_cursorPosition = m_view->GetGAL()->GetGridPoint( m_mousePosition ); - else - m_cursorPosition = m_mousePosition; + updateCursor(); bool isAutoPanning = false; if( m_autoPanEnabled ) - { isAutoPanning = handleAutoPanning( aEvent ); - } if( !isAutoPanning && aEvent.Dragging() ) { @@ -168,17 +161,13 @@ void WX_VIEW_CONTROLS::onButton( wxMouseEvent& aEvent ) } if( aEvent.LeftUp() ) - { m_state = IDLE; // Stop autopanning when user release left mouse button - } break; case DRAG_PANNING: if( aEvent.MiddleUp() ) - { m_state = IDLE; - } break; } @@ -210,8 +199,23 @@ void WX_VIEW_CONTROLS::onTimer( wxTimerEvent& aEvent ) dir = m_view->ToWorld( dir, false ); m_view->SetCenter( m_view->GetCenter() + dir * m_autoPanSpeed ); + updateCursor(); + // Notify tools that the cursor position has changed in the world coordinates - wxCommandEvent moveEvent( EVT_REFRESH_MOUSE ); + wxMouseEvent moveEvent( EVT_REFRESH_MOUSE ); + + // Set the modifiers state +#if wxCHECK_VERSION( 3, 0, 0 ) + moveEvent.SetControlDown( wxGetKeyState( WXK_CONTROL ) ); + moveEvent.SetShiftDown( wxGetKeyState( WXK_SHIFT ) ); + moveEvent.SetAltDown( wxGetKeyState( WXK_ALT) ); +#else + // wx <3.0 do not have accessors, but the fields are exposed + moveEvent.m_controlDown = wxGetKeyState( WXK_CONTROL ); + moveEvent.m_shiftDown = wxGetKeyState( WXK_SHIFT ); + moveEvent.m_altDown = wxGetKeyState( WXK_ALT ); +#endif + wxPostEvent( m_parentPanel, moveEvent ); } break; @@ -225,7 +229,7 @@ void WX_VIEW_CONTROLS::onTimer( wxTimerEvent& aEvent ) void WX_VIEW_CONTROLS::SetGrabMouse( bool aEnabled ) { - m_grabMouse = aEnabled; + VIEW_CONTROLS::SetGrabMouse( aEnabled ); if( aEnabled ) m_parentPanel->CaptureMouse(); @@ -243,15 +247,6 @@ const VECTOR2D WX_VIEW_CONTROLS::GetMousePosition() const } -const VECTOR2D WX_VIEW_CONTROLS::GetCursorPosition() const -{ - if( m_snappingEnabled ) - return m_view->GetGAL()->GetGridPoint( GetMousePosition() ); - else - return GetMousePosition(); -} - - bool WX_VIEW_CONTROLS::handleAutoPanning( const wxMouseEvent& aEvent ) { VECTOR2D p( aEvent.GetX(), aEvent.GetY() ); @@ -309,3 +304,14 @@ bool WX_VIEW_CONTROLS::handleAutoPanning( const wxMouseEvent& aEvent ) wxASSERT_MSG( false, wxT( "This line should never be reached" ) ); return false; // Should not be reached, just avoid the compiler warnings.. } + + +void WX_VIEW_CONTROLS::updateCursor() +{ + if( m_forceCursorPosition ) + m_cursorPosition = m_view->ToScreen( m_forcedPosition ); + else if( m_snappingEnabled ) + m_cursorPosition = m_view->GetGAL()->GetGridPoint( m_mousePosition ); + else + m_cursorPosition = m_mousePosition; +} diff --git a/common/worksheet_viewitem.cpp b/common/worksheet_viewitem.cpp index 7ecf6de8d7..ba4185f8af 100644 --- a/common/worksheet_viewitem.cpp +++ b/common/worksheet_viewitem.cpp @@ -36,10 +36,8 @@ using namespace KIGFX; -WORKSHEET_VIEWITEM::WORKSHEET_VIEWITEM( const std::string& aFileName, const std::string& aSheetName, - const PAGE_INFO* aPageInfo, const TITLE_BLOCK* aTitleBlock ) : +WORKSHEET_VIEWITEM::WORKSHEET_VIEWITEM( const PAGE_INFO* aPageInfo, const TITLE_BLOCK* aTitleBlock ) : EDA_ITEM( NOT_USED ), // this item is never added to a BOARD so it needs no type - m_fileName( aFileName ), m_sheetName( aSheetName ), m_titleBlock( aTitleBlock ), m_pageInfo( aPageInfo ), m_sheetNumber( 1 ), m_sheetCount( 1 ) {} diff --git a/cvpcb/class_DisplayFootprintsFrame.h b/cvpcb/class_DisplayFootprintsFrame.h index 52b1366813..3244d62325 100644 --- a/cvpcb/class_DisplayFootprintsFrame.h +++ b/cvpcb/class_DisplayFootprintsFrame.h @@ -124,7 +124,7 @@ public: * @param aTransformPoint = the reference point of the transformation, * for commands like move */ - virtual void SaveCopyInUndoList( PICKED_ITEMS_LIST& aItemsList, + virtual void SaveCopyInUndoList( const PICKED_ITEMS_LIST& aItemsList, UNDO_REDO_T aTypeCommand, const wxPoint& aTransformPoint = wxPoint( 0, 0 ) ) { diff --git a/eeschema/schematic_undo_redo.cpp b/eeschema/schematic_undo_redo.cpp index 2312cae2b1..caa2b4671b 100644 --- a/eeschema/schematic_undo_redo.cpp +++ b/eeschema/schematic_undo_redo.cpp @@ -160,7 +160,7 @@ void SCH_EDIT_FRAME::SaveCopyInUndoList( SCH_ITEM* aItem, } -void SCH_EDIT_FRAME::SaveCopyInUndoList( PICKED_ITEMS_LIST& aItemsList, +void SCH_EDIT_FRAME::SaveCopyInUndoList( const PICKED_ITEMS_LIST& aItemsList, UNDO_REDO_T aTypeCommand, const wxPoint& aTransformPoint ) { diff --git a/gerbview/gerbview_frame.h b/gerbview/gerbview_frame.h index 6a69191706..9cabd38b16 100644 --- a/gerbview/gerbview_frame.h +++ b/gerbview/gerbview_frame.h @@ -676,7 +676,7 @@ public: * @param aTransformPoint = the reference point of the transformation, * for commands like move */ - void SaveCopyInUndoList( PICKED_ITEMS_LIST& aItemsList, + void SaveCopyInUndoList( const PICKED_ITEMS_LIST& aItemsList, UNDO_REDO_T aTypeCommand, const wxPoint& aTransformPoint = wxPoint( 0, 0 ) ) { diff --git a/include/class_board_item.h b/include/class_board_item.h index 6f6bf201d6..ceb428af5e 100644 --- a/include/class_board_item.h +++ b/include/class_board_item.h @@ -83,8 +83,7 @@ protected: public: BOARD_ITEM( BOARD_ITEM* aParent, KICAD_T idtype ) : - EDA_ITEM( aParent, idtype ) - , m_Layer( FIRST_LAYER ) + EDA_ITEM( aParent, idtype ), m_Layer( FIRST_LAYER ) { } @@ -94,6 +93,16 @@ public: virtual void SetPosition( const wxPoint& aPos ) = 0; + /** + * Function IsConnected() + * Returns information if the object is derived from BOARD_CONNECTED_ITEM. + * @return True if the object is of BOARD_CONNECTED_ITEM type, false otherwise. + */ + virtual bool IsConnected() const + { + return false; + } + /** * A value of wxPoint(0,0) which can be passed to the Draw() functions. */ diff --git a/include/class_undoredo_container.h b/include/class_undoredo_container.h index 6c95bae24d..13c9e85b23 100644 --- a/include/class_undoredo_container.h +++ b/include/class_undoredo_container.h @@ -111,7 +111,7 @@ public: void SetStatus( UNDO_REDO_T aStatus ) { m_undoRedoStatus = aStatus; } - UNDO_REDO_T GetStatus() { return m_undoRedoStatus; } + UNDO_REDO_T GetStatus() const { return m_undoRedoStatus; } void SetFlags( STATUS_FLAGS aFlags ) { m_pickerFlags = aFlags; } @@ -148,7 +148,7 @@ public: * pushes \a aItem to the top of the list * @param aItem Picker to push on to the list. */ - void PushItem( ITEM_PICKER& aItem ); + void PushItem( const ITEM_PICKER& aItem ); /** * Function PopItem @@ -160,7 +160,14 @@ public: * Function IsItemInList * @return True if \a aItem is found in the pick list. */ - bool ContainsItem( EDA_ITEM* aItem ) const; + bool ContainsItem( const EDA_ITEM* aItem ) const; + + /** + * Function FindItem + * @return Index of the searched item. If the item is not stored in the list, negative value + * is returned. + */ + int FindItem( const EDA_ITEM* aItem ) const; /** * Function ClearItemsList @@ -201,21 +208,21 @@ public: * if this picker does not exist, a picker is returned, * with its members set to 0 or NULL */ - ITEM_PICKER GetItemWrapper( unsigned int aIdx ); + ITEM_PICKER GetItemWrapper( unsigned int aIdx ) const; /** * Function GetPickedItem * @return A pointer to the picked item * @param aIdx Index of the picked item in the picked list */ - EDA_ITEM* GetPickedItem( unsigned int aIdx ); + EDA_ITEM* GetPickedItem( unsigned int aIdx ) const; /** * Function GetPickedItemLink * @return link of the picked item, or null if does not exist * @param aIdx Index of the picked item in the picked list */ - EDA_ITEM* GetPickedItemLink( unsigned int aIdx ); + EDA_ITEM* GetPickedItemLink( unsigned int aIdx ) const; /** * Function GetPickedItemStatus @@ -223,7 +230,7 @@ public: * or UR_UNSPECIFIED if does not exist * @param aIdx Index of the picked item in the picked list */ - UNDO_REDO_T GetPickedItemStatus( unsigned int aIdx ); + UNDO_REDO_T GetPickedItemStatus( unsigned int aIdx ) const; /** * Function GetPickerFlags @@ -231,7 +238,7 @@ public: * @param aIdx Index of the picker in the picked list * @return The value stored in the picker, if the picker exists, or 0 if does not exist */ - STATUS_FLAGS GetPickerFlags( unsigned aIdx ); + STATUS_FLAGS GetPickerFlags( unsigned aIdx ) const; /** * Function SetPickedItem diff --git a/include/gal/color4d.h b/include/gal/color4d.h index c476f10e0e..fb4d9d9cf3 100644 --- a/include/gal/color4d.h +++ b/include/gal/color4d.h @@ -136,7 +136,7 @@ public: * Function Brightened * Returns a color that is brighter by a given factor, without modifying object. * @param aFactor Specifies how bright the color should become (valid values: 0.0 .. 1.0). - * @return COLOR4D Highlightedd color. + * @return COLOR4D Highlighted color. */ COLOR4D Brightened( double aFactor ) const { diff --git a/include/hashtables.h b/include/hashtables.h index edb3f798e0..ed319ec64c 100644 --- a/include/hashtables.h +++ b/include/hashtables.h @@ -98,6 +98,24 @@ struct fnv_1a }; +/// Hash function for wxString, counterpart of std::string hash +struct WXSTRING_HASH : std::unary_function +{ + std::size_t operator()( const wxString& aString ) const + { + std::size_t hash = 2166136261u; + + for( wxString::const_iterator it = aString.begin(); it != aString.end(); ++it ) + { + hash ^= (unsigned char) *it; + hash *= 16777619; + } + + return hash; + } +}; + + /** * Type KEYWORD_MAP * is a hashtable made of a const char* and an int. Note that use of this diff --git a/include/math/vector2d.h b/include/math/vector2d.h index 09cae7b31f..feee5ff060 100644 --- a/include/math/vector2d.h +++ b/include/math/vector2d.h @@ -31,6 +31,7 @@ #include #include #include +#include #include diff --git a/include/tool/action_manager.h b/include/tool/action_manager.h index 239ad606b7..fa66a23eba 100644 --- a/include/tool/action_manager.h +++ b/include/tool/action_manager.h @@ -47,6 +47,12 @@ public: */ ACTION_MANAGER( TOOL_MANAGER* aToolManager ); + /** + * Destructor. + * Unregisters every registered action. + */ + ~ACTION_MANAGER(); + /** * Function RegisterAction() * Adds a tool action to the manager and sets it up. After that is is possible to invoke @@ -75,18 +81,21 @@ public: */ bool RunAction( const std::string& aActionName ) const; - // TODO to be considered - // bool RunAction( int aActionId ) const; - // bool RunAction( TOOL_ACTION* aAction ) const; - /** * Function RunHotKey() * Runs an action associated with a hotkey (if there is one available). - * @param aHotKey is the hotkey to be served. + * @param aHotKey is the hotkey to be handled. * @return True if there was an action associated with the hotkey, false otherwise. */ bool RunHotKey( int aHotKey ) const; + /** + * Function ClearHotKey() + * Removes an action associated with a hotkey. + * @param aHotKey is the hotkey to be cleared. + */ + void ClearHotKey( int aHotKey ); + private: ///> Tool manager needed to run actions TOOL_MANAGER* m_toolMgr; diff --git a/include/tool/context_menu.h b/include/tool/context_menu.h index 90a5e106e8..df6f7cb0b7 100644 --- a/include/tool/context_menu.h +++ b/include/tool/context_menu.h @@ -78,6 +78,17 @@ public: */ void Clear(); + /** + * Function GetSelected() + * Returns the position of selected item. If the returned value is negative, that means that + * menu was dismissed. + * @return The position of selected item in the context menu. + */ + int GetSelected() const + { + return m_selected; + } + /** * Function GetMenu() * Returns the instance of wxMenu object used to display the menu. @@ -131,6 +142,9 @@ private: ///> Instance of wxMenu used for display of the context menu. wxMenu m_menu; + ///> Stores the id number of selected item. + int m_selected; + ///> Instance of menu event handler. CMEventHandler m_handler; diff --git a/include/tool/tool_base.h b/include/tool/tool_base.h index 7425ea8801..681e3099d9 100644 --- a/include/tool/tool_base.h +++ b/include/tool/tool_base.h @@ -70,6 +70,33 @@ public: virtual ~TOOL_BASE() {}; + ///> Determines the reason of reset for a tool + enum RESET_REASON + { + RUN, ///< Tool is invoked after being inactive + MODEL_RELOAD, ///< Model changes + GAL_SWITCH ///< Rendering engine changes + }; + + /** + * Function Init() + * Init() is called once upon a registration of the tool. + * + * @return True if the initialization went fine, false - otherwise. + */ + virtual bool Init() + { + return true; + } + + /** + * Function Reset() + * Brings the tool to a known, initial state. If the tool claimed anything from + * the model or the view, it must release it when its reset. + * @param aReason contains information about the reason of tool reset. + */ + virtual void Reset( RESET_REASON aReason ) = 0; + /** * Function GetType() * Returns the type of the tool. diff --git a/include/tool/tool_event.h b/include/tool/tool_event.h index 44cb4379cd..46b06e1eed 100644 --- a/include/tool/tool_event.h +++ b/include/tool/tool_event.h @@ -54,39 +54,46 @@ enum TOOL_EVENT_CATEGORY enum TOOL_ACTIONS { // UI input events - TA_NONE = 0x0000, - TA_MOUSE_CLICK = 0x0001, - TA_MOUSE_UP = 0x0002, - TA_MOUSE_DOWN = 0x0004, - TA_MOUSE_DRAG = 0x0008, - TA_MOUSE_MOTION = 0x0010, - TA_MOUSE_WHEEL = 0x0020, - TA_MOUSE = 0x003f, - TA_KEY_UP = 0x0040, - TA_KEY_DOWN = 0x0080, - TA_KEYBOARD = TA_KEY_UP | TA_KEY_DOWN, + TA_NONE = 0x0000, + TA_MOUSE_CLICK = 0x0001, + TA_MOUSE_DBLCLICK = 0x0002, + TA_MOUSE_UP = 0x0004, + TA_MOUSE_DOWN = 0x0008, + TA_MOUSE_DRAG = 0x0010, + TA_MOUSE_MOTION = 0x0020, + TA_MOUSE_WHEEL = 0x0040, + TA_MOUSE = 0x007f, + + TA_KEY_UP = 0x0080, + TA_KEY_DOWN = 0x0100, + TA_KEYBOARD = TA_KEY_UP | TA_KEY_DOWN, // View related events - TA_VIEW_REFRESH = 0x0100, - TA_VIEW_ZOOM = 0x0200, - TA_VIEW_PAN = 0x0400, - TA_VIEW_DIRTY = 0x0800, - TA_CHANGE_LAYER = 0x1000, + TA_VIEW_REFRESH = 0x0200, + TA_VIEW_ZOOM = 0x0400, + TA_VIEW_PAN = 0x0800, + TA_VIEW_DIRTY = 0x1000, + TA_VIEW = 0x1e00, + + TA_CHANGE_LAYER = 0x2000, // Tool cancel event. Issued automagically when the user hits escape or selects End Tool from // the context menu. - TA_CANCEL_TOOL = 0x2000, + TA_CANCEL_TOOL = 0x4000, // Context menu update. Issued whenever context menu is open and the user hovers the mouse // over one of choices. Used in dynamic highligting in disambiguation menu - TA_CONTEXT_MENU_UPDATE = 0x4000, + TA_CONTEXT_MENU_UPDATE = 0x8000, // Context menu choice. Sent if the user picked something from the context menu or // closed it without selecting anything. - TA_CONTEXT_MENU_CHOICE = 0x8000, + TA_CONTEXT_MENU_CHOICE = 0x10000, + + // This event is sent *before* undo/redo command is performed. + TA_UNDO_REDO = 0x20000, // Tool action (allows to control tools) - TA_ACTION = 0x10000, + TA_ACTION = 0x40000, TA_ANY = 0xffffffff }; @@ -233,6 +240,12 @@ public: && ( ( m_mouseButtons & aButtonMask ) == aButtonMask ); } + bool IsDblClick( int aButtonMask = BUT_ANY ) const + { + return ( m_actions == TA_MOUSE_DBLCLICK ) + && ( ( m_mouseButtons & aButtonMask ) == aButtonMask ); + } + bool IsDrag( int aButtonMask = BUT_ANY ) const { return ( m_actions == TA_MOUSE_DRAG ) && ( ( m_mouseButtons & aButtonMask ) == aButtonMask ); @@ -277,7 +290,7 @@ public: void SetMouseDragOrigin( const VECTOR2D& aP ) { m_mouseDragOrigin = aP; - } + } void SetMousePosition( const VECTOR2D& aP ) { @@ -311,6 +324,9 @@ public: if( m_commandId && aEvent.m_commandId ) return *m_commandId == *aEvent.m_commandId; + + // Command-type event has to contain either id or string + assert( false ); } return true; diff --git a/include/tool/tool_interactive.h b/include/tool/tool_interactive.h index 855f84af5c..7e816bd3a4 100644 --- a/include/tool/tool_interactive.h +++ b/include/tool/tool_interactive.h @@ -48,24 +48,6 @@ public: TOOL_INTERACTIVE( const std::string& aName ); virtual ~TOOL_INTERACTIVE(); - /** - * Function Reset() - * Brings the tool to a known, initial state. If the tool claimed anything from - * the model or the view, it must release it when its reset. - */ - virtual void Reset() = 0; - - /** - * Function Init() - * Init() is called once upon a registration of the tool. - * - * @return True if the initialization went fine, false - otherwise. - */ - virtual bool Init() - { - return true; - } - /** * Function SetContextMenu() * diff --git a/include/tool/tool_manager.h b/include/tool/tool_manager.h index 38a2879ccd..6e9c18acb0 100644 --- a/include/tool/tool_manager.h +++ b/include/tool/tool_manager.h @@ -99,6 +99,15 @@ public: */ void UnregisterAction( TOOL_ACTION* aAction ); + /** + * Function RunAction() + * Runs the specified action. The common format is "application.ToolName.Action". + * + * @param aActionName is the name of action to be invoked. + * @return True if the action finished successfully, false otherwise. + */ + bool RunAction( const std::string& aActionName ); + /** * Function FindTool() * Searches for a tool with given ID. @@ -118,10 +127,10 @@ public: TOOL_BASE* FindTool( const std::string& aName ) const; /** - * Resets the state of a given tool by clearing its wait and - * transition lists and calling tool's internal Reset() method. + * Function ResetTools() + * Resets all tools (i.e. calls their Reset() method). */ - void ResetTool( TOOL_BASE* aTool ); + void ResetTools( TOOL_BASE::RESET_REASON aReason ); /** * Takes an event from the TOOL_DISPATCHER and propagates it to diff --git a/include/ttl/halfedge/hetraits.h b/include/ttl/halfedge/hetraits.h index e25e993e0e..e24cd0697d 100644 --- a/include/ttl/halfedge/hetraits.h +++ b/include/ttl/halfedge/hetraits.h @@ -69,9 +69,6 @@ namespace hed { struct TTLtraits { - // The actual triangulation object - static Triangulation* triang_; - /** The floating point type used in calculations * involving scalar products and cross products. */ @@ -172,127 +169,6 @@ namespace hed { } //@} // End of Geometric Predicates Group - - - // A rationale for directing these functions to traits is: - // e.g., constraints - - //---------------------------------------------------------------------------------------------- - /* Checks if the edge associated with \e dart should be swapped - * according to the Delaunay criterion.
- * - * \note - * This function is also present in the TTL as ttl::swapTestDelaunay.
- * Thus, the function can be implemented simply as: - * \code - * { return ttl::swapTestDelaunay(dart); } - * \endcode - */ - //static bool swapTestDelaunay(const Dart& dart) { - // return ttl::swapTestDelaunay(dart); - //} - - - //---------------------------------------------------------------------------------------------- - /* Checks if the edge associated with \e dart can be swapped, i.e., - * if the edge is a diagonal in a (strictly) convex quadrilateral. - * This function is also present as ttl::swappableEdge. - */ - //static bool swappableEdge(const Dart& dart) { - // return ttl::swappableEdge(dart); - //} - - - //---------------------------------------------------------------------------------------------- - /* Checks if the edge associated with \e dart should be \e fixed, meaning - * that it should never be swapped. ??? Use when constraints. - */ - //static bool fixedEdge(const Dart& dart) { - // return dart.getEdge()->isConstrained(); - //} - - - //---------------------------------------------------------------------------------------------- - // ----------------------- Functions for Delaunay Triangulation Group ------------------------- - //---------------------------------------------------------------------------------------------- - - /** @name Functions for Delaunay Triangulation */ - //@{ - - //---------------------------------------------------------------------------------------------- - /** Swaps the edge associated with \e dart in the actual data structure. - * - *
- * \image html swapEdge.gif - *
- * - * \param dart - * Some of the functions require a dart as output. - * If this is required by the actual function, the dart should be delivered - * back in a position as seen if it was glued to the edge when swapping (rotating) - * the edge CCW; see the figure. - * - * \note - * - If the edge is \e constrained, or if it should not be swapped for - * some other reason, this function need not do the actual swap of the edge. - * - Some functions in TTL require that \c swapEdge is implemented such that - * darts outside the quadrilateral are not affected by the swap. - */ - static void swapEdge(Dart& dart) { - if (!dart.getEdge()->isConstrained()) triang_->swapEdge(dart.getEdge()); - } - - - //---------------------------------------------------------------------------------------------- - /** Splits the triangle associated with \e dart in the actual data structure into - * three new triangles joining at \e point. - * - *
- * \image html splitTriangle.gif - *
- * - * \param dart - * Output: A CCW dart incident with the new node; see the figure. - */ - static void splitTriangle(Dart& dart, NodePtr point) { - EdgePtr edge = triang_->splitTriangle(dart.getEdge(), point); - dart.init(edge); - } - - //@} // End of Functions for Delaunay Triangulation group - - - //---------------------------------------------------------------------------------------------- - // --------------------------- Functions for removing nodes Group ----------------------------- - //---------------------------------------------------------------------------------------------- - - /** @name Functions for removing nodes */ - //@{ - - //---------------------------------------------------------------------------------------------- - /** The reverse operation of TTLtraits::splitTriangle. - * This function is only required for functions that involve - * removal of interior nodes; see for example ttl::removeInteriorNode. - * - *
- * \image html reverse_splitTriangle.gif - *
- */ - static void reverse_splitTriangle(Dart& dart) { - triang_->reverse_splitTriangle(dart.getEdge()); - } - - - //---------------------------------------------------------------------------------------------- - /** Removes a triangle with an edge at the boundary of the triangulation - * in the actual data structure - */ - static void removeBoundaryTriangle(Dart& d) { - triang_->removeTriangle(d.getEdge()); - } - - //@} // End of Functions for removing nodes Group - }; }; // End of hed namespace diff --git a/include/ttl/halfedge/hetriang.h b/include/ttl/halfedge/hetriang.h index ccee31bc0c..2c5380864e 100644 --- a/include/ttl/halfedge/hetriang.h +++ b/include/ttl/halfedge/hetriang.h @@ -51,9 +51,13 @@ #include #include #include -#include #include #include +#include + +namespace ttl { + class TriangulationHelper; +}; //-------------------------------------------------------------------------------------------------- // The half-edge data structure @@ -65,6 +69,7 @@ namespace hed { class Edge; typedef boost::shared_ptr NodePtr; typedef boost::shared_ptr EdgePtr; + typedef boost::weak_ptr EdgeWeakPtr; typedef std::vector NodesContainer; //------------------------------------------------------------------------------------------------ @@ -151,8 +156,7 @@ public: class Edge { public: /// Constructor - Edge() : weight_(0) - { flags_.isLeadingEdge_ = false; flags_.isConstrained_ = false; } + Edge() : weight_(0), isLeadingEdge_(false) {} /// Destructor virtual ~Edge() {} @@ -167,49 +171,52 @@ public: void setTwinEdge(const EdgePtr& edge) { twinEdge_ = edge; } /// Sets the edge as a leading edge - void setAsLeadingEdge(bool val=true) { flags_.isLeadingEdge_ = val; } + void setAsLeadingEdge(bool val=true) { isLeadingEdge_ = val; } /// Checks if an edge is a leading edge - bool isLeadingEdge() const { return flags_.isLeadingEdge_; } - - /// Sets the edge as a constrained edge - void setConstrained(bool val=true) { flags_.isConstrained_ = val; - if (twinEdge_) twinEdge_->flags_.isConstrained_ = val; } - - /// Checks if an edge is constrained - bool isConstrained() const { return flags_.isConstrained_; } + bool isLeadingEdge() const { return isLeadingEdge_; } /// Returns the twin edge - const EdgePtr& getTwinEdge() const { return twinEdge_; }; + EdgePtr getTwinEdge() const { return twinEdge_.lock(); }; + + void clearTwinEdge() { twinEdge_.reset(); } /// Returns the next edge in face const EdgePtr& getNextEdgeInFace() const { return nextEdgeInFace_; } /// Retuns the source node - virtual const NodePtr& getSourceNode() const { return sourceNode_; } + const NodePtr& getSourceNode() const { return sourceNode_; } /// Returns the target node - virtual const NodePtr& getTargetNode() const { return getNextEdgeInFace()->getSourceNode(); } + virtual const NodePtr& getTargetNode() const { return nextEdgeInFace_->getSourceNode(); } void setWeight( unsigned int weight ) { weight_ = weight; } unsigned int getWeight() const { return weight_; } + void clear() + { + sourceNode_.reset(); + nextEdgeInFace_.reset(); + + if( !twinEdge_.expired() ) + { + twinEdge_.lock()->clearTwinEdge(); + twinEdge_.reset(); + } + } + protected: NodePtr sourceNode_; - EdgePtr twinEdge_; + EdgeWeakPtr twinEdge_; EdgePtr nextEdgeInFace_; unsigned int weight_; - - struct { - bool isLeadingEdge_; - bool isConstrained_; - } flags_; + bool isLeadingEdge_; }; // End of class Edge /** \class EdgeMST - * \brief \b %Specialization of Edge class to be used for Minimum Spanning Tree algorithm. + * \brief \b Specialization of %Edge class to be used for Minimum Spanning Tree algorithm. */ class EdgeMST : public Edge { @@ -221,10 +228,17 @@ public: target_(target) { sourceNode_ = source; weight_ = weight; } + EdgeMST( const Edge& edge ) + { + sourceNode_ = edge.getSourceNode(); + target_ = edge.getTargetNode(); + weight_ = edge.getWeight(); + } + ~EdgeMST() {}; /// @copydoc Edge::setSourceNode() - const NodePtr& getTargetNode() const { return target_; } + virtual const NodePtr& getTargetNode() const { return target_; } }; @@ -242,26 +256,75 @@ public: class Triangulation { protected: - list leadingEdges_; // one half-edge for each arc + std::list leadingEdges_; // one half-edge for each arc + + ttl::TriangulationHelper* helper; + void addLeadingEdge(EdgePtr& edge) { edge->setAsLeadingEdge(); leadingEdges_.push_front( edge ); } + bool removeLeadingEdgeFromList(EdgePtr& leadingEdge); + void cleanAll(); + /** Swaps the edge associated with \e dart in the actual data structure. + * + *
+ * \image html swapEdge.gif + *
+ * + * \param dart + * Some of the functions require a dart as output. + * If this is required by the actual function, the dart should be delivered + * back in a position as seen if it was glued to the edge when swapping (rotating) + * the edge CCW; see the figure. + * + * \note + * - If the edge is \e constrained, or if it should not be swapped for + * some other reason, this function need not do the actual swap of the edge. + * - Some functions in TTL require that \c swapEdge is implemented such that + * darts outside the quadrilateral are not affected by the swap. + */ + void swapEdge(Dart& dart); + + /** Splits the triangle associated with \e dart in the actual data structure into + * three new triangles joining at \e point. + * + *
+ * \image html splitTriangle.gif + *
+ * + * \param dart + * Output: A CCW dart incident with the new node; see the figure. + */ + void splitTriangle(Dart& dart, const NodePtr& point); + + /** The reverse operation of TTLtraits::splitTriangle. + * This function is only required for functions that involve + * removal of interior nodes; see for example TrinagulationHelper::removeInteriorNode. + * + *
+ * \image html reverse_splitTriangle.gif + *
+ */ + void reverse_splitTriangle(Dart& dart); + + /** Removes a triangle with an edge at the boundary of the triangulation + * in the actual data structure + */ + void removeBoundaryTriangle(Dart& d); + public: /// Default constructor - Triangulation() {} + Triangulation(); /// Copy constructor - Triangulation(const Triangulation& tr) { - std::cout << "Triangulation: Copy constructor not present - EXIT."; - exit(-1); - } + Triangulation(const Triangulation& tr); /// Destructor - ~Triangulation() { cleanAll(); } + ~Triangulation(); /// Creates a Delaunay triangulation from a set of points void createDelaunay(NodesContainer::iterator first, @@ -280,7 +343,7 @@ public: void swapEdge(EdgePtr& diagonal); /// Splits the triangle associated with edge into three new triangles joining at point - EdgePtr splitTriangle(EdgePtr& edge, NodePtr& point); + EdgePtr splitTriangle(EdgePtr& edge, const NodePtr& point); // Functions required by TTL for removing nodes in a Delaunay triangulation @@ -295,20 +358,20 @@ public: Dart createDart(); /// Returns a list of "triangles" (one leading half-edge for each triangle) - const list& getLeadingEdges() const { return leadingEdges_; } + const std::list& getLeadingEdges() const { return leadingEdges_; } /// Returns the number of triangles - int noTriangles() const { return (int)leadingEdges_.size(); } + int noTriangles() const { return (int)leadingEdges_.size(); } /// Returns a list of half-edges (one half-edge for each arc) - list* getEdges(bool skip_boundary_edges = false) const; + std::list* getEdges(bool skip_boundary_edges = false) const; #ifdef TTL_USE_NODE_FLAG /// Sets flag in all the nodes void flagNodes(bool flag) const; /// Returns a list of nodes. This function requires TTL_USE_NODE_FLAG to be defined. \see Node. - list* getNodes() const; + std::list* getNodes() const; #endif /// Swaps edges until the triangulation is Delaunay (constrained edges are not swapped) @@ -320,12 +383,16 @@ public: /// Returns an arbitrary interior node (as the source node of the returned edge) EdgePtr getInteriorNode() const; + EdgePtr getBoundaryEdgeInTriangle(const EdgePtr& e) const; + /// Returns an arbitrary boundary edge EdgePtr getBoundaryEdge() const; /// Print edges for plotting with, e.g., gnuplot void printEdges(std::ofstream& os) const; + friend class ttl::TriangulationHelper; + }; // End of class Triangulation diff --git a/include/ttl/ttl.h b/include/ttl/ttl.h index 003e0d81c6..7d7c655843 100644 --- a/include/ttl/ttl.h +++ b/include/ttl/ttl.h @@ -52,8 +52,6 @@ } #endif - using std::list; - // Next on TOPOLOGY: // - get triangle strips @@ -102,7 +100,7 @@ * - \e CW - clockwise * - \e 0_orbit, \e 1_orbit and \e 2_orbit: A sequence of darts around * a node, around an edge and in a triangle respectively; -* see ttl::get_0_orbit_interior and ttl::get_0_orbit_boundary +* see get_0_orbit_interior and get_0_orbit_boundary * - \e arc - In a triangulation an arc is equivalent with an edge * * \see @@ -115,15 +113,15 @@ namespace ttl { - +class TriangulationHelper +{ #ifndef DOXYGEN_SHOULD_SKIP_THIS - //------------------------------------------------------------------------------------------------ - // ----------------------------------- Forward declarations ------------------------------------- - //------------------------------------------------------------------------------------------------ -#if ((_MSC_VER > 0) && (_MSC_VER < 1300)) -#else - +public: + TriangulationHelper(hed::Triangulation& triang) : triangulation(triang) + { + } + // Delaunay Triangulation // ---------------------- template @@ -145,55 +143,55 @@ namespace ttl { // Topological and Geometric Queries // --------------------------------- template - bool locateFaceSimplest(const PointType& point, DartType& dart); + static bool locateFaceSimplest(const PointType& point, DartType& dart); template - bool locateTriangle(const PointType& point, DartType& dart); + static bool locateTriangle(const PointType& point, DartType& dart); template - bool inTriangleSimplest(const PointType& point, const DartType& dart); + static bool inTriangleSimplest(const PointType& point, const DartType& dart); template - bool inTriangle(const PointType& point, const DartType& dart); + static bool inTriangle(const PointType& point, const DartType& dart); template - void getBoundary(const DartType& dart, DartListType& boundary); + static void getBoundary(const DartType& dart, DartListType& boundary); template - bool isBoundaryEdge(const DartType& dart); + static bool isBoundaryEdge(const DartType& dart); template - bool isBoundaryFace(const DartType& dart); + static bool isBoundaryFace(const DartType& dart); template - bool isBoundaryNode(const DartType& dart); + static bool isBoundaryNode(const DartType& dart); template - int getDegreeOfNode(const DartType& dart); + static int getDegreeOfNode(const DartType& dart); template - void get_0_orbit_interior(const DartType& dart, DartListType& orbit); + static void get_0_orbit_interior(const DartType& dart, DartListType& orbit); template - void get_0_orbit_boundary(const DartType& dart, DartListType& orbit); + static void get_0_orbit_boundary(const DartType& dart, DartListType& orbit); template - bool same_0_orbit(const DartType& d1, const DartType& d2); + static bool same_0_orbit(const DartType& d1, const DartType& d2); template - bool same_1_orbit(const DartType& d1, const DartType& d2); + static bool same_1_orbit(const DartType& d1, const DartType& d2); template - bool same_2_orbit(const DartType& d1, const DartType& d2); + static bool same_2_orbit(const DartType& d1, const DartType& d2); template - bool swappableEdge(const DartType& dart, bool allowDegeneracy = false); + static bool swappableEdge(const DartType& dart, bool allowDegeneracy = false); template - void positionAtNextBoundaryEdge(DartType& dart); + static void positionAtNextBoundaryEdge(DartType& dart); template - bool convexBoundary(const DartType& dart); + static bool convexBoundary(const DartType& dart); // Utilities for Delaunay Triangulation @@ -205,7 +203,7 @@ namespace ttl { void optimizeDelaunay(DartListType& elist, const typename DartListType::iterator end); template - bool swapTestDelaunay(const DartType& dart, bool cycling_check = false); + bool swapTestDelaunay(const DartType& dart, bool cycling_check = false) const; template void recSwapDelaunay(DartType& diagonal); @@ -223,9 +221,29 @@ namespace ttl { // Constrained Triangulation // ------------------------- template - DartType insertConstraint(DartType& dstart, DartType& dend, bool optimize_delaunay); - -#endif + static DartType insertConstraint(DartType& dstart, DartType& dend, bool optimize_delaunay); + +private: + hed::Triangulation& triangulation; + + template + void insertNodes(ForwardIterator first, ForwardIterator last, DartType& dart); + + template + static bool isMemberOfFace(const TopologyElementType& topologyElement, const DartType& dart); + + template + static bool locateFaceWithNode(const NodeType& node, DartType& dart_iter); + + template + static void getAdjacentTriangles(const DartType& dart, DartType& t1, DartType& t2, DartType& t3); + + template + static void getNeighborNodes(const DartType& dart, std::list& node_list, bool& boundary); + + template + static bool degenerateTriangle(const DartType& dart); +}; #endif // DOXYGEN_SHOULD_SKIP_THIS @@ -245,7 +263,7 @@ namespace ttl { * can be created as two triangles forming a rectangle that contains * all the points. * After \c insertNode has been called repeatedly with all the points, - * ttl::removeRectangularBoundary can be called to remove triangles + * removeRectangularBoundary can be called to remove triangles * at the boundary of the triangulation so that the boundary * form the convex hull of the points. * @@ -268,19 +286,19 @@ namespace ttl { * - \ref hed::TTLtraits::splitTriangle "TraitsType::splitTriangle" (DartType&, const PointType&) * * \using - * - ttl::locateTriangle - * - ttl::recSwapDelaunay + * - locateTriangle + * - recSwapDelaunay * * \note * - For efficiency reasons \e dart should be close to the insertion \e point. * * \see - * ttl::removeRectangularBoundary + * removeRectangularBoundary */ template - bool insertNode(DartType& dart, PointType& point) { + bool TriangulationHelper::insertNode(DartType& dart, PointType& point) { - bool found = ttl::locateTriangle(point, dart); + bool found = locateTriangle(point, dart); if (!found) { #ifdef DEBUG_TTL cout << "ERROR: Triangulation::insertNode: NO triangle found. /n"; @@ -289,7 +307,7 @@ namespace ttl { } // ??? can we hide the dart? this is not possible if one triangle only - TraitsType::splitTriangle(dart, point); + triangulation.splitTriangle(dart, point); DartType d1 = dart; d1.alpha2().alpha1().alpha2().alpha0().alpha1(); @@ -304,14 +322,14 @@ namespace ttl { //DartType dsav = d3; d3.alpha0().alpha1(); - //if (!TraitsType::fixedEdge(d1) && !ttl::isBoundaryEdge(d1)) { - if (!ttl::isBoundaryEdge(d1)) { + //if (!TraitsType::fixedEdge(d1) && !isBoundaryEdge(d1)) { + if (!isBoundaryEdge(d1)) { d1.alpha2(); recSwapDelaunay(d1); } - //if (!TraitsType::fixedEdge(d2) && !ttl::isBoundaryEdge(d2)) { - if (!ttl::isBoundaryEdge(d2)) { + //if (!TraitsType::fixedEdge(d2) && !isBoundaryEdge(d2)) { + if (!isBoundaryEdge(d2)) { d2.alpha2(); recSwapDelaunay(d2); } @@ -319,8 +337,8 @@ namespace ttl { // Preserve the incoming dart as output incident to the node and CCW //d = dsav.alpha2(); dart.alpha2(); - //if (!TraitsType::fixedEdge(d3) && !ttl::isBoundaryEdge(d3)) { - if (!ttl::isBoundaryEdge(d3)) { + //if (!TraitsType::fixedEdge(d3) && !isBoundaryEdge(d3)) { + if (!isBoundaryEdge(d3)) { d3.alpha2(); recSwapDelaunay(d3); } @@ -332,7 +350,7 @@ namespace ttl { //------------------------------------------------------------------------------------------------ // Private/Hidden function (might change later) template - void insertNodes(ForwardIterator first, ForwardIterator last, DartType& dart) { + void TriangulationHelper::insertNodes(ForwardIterator first, ForwardIterator last, DartType& dart) { // Assumes that the dereferenced point objects are pointers. // References to the point objects are then passed to TTL. @@ -355,14 +373,14 @@ namespace ttl { * Output: A CCW dart at the new boundary * * \using - * - ttl::removeBoundaryNode + * - removeBoundaryNode * * \note * - This function requires that the boundary of the triangulation is * a rectangle with four nodes (one in each corner). */ template - void removeRectangularBoundary(DartType& dart) { + void TriangulationHelper::removeRectangularBoundary(DartType& dart) { DartType d_next = dart; DartType d_iter; @@ -370,8 +388,8 @@ namespace ttl { for (int i = 0; i < 4; i++) { d_iter = d_next; d_next.alpha0(); - ttl::positionAtNextBoundaryEdge(d_next); - ttl::removeBoundaryNode(d_iter); + positionAtNextBoundaryEdge(d_next); + removeBoundaryNode(d_iter); } dart = d_next; // Return a dart at the new boundary @@ -383,20 +401,20 @@ namespace ttl { * updates the triangulation to be Delaunay. * * \using - * - ttl::removeBoundaryNode if \e dart represents a node at the boundary - * - ttl::removeInteriorNode if \e dart represents an interior node + * - removeBoundaryNode if \e dart represents a node at the boundary + * - removeInteriorNode if \e dart represents an interior node * * \note * - The node cannot belong to a fixed (constrained) edge that is not * swappable. (An endless loop is likely to occur in this case). */ template - void removeNode(DartType& dart) { + void TriangulationHelper::removeNode(DartType& dart) { - if (ttl::isBoundaryNode(dart)) - ttl::removeBoundaryNode(dart); + if (isBoundaryNode(dart)) + removeBoundaryNode(dart); else - ttl::removeInteriorNode(dart); + removeInteriorNode(dart); } @@ -405,14 +423,14 @@ namespace ttl { * updates the triangulation to be Delaunay. * * \using - * - ttl::swapEdgesAwayFromBoundaryNode - * - ttl::optimizeDelaunay + * - swapEdgesAwayFromBoundaryNode + * - optimizeDelaunay * * \require * - \ref hed::TTLtraits::removeBoundaryTriangle "TraitsType::removeBoundaryTriangle" (Dart&) */ template - void removeBoundaryNode(DartType& dart) { + void TriangulationHelper::removeBoundaryNode(DartType& dart) { // ... and update Delaunay // - CCW dart must be given (for remove) @@ -420,13 +438,13 @@ namespace ttl { // we assume that there is not only one triangle left in the triangulation. // Position at boundary edge and CCW - if (!ttl::isBoundaryEdge(dart)) { + if (!isBoundaryEdge(dart)) { dart.alpha1(); // ensures that next function delivers back a CCW dart (if the given dart is CCW) - ttl::positionAtNextBoundaryEdge(dart); + positionAtNextBoundaryEdge(dart); } - list swapped_edges; - ttl::swapEdgesAwayFromBoundaryNode(dart, swapped_edges); + std::list swapped_edges; + swapEdgesAwayFromBoundaryNode(dart, swapped_edges); // Remove boundary triangles and remove the new boundary from the list // of swapped edges, see below. @@ -435,7 +453,7 @@ namespace ttl { bool bend = false; while (bend == false) { dnext.alpha1().alpha2(); - if (ttl::isBoundaryEdge(dnext)) + if (isBoundaryEdge(dnext)) bend = true; // Stop when boundary // Generic: Also remove the new boundary from the list of swapped edges @@ -443,20 +461,20 @@ namespace ttl { n_bedge.alpha1().alpha0().alpha1().alpha2(); // new boundary edge // ??? can we avoid find if we do this in swap away? - typename list::iterator it; + typename std::list::iterator it; it = find(swapped_edges.begin(), swapped_edges.end(), n_bedge); if (it != swapped_edges.end()) swapped_edges.erase(it); // Remove the boundary triangle - TraitsType::removeBoundaryTriangle(d_iter); + triangulation.removeBoundaryTriangle(d_iter); d_iter = dnext; } // Optimize Delaunay - typedef list DartListType; - ttl::optimizeDelaunay(swapped_edges); + typedef std::list DartListType; + optimizeDelaunay(swapped_edges); } @@ -465,8 +483,8 @@ namespace ttl { * updates the triangulation to be Delaunay. * * \using - * - ttl::swapEdgesAwayFromInteriorNode - * - ttl::optimizeDelaunay + * - swapEdgesAwayFromInteriorNode + * - optimizeDelaunay * * \require * - \ref hed::TTLtraits::reverse_splitTriangle "TraitsType::reverse_splitTriangle" (Dart&) @@ -476,7 +494,7 @@ namespace ttl { * swappable. (An endless loop is likely to occur in this case). */ template - void removeInteriorNode(DartType& dart) { + void TriangulationHelper::removeInteriorNode(DartType& dart) { // ... and update to Delaunay. // Must allow degeneracy temporarily, see comments in swap edges away @@ -492,13 +510,13 @@ namespace ttl { // Assumes dart is counterclockwise - list swapped_edges; - ttl::swapEdgesAwayFromInteriorNode(dart, swapped_edges); + std::list swapped_edges; + swapEdgesAwayFromInteriorNode(dart, swapped_edges); // The reverse operation of split triangle: // Make one triangle of the three triangles at the node associated with dart // TraitsType:: - TraitsType::reverse_splitTriangle(dart); + triangulation.reverse_splitTriangle(dart); // ???? Not generic yet if we are very strict: // When calling unsplit triangle, darts at the three opposite sides may @@ -511,7 +529,7 @@ namespace ttl { // Note the theoretical result: if there are no edges in the list, // the triangulation is Delaunay already - ttl::optimizeDelaunay(swapped_edges); + optimizeDelaunay(swapped_edges); } //@} // End of Delaunay Triangulation Group @@ -527,7 +545,7 @@ namespace ttl { //------------------------------------------------------------------------------------------------ // Private/Hidden function (might change later) template - bool isMemberOfFace(const TopologyElementType& topologyElement, const DartType& dart) { + bool TriangulationHelper::isMemberOfFace(const TopologyElementType& topologyElement, const DartType& dart) { // Check if the given topology element (node, edge or face) is a member of the face // Assumes: @@ -547,7 +565,7 @@ namespace ttl { //------------------------------------------------------------------------------------------------ // Private/Hidden function (might change later) template - bool locateFaceWithNode(const NodeType& node, DartType& dart_iter) { + bool TriangulationHelper::locateFaceWithNode(const NodeType& node, DartType& dart_iter) { // Locate a face in the topology structure with the given node as a member // Assumes: // - TraitsType::orient2d(DartType, DartType, NodeType) @@ -594,10 +612,10 @@ namespace ttl { * \e regular as explained above. * * \see - * ttl::locateTriangle + * locateTriangle */ template - bool locateFaceSimplest(const PointType& point, DartType& dart) { + bool TriangulationHelper::locateFaceSimplest(const PointType& point, DartType& dart) { // Not degenerate triangles if point is on the extension of the edges // But inTriangle may be called in case of true (may update to inFace2) // Convex boundary @@ -660,11 +678,11 @@ namespace ttl { * then the edge associated with \e dart will be at the boundary of the triangulation. * * \using - * - ttl::locateFaceSimplest - * - ttl::inTriangle + * - locateFaceSimplest + * - inTriangle */ template - bool locateTriangle(const PointType& point, DartType& dart) { + bool TriangulationHelper::locateTriangle(const PointType& point, DartType& dart) { // The purpose is to have a fast and stable procedure that // i) avoids concluding that a point is inside a triangle if it is not inside // ii) avoids infinite loops @@ -713,10 +731,10 @@ namespace ttl { * - \ref hed::TTLtraits::orient2d "TraitsType::orient2d" (DartType&, DartType&, PointType&) * * \see - * ttl::inTriangle for a more robust function + * inTriangle for a more robust function */ template - bool inTriangleSimplest(const PointType& point, const DartType& dart) { + bool TriangulationHelper::inTriangleSimplest(const PointType& point, const DartType& dart) { // Fast and simple: Do not deal with degenerate faces, i.e., if there is // degeneracy, true will be returned if the point is on the extension of the @@ -757,10 +775,10 @@ namespace ttl { * - \ref hed::TTLtraits::scalarProduct2d "TraitsType::scalarProduct2d" (DartType&, PointType&) * * \see - * ttl::inTriangleSimplest + * inTriangleSimplest */ template - bool inTriangle(const PointType& point, const DartType& dart) { + bool TriangulationHelper::inTriangle(const PointType& point, const DartType& dart) { // SHOULD WE INCLUDE A STRATEGY WITH EDGE X e_1 ETC? TO GUARANTEE THAT // ONLY ON ONE EDGE? BUT THIS DOES NOT SOLVE PROBLEMS WITH @@ -841,7 +859,7 @@ namespace ttl { //------------------------------------------------------------------------------------------------ // Private/Hidden function (might change later) template - void getAdjacentTriangles(const DartType& dart, DartType& t1, DartType& t2, DartType& t3) { + void TriangulationHelper::getAdjacentTriangles(const DartType& dart, DartType& t1, DartType& t2, DartType& t3) { DartType dart_iter = dart; @@ -886,7 +904,7 @@ namespace ttl { * - DartListType::push_back (DartType&) */ template - void getBoundary(const DartType& dart, DartListType& boundary) { + void TriangulationHelper::getBoundary(const DartType& dart, DartListType& boundary) { // assumes the given dart is at the boundary (by edge) DartType dart_iter(dart); @@ -932,7 +950,7 @@ namespace ttl { * \endcode */ template - bool isBoundaryEdge(const DartType& dart) { + bool TriangulationHelper::isBoundaryEdge(const DartType& dart) { DartType dart_iter = dart; if (dart_iter.alpha2() == dart) @@ -947,7 +965,7 @@ namespace ttl { * the boundary of the triangulation. */ template - bool isBoundaryFace(const DartType& dart) { + bool TriangulationHelper::isBoundaryFace(const DartType& dart) { // Strategy: boundary if alpha2(d)=d @@ -976,7 +994,7 @@ namespace ttl { * the boundary of the triangulation. */ template - bool isBoundaryNode(const DartType& dart) { + bool TriangulationHelper::isBoundaryNode(const DartType& dart) { // Strategy: boundary if alpha2(d)=d @@ -1009,7 +1027,7 @@ namespace ttl { * the number of edges joining \e V with another node in the triangulation. */ template - int getDegreeOfNode(const DartType& dart) { + int TriangulationHelper::getDegreeOfNode(const DartType& dart) { DartType dart_iter(dart); DartType dart_prev; @@ -1069,7 +1087,8 @@ namespace ttl { // Private/Hidden function template - void getNeighborNodes(const DartType& dart, std::list& node_list, bool& boundary) { + void TriangulationHelper::getNeighborNodes(const DartType& dart, + std::list& node_list, bool& boundary) { DartType dart_iter(dart); @@ -1131,10 +1150,10 @@ namespace ttl { * - DartListType::push_back (DartType&) * * \see - * ttl::get_0_orbit_boundary + * get_0_orbit_boundary */ template - void get_0_orbit_interior(const DartType& dart, DartListType& orbit) { + void TriangulationHelper::get_0_orbit_interior(const DartType& dart, DartListType& orbit) { DartType d_iter = dart; orbit.push_back(d_iter); @@ -1165,10 +1184,10 @@ namespace ttl { * - The last dart in the sequence have opposite orientation compared to the others! * * \see - * ttl::get_0_orbit_interior + * get_0_orbit_interior */ template - void get_0_orbit_boundary(const DartType& dart, DartListType& orbit) { + void TriangulationHelper::get_0_orbit_boundary(const DartType& dart, DartListType& orbit) { DartType dart_prev; DartType d_iter = dart; @@ -1195,17 +1214,17 @@ namespace ttl { * own version.) */ template - bool same_0_orbit(const DartType& d1, const DartType& d2) { + bool TriangulationHelper::same_0_orbit(const DartType& d1, const DartType& d2) { // Two copies of the same dart DartType d_iter = d2; DartType d_end = d2; - if (ttl::isBoundaryNode(d_iter)) { + if (isBoundaryNode(d_iter)) { // position at both boundary edges - ttl::positionAtNextBoundaryEdge(d_iter); + positionAtNextBoundaryEdge(d_iter); d_end.alpha1(); - ttl::positionAtNextBoundaryEdge(d_end); + positionAtNextBoundaryEdge(d_end); } for (;;) { @@ -1229,7 +1248,7 @@ namespace ttl { * \e d1 and/or \e d2 can be CCW or CW. */ template - bool same_1_orbit(const DartType& d1, const DartType& d2) { + bool TriangulationHelper::same_1_orbit(const DartType& d1, const DartType& d2) { DartType d_iter = d2; // (Also works at the boundary) @@ -1245,7 +1264,7 @@ namespace ttl { * \e d1 and/or \e d2 can be CCW or CW */ template - bool same_2_orbit(const DartType& d1, const DartType& d2) { + bool TriangulationHelper::same_2_orbit(const DartType& d1, const DartType& d2) { DartType d_iter = d2; if (d_iter == d1 || d_iter.alpha0() == d1 || @@ -1259,7 +1278,7 @@ namespace ttl { //------------------------------------------------------------------------------------------------ // Private/Hidden function template - bool degenerateTriangle(const DartType& dart) { + bool TriangulationHelper::degenerateTriangle(const DartType& dart) { // Check if triangle is degenerate // Assumes CCW dart @@ -1287,7 +1306,7 @@ namespace ttl { * - \ref hed::TTLtraits::crossProduct2d "TraitsType::crossProduct2d" (Dart&, Dart&) */ template - bool swappableEdge(const DartType& dart, bool allowDegeneracy) { + bool TriangulationHelper::swappableEdge(const DartType& dart, bool allowDegeneracy) { // How "safe" is it? @@ -1340,7 +1359,7 @@ namespace ttl { * infinit loop occurs. */ template - void positionAtNextBoundaryEdge(DartType& dart) { + void TriangulationHelper::positionAtNextBoundaryEdge(DartType& dart) { DartType dart_prev; @@ -1365,14 +1384,14 @@ namespace ttl { * - \ref hed::TTLtraits::crossProduct2d "TraitsType::crossProduct2d" (const Dart&, const Dart&) */ template - bool convexBoundary(const DartType& dart) { + bool TriangulationHelper::convexBoundary(const DartType& dart) { - list blist; - ttl::getBoundary(dart, blist); + std::list blist; + getBoundary(dart, blist); int no; no = (int)blist.size(); - typename list::const_iterator bit = blist.begin(); + typename std::list::const_iterator bit = blist.begin(); DartType d1 = *bit; ++bit; DartType d2; @@ -1428,17 +1447,17 @@ namespace ttl { * seen if it was glued to the edge when swapping (rotating) the edge CCW * * \using - * - ttl::swapTestDelaunay + * - swapTestDelaunay */ template - void optimizeDelaunay(DartListType& elist) { + void TriangulationHelper::optimizeDelaunay(DartListType& elist) { optimizeDelaunay(elist, elist.end()); } //------------------------------------------------------------------------------------------------ template - void optimizeDelaunay(DartListType& elist, const typename DartListType::iterator end) { + void TriangulationHelper::optimizeDelaunay(DartListType& elist, const typename DartListType::iterator end) { // CCW darts // Optimize here means Delaunay, but could be any criterion by @@ -1481,14 +1500,14 @@ namespace ttl { while(!optimal) { optimal = true; for (it = elist.begin(); it != end_opt; ++it) { - if (ttl::swapTestDelaunay(*it, cycling_check)) { + if (swapTestDelaunay(*it, cycling_check)) { // Preserve darts. Potential darts in the list are: // - The current dart // - the four CCW darts on the boundary of the quadrilateral // (the current arc has only one dart) - ttl::swapEdgeInList(it, elist); + swapEdgeInList(it, elist); optimal = false; } // end if should swap @@ -1513,9 +1532,9 @@ namespace ttl { */ template #if ((_MSC_VER > 0) && (_MSC_VER < 1300))//#ifdef _MSC_VER - bool swapTestDelaunay(const DartType& dart, bool cycling_check = false) { + bool TriangulationHelper::swapTestDelaunay(const DartType& dart, bool cycling_check = false) const { #else - bool swapTestDelaunay(const DartType& dart, bool cycling_check) { + bool TriangulationHelper::swapTestDelaunay(const DartType& dart, bool cycling_check) const { #endif // The general strategy is taken from Cline & Renka. They claim that @@ -1627,17 +1646,17 @@ namespace ttl { * - Calls itself recursively */ template - void recSwapDelaunay(DartType& diagonal) { + void TriangulationHelper::recSwapDelaunay(DartType& diagonal) { - if (!ttl::swapTestDelaunay(diagonal)) - // ??? ttl::swapTestDelaunay also checks if boundary, so this can be optimized + if (!swapTestDelaunay(diagonal)) + // ??? swapTestDelaunay also checks if boundary, so this can be optimized return; // Get the other "edges" of the current triangle; see illustration above. DartType oppEdge1 = diagonal; oppEdge1.alpha1(); bool b1; - if (ttl::isBoundaryEdge(oppEdge1)) + if (isBoundaryEdge(oppEdge1)) b1 = true; else { b1 = false; @@ -1648,7 +1667,7 @@ namespace ttl { DartType oppEdge2 = diagonal; oppEdge2.alpha0().alpha1().alpha0(); bool b2; - if (ttl::isBoundaryEdge(oppEdge2)) + if (isBoundaryEdge(oppEdge2)) b2 = true; else { b2 = false; @@ -1656,7 +1675,7 @@ namespace ttl { } // Swap the given diagonal - TraitsType::swapEdge(diagonal); + triangulation.swapEdge(diagonal); if (!b1) recSwapDelaunay(oppEdge1); @@ -1669,7 +1688,7 @@ namespace ttl { /** Swaps edges away from the (interior) node associated with * \e dart such that that exactly three edges remain incident * with the node. - * This function is used as a first step in ttl::removeInteriorNode + * This function is used as a first step in removeInteriorNode * * \retval dart * A CCW dart incident with the node @@ -1689,10 +1708,10 @@ namespace ttl { * at the node that is given as input. * * \see - * ttl::swapEdgesAwayFromBoundaryNode + * swapEdgesAwayFromBoundaryNode */ template - void swapEdgesAwayFromInteriorNode(DartType& dart, ListType& swapped_edges) { + void TriangulationHelper::swapEdgesAwayFromInteriorNode(DartType& dart, ListType& swapped_edges) { // Same iteration as in fixEdgesAtCorner, but not boundary DartType dnext = dart; @@ -1706,14 +1725,14 @@ namespace ttl { // infinite loop with degree > 3. bool allowDegeneracy = true; - int degree = ttl::getDegreeOfNode(dart); + int degree = getDegreeOfNode(dart); DartType d_iter; while (degree > 3) { d_iter = dnext; dnext.alpha1().alpha2(); - if (ttl::swappableEdge(d_iter, allowDegeneracy)) { - TraitsType::swapEdge(d_iter); // swap the edge away + if (swappableEdge(d_iter, allowDegeneracy)) { + triangulation.swapEdge(d_iter); // swap the edge away // Collect swapped edges in the list // "Hide" the dart on the other side of the edge to avoid it being changed for // other swaps @@ -1733,7 +1752,7 @@ namespace ttl { /** Swaps edges away from the (boundary) node associated with * \e dart in such a way that when removing the edges that remain incident * with the node, the boundary of the triangulation will be convex. - * This function is used as a first step in ttl::removeBoundaryNode + * This function is used as a first step in removeBoundaryNode * * \retval dart * A CCW dart incident with the node @@ -1747,10 +1766,10 @@ namespace ttl { * - The node associated with \e dart is at the boundary of the triangulation. * * \see - * ttl::swapEdgesAwayFromInteriorNode + * swapEdgesAwayFromInteriorNode */ template - void swapEdgesAwayFromBoundaryNode(DartType& dart, ListType& swapped_edges) { + void TriangulationHelper::swapEdgesAwayFromBoundaryNode(DartType& dart, ListType& swapped_edges) { // All darts that are swappable. // To treat collinear nodes at an existing boundary, we must allow degeneracy @@ -1762,7 +1781,7 @@ namespace ttl { // - A dart on the swapped edge is delivered back in a position as // seen if it was glued to the edge when swapping (rotating) the edge CCW - //int degree = ttl::getDegreeOfNode(dart); + //int degree = getDegreeOfNode(dart); passes: @@ -1780,7 +1799,7 @@ passes: while (!bend) { d_next.alpha1().alpha2(); - if (ttl::isBoundaryEdge(d_next)) + if (isBoundaryEdge(d_next)) bend = true; // then it is CW since alpha2 // To allow removing among collinear nodes at the boundary, @@ -1789,13 +1808,13 @@ passes: tmp1 = d_iter; tmp1.alpha1(); tmp2 = d_iter; tmp2.alpha2().alpha1(); // don't bother with boundary (checked later) - if (ttl::isBoundaryEdge(tmp1) && ttl::isBoundaryEdge(tmp2)) + if (isBoundaryEdge(tmp1) && isBoundaryEdge(tmp2)) allowDegeneracy = true; else allowDegeneracy = false; - if (ttl::swappableEdge(d_iter, allowDegeneracy)) { - TraitsType::swapEdge(d_iter); + if (swappableEdge(d_iter, allowDegeneracy)) { + triangulation.swapEdge(d_iter); // Collect swapped edges in the list // "Hide" the dart on the other side of the edge to avoid it being changed for @@ -1821,7 +1840,7 @@ passes: else { d_iter.alpha1(); // CW and see below } - ttl::positionAtNextBoundaryEdge(d_iter); // CCW + positionAtNextBoundaryEdge(d_iter); // CCW dart = d_iter; // for next pass or output @@ -1839,7 +1858,7 @@ passes: * keep them in \e elist. */ template - void swapEdgeInList(const typename DartListType::iterator& it, DartListType& elist) { + void TriangulationHelper::swapEdgeInList(const typename DartListType::iterator& it, DartListType& elist) { typename DartListType::iterator it1, it2, it3, it4; DartType dart(*it); @@ -1867,7 +1886,7 @@ passes: it3 = find(elist.begin(), elist.end(), d3); it4 = find(elist.begin(), elist.end(), d4); - TraitsType::swapEdge(dart); + triangulation.swapEdge(dart); // Update the current dart which may have changed *it = dart; diff --git a/include/ttl/ttl_constr.h b/include/ttl/ttl_constr.h index 67b46fcbf0..125bddeb23 100644 --- a/include/ttl/ttl_constr.h +++ b/include/ttl/ttl_constr.h @@ -51,9 +51,6 @@ static ofstream ofile_constr("qweCons.dat"); #endif - -//using namespace std; - /** \brief Constrained Delaunay triangulation * * Basic generic algorithms in TTL for inserting a constrained edge between two existing nodes.\n @@ -61,7 +58,7 @@ * See documentation for the namespace ttl for general requirements and assumptions. * * \author -* Øyvind Hjelle, oyvindhj@ifi.uio.no +* �yvind Hjelle, oyvindhj@ifi.uio.no */ namespace ttl_constr { @@ -73,6 +70,9 @@ namespace ttl_constr { #endif +class ConstrainedTriangulation +{ + public: //------------------------------------------------------------------------------------------------ /* Checks if \e dart has start and end points in \e dstart and \e dend. * @@ -89,14 +89,14 @@ namespace ttl_constr { * A bool confirming that it's the constraint or not * * \using - * ttl::same_0_orbit + * same_0_orbit */ template - bool isTheConstraint(const DartType& dart, const DartType& dstart, const DartType& dend) { + static bool isTheConstraint(const DartType& dart, const DartType& dstart, const DartType& dend) { DartType d0 = dart; d0.alpha0(); // CW - if ((ttl::same_0_orbit(dstart, dart) && ttl::same_0_orbit(dend, d0)) || - (ttl::same_0_orbit(dstart, d0) && ttl::same_0_orbit(dend, dart))) { + if ((ttl::TriangulationHelper::same_0_orbit(dstart, dart) && ttl::TriangulationHelper::same_0_orbit(dend, d0)) || + (ttl::TriangulationHelper::same_0_orbit(dstart, d0) && ttl::TriangulationHelper::same_0_orbit(dend, dart))) { return true; } return false; @@ -123,7 +123,7 @@ namespace ttl_constr { * TraitsType::orient2d */ template - bool crossesConstraint(DartType& dstart, DartType& dend, DartType& d1, DartType& d2) { + static bool crossesConstraint(DartType& dstart, DartType& dend, DartType& d1, DartType& d2) { typename TraitsType::real_type orient_1 = TraitsType::orient2d(dstart,d1,dend); typename TraitsType::real_type orient_2 = TraitsType::orient2d(dstart,d2,dend); @@ -156,12 +156,12 @@ namespace ttl_constr { * The dart \e d making the smallest positive (or == 0) angle * * \using - * ttl::isBoundaryNode - * ttl::positionAtNextBoundaryEdge + * isBoundaryNode + * positionAtNextBoundaryEdge * TraitsType::orient2d */ template - DartType getAtSmallestAngle(const DartType& dstart, const DartType& dend) { + static DartType getAtSmallestAngle(const DartType& dstart, const DartType& dend) { // - Must boundary be convex??? // - Handle the case where the constraint is already present??? @@ -169,9 +169,9 @@ namespace ttl_constr { // (dstart and dend may define a boundary edge) DartType d_iter = dstart; - if (ttl::isBoundaryNode(d_iter)) { + if (ttl::TriangulationHelper::isBoundaryNode(d_iter)) { d_iter.alpha1(); // CW - ttl::positionAtNextBoundaryEdge(d_iter); // CCW (was rotated CW to the boundary) + ttl::TriangulationHelper::positionAtNextBoundaryEdge(d_iter); // CCW (was rotated CW to the boundary) } // assume convex boundary; see comments @@ -273,7 +273,7 @@ namespace ttl_constr { * Returns the next "collinear" starting node such that dend is returned when done. */ template - DartType findCrossingEdges(const DartType& dstart, const DartType& dend, ListType& elist) { + static DartType findCrossingEdges(const DartType& dstart, const DartType& dend, ListType& elist) { const DartType my_start = getAtSmallestAngle(dstart, dend); DartType my_end = getAtSmallestAngle(dend, dstart); @@ -387,15 +387,16 @@ namespace ttl_constr { * A list containing all the edges crossing the spesified constraint * * \using - * ttl::swappableEdge - * ttl::swapEdgeInList - * ttl::crossesConstraint - * ttl::isTheConstraint + * swappableEdge + * swapEdgeInList + * crossesConstraint + * isTheConstraint */ template - void transformToConstraint(DartType& dstart, DartType& dend, std::list& elist) { + void transformToConstraint(ttl::TriangulationHelper helper, DartType& dstart, DartType& dend, + std::list& elist) const { - typename list::iterator it, used; + typename std::list::iterator it, used; // We may enter in a situation where dstart and dend are altered because of a swap. // (The general rule is that darts inside the actual quadrilateral can be changed, @@ -423,7 +424,7 @@ namespace ttl_constr { if (counter > dartsInList) break; - if (ttl::swappableEdge(*it, true)) { + if (ttl::TriangulationHelper::swappableEdge(*it, true)) { // Dyn & Goren & Rippa 's notation: // The node assosiated with dart *it is denoted u_m. u_m has edges crossing the constraint // named w_1, ... , w_r . The other node to the edge assosiated with dart *it is w_s. @@ -456,7 +457,7 @@ namespace ttl_constr { end = true; // This is the only place swapping is called when inserting a constraint - ttl::swapEdgeInList(it,elist); + helper.swapEdgeInList(it,elist); // If we, during look-ahead, found that dstart and/or dend were in the quadrilateral, // we update them. @@ -512,6 +513,8 @@ namespace ttl_constr { } +}; // End of ConstrainedTriangulation class + }; // End of ttl_constr namespace scope @@ -546,14 +549,14 @@ namespace ttl { // (extension) * - \ref hed::TTLtraits::swapEdge "TraitsType::swapEdge" (DartType&) * * \using - * - ttl::optimizeDelaunay if \e optimize_delaunay is set to \c true + * - optimizeDelaunay if \e optimize_delaunay is set to \c true * * \par Assumes: * - The constrained edge must be inside the existing triangulation (and it cannot * cross the boundary of the triangulation). */ template - DartType insertConstraint(DartType& dstart, DartType& dend, bool optimize_delaunay) { + DartType TriangulationHelper::insertConstraint(DartType& dstart, DartType& dend, bool optimize_delaunay) { // Assumes: // - It is the users responsibility to avoid crossing constraints @@ -567,8 +570,8 @@ namespace ttl { // (extension) // calls itself recursively. // RECURSION - list elist; - DartType next_start = ttl_constr::findCrossingEdges(dstart, dend, elist); + std::list elist; + DartType next_start = ttl_constr::ConstrainedTriangulation::findCrossingEdges(dstart, dend, elist); // If there are no crossing edges (elist is empty), we assume that the constraint // is an existing edge. @@ -583,7 +586,7 @@ namespace ttl { // (extension) // findCrossingEdges stops if it finds a node lying on the constraint. // A dart with this node as start node is returned // We call insertConstraint recursivly until the received dart is dend - if (!ttl::same_0_orbit(next_start, dend)) { + if (!same_0_orbit(next_start, dend)) { #ifdef DEBUG_TTL_CONSTR_PLOT cout << "RECURSION due to collinearity along constraint" << endl; @@ -594,7 +597,7 @@ namespace ttl { // (extension) // Swap edges such that the constraint edge is present in the transformed triangulation. if (elist.size() > 0) // by Thomas Sevaldrud - ttl_constr::transformToConstraint(dstart, next_start, elist); + ttl_constr::ConstrainedTriangulation::transformToConstraint(dstart, next_start, elist); #ifdef DEBUG_TTL_CONSTR_PLOT cout << "size of elist = " << elist.size() << endl; @@ -607,13 +610,13 @@ namespace ttl { // (extension) #endif // Optimize to constrained Delaunay triangulation if required. - typename list::iterator end_opt = elist.end(); + typename std::list::iterator end_opt = elist.end(); if (optimize_delaunay) { // Indicate that the constrained edge, which is the last element in the list, // should not be swapped --end_opt; - ttl::optimizeDelaunay(elist, end_opt); + optimizeDelaunay(elist, end_opt); } if(elist.size() == 0) // by Thomas Sevaldrud diff --git a/include/view/view.h b/include/view/view.h index a5e0756219..f7a7e90984 100644 --- a/include/view/view.h +++ b/include/view/view.h @@ -493,6 +493,14 @@ public: m_scaleLimits = VECTOR2D( aMaximum, aMinimum ); } + /** + * Function InvalidateItem() + * Manages dirty flags & redraw queueing when updating an item. + * @param aItem is the item to be updated. + * @param aUpdateFlags determines the way an item is refreshed. + */ + void InvalidateItem( VIEW_ITEM* aItem, int aUpdateFlags ); + static const int VIEW_MAX_LAYERS = 128; ///* maximum number of layers that may be shown private: @@ -563,11 +571,6 @@ private: */ void draw( VIEW_GROUP* aGroup, bool aImmediate = false ) const; - - ///* Manages dirty flags & redraw queueing when updating an item. Called internally - /// via VIEW_ITEM::ViewUpdate() - void invalidateItem( VIEW_ITEM* aItem, int aUpdateFlags ); - ///* Sorts m_orderedLayers when layer rendering order has changed void sortLayers(); diff --git a/include/view/view_controls.h b/include/view/view_controls.h index a51048dca3..5ec1a037a4 100644 --- a/include/view/view_controls.h +++ b/include/view/view_controls.h @@ -60,7 +60,7 @@ public: * * @param aEnabled says whether the opion should be enabled or disabled. */ - void SetSnapping( bool aEnabled ) + virtual void SetSnapping( bool aEnabled ) { m_snappingEnabled = aEnabled; } diff --git a/include/view/wx_view_controls.h b/include/view/wx_view_controls.h index f5561f7d2d..41540e951b 100644 --- a/include/view/wx_view_controls.h +++ b/include/view/wx_view_controls.h @@ -58,6 +58,13 @@ public: void onEnter( wxMouseEvent& WXUNUSED( aEvent ) ); void onTimer( wxTimerEvent& WXUNUSED( aEvent ) ); + ///> @copydoc VIEW_CONTROLS::SetSnapping() + void SetSnapping( bool aEnabled ) + { + VIEW_CONTROLS::SetSnapping( aEnabled ); + updateCursor(); + } + /** * Function SetGrabMouse() * Enables/disables mouse cursor grabbing (limits the movement field only to the panel area). @@ -84,7 +91,10 @@ public: const VECTOR2D GetMousePosition() const; /// @copydoc VIEW_CONTROLS::GetCursorPosition() - const VECTOR2D GetCursorPosition() const; + const VECTOR2D GetCursorPosition() const + { + return m_cursorPosition; + } /// Event that forces mouse move event in the dispatcher (eg. used in autopanning, when mouse /// cursor does not move in screen coordinates, but does in world coordinates) @@ -109,6 +119,12 @@ private: */ bool handleAutoPanning( const wxMouseEvent& aEvent ); + /** + * Function updateCursor() + * Recomputes the cursor coordinates basing on the current snapping settings and mouse position. + */ + void updateCursor(); + /// Current state of VIEW_CONTROLS STATE m_state; diff --git a/include/worksheet_viewitem.h b/include/worksheet_viewitem.h index 6380af9fd8..ca506c8577 100644 --- a/include/worksheet_viewitem.h +++ b/include/worksheet_viewitem.h @@ -47,8 +47,7 @@ class GAL; class WORKSHEET_VIEWITEM : public EDA_ITEM { public: - WORKSHEET_VIEWITEM( const std::string& aFileName, const std::string& aSheetName, - const PAGE_INFO* aPageInfo, const TITLE_BLOCK* aTitleBlock ); + WORKSHEET_VIEWITEM( const PAGE_INFO* aPageInfo, const TITLE_BLOCK* aTitleBlock ); /** * Function SetFileName() diff --git a/include/wxBasePcbFrame.h b/include/wxBasePcbFrame.h index 23935428c8..139b6f4d3f 100644 --- a/include/wxBasePcbFrame.h +++ b/include/wxBasePcbFrame.h @@ -622,7 +622,7 @@ public: * @param aTransformPoint = the reference point of the transformation, * for commands like move */ - virtual void SaveCopyInUndoList( PICKED_ITEMS_LIST& aItemsList, + virtual void SaveCopyInUndoList( const PICKED_ITEMS_LIST& aItemsList, UNDO_REDO_T aTypeCommand, const wxPoint& aTransformPoint = wxPoint( 0, 0 ) ) = 0; diff --git a/include/wxEeschemaStruct.h b/include/wxEeschemaStruct.h index 9956a37778..61eebdf8eb 100644 --- a/include/wxEeschemaStruct.h +++ b/include/wxEeschemaStruct.h @@ -1094,7 +1094,7 @@ public: * @param aTransformPoint = the reference point of the transformation, * for commands like move */ - void SaveCopyInUndoList( PICKED_ITEMS_LIST& aItemsList, + void SaveCopyInUndoList( const PICKED_ITEMS_LIST& aItemsList, UNDO_REDO_T aTypeCommand, const wxPoint& aTransformPoint = wxPoint( 0, 0 ) ); diff --git a/include/wxPcbStruct.h b/include/wxPcbStruct.h index b46756fe5e..219c411523 100644 --- a/include/wxPcbStruct.h +++ b/include/wxPcbStruct.h @@ -680,7 +680,7 @@ public: * @param aTransformPoint = the reference point of the transformation, for * commands like move */ - virtual void SaveCopyInUndoList( PICKED_ITEMS_LIST& aItemsList, + virtual void SaveCopyInUndoList( const PICKED_ITEMS_LIST& aItemsList, UNDO_REDO_T aTypeCommand, const wxPoint& aTransformPoint = wxPoint( 0, 0 ) ); @@ -705,7 +705,7 @@ public: * - Get an old version of the board from Redo list * @return none */ - void GetBoardFromRedoList( wxCommandEvent& event ); + void GetBoardFromRedoList( wxCommandEvent& aEvent ); /** * Function GetBoardFromUndoList @@ -714,7 +714,7 @@ public: * - Get an old version of the board from Undo list * @return none */ - void GetBoardFromUndoList( wxCommandEvent& event ); + void GetBoardFromUndoList( wxCommandEvent& aEvent ); /* Block operations: */ diff --git a/pcbnew/CMakeLists.txt b/pcbnew/CMakeLists.txt index 87455ff48e..50061110f1 100644 --- a/pcbnew/CMakeLists.txt +++ b/pcbnew/CMakeLists.txt @@ -226,7 +226,6 @@ set( PCBNEW_CLASS_SRCS print_board_functions.cpp printout_controler.cpp ratsnest.cpp - ratsnest_data.cpp ratsnest_viewitem.cpp # specctra.cpp #moved in pcbcommon lib # specctra_export.cpp @@ -256,7 +255,7 @@ set( PCBNEW_CLASS_SRCS tools/selection_tool.cpp tools/selection_area.cpp tools/bright_box.cpp - tools/move_tool.cpp + tools/edit_tool.cpp tools/pcb_tools.cpp tools/common_actions.cpp ) diff --git a/pcbnew/attribut.cpp b/pcbnew/attribut.cpp index 2bc380abf1..c56f09da24 100644 --- a/pcbnew/attribut.cpp +++ b/pcbnew/attribut.cpp @@ -103,7 +103,7 @@ void PCB_EDIT_FRAME::Attribut_net( wxDC* DC, int net_code, bool Flag_On ) { for( ; Track != NULL; Track = Track->Next() ) { - if( net_code == Track->GetNet() ) + if( net_code == Track->GetNetCode() ) break; } } @@ -112,7 +112,7 @@ void PCB_EDIT_FRAME::Attribut_net( wxDC* DC, int net_code, bool Flag_On ) while( Track ) /* Flag change */ { - if( (net_code >= 0 ) && (net_code != Track->GetNet()) ) + if( ( net_code >= 0 ) && ( net_code != Track->GetNetCode() ) ) break; OnModify(); diff --git a/pcbnew/autorouter/auto_place_footprints.cpp b/pcbnew/autorouter/auto_place_footprints.cpp index 7322f5690b..0351c43bd1 100644 --- a/pcbnew/autorouter/auto_place_footprints.cpp +++ b/pcbnew/autorouter/auto_place_footprints.cpp @@ -499,7 +499,7 @@ int genPlacementRoutingMatrix( BOARD* aBrd, EDA_MSG_PANEL* messagePanel ) TRACK TmpSegm( NULL ); TmpSegm.SetLayer( UNDEFINED_LAYER ); - TmpSegm.SetNet( -1 ); + TmpSegm.SetNetCode( -1 ); TmpSegm.SetWidth( RoutingMatrix.m_GridRouting / 2 ); EDA_ITEM* PtStruct = aBrd->m_Drawings; diff --git a/pcbnew/autorouter/autorout.cpp b/pcbnew/autorouter/autorout.cpp index b0dc59b0b7..88f2e12e6e 100644 --- a/pcbnew/autorouter/autorout.cpp +++ b/pcbnew/autorouter/autorout.cpp @@ -78,7 +78,7 @@ void PCB_EDIT_FRAME::Autoroute( wxDC* DC, int mode ) { case PCB_PAD_T: Pad = (D_PAD*) GetScreen()->GetCurItem(); - autoroute_net_code = Pad->GetNet(); + autoroute_net_code = Pad->GetNetCode(); break; default: diff --git a/pcbnew/autorouter/routing_matrix.cpp b/pcbnew/autorouter/routing_matrix.cpp index 1e57b80293..b5d02e926a 100644 --- a/pcbnew/autorouter/routing_matrix.cpp +++ b/pcbnew/autorouter/routing_matrix.cpp @@ -215,7 +215,7 @@ void PlaceCells( BOARD* aPcb, int net_code, int flag ) { D_PAD* pad = aPcb->GetPad( i ); - if( net_code != pad->GetNet() || (flag & FORCE_PADS) ) + if( net_code != pad->GetNetCode() || (flag & FORCE_PADS) ) { ::PlacePad( pad, HOLE, marge, WRITE_CELL ); } @@ -247,7 +247,7 @@ void PlaceCells( BOARD* aPcb, int net_code, int flag ) tmpSegm.SetShape( edge->GetShape() ); tmpSegm.SetWidth( edge->GetWidth() ); tmpSegm.m_Param = edge->GetAngle(); - tmpSegm.SetNet( -1 ); + tmpSegm.SetNetCode( -1 ); TraceSegmentPcb( &tmpSegm, HOLE, marge, WRITE_CELL ); TraceSegmentPcb( &tmpSegm, VIA_IMPOSSIBLE, via_marge, WRITE_OR_CELL ); @@ -284,7 +284,7 @@ void PlaceCells( BOARD* aPcb, int net_code, int flag ) tmpSegm.SetShape( DrawSegm->GetShape() ); tmpSegm.SetWidth( DrawSegm->GetWidth() ); tmpSegm.m_Param = DrawSegm->GetAngle(); - tmpSegm.SetNet( -1 ); + tmpSegm.SetNetCode( -1 ); TraceSegmentPcb( &tmpSegm, type_cell, marge, WRITE_CELL ); } @@ -335,7 +335,7 @@ void PlaceCells( BOARD* aPcb, int net_code, int flag ) /* Put tracks and vias on matrix */ for( TRACK* track = aPcb->m_Track; track; track = track->Next() ) { - if( net_code == track->GetNet() ) + if( net_code == track->GetNetCode() ) continue; TraceSegmentPcb( track, HOLE, marge, WRITE_CELL ); @@ -374,7 +374,7 @@ int Build_Work( BOARD* Pcb ) pt_pad = pt_rats->m_PadStart; - current_net_code = pt_pad->GetNet(); + current_net_code = pt_pad->GetNetCode(); pt_ch = pt_rats; r1 = ( pt_pad->GetPosition().y - RoutingMatrix.m_BrdBox.GetY() + demi_pas ) diff --git a/pcbnew/autorouter/solve.cpp b/pcbnew/autorouter/solve.cpp index c06d8545eb..063d56c702 100644 --- a/pcbnew/autorouter/solve.cpp +++ b/pcbnew/autorouter/solve.cpp @@ -1180,7 +1180,7 @@ static void OrCell_Trace( BOARD* pcb, int col, int row, g_CurrentTrackSegment->SetWidth( pcb->GetCurrentViaSize() ); g_CurrentTrackSegment->SetShape( pcb->GetDesignSettings().m_CurrentViaType ); - g_CurrentTrackSegment->SetNet( current_net_code ); + g_CurrentTrackSegment->SetNetCode( current_net_code ); } else // placement of a standard segment { @@ -1198,7 +1198,7 @@ static void OrCell_Trace( BOARD* pcb, int col, int row, ( RoutingMatrix.m_GridRouting * row ), pcb->GetBoundingBox().GetY() + ( RoutingMatrix.m_GridRouting * col ))); - g_CurrentTrackSegment->SetNet( current_net_code ); + g_CurrentTrackSegment->SetNetCode( current_net_code ); if( g_CurrentTrackSegment->Back() == NULL ) /* Start trace. */ { @@ -1319,7 +1319,7 @@ static void AddNewTrace( PCB_EDIT_FRAME* pcbframe, wxDC* DC ) } // Insert new segments in real board - int netcode = g_FirstTrackSegment->GetNet(); + int netcode = g_FirstTrackSegment->GetNetCode(); TRACK* firstTrack = g_FirstTrackSegment; int newCount = g_CurrentTrackList.GetCount(); diff --git a/pcbnew/board_undo_redo.cpp b/pcbnew/board_undo_redo.cpp index cd058e172b..a5a3ad314e 100644 --- a/pcbnew/board_undo_redo.cpp +++ b/pcbnew/board_undo_redo.cpp @@ -25,6 +25,7 @@ #include #include +#include #include #include @@ -40,6 +41,10 @@ #include #include +#include + +#include +#include /* Functions to undo and redo edit commands. * commands to undo are stored in CurrentScreen->m_UndoList @@ -292,6 +297,17 @@ void PCB_EDIT_FRAME::SaveCopyInUndoList( BOARD_ITEM* aItem, if( aItem == NULL ) // Nothing to save return; + // For texts belonging to modules, we need to save state of the parent module + if( aItem->Type() == PCB_MODULE_TEXT_T ) + { + aItem = aItem->GetParent(); + wxASSERT( aItem->Type() == PCB_MODULE_T ); + aCommandType = UR_CHANGED; + + if( aItem == NULL ) + return; + } + PICKED_ITEMS_LIST* commandToUndo = new PICKED_ITEMS_LIST(); commandToUndo->m_TransformPoint = aTransformPoint; @@ -346,7 +362,7 @@ void PCB_EDIT_FRAME::SaveCopyInUndoList( BOARD_ITEM* aItem, } -void PCB_EDIT_FRAME::SaveCopyInUndoList( PICKED_ITEMS_LIST& aItemsList, +void PCB_EDIT_FRAME::SaveCopyInUndoList( const PICKED_ITEMS_LIST& aItemsList, UNDO_REDO_T aTypeCommand, const wxPoint& aTransformPoint ) { @@ -361,6 +377,20 @@ void PCB_EDIT_FRAME::SaveCopyInUndoList( PICKED_ITEMS_LIST& aItemsList, for( unsigned ii = 0; ii < commandToUndo->GetCount(); ii++ ) { BOARD_ITEM* item = (BOARD_ITEM*) commandToUndo->GetPickedItem( ii ); + + // For texts belonging to modules, we need to save state of the parent module + if( item->Type() == PCB_MODULE_TEXT_T ) + { + item = item->GetParent(); + wxASSERT( item->Type() == PCB_MODULE_T ); + + if( item == NULL ) + continue; + + commandToUndo->SetPickedItem( item, ii ); + commandToUndo->SetPickedItemStatus( UR_CHANGED, ii ); + } + UNDO_REDO_T command = commandToUndo->GetPickedItemStatus( ii ); if( command == UR_UNSPECIFIED ) @@ -424,13 +454,15 @@ void PCB_EDIT_FRAME::PutDataInPreviousState( PICKED_ITEMS_LIST* aList, bool aRed BOARD_ITEM* item; bool not_found = false; bool reBuild_ratsnest = false; + KIGFX::VIEW* view = GetGalCanvas()->GetView(); + RN_DATA* ratsnest = GetBoard()->GetRatsnest(); // Undo in the reverse order of list creation: (this can allow stacked changes // like the same item can be changes and deleted in the same complex command bool build_item_list = true; // if true the list of existing items must be rebuilt - for( int ii = aList->GetCount()-1; ii >= 0 ; ii-- ) + for( int ii = aList->GetCount() - 1; ii >= 0 ; ii-- ) { item = (BOARD_ITEM*) aList->GetPickedItem( ii ); wxASSERT( item ); @@ -484,37 +516,85 @@ void PCB_EDIT_FRAME::PutDataInPreviousState( PICKED_ITEMS_LIST* aList, bool aRed case UR_CHANGED: /* Exchange old and new data for each item */ { BOARD_ITEM* image = (BOARD_ITEM*) aList->GetPickedItemLink( ii ); + + // Remove all pads/drawings/texts, as they become invalid + // for the VIEW after SwapData() called for modules + if( item->Type() == PCB_MODULE_T ) + { + MODULE* oldModule = static_cast( item ); + oldModule->RunOnChildren( std::bind1st( std::mem_fun( &KIGFX::VIEW::Remove ), view ) ); + } + ratsnest->Remove( item ); + item->SwapData( image ); + + // Update all pads/drawings/texts, as they become invalid + // for the VIEW after SwapData() called for modules + if( item->Type() == PCB_MODULE_T ) + { + MODULE* newModule = static_cast( item ); + newModule->RunOnChildren( std::bind1st( std::mem_fun( &KIGFX::VIEW::Add ), view ) ); + } + ratsnest->Add( item ); + + item->ClearFlags( SELECTED ); + item->ViewUpdate( KIGFX::VIEW_ITEM::LAYERS ); } break; case UR_NEW: /* new items are deleted */ aList->SetPickedItemStatus( UR_DELETED, ii ); GetBoard()->Remove( item ); + + if( item->Type() == PCB_MODULE_T ) + { + MODULE* module = static_cast( item ); + module->RunOnChildren( std::bind1st( std::mem_fun( &KIGFX::VIEW::Remove ), view ) ); + } + view->Remove( item ); + + item->ViewUpdate( KIGFX::VIEW_ITEM::GEOMETRY ); break; case UR_DELETED: /* deleted items are put in List, as new items */ aList->SetPickedItemStatus( UR_NEW, ii ); GetBoard()->Add( item ); + + if( item->Type() == PCB_MODULE_T ) + { + MODULE* module = static_cast( item ); + module->RunOnChildren( std::bind1st( std::mem_fun( &KIGFX::VIEW::Add ), view ) ); + } + view->Add( item ); + + item->ViewUpdate( KIGFX::VIEW_ITEM::GEOMETRY ); build_item_list = true; break; case UR_MOVED: item->Move( aRedoCommand ? aList->m_TransformPoint : -aList->m_TransformPoint ); + item->ViewUpdate( KIGFX::VIEW_ITEM::GEOMETRY ); + ratsnest->Update( item ); break; case UR_ROTATED: item->Rotate( aList->m_TransformPoint, aRedoCommand ? m_rotationAngle : -m_rotationAngle ); + item->ViewUpdate( KIGFX::VIEW_ITEM::GEOMETRY ); + ratsnest->Update( item ); break; case UR_ROTATED_CLOCKWISE: item->Rotate( aList->m_TransformPoint, aRedoCommand ? -m_rotationAngle : m_rotationAngle ); + item->ViewUpdate( KIGFX::VIEW_ITEM::GEOMETRY ); + ratsnest->Update( item ); break; case UR_FLIPPED: item->Flip( aList->m_TransformPoint ); + item->ViewUpdate( KIGFX::VIEW_ITEM::LAYERS ); + ratsnest->Update( item ); break; default: @@ -533,15 +613,24 @@ void PCB_EDIT_FRAME::PutDataInPreviousState( PICKED_ITEMS_LIST* aList, bool aRed // Rebuild pointers and ratsnest that can be changed. if( reBuild_ratsnest && aRebuildRatsnet ) - Compile_Ratsnest( NULL, true ); + { + if( IsGalCanvasActive() ) + ratsnest->Recalculate(); + else + Compile_Ratsnest( NULL, true ); + } } -void PCB_EDIT_FRAME::GetBoardFromUndoList( wxCommandEvent& event ) +void PCB_EDIT_FRAME::GetBoardFromUndoList( wxCommandEvent& aEvent ) { if( GetScreen()->GetUndoCommandCount() <= 0 ) return; + // Inform tools that undo command was issued + TOOL_EVENT event( TC_MESSAGE, TA_UNDO_REDO, AS_GLOBAL ); + m_toolManager->ProcessEvent( event ); + /* Get the old list */ PICKED_ITEMS_LIST* List = GetScreen()->PopCommandFromUndoList(); /* Undo the command */ @@ -556,11 +645,14 @@ void PCB_EDIT_FRAME::GetBoardFromUndoList( wxCommandEvent& event ) } -void PCB_EDIT_FRAME::GetBoardFromRedoList( wxCommandEvent& event ) +void PCB_EDIT_FRAME::GetBoardFromRedoList( wxCommandEvent& aEvent ) { if( GetScreen()->GetRedoCommandCount() == 0 ) return; + // Inform tools that redo command was issued + TOOL_EVENT event( TC_MESSAGE, TA_UNDO_REDO, AS_GLOBAL ); + m_toolManager->ProcessEvent( event ); /* Get the old list */ PICKED_ITEMS_LIST* List = GetScreen()->PopCommandFromRedoList(); diff --git a/pcbnew/class_board.cpp b/pcbnew/class_board.cpp index e6f1619d18..ff2a89a0d5 100644 --- a/pcbnew/class_board.cpp +++ b/pcbnew/class_board.cpp @@ -43,6 +43,8 @@ #include #include #include +#include +#include #include #include @@ -104,22 +106,29 @@ BOARD::BOARD() : SetCurrentNetClass( m_NetClasses.GetDefault()->GetName() ); + // Initialize ratsnest m_ratsnest = new RN_DATA( this ); + m_ratsnestViewItem = new KIGFX::RATSNEST_VIEWITEM( m_ratsnest ); + + // Initialize view item for displaying worksheet frame + m_worksheetViewItem = new KIGFX::WORKSHEET_VIEWITEM( &m_paper, &m_titles ); + m_worksheetViewItem->SetFileName( std::string( m_fileName.mb_str() ) ); } BOARD::~BOARD() { - delete m_ratsnest; - while( m_ZoneDescriptorList.size() ) { ZONE_CONTAINER* area_to_remove = m_ZoneDescriptorList[0]; Delete( area_to_remove ); } - m_FullRatsnest.clear(); + delete m_worksheetViewItem; + delete m_ratsnestViewItem; + delete m_ratsnest; + m_FullRatsnest.clear(); m_LocalRatsnest.clear(); DeleteMARKERs(); @@ -206,7 +215,7 @@ void BOARD::chainMarkedSegments( wxPoint aPosition, LAYER_MSK aLayerMask, TRACK_ */ for( ; ; ) { - if( GetPadFast( aPosition, aLayerMask ) != NULL ) + if( GetPad( aPosition, aLayerMask ) != NULL ) return; /* Test for a via: a via changes the layer mask and can connect a lot @@ -842,6 +851,8 @@ void BOARD::Add( BOARD_ITEM* aBoardItem, int aControl ) } break; } + + m_ratsnest->Add( aBoardItem ); } @@ -905,6 +916,8 @@ BOARD_ITEM* BOARD::Remove( BOARD_ITEM* aBoardItem ) wxFAIL_MSG( wxT( "BOARD::Remove() needs more ::Type() support" ) ); } + m_ratsnest->Remove( aBoardItem ); + return aBoardItem; } @@ -1341,93 +1354,13 @@ NETINFO_ITEM* BOARD::FindNet( int aNetcode ) const // NULL is returned for non valid netcodes NETINFO_ITEM* net = m_NetInfo.GetNetItem( aNetcode ); -#if defined(DEBUG) - if( net && aNetcode != net->GetNet()) // item can be NULL if anetcode is not valid - { - wxLogError( wxT( "FindNet() anetcode %d != GetNet() %d (net: %s)\n" ), - aNetcode, net->GetNet(), TO_UTF8( net->GetNetname() ) ); - } -#endif - return net; } NETINFO_ITEM* BOARD::FindNet( const wxString& aNetname ) const { - // the first valid netcode is 1. - // zero is reserved for "no connection" and is not used. - if( aNetname.IsEmpty() ) - return NULL; - - int ncount = m_NetInfo.GetNetCount(); - - // Search for a netname = aNetname -#if 0 - - // Use a sequential search: easy to understand, but slow - for( int ii = 1; ii < ncount; ii++ ) - { - NETINFO_ITEM* item = m_NetInfo.GetNetItem( ii ); - - if( item && item->GetNetname() == aNetname ) - { - return item; - } - } - -#else - - // Use a fast binary search, - // this is possible because Nets are alphabetically ordered in list - // see NETINFO_LIST::BuildListOfNets() and - // NETINFO_LIST::Build_Pads_Full_List() - int imax = ncount - 1; - int index = imax; - - while( ncount > 0 ) - { - int ii = ncount; - ncount >>= 1; - - if( (ii & 1) && ( ii > 1 ) ) - ncount++; - - NETINFO_ITEM* item = m_NetInfo.GetNetItem( index ); - - if( item == NULL ) - return NULL; - - int icmp = item->GetNetname().Cmp( aNetname ); - - if( icmp == 0 ) // found ! - { - return item; - } - - if( icmp < 0 ) // must search after item - { - index += ncount; - - if( index > imax ) - index = imax; - - continue; - } - - if( icmp > 0 ) // must search before item - { - index -= ncount; - - if( index < 1 ) - index = 1; - - continue; - } - } - -#endif - return NULL; + return m_NetInfo.GetNetItem( aNetname ); } @@ -1512,10 +1445,11 @@ int BOARD::ReturnSortedNetnamesList( wxArrayString& aNames, bool aSortbyPadsCoun netBuffer.reserve( m_NetInfo.GetNetCount() ); - for( unsigned ii = 1; ii < m_NetInfo.GetNetCount(); ii++ ) + for( NETINFO_LIST::iterator net( m_NetInfo.begin() ), netEnd( m_NetInfo.end() ); + net != netEnd; ++net ) { - if( m_NetInfo.GetNetItem( ii )->GetNet() > 0 ) - netBuffer.push_back( m_NetInfo.GetNetItem( ii ) ); + if( net->GetNet() > 0 ) + netBuffer.push_back( *net ); } // sort the list @@ -1582,7 +1516,7 @@ ZONE_CONTAINER* BOARD::HitTestForAnyFilledArea( const wxPoint& aRefPos, if( area->GetState( BUSY ) ) continue; - if( aNetCode >= 0 && area->GetNet() != aNetCode ) + if( aNetCode >= 0 && area->GetNetCode() != aNetCode ) continue; if( area->HitTestFilledArea( aRefPos ) ) @@ -1601,24 +1535,24 @@ int BOARD::SetAreasNetCodesFromNetNames( void ) { if( !GetArea( ii )->IsOnCopperLayer() ) { - GetArea( ii )->SetNet( 0 ); + GetArea( ii )->SetNetCode( NETINFO_LIST::UNCONNECTED ); continue; } - if( GetArea( ii )->GetNet() != 0 ) // i.e. if this zone is connected to a net + if( GetArea( ii )->GetNetCode() != 0 ) // i.e. if this zone is connected to a net { - const NETINFO_ITEM* net = FindNet( GetArea( ii )->GetNetName() ); + const NETINFO_ITEM* net = GetArea( ii )->GetNet(); if( net ) { - GetArea( ii )->SetNet( net->GetNet() ); + GetArea( ii )->SetNetCode( net->GetNet() ); } else { error_count++; // keep Net Name and set m_NetCode to -1 : error flag. - GetArea( ii )->SetNet( -1 ); + GetArea( ii )->SetNetCode( -1 ); } } } @@ -2338,7 +2272,7 @@ ZONE_CONTAINER* BOARD::InsertArea( int netcode, int iarea, LAYER_NUM layer, int { ZONE_CONTAINER* new_area = new ZONE_CONTAINER( this ); - new_area->SetNet( netcode ); + new_area->SetNetCode( netcode ); new_area->SetLayer( layer ); new_area->SetTimeStamp( GetNewTimeStamp() ); @@ -2377,7 +2311,7 @@ bool BOARD::NormalizeAreaPolygon( PICKED_ITEMS_LIST * aNewZonesList, ZONE_CONTAI { // create new copper area and copy poly into it CPolyLine* new_p = (*pa)[ip - 1]; - NewArea = AddArea( aNewZonesList, aCurrArea->GetNet(), aCurrArea->GetLayer(), + NewArea = AddArea( aNewZonesList, aCurrArea->GetNetCode(), aCurrArea->GetLayer(), wxPoint(0, 0), CPolyLine::NO_HATCH ); // remove the poly that was automatically created for the new area @@ -2618,7 +2552,7 @@ void BOARD::ReplaceNetlist( NETLIST& aNetlist, bool aDeleteSinglePadNets, } if( !aNetlist.IsDryRun() ) - pad->SetNetname( wxEmptyString ); + pad->SetNetCode( NETINFO_LIST::UNCONNECTED ); } } else // Footprint pad has a net. @@ -2638,7 +2572,17 @@ void BOARD::ReplaceNetlist( NETLIST& aNetlist, bool aDeleteSinglePadNets, } if( !aNetlist.IsDryRun() ) - pad->SetNetname( net.GetNetName() ); + { + NETINFO_ITEM* netinfo = FindNet( net.GetNetName() ); + if( netinfo == NULL ) + { + // It is a new net, we have to add it + netinfo = new NETINFO_ITEM( this, net.GetNetName() ); + m_NetInfo.AppendNet( netinfo ); + } + + pad->SetNetCode( netinfo->GetNet() ); + } } } } @@ -2710,7 +2654,8 @@ void BOARD::ReplaceNetlist( NETLIST& aNetlist, bool aDeleteSinglePadNets, GetChars( previouspad->GetPadName() ) ); aReporter->Report( msg ); } - previouspad->SetNetname( wxEmptyString ); + + previouspad->SetNetCode( NETINFO_LIST::UNCONNECTED ); } netname = pad->GetNetname(); count = 1; @@ -2723,7 +2668,7 @@ void BOARD::ReplaceNetlist( NETLIST& aNetlist, bool aDeleteSinglePadNets, // Examine last pad if( pad && count == 1 ) - pad->SetNetname( wxEmptyString ); + pad->SetNetCode( NETINFO_LIST::UNCONNECTED ); } // Last step: Some tests: @@ -2760,31 +2705,6 @@ void BOARD::ReplaceNetlist( NETLIST& aNetlist, bool aDeleteSinglePadNets, } } } - - // Verify zone net names validity: - // After schematic changes, a zone can have a non existing net name. - // It should be reported - if( aReporter && aReporter->ReportErrors() ) - { - //Loop through all copper zones - for( i = 0; i < m_ZoneDescriptorList.size(); i++ ) - { - ZONE_CONTAINER* zone = m_ZoneDescriptorList[i]; - - if( zone->GetNet() >= 0 || !zone->IsOnCopperLayer() ) - continue; - - // Net name not valid, report error - wxString coord; - coord << zone->GetPosition(); - msg.Printf( _( "*** Error: Zone '%s' layer '%s'" - " has non-existent net name '%s' ***\n" ), - GetChars( coord ), - GetChars( zone->GetLayerName() ), - GetChars( zone->GetNetName() ) ); - aReporter->Report( msg ); - } - } } /* Extracts the board outlines and build a closed polygon diff --git a/pcbnew/class_board.h b/pcbnew/class_board.h index cd20413baa..cac0f66ffd 100644 --- a/pcbnew/class_board.h +++ b/pcbnew/class_board.h @@ -58,6 +58,12 @@ class NETLIST; class REPORTER; class RN_DATA; +namespace KIGFX +{ + class RATSNEST_VIEWITEM; + class WORKSHEET_VIEWITEM; +} + // non-owning container of item candidates when searching for items on the same track. typedef std::vector< TRACK* > TRACK_PTRS; @@ -227,6 +233,8 @@ private: EDA_RECT m_BoundingBox; NETINFO_LIST m_NetInfo; ///< net info list (name, design constraints .. RN_DATA* m_ratsnest; + KIGFX::RATSNEST_VIEWITEM* m_ratsnestViewItem; ///< VIEW_ITEM that draws ratsnest + KIGFX::WORKSHEET_VIEWITEM* m_worksheetViewItem; ///< VIEW_ITEM that draws worksheet frame BOARD_DESIGN_SETTINGS m_designSettings; ZONE_SETTINGS m_zoneSettings; @@ -367,6 +375,24 @@ public: return m_ratsnest; } + /** + * Function GetRatsnestViewItem() + * returns VIEW_ITEM responsible for drawing the ratsnest for the board. + */ + KIGFX::RATSNEST_VIEWITEM* GetRatsnestViewItem() const + { + return m_ratsnestViewItem; + } + + /** + * Function GetWorksheetViewItem() + * returns VIEW_ITEM responsible for drawing the worksheet frame. + */ + KIGFX::WORKSHEET_VIEWITEM* GetWorksheetViewItem() const + { + return m_worksheetViewItem; + } + /** * Function DeleteMARKERs * deletes ALL MARKERS from the board. @@ -845,6 +871,24 @@ public: m_NetInfo.AppendNet( aNewNet ); } + /** + * Function BeginNets + * @return iterator to the first element of the NETINFO_ITEMs list + */ + NETINFO_LIST::iterator BeginNets() const + { + return m_NetInfo.begin(); + } + + /** + * Function EndNets + * @return iterator to the last element of the NETINFO_ITEMs list + */ + NETINFO_LIST::iterator EndNets() const + { + return m_NetInfo.end(); + } + /** * Function GetNetCount * @return the number of nets (NETINFO_ITEM) diff --git a/pcbnew/class_board_connected_item.cpp b/pcbnew/class_board_connected_item.cpp index eaf793f9b7..73bdced99a 100644 --- a/pcbnew/class_board_connected_item.cpp +++ b/pcbnew/class_board_connected_item.cpp @@ -1,8 +1,3 @@ -/** - * @file class_board_connected_item.cpp - * @brief BOARD_CONNECTED_ITEM class functions. - */ - /* * This program source code file is part of KiCad, a free EDA CAD application. * @@ -28,76 +23,67 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */ +/** + * @file class_board_connected_item.cpp + * @brief BOARD_CONNECTED_ITEM class functions. + */ + #include #include #include #include - BOARD_CONNECTED_ITEM::BOARD_CONNECTED_ITEM( BOARD_ITEM* aParent, KICAD_T idtype ) : - BOARD_ITEM( aParent, idtype ) + BOARD_ITEM( aParent, idtype ), m_netinfo( &NETINFO_LIST::ORPHANED ), + m_Subnet( 0 ), m_ZoneSubnet( 0 ) { - m_NetCode = 0; - m_Subnet = 0; - m_ZoneSubnet = 0; + // The unconnected net is set only in case the item belongs to a BOARD + SetNetCode( NETINFO_LIST::UNCONNECTED ); } BOARD_CONNECTED_ITEM::BOARD_CONNECTED_ITEM( const BOARD_CONNECTED_ITEM& aItem ) : - BOARD_ITEM( aItem ) + BOARD_ITEM( aItem ), m_netinfo( aItem.m_netinfo ), m_Subnet( aItem.m_Subnet ), + m_ZoneSubnet( aItem.m_ZoneSubnet ) { - m_NetCode = aItem.m_NetCode; - m_Subnet = aItem.m_Subnet; - m_ZoneSubnet = aItem.m_ZoneSubnet; } -/** - * Function GetNet - * @return int - the net code. - */ -int BOARD_CONNECTED_ITEM::GetNet() const +int BOARD_CONNECTED_ITEM::GetNetCode() const { - return m_NetCode; + return m_netinfo->GetNet(); } -void BOARD_CONNECTED_ITEM::SetNet( int aNetCode ) +void BOARD_CONNECTED_ITEM::SetNetCode( int aNetCode ) { - m_NetCode = aNetCode; + BOARD* board = GetBoard(); + if( board ) + { + m_netinfo = board->FindNet( aNetCode ); + + // The requested net does not exist, mark it as unconnected + if( m_netinfo == NULL ) + m_netinfo = board->FindNet( NETINFO_LIST::UNCONNECTED ); + } + else + { + // There is no board that contains list of nets, the item is orphaned + m_netinfo = &NETINFO_LIST::ORPHANED; + } } -/** - * Function GetSubNet - * @return int - the sub net code. - */ -int BOARD_CONNECTED_ITEM::GetSubNet() const +const wxString& BOARD_CONNECTED_ITEM::GetNetname() const { - return m_Subnet; + return m_netinfo->GetNetname(); } -void BOARD_CONNECTED_ITEM::SetSubNet( int aSubNetCode ) +const wxString& BOARD_CONNECTED_ITEM::GetShortNetname() const { - m_Subnet = aSubNetCode; -} - - -/** - * Function GetZoneSubNet - * @return int - the sub net code in zone connections. - */ -int BOARD_CONNECTED_ITEM::GetZoneSubNet() const -{ - return m_ZoneSubnet; -} - - -void BOARD_CONNECTED_ITEM::SetZoneSubNet( int aSubNetCode ) -{ - m_ZoneSubnet = aSubNetCode; + return m_netinfo->GetShortNetname(); } @@ -132,11 +118,6 @@ int BOARD_CONNECTED_ITEM::GetClearance( BOARD_CONNECTED_ITEM* aItem ) const } -/** return a pointer to the netclass of the zone - * if the net is not found (can happen when a netlist is reread, - * and the net name is not existant, return the default net class - * So should not return a null pointer - */ NETCLASS* BOARD_CONNECTED_ITEM::GetNetClass() const { // It is important that this be implemented without any sequential searching. @@ -155,8 +136,7 @@ NETCLASS* BOARD_CONNECTED_ITEM::GetNetClass() const } NETCLASS* netclass = NULL; - int netcode = GetNet(); - NETINFO_ITEM* net = board->FindNet( netcode ); + NETINFO_ITEM* net = board->FindNet( GetNetCode() ); if( net ) { @@ -176,10 +156,7 @@ NETCLASS* BOARD_CONNECTED_ITEM::GetNetClass() const return board->m_NetClasses.GetDefault(); } -/** - * Function GetNetClassName - * @return the Net Class name of this item - */ + wxString BOARD_CONNECTED_ITEM::GetNetClassName() const { wxString name; diff --git a/pcbnew/class_board_connected_item.h b/pcbnew/class_board_connected_item.h index 67cd457398..2742fa3106 100644 --- a/pcbnew/class_board_connected_item.h +++ b/pcbnew/class_board_connected_item.h @@ -1,3 +1,28 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2012 Jean-Pierre Charras, jean-pierre.charras@ujf-grenoble.fr + * Copyright (C) 2012 SoftPLC Corporation, Dick Hollenbeck + * Copyright (C) 1992-2012 KiCad Developers, see AUTHORS.txt for contributors. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, you may find one here: + * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html + * or you may search the http://www.gnu.org website for the version 2 license, + * or you may write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + /** * @file class_board_connected_item.h * @brief Class BOARD_CONNECTED_ITEM. @@ -6,9 +31,9 @@ #ifndef BOARD_CONNECTED_ITEM_H #define BOARD_CONNECTED_ITEM_H - #include +class NETINFO_ITEM; class NETCLASS; class TRACK; class D_PAD; @@ -29,41 +54,78 @@ public: std::vector m_TracksConnected; // list of other tracks connected to me std::vector m_PadsConnected; // list of other pads connected to me -private: - int m_NetCode; // Net number - - int m_Subnet; /* In rastnest routines : for the current net, block number - * (number common to the current connected items found) - */ - - int m_ZoneSubnet; // used in rastnest computations : for the current net, - // handle cluster number in zone connection - -public: BOARD_CONNECTED_ITEM( BOARD_ITEM* aParent, KICAD_T idtype ); BOARD_CONNECTED_ITEM( const BOARD_CONNECTED_ITEM& aItem ); + ///> @copydoc BOARD_ITEM::IsConnected() + bool IsConnected() const + { + return true; + } + /** * Function GetNet + * Returns NET_INFO object for a given item. + */ + NETINFO_ITEM* GetNet() const + { + return m_netinfo; + } + + /** + * Function GetNetCode * @return int - the net code. */ - int GetNet() const; - virtual void SetNet( int aNetCode ); + int GetNetCode() const; + + /** + * Function SetNetCode + * sets net using a net code. + * @param aNetCode is a net code for the new net. It has to exist in NETINFO_LIST held by BOARD. + * Otherwise, item is assigned to the unconnected net. + */ + void SetNetCode( int aNetCode ); /** * Function GetSubNet * @return int - the sub net code. */ - int GetSubNet() const; - void SetSubNet( int aSubNetCode ); + int GetSubNet() const + { + return m_Subnet; + } + + void SetSubNet( int aSubNetCode ) + { + m_Subnet = aSubNetCode; + } /** * Function GetZoneSubNet * @return int - the sub net code in zone connections. */ - int GetZoneSubNet() const; - void SetZoneSubNet( int aSubNetCode ); + int GetZoneSubNet() const + { + return m_ZoneSubnet; + } + + void SetZoneSubNet( int aSubNetCode ) + { + m_ZoneSubnet = aSubNetCode; + } + + /** + * Function GetNetname + * @return wxString - the full netname + */ + const wxString& GetNetname() const; + + /** + * Function GetShortNetname + * @return wxString - the short netname + */ + const wxString& GetShortNetname() const; /** * Function GetClearance @@ -84,9 +146,25 @@ public: /** * Function GetNetClassName + * returns a pointer to the netclass of the zone. + * If the net is not found (can happen when a netlist is reread, + * and the net name does not exist, return the default net class + * (should not return a null pointer). * @return the Net Class name of this item */ wxString GetNetClassName() const; + +protected: + /// Stores all informations about the net that item belongs to + NETINFO_ITEM* m_netinfo; + +private: + int m_Subnet; /* In rastnest routines : for the current net, block number + * (number common to the current connected items found) + */ + + int m_ZoneSubnet; // used in rastnest computations : for the current net, + // handle cluster number in zone connection }; diff --git a/pcbnew/class_board_design_settings.cpp b/pcbnew/class_board_design_settings.cpp index 654ca11653..ef1b02159b 100644 --- a/pcbnew/class_board_design_settings.cpp +++ b/pcbnew/class_board_design_settings.cpp @@ -52,7 +52,7 @@ BOARD_DESIGN_SETTINGS::BOARD_DESIGN_SETTINGS() : - m_Pad_Master( 0 ) + m_Pad_Master( NULL ) { m_EnabledLayers = ALL_LAYERS; // All layers enabled at first. // SetCopperLayerCount() will adjust this. diff --git a/pcbnew/class_drawsegment.cpp b/pcbnew/class_drawsegment.cpp index 4f2376de74..d1e9799258 100644 --- a/pcbnew/class_drawsegment.cpp +++ b/pcbnew/class_drawsegment.cpp @@ -134,7 +134,7 @@ const wxPoint DRAWSEGMENT::GetArcEnd() const return endPoint; // after rotation, the end of the arc. } -const double DRAWSEGMENT::GetArcAngleStart() const +double DRAWSEGMENT::GetArcAngleStart() const { // due to the Y axis orient atan2 needs - y value double angleStart = ArcTangente( GetArcStart().y - GetCenter().y, @@ -148,6 +148,7 @@ const double DRAWSEGMENT::GetArcAngleStart() const return angleStart; } + void DRAWSEGMENT::SetAngle( double aAngle ) { NORMALIZE_ANGLE_360( aAngle ); @@ -379,6 +380,59 @@ const EDA_RECT DRAWSEGMENT::GetBoundingBox() const wxPoint end = m_End; RotatePoint( &end, m_Start, -m_Angle ); bbox.Merge( end ); + + // Determine the starting quarter + // 0 right-bottom + // 1 left-bottom + // 2 left-top + // 3 right-top + unsigned int quarter = 0; // assume right-bottom + + if( m_End.y < m_Start.y ) // change to left-top + quarter |= 3; + + if( m_End.x < m_Start.x ) // for left side, the LSB is 2nd bit negated + quarter ^= 1; + + int radius = GetRadius(); + int angle = (int) GetArcAngleStart() % 900 + m_Angle; + bool directionCW = ( m_Angle > 0 ); // Is the direction of arc clockwise? + + if( !directionCW ) + { + angle = 900 - angle; + quarter = ( quarter + 3 ) % 4; // -1 modulo arithmetic + } + + while( angle > 900 ) + { + switch( quarter ) + { + case 0: + bbox.Merge( wxPoint( m_Start.x, m_Start.y + radius ) ); // down + break; + + case 1: + bbox.Merge( wxPoint( m_Start.x - radius, m_Start.y ) ); // left + break; + + case 2: + bbox.Merge( wxPoint( m_Start.x, m_Start.y - radius ) ); // up + break; + + case 3: + bbox.Merge( wxPoint( m_Start.x + radius, m_Start.y ) ); // right + break; + } + + if( directionCW ) + ++quarter; + else + quarter += 3; // -1 modulo arithmetic + + quarter %= 4; + angle -= 900; + } } break; diff --git a/pcbnew/class_drawsegment.h b/pcbnew/class_drawsegment.h index dacd8061d2..635a3235d7 100644 --- a/pcbnew/class_drawsegment.h +++ b/pcbnew/class_drawsegment.h @@ -30,7 +30,6 @@ #ifndef CLASS_DRAWSEGMENT_H_ #define CLASS_DRAWSEGMENT_H_ - #include #include #include @@ -126,9 +125,9 @@ public: /** * function GetArcAngleStart() - * @return the angle of the stating point of this arc, between 0 and 3600 in 0.1 deg + * @return the angle of the starting point of this arc, between 0 and 3600 in 0.1 deg */ - const double GetArcAngleStart() const; + double GetArcAngleStart() const; /** * Function GetRadius diff --git a/pcbnew/class_module.cpp b/pcbnew/class_module.cpp index 95db2ce46f..7379e45fe1 100644 --- a/pcbnew/class_module.cpp +++ b/pcbnew/class_module.cpp @@ -728,6 +728,41 @@ EDA_ITEM* MODULE::Clone() const } +void MODULE::RunOnChildren( boost::function aFunction ) +{ + for( D_PAD* pad = m_Pads.GetFirst(); pad; pad = pad->Next() ) + aFunction( static_cast( pad ) ); + + for( BOARD_ITEM* drawing = m_Drawings.GetFirst(); drawing; drawing = drawing->Next() ) + aFunction( drawing ); + + aFunction( static_cast( m_Reference ) ); + aFunction( static_cast( m_Value ) ); +} + + +void MODULE::ViewUpdate( int aUpdateFlags ) +{ + if( !m_view ) + return; + + // Update pads + for( D_PAD* pad = m_Pads.GetFirst(); pad; pad = pad->Next() ) + m_view->InvalidateItem( pad, aUpdateFlags ); + + // Update module's drawing (mostly silkscreen) + for( BOARD_ITEM* drawing = m_Drawings.GetFirst(); drawing; drawing = drawing->Next() ) + m_view->InvalidateItem( drawing, aUpdateFlags ); + + // Update module's texts + m_view->InvalidateItem( m_Reference, aUpdateFlags ); + m_view->InvalidateItem( m_Value, aUpdateFlags ); + + // Update the module itself + m_view->InvalidateItem( this, aUpdateFlags ); +} + + /* Test for validity of the name in a library of the footprint * ( no spaces, dir separators ... ) * return true if the given name is valid diff --git a/pcbnew/class_module.h b/pcbnew/class_module.h index 34a8c11788..aa4f87cec2 100644 --- a/pcbnew/class_module.h +++ b/pcbnew/class_module.h @@ -41,6 +41,7 @@ #include #include "zones.h" +#include class LINE_READER; class EDA_3D_CANVAS; @@ -453,6 +454,17 @@ public: EDA_ITEM* Clone() const; + /** + * Function RunOnChildren + * + * Invokes a function on all BOARD_ITEMs that belong to the module (pads, drawings, texts). + * @param aFunction is the function to be invoked. + */ + void RunOnChildren( boost::function aFunction ); + + /// @copydoc VIEW_ITEM::ViewUpdate() + void ViewUpdate( int aUpdateFlags ); + /** * Function CopyNetlistSettings * copies the netlist settings to \a aModule. diff --git a/pcbnew/class_netclass.cpp b/pcbnew/class_netclass.cpp index f945963a95..655595a41d 100644 --- a/pcbnew/class_netclass.cpp +++ b/pcbnew/class_netclass.cpp @@ -203,12 +203,10 @@ void BOARD::SynchronizeNetsAndNetClasses() // set all NETs to the default NETCLASS, then later override some // as we go through the NETCLASSes. - int count = m_NetInfo.GetNetCount(); - for( int i=0; iSetClass( m_NetClasses.GetDefault() ); + net->SetClass( m_NetClasses.GetDefault() ); } // Add netclass name and pointer to nets. If a net is in more than one netclass, @@ -248,21 +246,18 @@ void BOARD::SynchronizeNetsAndNetClasses() m_NetClasses.GetDefault()->Clear(); - for( int i=0; iGetClassName(); + const wxString& classname = net->GetClassName(); - // because of the std:map<> this should be fast, and because of - // prior logic, netclass should not be NULL. - NETCLASS* netclass = m_NetClasses.Find( classname ); + // because of the std:map<> this should be fast, and because of + // prior logic, netclass should not be NULL. + NETCLASS* netclass = m_NetClasses.Find( classname ); - wxASSERT( netclass ); + wxASSERT( netclass ); - netclass->Add( net->GetNetname() ); - } + netclass->Add( net->GetNetname() ); } // D(printf("stop\n");) @@ -337,8 +332,15 @@ void NETCLASS::Format( OUTPUTFORMATTER* aFormatter, int aNestLevel, int aControl aFormatter->Print( aNestLevel+1, "(uvia_dia %s)\n", FMT_IU( GetuViaDiameter() ).c_str() ); aFormatter->Print( aNestLevel+1, "(uvia_drill %s)\n", FMT_IU( GetuViaDrill() ).c_str() ); - for( NETCLASS::const_iterator it = begin(); it!= end(); ++it ) - aFormatter->Print( aNestLevel+1, "(add_net %s)\n", aFormatter->Quotew( *it ).c_str() ); + for( NETCLASS::const_iterator it = begin(); it != end(); ++it ) + { + NETINFO_ITEM* netinfo = m_Parent->FindNet( *it ); + + if( netinfo && netinfo->GetNodesCount() > 0 ) + { + aFormatter->Print( aNestLevel+1, "(add_net %s)\n", aFormatter->Quotew( *it ).c_str() ); + } + } aFormatter->Print( aNestLevel, ")\n\n" ); } diff --git a/pcbnew/class_netinfo.h b/pcbnew/class_netinfo.h index 427a7b5685..f566926fcc 100644 --- a/pcbnew/class_netinfo.h +++ b/pcbnew/class_netinfo.h @@ -34,9 +34,10 @@ #define __CLASSES_NETINFO__ -#include #include #include +#include +#include class wxDC; @@ -115,6 +116,120 @@ public: }; +class NETINFO_MAPPING +{ +public: + /** + * Function SetBoard + * Sets a BOARD object that is used to prepare the net code map. + */ + void SetBoard( const BOARD* aBoard ) + { + m_board = aBoard; + Update(); + } + + /** + * Function Update + * Prepares a mapping for net codes so they can be saved as consecutive numbers. + * To retrieve a mapped net code, use translateNet() function after calling this. + */ + void Update(); + + /** + * Function Translate + * Translates net number according to the map prepared by Update() function. It + * allows to have items stored with consecutive net codes. + * @param aNetCode is an old net code. + * @return Net code that follows the mapping. + */ + int Translate( int aNetCode ) const; + + ///> Wrapper class, so you can iterate through NETINFO_ITEM*s, not + ///> std::pair + class iterator + { + public: + iterator( std::map::const_iterator aIter, const NETINFO_MAPPING* aMapping ) : + m_iterator( aIter ), m_mapping( aMapping ) + { + } + + /// pre-increment operator + const iterator& operator++() + { + ++m_iterator; + + return *this; + } + + /// post-increment operator + iterator operator++( int ) + { + iterator ret = *this; + ++m_iterator; + + return ret; + } + + NETINFO_ITEM* operator*() const; + + NETINFO_ITEM* operator->() const; + + bool operator!=( const iterator& aOther ) const + { + return m_iterator != aOther.m_iterator; + } + + bool operator==( const iterator& aOther ) const + { + return m_iterator == aOther.m_iterator; + } + + private: + std::map::const_iterator m_iterator; + const NETINFO_MAPPING* m_mapping; + }; + + /** + * Function begin() + * Returns iterator to the first entry in the mapping. + * NOTE: The entry is a pointer to the original NETINFO_ITEM object, this it contains + * not mapped net code. + */ + iterator begin() const + { + return iterator( m_netMapping.begin(), this ); + } + + /** + * Function end() + * Returns iterator to the last entry in the mapping. + * NOTE: The entry is a pointer to the original NETINFO_ITEM object, this it contains + * not mapped net code. + */ + iterator end() const + { + return iterator( m_netMapping.end(), this ); + } + + /** + * Function GetSize + * @return Number of mapped nets (i.e. not empty nets for a given BOARD object). + */ + int GetSize() const + { + return m_netMapping.size(); + } + +private: + ///> Board for which mapping is prepared + const BOARD* m_board; + + ///> Map that allows saving net codes with consecutive numbers (for compatibility reasons) + std::map m_netMapping; +}; + /** * Class NETINFO @@ -131,14 +246,30 @@ public: /** * Function GetItem - * @param aNetcode = netcode to identify a given NETINFO_ITEM - * @return NETINFO_ITEM* - by \a aNetcode, or NULL if not found + * @param aNetCode = netcode to identify a given NETINFO_ITEM + * @return NETINFO_ITEM* - by \a aNetCode, or NULL if not found */ - NETINFO_ITEM* GetNetItem( int aNetcode ) const + NETINFO_ITEM* GetNetItem( int aNetCode ) const { - if( unsigned( aNetcode ) >= GetNetCount() ) // catches < 0 too - return NULL; - return m_NetBuffer[aNetcode]; + NETCODES_MAP::const_iterator result = m_netCodes.find( aNetCode ); + if( result != m_netCodes.end() ) + return (*result).second; + + return NULL; + } + + /** + * Function GetItem + * @param aNetName = net name to identify a given NETINFO_ITEM + * @return NETINFO_ITEM* - by \a aNetName, or NULL if not found + */ + NETINFO_ITEM* GetNetItem( const wxString& aNetName ) const + { + NETNAMES_MAP::const_iterator result = m_netNames.find( aNetName ); + if( result != m_netNames.end() ) + return (*result).second; + + return NULL; } /** @@ -146,7 +277,7 @@ public: * @return the number of nets ( always >= 1 ) * because the first net is the "not connected" net and always exists */ - unsigned GetNetCount() const { return m_NetBuffer.size(); } + unsigned GetNetCount() const { return m_netNames.size(); } /** * Function Append @@ -184,12 +315,81 @@ public: return NULL; } + ///> Constant that holds the unconnected net number + static const int UNCONNECTED; + + ///> NETINFO_ITEM meaning that there was no net assigned for an item, as there was no + ///> board storing net list available. + static NETINFO_ITEM ORPHANED; + #if defined(DEBUG) void Show() const; #endif -private: + typedef boost::unordered_map NETNAMES_MAP; + typedef boost::unordered_map NETCODES_MAP; + ///> Wrapper class, so you can iterate through NETINFO_ITEM*s, not + ///> std::pair + class iterator + { + public: + iterator( NETNAMES_MAP::const_iterator aIter ) : m_iterator( aIter ) + { + } + + /// pre-increment operator + const iterator& operator++() + { + ++m_iterator; + + return *this; + } + + /// post-increment operator + iterator operator++( int ) + { + iterator ret = *this; + ++m_iterator; + + return ret; + } + + NETINFO_ITEM* operator*() const + { + return m_iterator->second; + } + + NETINFO_ITEM* operator->() const + { + return m_iterator->second; + } + + bool operator!=( const iterator& aOther ) const + { + return m_iterator != aOther.m_iterator; + } + + bool operator==( const iterator& aOther ) const + { + return m_iterator == aOther.m_iterator; + } + + private: + NETNAMES_MAP::const_iterator m_iterator; + }; + + iterator begin() const + { + return iterator( m_netNames.begin() ); + } + + iterator end() const + { + return iterator( m_netNames.end() ); + } + +private: /** * Function DeleteData * deletes the list of nets (and free memory) @@ -213,10 +413,18 @@ private: */ void buildPadsFullList(); - BOARD* m_Parent; - std::vector m_NetBuffer; ///< net list (name, design constraints ..) + /** + * Function getFreeNetCode + * returns the first available net code that is not used by any other net. + */ + int getFreeNetCode() const; - std::vector m_PadsFullList; ///< contains all pads, sorted by pad's netname. + BOARD* m_Parent; + + NETNAMES_MAP m_netNames; ///< map for a fast look up by net names + NETCODES_MAP m_netCodes; ///< map for a fast look up by net codes + + std::vector m_PadsFullList; ///< contains all pads, sorted by pad's netname. ///< can be used in ratsnest calculations. }; @@ -227,15 +435,17 @@ private: */ class NETINFO_ITEM { + friend class NETINFO_LIST; + private: - int m_NetCode; ///< A number equivalent to the net name. + const int m_NetCode; ///< A number equivalent to the net name. ///< Used for fast comparisons in ratsnest and DRC computations. - wxString m_Netname; ///< Full net name like /mysheet/mysubsheet/vout + const wxString m_Netname; ///< Full net name like /mysheet/mysubsheet/vout ///< used by Eeschema - wxString m_ShortNetname; // short net name, like vout from - // /mysheet/mysubsheet/vout + const wxString m_ShortNetname; // short net name, like vout from + // /mysheet/mysubsheet/vout wxString m_NetClassName; // Net Class name. if void this is equivalent // to "default" (the first @@ -246,12 +456,6 @@ private: BOARD_ITEM* m_parent; ///< The parent board item object the net belongs to. public: - int m_NbNodes; // Pads count for this net - int m_NbLink; // Ratsnets count for this net - int m_NbNoconn; // Ratsnets remaining to route count - int m_Flag; // used in some calculations. Had no - // special meaning - std::vector m_PadInNetList; // List of pads connected to this net unsigned m_RatsnestStartIdx; /* Starting point of ratsnests of this @@ -262,7 +466,7 @@ public: unsigned m_RatsnestEndIdx; // Ending point of ratsnests of this net // (excluded) in this buffer - NETINFO_ITEM( BOARD_ITEM* aParent, const wxString& aNetName = wxEmptyString, int aNetCode = 0 ); + NETINFO_ITEM( BOARD_ITEM* aParent, const wxString& aNetName = wxEmptyString, int aNetCode = -1 ); ~NETINFO_ITEM(); /** @@ -386,27 +590,23 @@ public: */ int GetNet() const { return m_NetCode; } - void SetNet( int aNetCode ) { m_NetCode = aNetCode; } - + /** + * Function GetNodesCount + * @return int - number of nodes in the net + */ int GetNodesCount() const { return m_PadInNetList.size(); } /** * Function GetNetname - * @return const wxString * , a pointer to the full netname + * @return const wxString&, a reference to the full netname */ - wxString GetNetname() const { return m_Netname; } + const wxString& GetNetname() const { return m_Netname; } /** * Function GetShortNetname - * @return const wxString * , a pointer to the short netname + * @return const wxString &, a reference to the short netname */ - wxString GetShortNetname() const { return m_ShortNetname; } - - /** - * Function SetNetname - * @param aNetname : the new netname - */ - void SetNetname( const wxString& aNetname ); + const wxString& GetShortNetname() const { return m_ShortNetname; } /** * Function GetMsgPanelInfo @@ -416,6 +616,21 @@ public: * @param aList is the list in which to place the status information. */ void GetMsgPanelInfo( std::vector< MSG_PANEL_ITEM >& aList ); + + /** + * Function Clear + * sets all fields to their defaults values. + */ + void Clear() + { + m_PadInNetList.clear(); + + m_RatsnestStartIdx = 0; // Starting point of ratsnests of this net in a + // general buffer of ratsnest + m_RatsnestEndIdx = 0; // Ending point of ratsnests of this net + + SetClass( NULL ); + } }; diff --git a/pcbnew/class_netinfo_item.cpp b/pcbnew/class_netinfo_item.cpp index f96132dfc1..f61705385f 100644 --- a/pcbnew/class_netinfo_item.cpp +++ b/pcbnew/class_netinfo_item.cpp @@ -49,25 +49,16 @@ /* class NETINFO_ITEM: handle data relative to a given net */ /*********************************************************/ -NETINFO_ITEM::NETINFO_ITEM( BOARD_ITEM* aParent, const wxString& aNetName, int aNetCode ) +NETINFO_ITEM::NETINFO_ITEM( BOARD_ITEM* aParent, const wxString& aNetName, int aNetCode ) : + m_NetCode( aNetCode ), m_Netname( aNetName ), m_ShortNetname( m_Netname.AfterLast( '/' ) ) { - SetNet( aNetCode ); - - if( aNetName.size() ) - SetNetname( aNetName ); - m_parent = aParent; - m_NbNodes = 0; - m_NbLink = 0; - m_NbNoconn = 0; - m_Flag = 0; m_RatsnestStartIdx = 0; // Starting point of ratsnests of this net in a // general buffer of ratsnest m_RatsnestEndIdx = 0; // Ending point of ratsnests of this net m_NetClassName = NETCLASS::Default; - - m_NetClass = 0; + m_NetClass = NULL; } @@ -77,17 +68,6 @@ NETINFO_ITEM::~NETINFO_ITEM() } -/** - * Function SetNetname - * @param aNetname : the new netname - */ -void NETINFO_ITEM::SetNetname( const wxString& aNetname ) -{ - m_Netname = aNetname; - m_ShortNetname = m_Netname.AfterLast( '/' ); -} - - /** * Function Draw (TODO) */ @@ -121,7 +101,7 @@ void NETINFO_ITEM::GetMsgPanelInfo( std::vector< MSG_PANEL_ITEM >& aList ) { for( pad = module->Pads(); pad != 0; pad = pad->Next() ) { - if( pad->GetNet() == GetNet() ) + if( pad->GetNetCode() == GetNet() ) { count++; lengthPadToDie += pad->GetPadToDieLength(); @@ -139,13 +119,13 @@ void NETINFO_ITEM::GetMsgPanelInfo( std::vector< MSG_PANEL_ITEM >& aList ) { if( Struct->Type() == PCB_VIA_T ) { - if( ( (SEGVIA*) Struct )->GetNet() == GetNet() ) + if( ( (SEGVIA*) Struct )->GetNetCode() == GetNet() ) count++; } if( Struct->Type() == PCB_TRACE_T ) { - if( ( (TRACK*) Struct )->GetNet() == GetNet() ) + if( ( (TRACK*) Struct )->GetNetCode() == GetNet() ) lengthnet += ( (TRACK*) Struct )->GetLength(); } } diff --git a/pcbnew/class_netinfolist.cpp b/pcbnew/class_netinfolist.cpp index df5f8039de..da3bd875d1 100644 --- a/pcbnew/class_netinfolist.cpp +++ b/pcbnew/class_netinfolist.cpp @@ -1,3 +1,27 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2009 Jean-Pierre Charras, jaen-pierre.charras@gipsa-lab.inpg.com + * Copyright (C) 1992-2012 KiCad Developers, see AUTHORS.txt for contributors. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, you may find one here: + * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html + * or you may search the http://www.gnu.org website for the version 2 license, + * or you may write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + /** * @file class_netinfolist.cpp */ @@ -11,13 +35,17 @@ #include #include +#include +#include +#include #include // Constructor and destructor -NETINFO_LIST::NETINFO_LIST( BOARD* aParent ) +NETINFO_LIST::NETINFO_LIST( BOARD* aParent ) : m_Parent( aParent ) { - m_Parent = aParent; + // Make sure that the unconnected net has number 0 + AppendNet( new NETINFO_ITEM( aParent, wxEmptyString, 0 ) ); } @@ -29,23 +57,29 @@ NETINFO_LIST::~NETINFO_LIST() void NETINFO_LIST::clear() { - for( unsigned ii = 0; ii < GetNetCount(); ii++ ) - delete m_NetBuffer[ii]; + NETNAMES_MAP::iterator it, itEnd; + for( it = m_netNames.begin(), itEnd = m_netNames.end(); it != itEnd; ++it ) + delete it->second; - m_NetBuffer.clear(); m_PadsFullList.clear(); + m_netNames.clear(); + m_netCodes.clear(); } -/** - * Function Append - * adds \a aNewElement to the end of the list. - */ void NETINFO_LIST::AppendNet( NETINFO_ITEM* aNewElement ) { - m_NetBuffer.push_back( aNewElement ); + // negative net code means that it has to be auto assigned + if( aNewElement->m_NetCode < 0 ) + const_cast( aNewElement->m_NetCode ) = getFreeNetCode(); - // D(Show();) + // net names & codes are supposed to be unique + assert( GetNetItem( aNewElement->GetNetname() ) == NULL ); + assert( GetNetItem( aNewElement->GetNet() ) == NULL ); + + // add an entry for fast look up by a net name using a map + m_netNames.insert( std::make_pair( aNewElement->GetNetname(), aNewElement ) ); + m_netCodes.insert( std::make_pair( aNewElement->GetNet(), aNewElement ) ); } @@ -78,48 +112,31 @@ void NETINFO_LIST::buildListOfNets() { D_PAD* pad; int nodes_count = 0; - NETINFO_ITEM* net_item; - - clear(); // Remove all nets info and free memory - - // Create and add the "unconnected net", always existing, - // used to handle pads and tracks that are not member of a "real" net - net_item = new NETINFO_ITEM( m_Parent ); - AppendNet( net_item ); // Build the PAD list, sorted by net buildPadsFullList(); - // Build netnames list, and create a netcode for each netname - D_PAD* last_pad = NULL; - int netcode = 0; + // Restore the initial state of NETINFO_ITEMs + for( NETINFO_LIST::iterator net( begin() ), netEnd( end() ); net != netEnd; ++net ) + net->Clear(); + // Assign pads to appropriate NETINFO_ITEMs for( unsigned ii = 0; ii < m_PadsFullList.size(); ii++ ) { pad = m_PadsFullList[ii]; - if( pad->GetNetname().IsEmpty() ) // pad not connected - { - pad->SetNet( 0 ); + if( pad->GetNetCode() == NETINFO_LIST::UNCONNECTED ) // pad not connected continue; - } - /* if the current netname was already found: add pad to the current net_item , - * else create a new net_code and a new net_item - */ - if( last_pad == NULL || ( pad->GetNetname() != last_pad->GetNetname() ) ) - { - netcode++; - net_item = new NETINFO_ITEM( m_Parent, pad->GetNetname(), netcode ); - AppendNet( net_item ); - } + // Add pad to the appropriate list of pads + NETINFO_ITEM* net = pad->GetNet(); + // it should not be possible for BOARD_CONNECTED_ITEM to return NULL as a result of GetNet() + wxASSERT( net ); - pad->SetNet( netcode ); - net_item->m_PadInNetList.push_back( pad ); + if( net ) + net->m_PadInNetList.push_back( pad ); - nodes_count++; - - last_pad = pad; + ++nodes_count; } m_Parent->SetNodeCount( nodes_count ); @@ -129,18 +146,18 @@ void NETINFO_LIST::buildListOfNets() m_Parent->m_Status_Pcb |= NET_CODES_OK; m_Parent->SetAreasNetCodesFromNetNames(); - - // D( Show(); ) } #if defined(DEBUG) void NETINFO_LIST::Show() const { - for( unsigned i=0; i < m_NetBuffer.size(); ++i ) + int i = 0; + NETNAMES_MAP::const_iterator it, itEnd; + for( it = m_netNames.begin(), itEnd = m_netNames.end(); it != itEnd; ++it ) { printf( "[%d]: netcode:%d netname:<%s>\n", - i, m_NetBuffer[i]->GetNet(), - TO_UTF8( m_NetBuffer[i]->GetNetname() ) ); + i++, it->second->GetNet(), + TO_UTF8( it->second->GetNetname() ) ); } } #endif @@ -183,3 +200,84 @@ void NETINFO_LIST::buildPadsFullList() m_Parent->m_Status_Pcb = LISTE_PAD_OK; } + + +int NETINFO_LIST::getFreeNetCode() const +{ + static int m_newNetCode = 0; + + do { + if( m_newNetCode < 0 ) + m_newNetCode = 0; + } while( m_netCodes.count( ++m_newNetCode ) != 0 ); + + return m_newNetCode; +} + + +int NETINFO_MAPPING::Translate( int aNetCode ) const +{ + std::map::const_iterator value = m_netMapping.find( aNetCode ); + + if( value != m_netMapping.end() ) + return value->second; + + // There was no entry for the given net code + return aNetCode; +} + + +void NETINFO_MAPPING::Update() +{ + // Collect all the used nets + std::set nets; + + // Be sure that the unconnected gets 0 and is mapped as 0 + nets.insert( 0 ); + + // Zones + for( int i = 0; i < m_board->GetAreaCount(); ++i ) + nets.insert( m_board->GetArea( i )->GetNetCode() ); + + // Tracks + for( TRACK* track = m_board->m_Track; track; track = track->Next() ) + nets.insert( track->GetNetCode() ); + + // Modules/pads + for( MODULE* module = m_board->m_Modules; module; module = module->Next() ) + { + for( D_PAD* pad = module->Pads().GetFirst(); pad; pad = pad->Next() ) + { + nets.insert( pad->GetNetCode() ); + } + } + + // Segzones + for( SEGZONE* zone = m_board->m_Zone; zone; zone = zone->Next() ) + nets.insert( zone->GetNetCode() ); + + // Prepare the new mapping + m_netMapping.clear(); + + // Now the nets variable stores all the used net codes (not only for pads) and we are ready to + // assign new consecutive net numbers + int newNetCode = 0; + for( std::set::const_iterator it = nets.begin(), itEnd = nets.end(); it != itEnd; ++it ) + m_netMapping[*it] = newNetCode++; +} + + +NETINFO_ITEM* NETINFO_MAPPING::iterator::operator*() const +{ + return m_mapping->m_board->FindNet( m_iterator->first ); +} + + +NETINFO_ITEM* NETINFO_MAPPING::iterator::operator->() const +{ + return m_mapping->m_board->FindNet( m_iterator->first ); +} + + +const int NETINFO_LIST::UNCONNECTED = 0; +NETINFO_ITEM NETINFO_LIST::ORPHANED = NETINFO_ITEM( NULL, wxEmptyString, NETINFO_LIST::UNCONNECTED ); diff --git a/pcbnew/class_pad.cpp b/pcbnew/class_pad.cpp index 405c398db0..d3ff34f92c 100644 --- a/pcbnew/class_pad.cpp +++ b/pcbnew/class_pad.cpp @@ -364,13 +364,6 @@ void D_PAD::SetPadName( const wxString& name ) } -void D_PAD::SetNetname( const wxString& aNetname ) -{ - m_Netname = aNetname; - m_ShortNetname = m_Netname.AfterLast( '/' ); -} - - void D_PAD::Copy( D_PAD* source ) { if( source == NULL ) @@ -380,7 +373,7 @@ void D_PAD::Copy( D_PAD* source ) m_layerMask = source->m_layerMask; m_NumPadName = source->m_NumPadName; - SetNet( source->GetNet() ); + m_netinfo = source->m_netinfo; m_Drill = source->m_Drill; m_drillShape = source->m_drillShape; m_Offset = source->m_Offset; @@ -402,8 +395,6 @@ void D_PAD::Copy( D_PAD* source ) SetSubRatsnest( 0 ); SetSubNet( 0 ); - m_Netname = source->m_Netname; - m_ShortNetname = source->m_ShortNetname; } @@ -412,7 +403,7 @@ void D_PAD::CopyNetlistSettings( D_PAD* aPad ) // Don't do anything foolish like trying to copy to yourself. wxCHECK_RET( aPad != NULL && aPad != this, wxT( "Cannot copy to NULL or yourself." ) ); - aPad->SetNetname( GetNetname() ); + aPad->SetNetCode( GetNetCode() ); aPad->SetLocalClearance( m_LocalClearance ); aPad->SetLocalSolderMaskMargin( m_LocalSolderMaskMargin ); @@ -577,7 +568,7 @@ void D_PAD::GetMsgPanelInfo( std::vector< MSG_PANEL_ITEM>& aList ) aList.push_back( MSG_PANEL_ITEM( _( "Pad" ), Line, BROWN ) ); } - aList.push_back( MSG_PANEL_ITEM( _( "Net" ), m_Netname, DARKCYAN ) ); + aList.push_back( MSG_PANEL_ITEM( _( "Net" ), GetNetname(), DARKCYAN ) ); /* For test and debug only: display m_physical_connexion and * m_logical_connexion */ diff --git a/pcbnew/class_pad.h b/pcbnew/class_pad.h index a32bb06acf..7ceb06016d 100644 --- a/pcbnew/class_pad.h +++ b/pcbnew/class_pad.h @@ -118,24 +118,6 @@ public: return m_NumPadName == other->m_NumPadName; // hide tricks behind sensible API } - /** - * Function SetNetname - * @param aNetname: the new netname - */ - void SetNetname( const wxString& aNetname ); - - /** - * Function GetNetname - * @return const wxString& - the full netname - */ - const wxString& GetNetname() const { return m_Netname; } - - /** - * Function GetShortNetname - * @return const wxString& - the short netname - */ - const wxString& GetShortNetname() const { return m_ShortNetname; } - /** * Function GetShape * @return the shape of this pad. @@ -470,10 +452,6 @@ private: int m_boundingRadius; ///< radius of the circle containing the pad shape - - wxString m_Netname; ///< Full net name like /mysheet/mysubsheet/vout used by Eeschema - wxString m_ShortNetname; ///< short net name, like vout from /mysheet/mysubsheet/vout - /// Pad name (4 char) or a long identifier (used in pad name /// comparisons because this is faster than string comparison) union diff --git a/pcbnew/class_pad_draw_functions.cpp b/pcbnew/class_pad_draw_functions.cpp index 56f60c2eee..7c21d9c4b2 100644 --- a/pcbnew/class_pad_draw_functions.cpp +++ b/pcbnew/class_pad_draw_functions.cpp @@ -473,7 +473,7 @@ void D_PAD::DrawShape( EDA_RECT* aClipBox, wxDC* aDC, PAD_DRAWINFO& aDrawInfo ) GRSetDrawMode( aDC, aDrawInfo.m_DrawMode ); // Draw "No connect" ( / or \ or cross X ) if necessary - if( m_Netname.IsEmpty() && aDrawInfo.m_ShowNCMark ) + if( GetNetCode() == 0 && aDrawInfo.m_ShowNCMark ) { int dx0 = std::min( halfsize.x, halfsize.y ); EDA_COLOR_T nc_color = BLUE; @@ -499,7 +499,7 @@ void D_PAD::DrawShape( EDA_RECT* aClipBox, wxDC* aDC, PAD_DRAWINFO& aDrawInfo ) wxPoint tpos0 = shape_pos; // Position of the centre of text wxPoint tpos = tpos0; wxSize AreaSize; // size of text area, normalized to AreaSize.y < AreaSize.x - int shortname_len = m_ShortNetname.Len(); + int shortname_len = GetShortNetname().Len(); if( !aDrawInfo.m_Display_netname ) shortname_len = 0; @@ -583,7 +583,7 @@ void D_PAD::DrawShape( EDA_RECT* aClipBox, wxDC* aDC, PAD_DRAWINFO& aDrawInfo ) tsize = ( tsize * 7 ) / 10; DrawGraphicHaloText( clipBox, aDC, tpos, aDrawInfo.m_Color, BLACK, WHITE, - m_ShortNetname, t_angle, + GetShortNetname(), t_angle, wxSize( tsize, tsize ), GR_TEXT_HJUSTIFY_CENTER, GR_TEXT_VJUSTIFY_CENTER, tsize / 7, false, false ); } diff --git a/pcbnew/class_text_mod.cpp b/pcbnew/class_text_mod.cpp index b8d1392488..e5e7a2d2be 100644 --- a/pcbnew/class_text_mod.cpp +++ b/pcbnew/class_text_mod.cpp @@ -415,6 +415,18 @@ EDA_ITEM* TEXTE_MODULE::Clone() const } +const BOX2I TEXTE_MODULE::ViewBBox() const +{ + double angle = GetDrawRotation(); + EDA_RECT text_area = GetTextBox( -1, -1 ); + + if( angle ) + text_area = text_area.GetBoundingBoxRotated( m_Pos, angle ); + + return BOX2I( text_area.GetPosition(), text_area.GetSize() ); +} + + void TEXTE_MODULE::ViewGetLayers( int aLayers[], int& aCount ) const { if( m_NoShow ) // Hidden text diff --git a/pcbnew/class_text_mod.h b/pcbnew/class_text_mod.h index 3452d4f316..97e15ab202 100644 --- a/pcbnew/class_text_mod.h +++ b/pcbnew/class_text_mod.h @@ -165,6 +165,9 @@ public: EDA_ITEM* Clone() const; + /// @copydoc VIEW_ITEM::ViewBBox() + virtual const BOX2I ViewBBox() const; + /// @copydoc VIEW_ITEM::ViewGetLayers() virtual void ViewGetLayers( int aLayers[], int& aCount ) const; diff --git a/pcbnew/class_track.cpp b/pcbnew/class_track.cpp index ee3e198bff..6221756253 100644 --- a/pcbnew/class_track.cpp +++ b/pcbnew/class_track.cpp @@ -160,15 +160,11 @@ EDA_ITEM* SEGZONE::Clone() const wxString SEGZONE::GetSelectMenuText() const { wxString text, nettxt; - NETINFO_ITEM* net; BOARD* board = GetBoard(); if( board ) { - net = board->FindNet( GetNet() ); - - if( net ) - nettxt = net->GetNetname(); + nettxt = GetNetname(); } else { @@ -201,7 +197,6 @@ wxString SEGVIA::GetSelectMenuText() const { wxString text; wxString format; - NETINFO_ITEM* net; BOARD* board = GetBoard(); int shape = GetShape(); @@ -215,18 +210,14 @@ wxString SEGVIA::GetSelectMenuText() const if( board ) { - net = board->FindNet( GetNet() ); - wxString netname; - - if( net ) - netname = net->GetNetname(); + wxString netname = GetNetname(); // say which layers, only two for now LAYER_NUM topLayer; LAYER_NUM botLayer; ReturnLayerPair( &topLayer, &botLayer ); text.Printf( format.GetData(), GetChars( ShowWidth() ), - GetChars( netname ), GetNet(), + GetChars( netname ), GetNetCode(), GetChars( board->GetLayerName( topLayer ) ), GetChars( board->GetLayerName( botLayer ) ) ); @@ -496,7 +487,7 @@ TRACK* TRACK::GetBestInsertPoint( BOARD* aPcb ) for( ; track; track = track->Next() ) { - if( GetNet() <= track->GetNet() ) + if( GetNetCode() <= track->GetNetCode() ) return track; } @@ -510,14 +501,14 @@ TRACK* TRACK::GetStartNetCode( int NetCode ) int ii = 0; if( NetCode == -1 ) - NetCode = GetNet(); + NetCode = GetNetCode(); while( Track != NULL ) { - if( Track->GetNet() > NetCode ) + if( Track->GetNetCode() > NetCode ) break; - if( Track->GetNet() == NetCode ) + if( Track->GetNetCode() == NetCode ) { ii++; break; @@ -542,19 +533,19 @@ TRACK* TRACK::GetEndNetCode( int NetCode ) return NULL; if( NetCode == -1 ) - NetCode = GetNet(); + NetCode = GetNetCode(); while( Track != NULL ) { NextS = (TRACK*) Track->Pnext; - if( Track->GetNet() == NetCode ) + if( Track->GetNetCode() == NetCode ) ii++; if( NextS == NULL ) break; - if( NextS->GetNet() > NetCode ) + if( NextS->GetNetCode() > NetCode ) break; Track = NextS; @@ -690,10 +681,10 @@ void TRACK::Draw( EDA_DRAW_PANEL* panel, wxDC* aDC, GR_DRAWMODE aDrawMode, if( aDC->LogicalToDeviceXRel( m_Width ) < MIN_TEXT_SIZE ) return; - if( GetNet() == 0 ) + if( GetNetCode() == NETINFO_LIST::UNCONNECTED ) return; - NETINFO_ITEM* net = ( (BOARD*) GetParent() )->FindNet( GetNet() ); + NETINFO_ITEM* net = GetNet(); if( net == NULL ) return; @@ -952,13 +943,13 @@ void SEGVIA::Draw( EDA_DRAW_PANEL* panel, wxDC* aDC, GR_DRAWMODE aDrawMode, } // Display the short netname: - if( GetNet() == 0 ) + if( GetNetCode() == NETINFO_LIST::UNCONNECTED ) return; if( DisplayOpt.DisplayNetNamesMode == 0 || DisplayOpt.DisplayNetNamesMode == 1 ) return; - NETINFO_ITEM* net = ( (BOARD*) GetParent() )->FindNet( GetNet() ); + NETINFO_ITEM* net = GetNet(); if( net == NULL ) return; @@ -1095,7 +1086,7 @@ void TRACK::GetMsgPanelInfoBase( std::vector< MSG_PANEL_ITEM >& aList ) // Display Net Name (in Pcbnew) if( board ) { - NETINFO_ITEM* net = board->FindNet( GetNet() ); + NETINFO_ITEM* net = GetNet(); if( net ) msg = net->GetNetname(); @@ -1105,7 +1096,7 @@ void TRACK::GetMsgPanelInfoBase( std::vector< MSG_PANEL_ITEM >& aList ) aList.push_back( MSG_PANEL_ITEM( _( "NetName" ), msg, RED ) ); /* Display net code : (useful in test or debug) */ - msg.Printf( wxT( "%d.%d" ), GetNet(), GetSubNet() ); + msg.Printf( wxT( "%d.%d" ), GetNetCode(), GetSubNet() ); aList.push_back( MSG_PANEL_ITEM( _( "NetCode" ), msg, RED ) ); } @@ -1576,7 +1567,7 @@ wxString TRACK::GetSelectMenuText() const // disambiguate all the choices under the cursor! if( board ) { - net = board->FindNet( GetNet() ); + net = GetNet(); if( net ) netname = net->GetNetname(); @@ -1591,7 +1582,7 @@ wxString TRACK::GetSelectMenuText() const text.Printf( _("Track %s, net [%s] (%d) on layer %s, length: %s" ), GetChars( ShowWidth() ), GetChars( netname ), - GetNet(), GetChars( GetLayerName() ), + GetNetCode(), GetChars( GetLayerName() ), GetChars( ::LengthDoubleToString( GetLength() ) ) ); return text; diff --git a/pcbnew/class_zone.cpp b/pcbnew/class_zone.cpp index b1d8405c81..6679fee49a 100644 --- a/pcbnew/class_zone.cpp +++ b/pcbnew/class_zone.cpp @@ -53,7 +53,6 @@ ZONE_CONTAINER::ZONE_CONTAINER( BOARD* aBoard ) : BOARD_CONNECTED_ITEM( aBoard, PCB_ZONE_AREA_T ) { - SetNet( -1 ); // Net number for fast comparisons m_CornerSelection = -1; m_IsFilled = false; // fill status : true when the zone is filled m_FillMode = 0; // How to fill areas: 0 = use filled polygons, != 0 fill with segments @@ -75,7 +74,7 @@ ZONE_CONTAINER::ZONE_CONTAINER( const ZONE_CONTAINER& aZone ) : BOARD_CONNECTED_ITEM( aZone ) { // Should the copy be on the same net? - SetNet( aZone.GetNet() ); + SetNetCode( aZone.GetNetCode() ); m_Poly = new CPolyLine( *aZone.m_Poly ); // For corner moving, corner index to drag, or -1 if no selection @@ -138,31 +137,6 @@ const wxPoint& ZONE_CONTAINER::GetPosition() const } -void ZONE_CONTAINER::SetNet( int aNetCode ) -{ - BOARD_CONNECTED_ITEM::SetNet( aNetCode ); - - if( aNetCode < 0 ) - return; - - BOARD* board = GetBoard(); - - if( board ) - { - NETINFO_ITEM* net = board->FindNet( aNetCode ); - - if( net ) - m_Netname = net->GetNetname(); - else - m_Netname.Empty(); - } - else - { - m_Netname.Empty(); - } -} - - void ZONE_CONTAINER::Draw( EDA_DRAW_PANEL* panel, wxDC* DC, GR_DRAWMODE aDrawMode, const wxPoint& offset ) { @@ -614,10 +588,6 @@ void ZONE_CONTAINER::GetMsgPanelInfo( std::vector< MSG_PANEL_ITEM >& aList ) { wxString msg; - BOARD* board = (BOARD*) m_Parent; - - wxASSERT( board ); - msg = _( "Zone Outline" ); // Display Cutout instead of Outline for holes inside a zone @@ -646,9 +616,9 @@ void ZONE_CONTAINER::GetMsgPanelInfo( std::vector< MSG_PANEL_ITEM >& aList ) } else if( IsOnCopperLayer() ) { - if( GetNet() >= 0 ) + if( GetNetCode() >= 0 ) { - NETINFO_ITEM* equipot = board->FindNet( GetNet() ); + NETINFO_ITEM* equipot = GetNet(); if( equipot ) msg = equipot->GetNetname(); @@ -658,7 +628,7 @@ void ZONE_CONTAINER::GetMsgPanelInfo( std::vector< MSG_PANEL_ITEM >& aList ) else // a netcode < 0 is an error { msg = wxT( " [" ); - msg << m_Netname + wxT( "]" ); + msg << GetNetname() + wxT( "]" ); msg << wxT( " <" ) << _( "Not Found" ) << wxT( ">" ); } @@ -666,7 +636,7 @@ void ZONE_CONTAINER::GetMsgPanelInfo( std::vector< MSG_PANEL_ITEM >& aList ) #if 1 // Display net code : (useful in test or debug) - msg.Printf( wxT( "%d" ), GetNet() ); + msg.Printf( wxT( "%d" ), GetNetCode() ); aList.push_back( MSG_PANEL_ITEM( _( "NetCode" ), msg, RED ) ); #endif @@ -827,7 +797,7 @@ void ZONE_CONTAINER::Copy( ZONE_CONTAINER* src ) { m_Parent = src->m_Parent; m_Layer = src->m_Layer; - SetNet( src->GetNet() ); + SetNetCode( src->GetNetCode() ); SetTimeStamp( src->m_TimeStamp ); m_Poly->RemoveAllContours(); m_Poly->Copy( src->m_Poly ); // copy outlines @@ -849,20 +819,6 @@ void ZONE_CONTAINER::Copy( ZONE_CONTAINER* src ) } -bool ZONE_CONTAINER::SetNetNameFromNetCode( void ) -{ - NETINFO_ITEM* net; - - if( m_Parent && ( net = ( (BOARD*) m_Parent )->FindNet( GetNet() ) ) ) - { - m_Netname = net->GetNetname(); - return true; - } - - return false; -} - - ZoneConnection ZONE_CONTAINER::GetPadConnection( D_PAD* aPad ) const { if( aPad == NULL || aPad->GetZoneConnection() == UNDEFINED_CONNECTION ) @@ -909,11 +865,11 @@ wxString ZONE_CONTAINER::GetSelectMenuText() const // Display net name for copper zones if( !GetIsKeepout() ) { - if( GetNet() >= 0 ) + if( GetNetCode() >= 0 ) { if( board ) { - net = board->FindNet( GetNet() ); + net = GetNet(); if( net ) { @@ -928,7 +884,7 @@ wxString ZONE_CONTAINER::GetSelectMenuText() const else { // A netcode < 0 is an error: // Netname not found or area not initialised - text << wxT( " [" ) << m_Netname << wxT( "]" ); + text << wxT( " [" ) << GetNetname() << wxT( "]" ); text << wxT( " <" ) << _( "Not Found" ) << wxT( ">" ); } } diff --git a/pcbnew/class_zone.h b/pcbnew/class_zone.h index 513859b9d8..6423d85396 100644 --- a/pcbnew/class_zone.h +++ b/pcbnew/class_zone.h @@ -186,31 +186,6 @@ public: return ( GetLayer() < FIRST_NON_COPPER_LAYER ) ? true : false; } - /** - * Function SetNet - * sets the netcode and the netname. - * - * @param aNetCode The net code of the zone container if greater than or equal to - * zero. Otherwise the current net code is kept and set the net - * code error flag. - */ - virtual void SetNet( int aNetCode ); - - /** - * Function SetNetNameFromNetCode - * Find the net name corresponding to the net code. - * @return bool - true if net found, else false - */ - bool SetNetNameFromNetCode( void ); - - /** - * Function GetNetName - * returns the net name. - * @return const wxString& - The net name. - */ - const wxString& GetNetName() const { return m_Netname; }; - void SetNetName( const wxString& aName ) { m_Netname = aName; } - /// How to fill areas: 0 = use filled polygons, 1 => fill with segments. void SetFillMode( int aFillMode ) { m_FillMode = aFillMode; } int GetFillMode() const { return m_FillMode; } @@ -607,7 +582,6 @@ public: private: CPolyLine* m_Poly; ///< Outline of the zone. - wxString m_Netname; ///< Name of the net assigned to the zone. CPolyLine* m_smoothedPoly; // Corner-smoothed version of m_Poly int m_cornerSmoothingType; unsigned int m_cornerRadius; diff --git a/pcbnew/class_zone_settings.cpp b/pcbnew/class_zone_settings.cpp index bdf85dbbd6..b17968123f 100644 --- a/pcbnew/class_zone_settings.cpp +++ b/pcbnew/class_zone_settings.cpp @@ -76,7 +76,7 @@ ZONE_SETTINGS& ZONE_SETTINGS::operator << ( const ZONE_CONTAINER& aSource ) m_FillMode = aSource.GetFillMode(); m_ZoneClearance = aSource.GetClearance(); m_ZoneMinThickness = aSource.GetMinThickness(); - m_NetcodeSelection = aSource.GetNet(); + m_NetcodeSelection = aSource.GetNetCode(); m_CurrentZone_Layer = aSource.GetLayer(); m_Zone_HatchingStyle = aSource.GetHatchStyle(); m_ArcToSegmentsCount = aSource.GetArcSegmentCount(); @@ -113,7 +113,7 @@ void ZONE_SETTINGS::ExportSetting( ZONE_CONTAINER& aTarget, bool aFullExport ) c if( aFullExport ) { aTarget.SetPriority( m_ZonePriority ); - aTarget.SetNet( m_NetcodeSelection ); + aTarget.SetNetCode( m_NetcodeSelection ); aTarget.SetLayer( m_CurrentZone_Layer ); aTarget.Outline()->SetLayer( m_CurrentZone_Layer ); } diff --git a/pcbnew/clean.cpp b/pcbnew/clean.cpp index 2fdd6e9975..8e2f77d506 100644 --- a/pcbnew/clean.cpp +++ b/pcbnew/clean.cpp @@ -323,14 +323,14 @@ bool TRACKS_CLEANER::deleteUnconnectedTracks() zone = m_Brd->HitTestForAnyFilledArea( track->GetStart(), track->GetLayer(), track->GetLayer(), - track->GetNet() ); + track->GetNetCode() ); } else { ((SEGVIA*)track)->ReturnLayerPair( &top_layer, &bottom_layer ); zone = m_Brd->HitTestForAnyFilledArea( track->GetStart(), top_layer, bottom_layer, - track->GetNet() ); + track->GetNetCode() ); } } @@ -359,7 +359,7 @@ bool TRACKS_CLEANER::deleteUnconnectedTracks() zone = m_Brd->HitTestForAnyFilledArea( via->GetStart(), bottom_layer, top_layer, - via->GetNet() ); + via->GetNetCode() ); } if( (other == NULL) && (zone == NULL) ) @@ -383,14 +383,14 @@ bool TRACKS_CLEANER::deleteUnconnectedTracks() zone = m_Brd->HitTestForAnyFilledArea( track->GetEnd(), track->GetLayer(), track->GetLayer(), - track->GetNet() ); + track->GetNetCode() ); } else { ((SEGVIA*)track)->ReturnLayerPair( &top_layer, &bottom_layer ); zone = m_Brd->HitTestForAnyFilledArea( track->GetEnd(), top_layer, bottom_layer, - track->GetNet() ); + track->GetNetCode() ); } } @@ -419,7 +419,7 @@ bool TRACKS_CLEANER::deleteUnconnectedTracks() via->ReturnLayerPair( &top_layer, &bottom_layer ); zone = m_Brd->HitTestForAnyFilledArea( via->GetEnd(), bottom_layer, top_layer, - via->GetNet() ); + via->GetNetCode() ); } if( (other == NULL) && (zone == NULL) ) @@ -479,7 +479,7 @@ bool TRACKS_CLEANER::clean_segments() if( segment->GetLayer() != other->GetLayer() ) continue; - if( segment->GetNet() != other->GetNet() ) + if( segment->GetNetCode() != other->GetNetCode() ) break; if( ( segment->GetStart() == other->GetStart() ) && @@ -748,14 +748,14 @@ bool PCB_EDIT_FRAME::RemoveMisConnectedTracks() if( segment->start && segment->start->Type()==PCB_PAD_T ) { // get the netcode of the pad to propagate. - net_code_s = ((D_PAD*)(segment->start))->GetNet(); + net_code_s = ((D_PAD*)(segment->start))->GetNetCode(); } else { other = segment->GetTrace( GetBoard()->m_Track, NULL, FLG_START ); if( other ) - net_code_s = other->GetNet(); + net_code_s = other->GetNetCode(); } if( net_code_s < 0 ) @@ -766,14 +766,14 @@ bool PCB_EDIT_FRAME::RemoveMisConnectedTracks() if( segment->end && segment->end->Type()==PCB_PAD_T ) { - net_code_e = ((D_PAD*)(segment->end))->GetNet(); + net_code_e = ((D_PAD*)(segment->end))->GetNetCode(); } else { other = segment->GetTrace( GetBoard()->m_Track, NULL, FLG_END ); if( other ) - net_code_e = other->GetNet(); + net_code_e = other->GetNetCode(); } if( net_code_e < 0 ) diff --git a/pcbnew/connect.cpp b/pcbnew/connect.cpp index aa8d4867e6..9fd2c7ad47 100644 --- a/pcbnew/connect.cpp +++ b/pcbnew/connect.cpp @@ -718,7 +718,7 @@ void PCB_BASE_FRAME::TestConnections() for( TRACK* track = m_Pcb->m_Track; track; ) { // At this point, track is the first track of a given net - current_net_code = track->GetNet(); + current_net_code = track->GetNetCode(); // Get last track of the current net TRACK* lastTrack = track->GetEndNetCode( current_net_code ); @@ -760,7 +760,7 @@ void PCB_BASE_FRAME::TestNetConnection( wxDC* aDC, int aNetCode ) for( unsigned i = 0; i < m_Pcb->GetPadCount(); ++i ) { D_PAD* pad = m_Pcb->GetPad(i); - int pad_net_code = pad->GetNet(); + int pad_net_code = pad->GetNetCode(); if( pad_net_code < aNetCode ) continue; @@ -786,7 +786,7 @@ void PCB_BASE_FRAME::TestNetConnection( wxDC* aDC, int aNetCode ) if( firstTrack && lastTrack ) // i.e. if there are segments { - connections.Build_CurrNet_SubNets_Connections( firstTrack, lastTrack, firstTrack->GetNet() ); + connections.Build_CurrNet_SubNets_Connections( firstTrack, lastTrack, firstTrack->GetNetCode() ); } } @@ -842,7 +842,7 @@ void PCB_BASE_FRAME::RecalculateAllTracksNetcode() curr_track->end = NULL; curr_track->SetState( BUSY | IN_EDIT | BEGIN_ONPAD | END_ONPAD, false ); curr_track->SetZoneSubNet( 0 ); - curr_track->SetNet( 0 ); // net code = 0 means not connected + curr_track->SetNetCode( NETINFO_LIST::UNCONNECTED ); } // If no pad, reset pointers and netcode, and do nothing else @@ -863,7 +863,7 @@ void PCB_BASE_FRAME::RecalculateAllTracksNetcode() for( ; curr_track != NULL; curr_track = curr_track->Next() ) { if( curr_track->m_PadsConnected.size() ) - curr_track->SetNet( curr_track->m_PadsConnected[0]->GetNet() ); + curr_track->SetNetCode( curr_track->m_PadsConnected[0]->GetNetCode() ); } // Pass 2: build connections between track ends @@ -883,17 +883,17 @@ void PCB_BASE_FRAME::RecalculateAllTracksNetcode() for( curr_track = m_Pcb->m_Track; curr_track; curr_track = curr_track->Next() ) { - int netcode = curr_track->GetNet(); + int netcode = curr_track->GetNetCode(); if( netcode == 0 ) { // try to find a connected item having a netcode for( unsigned kk = 0; kk < curr_track->m_TracksConnected.size(); kk++ ) { - int altnetcode = curr_track->m_TracksConnected[kk]->GetNet(); + int altnetcode = curr_track->m_TracksConnected[kk]->GetNetCode(); if( altnetcode ) { new_pass_request = true; netcode = altnetcode; - curr_track->SetNet(netcode); + curr_track->SetNetCode(netcode); break; } } @@ -902,10 +902,10 @@ void PCB_BASE_FRAME::RecalculateAllTracksNetcode() { // propagate this netcode to connected tracks having no netcode for( unsigned kk = 0; kk < curr_track->m_TracksConnected.size(); kk++ ) { - int altnetcode = curr_track->m_TracksConnected[kk]->GetNet(); + int altnetcode = curr_track->m_TracksConnected[kk]->GetNetCode(); if( altnetcode == 0 ) { - curr_track->m_TracksConnected[kk]->SetNet(netcode); + curr_track->m_TracksConnected[kk]->SetNetCode(netcode); new_pass_request = true; } } @@ -926,10 +926,10 @@ void PCB_BASE_FRAME::RecalculateAllTracksNetcode() static bool SortTracksByNetCode( const TRACK* const & ref, const TRACK* const & compare ) { // For items having the same Net, keep the order in list - if( ref->GetNet() == compare->GetNet()) + if( ref->GetNetCode() == compare->GetNetCode()) return ref->m_Param < compare->m_Param; - return ref->GetNet() < compare->GetNet(); + return ref->GetNetCode() < compare->GetNetCode(); } /** diff --git a/pcbnew/cross-probing.cpp b/pcbnew/cross-probing.cpp index d1f41b791f..8042a892a0 100644 --- a/pcbnew/cross-probing.cpp +++ b/pcbnew/cross-probing.cpp @@ -87,7 +87,7 @@ void PCB_EDIT_FRAME::ExecuteRemoteCommand( const char* cmdline ) if( pad ) { - netcode = pad->GetNet(); + netcode = pad->GetNetCode(); // put cursor on the pad: pos = pad->GetPosition(); diff --git a/pcbnew/deltrack.cpp b/pcbnew/deltrack.cpp index 2a77f9faec..331fbd22ab 100644 --- a/pcbnew/deltrack.cpp +++ b/pcbnew/deltrack.cpp @@ -120,7 +120,7 @@ TRACK* PCB_EDIT_FRAME::Delete_Segment( wxDC* DC, TRACK* aTrack ) return NULL; } - current_net_code = aTrack->GetNet(); + current_net_code = aTrack->GetNetCode(); DLIST* container = (DLIST*)aTrack->GetList(); wxASSERT( container ); @@ -142,7 +142,7 @@ void PCB_EDIT_FRAME::Delete_Track( wxDC* DC, TRACK* aTrack ) { if( aTrack != NULL ) { - int current_net_code = aTrack->GetNet(); + int current_net_code = aTrack->GetNetCode(); Remove_One_Track( DC, aTrack ); OnModify(); TestNetConnection( DC, current_net_code ); @@ -160,7 +160,7 @@ void PCB_EDIT_FRAME::Delete_net( wxDC* DC, TRACK* aTrack ) PICKED_ITEMS_LIST itemsList; ITEM_PICKER picker( NULL, UR_DELETED ); - int net_code_delete = aTrack->GetNet(); + int net_code_delete = aTrack->GetNetCode(); /* Search the first item for the given net code */ TRACK* trackList = GetBoard()->m_Track->GetStartNetCode( net_code_delete ); @@ -171,7 +171,7 @@ void PCB_EDIT_FRAME::Delete_net( wxDC* DC, TRACK* aTrack ) for( TRACK* segm = trackList; segm; segm = next_track, ++ii ) { next_track = segm->Next(); - if( segm->GetNet() != net_code_delete ) + if( segm->GetNetCode() != net_code_delete ) break; GetBoard()->m_Track.Remove( segm ); @@ -202,7 +202,7 @@ void PCB_EDIT_FRAME::Remove_One_Track( wxDC* DC, TRACK* pt_segm ) if( segments_to_delete_count == 0 ) return; - int net_code = pt_segm->GetNet(); + int net_code = pt_segm->GetNetCode(); PICKED_ITEMS_LIST itemsList; ITEM_PICKER picker( NULL, UR_DELETED ); diff --git a/pcbnew/dialogs/dialog_pad_properties.cpp b/pcbnew/dialogs/dialog_pad_properties.cpp index 49e2e3d2b2..42f75d220c 100644 --- a/pcbnew/dialogs/dialog_pad_properties.cpp +++ b/pcbnew/dialogs/dialog_pad_properties.cpp @@ -151,7 +151,8 @@ DIALOG_PAD_PROPERTIES::DIALOG_PAD_PROPERTIES( PCB_BASE_FRAME* aParent, D_PAD* aP m_parent = aParent; m_currentPad = aPad; m_board = m_parent->GetBoard(); - m_dummyPad = new D_PAD( (MODULE*) NULL ); + m_dummyPad = new D_PAD( aPad->GetParent() ); + m_padMaster.SetParent( aPad->GetParent() ); if( aPad ) m_dummyPad->Copy( aPad ); @@ -810,25 +811,16 @@ void DIALOG_PAD_PROPERTIES::PadPropertiesAccept( wxCommandEvent& event ) m_currentPad->SetPadName( m_padMaster.GetPadName() ); - if( m_currentPad->GetNetname() != m_padMaster.GetNetname() ) + if( m_currentPad->GetNetname() != m_PadNetNameCtrl->GetValue() ) { - if( m_padMaster.GetNetname().IsEmpty() ) + if( !m_PadNetNameCtrl->GetValue().IsEmpty() && m_padMaster.GetNetCode() == 0 ) { - rastnestIsChanged = true; - m_currentPad->SetNet( 0 ); - m_currentPad->SetNetname( wxEmptyString ); + DisplayError( NULL, _( "Unknown netname, netname not changed" ) ); } else { - const NETINFO_ITEM* net = m_board->FindNet( m_padMaster.GetNetname() ); - if( net ) - { - rastnestIsChanged = true; - m_currentPad->SetNetname( m_padMaster.GetNetname() ); - m_currentPad->SetNet( net->GetNet() ); - } - else - DisplayError( NULL, _( "Unknown netname, netname not changed" ) ); + rastnestIsChanged = true; + m_currentPad->SetNetCode( m_padMaster.GetNetCode() ); } } @@ -987,7 +979,13 @@ bool DIALOG_PAD_PROPERTIES::transferDataToPad( D_PAD* aPad ) msg = m_PadNumCtrl->GetValue().Left( 4 ); aPad->SetPadName( msg ); - aPad->SetNetname( m_PadNetNameCtrl->GetValue() ); + + // Check if user has set an existing net name + const NETINFO_ITEM* netinfo = m_board->FindNet( m_PadNetNameCtrl->GetValue() ); + if( netinfo != NULL ) + aPad->SetNetCode( netinfo->GetNet() ); + else + aPad->SetNetCode( NETINFO_LIST::UNCONNECTED ); // Clear some values, according to the pad type and shape switch( aPad->GetShape() ) @@ -1035,7 +1033,7 @@ bool DIALOG_PAD_PROPERTIES::transferDataToPad( D_PAD* aPad ) // no offset, no net name, no pad name allowed aPad->SetOffset( wxPoint( 0, 0 ) ); aPad->SetPadName( wxEmptyString ); - aPad->SetNetname( wxEmptyString ); + aPad->SetNetCode( NETINFO_LIST::UNCONNECTED ); break; default: diff --git a/pcbnew/dragsegm.cpp b/pcbnew/dragsegm.cpp index 0e0303f860..122d1ea110 100644 --- a/pcbnew/dragsegm.cpp +++ b/pcbnew/dragsegm.cpp @@ -342,7 +342,7 @@ void Collect_TrackSegmentsToDrag( BOARD* aPcb, const wxPoint& aRefPos, LAYER_MSK for( ; track; track = track->Next() ) { - if( track->GetNet() != aNetCode ) // not the same netcodenet code: all candidates tested + if( track->GetNetCode() != aNetCode ) // not the same netcode: all candidates tested break; if( ( aLayerMask & track->GetLayerMask() ) == 0 ) diff --git a/pcbnew/drc.cpp b/pcbnew/drc.cpp index bad9f65fd7..c10f0537b0 100644 --- a/pcbnew/drc.cpp +++ b/pcbnew/drc.cpp @@ -549,7 +549,7 @@ void DRC::testZones() if( !test_area->IsOnCopperLayer() ) continue; - if( test_area->GetNet() < 0 ) + if( test_area->GetNetCode() < 0 ) { m_currentMarker = fillMarker( test_area, DRCE_NON_EXISTANT_NET_FOR_ZONE_OUTLINE, m_currentMarker ); @@ -756,7 +756,7 @@ bool DRC::doPadToPadsDrc( D_PAD* aRefPad, D_PAD** aStart, D_PAD** aEnd, int x_li // The pad must be in a net (i.e pt_pad->GetNet() != 0 ), // But no problem if pads have the same netcode (same net) - if( pad->GetNet() && ( aRefPad->GetNet() == pad->GetNet() ) ) + if( pad->GetNetCode() && ( aRefPad->GetNetCode() == pad->GetNetCode() ) ) continue; // if pads are from the same footprint diff --git a/pcbnew/drc_clearance_test_functions.cpp b/pcbnew/drc_clearance_test_functions.cpp index 1fd8a94ccd..06bc935cd1 100644 --- a/pcbnew/drc_clearance_test_functions.cpp +++ b/pcbnew/drc_clearance_test_functions.cpp @@ -164,7 +164,7 @@ bool DRC::doTrackDrc( TRACK* aRefSeg, TRACK* aStart, bool testPads ) m_segmAngle = 0; layerMask = aRefSeg->GetLayerMask(); - net_code_ref = aRefSeg->GetNet(); + net_code_ref = aRefSeg->GetNetCode(); // Phase 0 : Test vias if( aRefSeg->Type() == PCB_VIA_T ) @@ -310,8 +310,8 @@ bool DRC::doTrackDrc( TRACK* aRefSeg, TRACK* aStart, bool testPads ) // The pad must be in a net (i.e pt_pad->GetNet() != 0 ) // but no problem if the pad netcode is the current netcode (same net) - if( pad->GetNet() // the pad must be connected - && net_code_ref == pad->GetNet() ) // the pad net is the same as current net -> Ok + if( pad->GetNetCode() // the pad must be connected + && net_code_ref == pad->GetNetCode() ) // the pad net is the same as current net -> Ok continue; // DRC for the pad @@ -339,7 +339,7 @@ bool DRC::doTrackDrc( TRACK* aRefSeg, TRACK* aStart, bool testPads ) for( track = aStart; track; track = track->Next() ) { // No problem if segments have the same net code: - if( net_code_ref == track->GetNet() ) + if( net_code_ref == track->GetNetCode() ) continue; // No problem if segment are on different layers : diff --git a/pcbnew/eagle_plugin.cpp b/pcbnew/eagle_plugin.cpp index 80b2fe78c5..f8e31fddec 100644 --- a/pcbnew/eagle_plugin.cpp +++ b/pcbnew/eagle_plugin.cpp @@ -1493,7 +1493,7 @@ void EAGLE_PLUGIN::loadPlain( CPTREE& aGraphics ) zone->SetTimeStamp( timeStamp( gr->second ) ); zone->SetLayer( layer ); - zone->SetNet( 0 ); + zone->SetNetCode( NETINFO_LIST::UNCONNECTED ); CPolyLine::HATCH_STYLE outline_hatch = CPolyLine::DIAGONAL_EDGE; @@ -1696,8 +1696,7 @@ void EAGLE_PLUGIN::loadElements( CPTREE& aElements ) if( ni != m_pads_to_nets.end() ) { const ENET* enet = &ni->second; - pad->SetNetname( FROM_UTF8( enet->netname.c_str() ) ); - pad->SetNet( enet->netcode ); + pad->SetNetCode( enet->netcode ); } } @@ -1880,7 +1879,7 @@ void EAGLE_PLUGIN::orientModuleText( MODULE* m, const EELEMENT& e, MODULE* EAGLE_PLUGIN::makeModule( CPTREE& aPackage, const string& aPkgName ) const { - std::auto_ptr m( new MODULE( NULL ) ); + std::auto_ptr m( new MODULE( m_board ) ); m->SetFPID( FPID( aPkgName ) ); @@ -2260,7 +2259,6 @@ void EAGLE_PLUGIN::packageHole( MODULE* aModule, CPTREE& aTree ) const // no offset, no net name, no pad name allowed // pad->SetOffset( wxPoint( 0, 0 ) ); // pad->SetPadName( wxEmptyString ); - // pad->SetNetname( wxEmptyString ); wxPoint padpos( kicad_x( e.x ), kicad_y( e.y ) ); @@ -2353,6 +2351,7 @@ void EAGLE_PLUGIN::loadSignals( CPTREE& aSignals ) const string& nname = net->second.get( ".name" ); wxString netName = FROM_UTF8( nname.c_str() ); + m_board->AppendNet( new NETINFO_ITEM( m_board, netName, netCode ) ); m_xpath->Value( nname.c_str() ); @@ -2388,7 +2387,7 @@ void EAGLE_PLUGIN::loadSignals( CPTREE& aSignals ) t->SetWidth( width ); t->SetLayer( layer ); - t->SetNet( netCode ); + t->SetNetCode( netCode ); m_board->m_Track.Insert( t, NULL ); } @@ -2453,7 +2452,7 @@ void EAGLE_PLUGIN::loadSignals( CPTREE& aSignals ) via->SetPosition( pos ); via->SetEnd( pos ); - via->SetNet( netCode ); + via->SetNetCode( netCode ); via->SetShape( S_CIRCLE ); // @todo should be in SEGVIA constructor } @@ -2496,8 +2495,7 @@ void EAGLE_PLUGIN::loadSignals( CPTREE& aSignals ) zone->SetTimeStamp( timeStamp( it->second ) ); zone->SetLayer( layer ); - zone->SetNet( netCode ); - zone->SetNetName( netName ); + zone->SetNetCode( netCode ); CPolyLine::HATCH_STYLE outline_hatch = CPolyLine::DIAGONAL_EDGE; @@ -2553,15 +2551,12 @@ void EAGLE_PLUGIN::loadSignals( CPTREE& aSignals ) // KiCad does not support an unconnected zone with its own non-zero netcode, // but only when assigned netcode = 0 w/o a name... for( ZONES::iterator it = zones.begin(); it != zones.end(); ++it ) - { - (*it)->SetNet( 0 ); - (*it)->SetNetName( wxEmptyString ); - } + (*it)->SetNetCode( NETINFO_LIST::UNCONNECTED ); // therefore omit this signal/net. } else - m_board->AppendNet( new NETINFO_ITEM( m_board, netName, netCode++ ) ); + netCode++; } m_xpath->pop(); // "signals.signal" diff --git a/pcbnew/edit.cpp b/pcbnew/edit.cpp index e2ccdd8a8f..9356d9787a 100644 --- a/pcbnew/edit.cpp +++ b/pcbnew/edit.cpp @@ -328,7 +328,7 @@ void PCB_EDIT_FRAME::Process_Special_Functions( wxCommandEvent& event ) if( type == PCB_TRACE_T || type == PCB_VIA_T ) { BOARD_CONNECTED_ITEM*item = (BOARD_CONNECTED_ITEM*) GetCurItem(); - DIALOG_GLOBAL_EDIT_TRACKS_AND_VIAS dlg( this, item->GetNet() ); + DIALOG_GLOBAL_EDIT_TRACKS_AND_VIAS dlg( this, item->GetNetCode() ); dlg.ShowModal(); } @@ -468,11 +468,11 @@ void PCB_EDIT_FRAME::Process_Special_Functions( wxCommandEvent& event ) break; case ID_POPUP_PCB_LOCK_ON_NET: - Attribut_net( &dc, ( (TRACK*) GetCurItem() )->GetNet(), true ); + Attribut_net( &dc, ( (TRACK*) GetCurItem() )->GetNetCode(), true ); break; case ID_POPUP_PCB_LOCK_OFF_NET: - Attribut_net( &dc, ( (TRACK*) GetCurItem() )->GetNet(), false ); + Attribut_net( &dc, ( (TRACK*) GetCurItem() )->GetNetCode(), false ); break; case ID_POPUP_PCB_SETFLAGS_TRACK_MNU: @@ -486,7 +486,7 @@ void PCB_EDIT_FRAME::Process_Special_Functions( wxCommandEvent& event ) { SEGZONE* zsegm = (SEGZONE*) GetCurItem(); - int netcode = zsegm->GetNet(); + int netcode = zsegm->GetNetCode(); Delete_OldZone_Fill( zsegm ); SetCurItem( NULL ); TestNetConnection( NULL, netcode ); @@ -523,7 +523,7 @@ void PCB_EDIT_FRAME::Process_Special_Functions( wxCommandEvent& event ) case ID_POPUP_PCB_DELETE_ZONE_CUTOUT: m_canvas->MoveCursorToCrossHair(); { - int netcode = ( (ZONE_CONTAINER*) GetCurItem() )->GetNet(); + int netcode = ( (ZONE_CONTAINER*) GetCurItem() )->GetNetCode(); Delete_Zone_Contour( &dc, (ZONE_CONTAINER*) GetCurItem() ); SetCurItem( NULL ); TestNetConnection( NULL, netcode ); @@ -604,7 +604,7 @@ void PCB_EDIT_FRAME::Process_Special_Functions( wxCommandEvent& event ) { ZONE_CONTAINER* zone_container = (ZONE_CONTAINER*) GetCurItem(); zone_container->UnFill(); - TestNetConnection( NULL, zone_container->GetNet() ); + TestNetConnection( NULL, zone_container->GetNetCode() ); OnModify(); SetMsgPanel( GetBoard() ); m_canvas->Refresh(); @@ -633,7 +633,7 @@ void PCB_EDIT_FRAME::Process_Special_Functions( wxCommandEvent& event ) case ID_POPUP_PCB_FILL_ZONE: m_canvas->MoveCursorToCrossHair(); Fill_Zone( (ZONE_CONTAINER*) GetCurItem() ); - TestNetConnection( NULL, ( (ZONE_CONTAINER*) GetCurItem() )->GetNet() ); + TestNetConnection( NULL, ( (ZONE_CONTAINER*) GetCurItem() )->GetNetCode() ); SetMsgPanel( GetBoard() ); m_canvas->Refresh(); break; @@ -1156,7 +1156,7 @@ void PCB_EDIT_FRAME::Process_Special_Functions( wxCommandEvent& event ) newtrack->Draw( m_canvas, &dc, GR_XOR ); // compute the new ratsnest, because connectivity could change - TestNetConnection( &dc, track->GetNet() ); + TestNetConnection( &dc, track->GetNetCode() ); } break; @@ -1248,7 +1248,7 @@ void PCB_EDIT_FRAME::RemoveStruct( BOARD_ITEM* Item, wxDC* DC ) case PCB_ZONE_AREA_T: { SetCurItem( NULL ); - int netcode = ( (ZONE_CONTAINER*) Item )->GetNet(); + int netcode = ( (ZONE_CONTAINER*) Item )->GetNetCode(); Delete_Zone_Contour( DC, (ZONE_CONTAINER*) Item ); TestNetConnection( NULL, netcode ); SetMsgPanel( GetBoard() ); diff --git a/pcbnew/edit_track_width.cpp b/pcbnew/edit_track_width.cpp index 6698f2be1a..4c2d5e8327 100644 --- a/pcbnew/edit_track_width.cpp +++ b/pcbnew/edit_track_width.cpp @@ -36,7 +36,7 @@ bool PCB_EDIT_FRAME::SetTrackSegmentWidth( TRACK* aTrackItem, NETINFO_ITEM* net = NULL; if( aUseNetclassValue ) - net = GetBoard()->FindNet( aTrackItem->GetNet() ); + net = aTrackItem->GetNet(); initial_width = aTrackItem->GetWidth(); @@ -224,7 +224,7 @@ bool PCB_EDIT_FRAME::Change_Net_Tracks_And_Vias_Sizes( int aNetcode, bool aUseNe for( pt_segm = GetBoard()->m_Track; pt_segm != NULL; pt_segm = pt_segm->Next() ) { - if( aNetcode != pt_segm->GetNet() ) // not in net + if( aNetcode != pt_segm->GetNetCode() ) // not in net continue; // we have found a item member of the net diff --git a/pcbnew/editrack-part2.cpp b/pcbnew/editrack-part2.cpp index 81ba0cbd8b..e394ad1ca3 100644 --- a/pcbnew/editrack-part2.cpp +++ b/pcbnew/editrack-part2.cpp @@ -99,7 +99,7 @@ bool PCB_EDIT_FRAME::Other_Layer_Route( TRACK* aTrack, wxDC* DC ) via->SetFlags( IS_NEW ); via->SetShape( GetDesignSettings().m_CurrentViaType ); via->SetWidth( GetBoard()->GetCurrentViaSize()); - via->SetNet( GetBoard()->GetHighLightNetCode() ); + via->SetNetCode( GetBoard()->GetHighLightNetCode() ); via->SetEnd( g_CurrentTrackSegment->GetEnd() ); via->SetStart( g_CurrentTrackSegment->GetEnd() ); @@ -139,7 +139,7 @@ bool PCB_EDIT_FRAME::Other_Layer_Route( TRACK* aTrack, wxDC* DC ) // else error: will be removed later via->SetLayerPair( first_layer, last_layer ); { - NETINFO_ITEM* net = GetBoard()->FindNet( via->GetNet() ); + NETINFO_ITEM* net = via->GetNet(); via->SetWidth( net->GetMicroViaSize() ); } } @@ -244,7 +244,7 @@ void PCB_EDIT_FRAME::Show_1_Ratsnest( EDA_ITEM* item, wxDC* DC ) { RATSNEST_ITEM* net = &GetBoard()->m_FullRatsnest[ii]; - if( net->GetNet() == pt_pad->GetNet() ) + if( net->GetNet() == pt_pad->GetNetCode() ) { if( ( net->m_Status & CH_VISIBLE ) != 0 ) continue; diff --git a/pcbnew/editrack.cpp b/pcbnew/editrack.cpp index 24223bc8f4..41cc2d7e30 100644 --- a/pcbnew/editrack.cpp +++ b/pcbnew/editrack.cpp @@ -133,12 +133,12 @@ TRACK* PCB_EDIT_FRAME::Begin_Route( TRACK* aTrack, wxDC* aDC ) // A pad is found: put the starting point on pad center pos = pad->GetPosition(); - GetBoard()->SetHighLightNet( pad->GetNet() ); + GetBoard()->SetHighLightNet( pad->GetNetCode() ); } else // A track segment is found { TrackOnStartPoint = (TRACK*) LockPoint; - GetBoard()->SetHighLightNet( TrackOnStartPoint->GetNet() ); + GetBoard()->SetHighLightNet( TrackOnStartPoint->GetNetCode() ); GetBoard()->CreateLockPoint( pos, TrackOnStartPoint, &s_ItemsListPicker ); } } @@ -153,7 +153,7 @@ TRACK* PCB_EDIT_FRAME::Begin_Route( TRACK* aTrack, wxDC* aDC ) -1 ); if( zone ) - GetBoard()->SetHighLightNet( zone->GetNet() ); + GetBoard()->SetHighLightNet( zone->GetNetCode() ); } DBG( g_CurrentTrackList.VerifyListIntegrity() ); @@ -166,7 +166,7 @@ TRACK* PCB_EDIT_FRAME::Begin_Route( TRACK* aTrack, wxDC* aDC ) GetBoard()->DrawHighLight( m_canvas, aDC, GetBoard()->GetHighLightNetCode() ); // Display info about track Net class, and init track and vias sizes: - g_CurrentTrackSegment->SetNet( GetBoard()->GetHighLightNetCode() ); + g_CurrentTrackSegment->SetNetCode( GetBoard()->GetHighLightNetCode() ); GetBoard()->SetCurrentNetClass( g_CurrentTrackSegment->GetNetClassName() ); g_CurrentTrackSegment->SetLayer( GetScreen()->m_Active_Layer ); @@ -476,7 +476,7 @@ bool PCB_EDIT_FRAME::End_Route( TRACK* aTrack, wxDC* aDC ) // g_FirstTrackSegment can be NULL on a double click on the starting point if( g_FirstTrackSegment != NULL ) { - int netcode = g_FirstTrackSegment->GetNet(); + int netcode = g_FirstTrackSegment->GetNetCode(); TRACK* firstTrack = g_FirstTrackSegment; int newCount = g_CurrentTrackList.GetCount(); @@ -540,7 +540,7 @@ bool PCB_EDIT_FRAME::End_Route( TRACK* aTrack, wxDC* aDC ) TRACK* LocateIntrusion( TRACK* listStart, TRACK* aTrack, LAYER_NUM aLayer, const wxPoint& aRef ) { - int net = aTrack->GetNet(); + int net = aTrack->GetNetCode(); int width = aTrack->GetWidth(); TRACK* found = NULL; @@ -555,7 +555,7 @@ TRACK* LocateIntrusion( TRACK* listStart, TRACK* aTrack, LAYER_NUM aLayer, const if( aLayer != track->GetLayer() ) continue; - if( track->GetNet() == net ) + if( track->GetNetCode() == net ) continue; // TRACK::HitTest @@ -614,7 +614,7 @@ static void PushTrack( EDA_DRAW_PANEL* panel ) if( !other ) return; - if( other->GetNet() == track->GetNet() ) + if( other->GetNetCode() == track->GetNetCode() ) return; cv = cursor - other->GetStart(); diff --git a/pcbnew/exporters/export_d356.cpp b/pcbnew/exporters/export_d356.cpp index e8ef8f3fbf..1c64ff64bd 100644 --- a/pcbnew/exporters/export_d356.cpp +++ b/pcbnew/exporters/export_d356.cpp @@ -199,7 +199,7 @@ static void build_via_testpoints( BOARD *aPcb, if( track->Type() == PCB_VIA_T ) { SEGVIA *via = (SEGVIA*) track; - NETINFO_ITEM *net = aPcb->FindNet( track->GetNet() ); + NETINFO_ITEM *net = track->GetNet(); D356_RECORD rk; rk.smd = false; diff --git a/pcbnew/exporters/export_gencad.cpp b/pcbnew/exporters/export_gencad.cpp index f04496ff7c..638d22f55d 100644 --- a/pcbnew/exporters/export_gencad.cpp +++ b/pcbnew/exporters/export_gencad.cpp @@ -647,7 +647,6 @@ static void CreateSignalsSection( FILE* aFile, BOARD* aPcb ) if( net->GetNetname() == wxEmptyString ) // dummy netlist (no connection) { wxString msg; msg << wxT( "NoConnection" ) << NbNoConn++; - net->SetNetname( msg ); } if( net->GetNet() <= 0 ) // dummy netlist (no connection) @@ -664,7 +663,7 @@ static void CreateSignalsSection( FILE* aFile, BOARD* aPcb ) { wxString padname; - if( pad->GetNet() != net->GetNet() ) + if( pad->GetNetCode() != net->GetNet() ) continue; pad->ReturnStringPadName( padname ); @@ -731,7 +730,7 @@ static int TrackListSortByNetcode( const void* refptr, const void* objptr ) ref = *( (TRACK**) refptr ); cmp = *( (TRACK**) objptr ); - if( ( diff = ref->GetNet() - cmp->GetNet() ) ) + if( ( diff = ref->GetNetCode() - cmp->GetNetCode() ) ) return diff; if( ( diff = ref->GetWidth() - cmp->GetWidth() ) ) @@ -798,10 +797,10 @@ static void CreateRoutesSection( FILE* aFile, BOARD* aPcb ) { track = tracklist[ii]; - if( old_netcode != track->GetNet() ) + if( old_netcode != track->GetNetCode() ) { - old_netcode = track->GetNet(); - NETINFO_ITEM* net = aPcb->FindNet( track->GetNet() ); + old_netcode = track->GetNetCode(); + NETINFO_ITEM* net = track->GetNet(); wxString netname; if( net && (net->GetNetname() != wxEmptyString) ) diff --git a/pcbnew/footprint_wizard_frame.h b/pcbnew/footprint_wizard_frame.h index 653545d698..da1b6c86b0 100644 --- a/pcbnew/footprint_wizard_frame.h +++ b/pcbnew/footprint_wizard_frame.h @@ -194,7 +194,7 @@ private: */ void OnLeftDClick( wxDC*, const wxPoint& ) {} void SaveCopyInUndoList( BOARD_ITEM*, UNDO_REDO_T, const wxPoint& ) {} - void SaveCopyInUndoList( PICKED_ITEMS_LIST&, UNDO_REDO_T, const wxPoint& ) {} + void SaveCopyInUndoList( const PICKED_ITEMS_LIST&, UNDO_REDO_T, const wxPoint& ) {} DECLARE_EVENT_TABLE() diff --git a/pcbnew/highlight.cpp b/pcbnew/highlight.cpp index fc8e805ed1..d4188bdb4d 100644 --- a/pcbnew/highlight.cpp +++ b/pcbnew/highlight.cpp @@ -142,7 +142,7 @@ int PCB_EDIT_FRAME::SelectHighLight( wxDC* DC ) switch( item->Type() ) { case PCB_PAD_T: - netcode = ( (D_PAD*) item )->GetNet(); + netcode = ( (D_PAD*) item )->GetNetCode(); SendMessageToEESCHEMA( item ); break; @@ -151,11 +151,11 @@ int PCB_EDIT_FRAME::SelectHighLight( wxDC* DC ) case PCB_ZONE_T: // since these classes are all derived from TRACK, use a common // GetNet() function: - netcode = ( (TRACK*) item )->GetNet(); + netcode = ( (TRACK*) item )->GetNetCode(); break; case PCB_ZONE_AREA_T: - netcode = ( (ZONE_CONTAINER*) item )->GetNet(); + netcode = ( (ZONE_CONTAINER*) item )->GetNetCode(); break; default: diff --git a/pcbnew/kicad_plugin.cpp b/pcbnew/kicad_plugin.cpp index 99211a7e4d..f8ef4c8d13 100644 --- a/pcbnew/kicad_plugin.cpp +++ b/pcbnew/kicad_plugin.cpp @@ -380,6 +380,9 @@ void PCB_IO::Save( const wxString& aFileName, BOARD* aBoard, const PROPERTIES* a m_board = aBoard; // after init() + // Prepare net mapping that assures that net codes saved in a file are consecutive integers + m_mapping->SetBoard( aBoard ); + FILE_OUTPUTFORMATTER formatter( aFileName ); m_out = &formatter; // no ownership @@ -499,7 +502,7 @@ void PCB_IO::format( BOARD* aBoard, int aNestLevel ) const m_out->Print( aNestLevel+1, "(tracks %d)\n", aBoard->GetNumSegmTrack() ); m_out->Print( aNestLevel+1, "(zones %d)\n", aBoard->GetNumSegmZone() ); m_out->Print( aNestLevel+1, "(modules %d)\n", aBoard->m_Modules.GetCount() ); - m_out->Print( aNestLevel+1, "(nets %d)\n", aBoard->GetNetCount() ); + m_out->Print( aNestLevel+1, "(nets %d)\n", (int) m_mapping->GetSize() ); m_out->Print( aNestLevel, ")\n\n" ); aBoard->GetPageSettings().Format( m_out, aNestLevel, m_ctl ); @@ -654,15 +657,14 @@ void PCB_IO::format( BOARD* aBoard, int aNestLevel ) const m_out->Print( aNestLevel, ")\n\n" ); - int netcount = aBoard->GetNetCount(); - - for( int i = 0; i < netcount; ++i ) + // Save net codes and names + for( NETINFO_MAPPING::iterator net = m_mapping->begin(), netEnd = m_mapping->end(); + net != netEnd; ++net ) { - NETINFO_ITEM* net = aBoard->FindNet( i ); m_out->Print( aNestLevel, "(net %d %s)\n", - net->GetNet(), - m_out->Quotew( net->GetNetname() ).c_str() ); - } + m_mapping->Translate( net->GetNet() ), + m_out->Quotew( net->GetNetname() ).c_str() ); + } m_out->Print( 0, "\n" ); @@ -1228,8 +1230,9 @@ void PCB_IO::format( D_PAD* aPad, int aNestLevel ) const std::string output; // Unconnected pad is default net so don't save it. - if( !(m_ctl & CTL_OMIT_NETS) && aPad->GetNet() != 0 ) - StrPrintf( &output, " (net %d %s)", aPad->GetNet(), m_out->Quotew( aPad->GetNetname() ).c_str() ); + if( !(m_ctl & CTL_OMIT_NETS) && aPad->GetNetCode() != 0 ) + StrPrintf( &output, " (net %d %s)", m_mapping->Translate( aPad->GetNetCode() ), + m_out->Quotew( aPad->GetNetname() ).c_str() ); if( aPad->GetPadToDieLength() != 0 ) StrPrintf( &output, " (die_length %s)", FMT_IU( aPad->GetPadToDieLength() ).c_str() ); @@ -1386,7 +1389,7 @@ void PCB_IO::format( TRACK* aTrack, int aNestLevel ) const m_out->Print( 0, " (layer %s)", m_out->Quotew( aTrack->GetLayerName() ).c_str() ); } - m_out->Print( 0, " (net %d)", aTrack->GetNet() ); + m_out->Print( 0, " (net %d)", m_mapping->Translate( aTrack->GetNetCode() ) ); if( aTrack->GetTimeStamp() != 0 ) m_out->Print( 0, " (tstamp %lX)", aTrack->GetTimeStamp() ); @@ -1405,8 +1408,8 @@ void PCB_IO::format( ZONE_CONTAINER* aZone, int aNestLevel ) const // so be sure a dummy value is stored, just for ZONE_CONTAINER compatibility // (perhaps netcode and netname should be not stored) m_out->Print( aNestLevel, "(zone (net %d) (net_name %s)", - aZone->GetIsKeepout() ? 0 : aZone->GetNet(), - m_out->Quotew( aZone->GetIsKeepout() ? wxT("") : aZone->GetNetName() ).c_str() ); + aZone->GetIsKeepout() ? 0 : m_mapping->Translate( aZone->GetNetCode() ), + m_out->Quotew( aZone->GetIsKeepout() ? wxT("") : aZone->GetNetname() ).c_str() ); formatLayer( aZone ); @@ -1622,20 +1625,11 @@ void PCB_IO::format( ZONE_CONTAINER* aZone, int aNestLevel ) const } -PCB_IO::PCB_IO() : - m_cache( 0 ), - m_ctl( CTL_FOR_BOARD ), // expecting to OUTPUTFORMAT into BOARD files. - m_parser( new PCB_PARSER() ) -{ - init( 0 ); - m_out = &m_sf; -} - - PCB_IO::PCB_IO( int aControlFlags ) : m_cache( 0 ), m_ctl( aControlFlags ), - m_parser( new PCB_PARSER() ) + m_parser( new PCB_PARSER() ), + m_mapping( new NETINFO_MAPPING() ) { init( 0 ); m_out = &m_sf; @@ -1646,6 +1640,7 @@ PCB_IO::~PCB_IO() { delete m_cache; delete m_parser; + delete m_mapping; } diff --git a/pcbnew/kicad_plugin.h b/pcbnew/kicad_plugin.h index ce7c40ef38..95986e7531 100644 --- a/pcbnew/kicad_plugin.h +++ b/pcbnew/kicad_plugin.h @@ -32,6 +32,7 @@ class BOARD; class BOARD_ITEM; class FP_CACHE; class PCB_PARSER; +class NETINFO_MAPPING; /// Current s-expression file format version. 2 was the last legacy format version. @@ -122,9 +123,7 @@ public: //------------------------------------------------------------- - PCB_IO(); - - PCB_IO( int aControlFlags ); + PCB_IO( int aControlFlags = CTL_FOR_BOARD ); ~PCB_IO(); @@ -171,6 +170,8 @@ protected: OUTPUTFORMATTER* m_out; ///< output any Format()s to this, no ownership int m_ctl; PCB_PARSER* m_parser; + NETINFO_MAPPING* m_mapping; ///< mapping for net codes, so only not empty net codes + ///< are stored with consecutive integers as net codes /// we only cache one footprint library, this determines which one. void cacheLib( const wxString& aLibraryPath, const wxString& aFootprintName = wxEmptyString ); diff --git a/pcbnew/legacy_plugin.cpp b/pcbnew/legacy_plugin.cpp index a1fd78a9b0..f548c2b997 100644 --- a/pcbnew/legacy_plugin.cpp +++ b/pcbnew/legacy_plugin.cpp @@ -1299,11 +1299,14 @@ void LEGACY_PLUGIN::loadPAD( MODULE* aModule ) char buf[1024]; // can be fairly long int netcode = intParse( line + SZ( "Ne" ), &data ); - pad->SetNet( netcode ); + pad->SetNetCode( netcode ); // read Netname ReadDelimitedText( buf, data, sizeof(buf) ); - pad->SetNetname( FROM_UTF8( StrPurge( buf ) ) ); +#ifndef NDEBUG + if( m_board ) + assert( m_board->FindNet( netcode )->GetNetname() == FROM_UTF8( StrPurge( buf ) ) ); +#endif /* NDEBUG */ } else if( TESTLINE( "Po" ) ) // (Po)sition @@ -1811,7 +1814,7 @@ void LEGACY_PLUGIN::loadNETINFO_ITEM() { char buf[1024]; - NETINFO_ITEM* net = new NETINFO_ITEM( m_board ); + NETINFO_ITEM* net = NULL; char* line; while( ( line = READLINE( m_reader ) ) != NULL ) @@ -1822,18 +1825,17 @@ void LEGACY_PLUGIN::loadNETINFO_ITEM() { // e.g. "Na 58 "/cpu.sch/PAD7"\r\n" - int tmp = intParse( line + SZ( "Na" ), &data ); - net->SetNet( tmp ); + int netCode = intParse( line + SZ( "Na" ), &data ); ReadDelimitedText( buf, data, sizeof(buf) ); - net->SetNetname( FROM_UTF8( buf ) ); + net = new NETINFO_ITEM( m_board, FROM_UTF8( buf ), netCode ); } else if( TESTLINE( "$EndEQUIPOT" ) ) { // net 0 should be already in list, so store this net // if it is not the net 0, or if the net 0 does not exists. - if( net->GetNet() > 0 || m_board->FindNet( 0 ) == NULL ) + if( net != NULL && ( net->GetNet() > 0 || m_board->FindNet( 0 ) == NULL ) ) m_board->AppendNet( net ); else delete net; @@ -2088,7 +2090,7 @@ void LEGACY_PLUGIN::loadTrackList( int aStructType ) ( (SEGVIA*) newTrack )->SetLayerPair( LAYER_N_FRONT, LAYER_N_BACK ); } - newTrack->SetNet( net_code ); + newTrack->SetNetCode( net_code ); newTrack->SetState( flags, true ); } @@ -2238,8 +2240,7 @@ void LEGACY_PLUGIN::loadZONE_CONTAINER() // Init the net code only, not the netname, to be sure // the zone net name is the name read in file. // (When mismatch, the user will be prompted in DRC, to fix the actual name) - zc->BOARD_CONNECTED_ITEM::SetNet( netcode ); - zc->SetNetName( FROM_UTF8( buf ) ); // init the net name here + zc->BOARD_CONNECTED_ITEM::SetNetCode( netcode ); } else if( TESTLINE( "ZLayer" ) ) // layer found @@ -2256,7 +2257,7 @@ void LEGACY_PLUGIN::loadZONE_CONTAINER() if( !hopt ) { - m_error.Printf( wxT( "Bad ZAux for CZONE_CONTAINER '%s'" ), zc->GetNetName().GetData() ); + m_error.Printf( wxT( "Bad ZAux for CZONE_CONTAINER '%s'" ), zc->GetNetname().GetData() ); THROW_IO_ERROR( m_error ); } @@ -2267,7 +2268,7 @@ void LEGACY_PLUGIN::loadZONE_CONTAINER() case 'F': outline_hatch = CPolyLine::DIAGONAL_FULL; break; default: - m_error.Printf( wxT( "Bad ZAux for CZONE_CONTAINER '%s'" ), zc->GetNetName().GetData() ); + m_error.Printf( wxT( "Bad ZAux for CZONE_CONTAINER '%s'" ), zc->GetNetname().GetData() ); THROW_IO_ERROR( m_error ); } @@ -2284,7 +2285,7 @@ void LEGACY_PLUGIN::loadZONE_CONTAINER() if( smoothing >= ZONE_SETTINGS::SMOOTHING_LAST || smoothing < 0 ) { - m_error.Printf( wxT( "Bad ZSmoothing for CZONE_CONTAINER '%s'" ), zc->GetNetName().GetData() ); + m_error.Printf( wxT( "Bad ZSmoothing for CZONE_CONTAINER '%s'" ), zc->GetNetname().GetData() ); THROW_IO_ERROR( m_error ); } @@ -2359,7 +2360,7 @@ void LEGACY_PLUGIN::loadZONE_CONTAINER() default: m_error.Printf( wxT( "Bad ZClearance padoption for CZONE_CONTAINER '%s'" ), - zc->GetNetName().GetData() ); + zc->GetNetname().GetData() ); THROW_IO_ERROR( m_error ); } @@ -2423,10 +2424,7 @@ void LEGACY_PLUGIN::loadZONE_CONTAINER() // Ensure keepout does not have a net // (which have no sense for a keepout zone) if( zc->GetIsKeepout() ) - { - zc->SetNet(0); - zc->SetNetName( wxEmptyString ); - } + zc->SetNetCode( NETINFO_LIST::UNCONNECTED ); // should always occur, but who knows, a zone without two corners // is no zone at all, it's a spot? @@ -2436,7 +2434,7 @@ void LEGACY_PLUGIN::loadZONE_CONTAINER() if( !zc->IsOnCopperLayer() ) { zc->SetFillMode( 0 ); - zc->SetNet( 0 ); + zc->SetNetCode( NETINFO_LIST::UNCONNECTED ); } // Hatch here, after outlines corners are read @@ -2904,6 +2902,8 @@ do { \ void LEGACY_PLUGIN::SaveBOARD( const BOARD* aBoard ) const { + m_mapping->SetBoard( aBoard ); + saveGENERAL( aBoard ); saveSHEET( aBoard ); @@ -2952,7 +2952,7 @@ void LEGACY_PLUGIN::saveGENERAL( const BOARD* aBoard ) const fprintf( m_fp, "Nzone %d\n", aBoard->GetNumSegmZone() ); fprintf( m_fp, "BoardThickness %s\n", fmtBIU( aBoard->GetDesignSettings().GetBoardThickness() ).c_str() ); fprintf( m_fp, "Nmodule %d\n", aBoard->m_Modules.GetCount() ); - fprintf( m_fp, "Nnets %d\n", aBoard->GetNetCount() ); + fprintf( m_fp, "Nnets %d\n", m_mapping->GetSize() ); fprintf( m_fp, "$EndGENERAL\n\n" ); } @@ -3093,9 +3093,11 @@ void LEGACY_PLUGIN::saveSETUP( const BOARD* aBoard ) const void LEGACY_PLUGIN::saveBOARD_ITEMS( const BOARD* aBoard ) const { // save the nets - int netcount = aBoard->GetNetCount(); - for( int i = 0; i < netcount; ++i ) - saveNETINFO_ITEM( aBoard->FindNet( i ) ); + for( NETINFO_MAPPING::iterator net = m_mapping->begin(), netEnd = m_mapping->end(); + net != netEnd; ++net ) + { + saveNETINFO_ITEM( *net ); + } // Saved nets do not include netclass names, so save netclasses after nets. saveNETCLASSES( &aBoard->m_NetClasses ); @@ -3153,7 +3155,8 @@ void LEGACY_PLUGIN::saveBOARD_ITEMS( const BOARD* aBoard ) const void LEGACY_PLUGIN::saveNETINFO_ITEM( const NETINFO_ITEM* aNet ) const { fprintf( m_fp, "$EQUIPOT\n" ); - fprintf( m_fp, "Na %d %s\n", aNet->GetNet(), EscapedUTF8( aNet->GetNetname() ).c_str() ); + fprintf( m_fp, "Na %d %s\n", m_mapping->Translate( aNet->GetNet() ), + EscapedUTF8( aNet->GetNetname() ).c_str() ); fprintf( m_fp, "St %s\n", "~" ); fprintf( m_fp, "$EndEQUIPOT\n" ); @@ -3370,7 +3373,7 @@ void LEGACY_PLUGIN::savePAD( const D_PAD* me ) const fprintf( m_fp, "At %s N %08X\n", texttype, me->GetLayerMask() ); - fprintf( m_fp, "Ne %d %s\n", me->GetNet(), EscapedUTF8( me->GetNetname() ).c_str() ); + fprintf( m_fp, "Ne %d %s\n", me->GetNetCode(), EscapedUTF8( me->GetNetname() ).c_str() ); fprintf( m_fp, "Po %s\n", fmtBIUPoint( me->GetPos0() ).c_str() ); @@ -3630,7 +3633,7 @@ void LEGACY_PLUGIN::saveTRACK( const TRACK* me ) const "-1" : fmtBIU( me->GetDrill() ).c_str() ); fprintf(m_fp, "De %d %d %d %lX %X\n", - me->GetLayer(), type, me->GetNet(), + me->GetLayer(), type, me->GetNetCode(), me->GetTimeStamp(), me->GetStatus() ); } @@ -3644,8 +3647,8 @@ void LEGACY_PLUGIN::saveZONE_CONTAINER( const ZONE_CONTAINER* me ) const // just for ZONE_CONTAINER compatibility fprintf( m_fp, "ZInfo %lX %d %s\n", me->GetTimeStamp(), - me->GetIsKeepout() ? 0 : me->GetNet(), - EscapedUTF8( me->GetIsKeepout() ? wxT("") : me->GetNetName() ).c_str() ); + me->GetIsKeepout() ? 0 : me->GetNetCode(), + EscapedUTF8( me->GetIsKeepout() ? wxT("") : me->GetNetname() ).c_str() ); // Save the outline layer info fprintf( m_fp, "ZLayer %d\n", me->GetLayer() ); @@ -4422,7 +4425,8 @@ LEGACY_PLUGIN::LEGACY_PLUGIN() : m_props( 0 ), m_reader( 0 ), m_fp( 0 ), - m_cache( 0 ) + m_cache( 0 ), + m_mapping( new NETINFO_MAPPING() ) { init( NULL ); } @@ -4431,4 +4435,5 @@ LEGACY_PLUGIN::LEGACY_PLUGIN() : LEGACY_PLUGIN::~LEGACY_PLUGIN() { delete m_cache; + delete m_mapping; } diff --git a/pcbnew/legacy_plugin.h b/pcbnew/legacy_plugin.h index c5eba40083..dec3bfcbac 100644 --- a/pcbnew/legacy_plugin.h +++ b/pcbnew/legacy_plugin.h @@ -44,6 +44,7 @@ class NETCLASSES; class ZONE_CONTAINER; class DIMENSION; class NETINFO_ITEM; +class NETINFO_MAPPING; class TEXTE_MODULE; class EDGE_MODULE; class TRACK; @@ -124,6 +125,9 @@ protected: int m_loading_format_version; ///< which BOARD_FORMAT_VERSION am I Load()ing? LP_CACHE* m_cache; + NETINFO_MAPPING* m_mapping; ///< mapping for net codes, so only not empty net codes + ///< are stored with consecutive integers as net codes + /// initialize PLUGIN like a constructor would, and futz with fresh BOARD if needed. void init( const PROPERTIES* aProperties ); diff --git a/pcbnew/magnetic_tracks_functions.cpp b/pcbnew/magnetic_tracks_functions.cpp index 8f7a8e5064..5c84d0d6d8 100644 --- a/pcbnew/magnetic_tracks_functions.cpp +++ b/pcbnew/magnetic_tracks_functions.cpp @@ -161,7 +161,7 @@ bool Magnetize( PCB_EDIT_FRAME* frame, int aCurrentTool, wxSize aGridSize, if( pad ) { - if( doCheckNet && currTrack && currTrack->GetNet() != pad->GetNet() ) + if( doCheckNet && currTrack && currTrack->GetNetCode() != pad->GetNetCode() ) return false; *curpos = pad->GetPosition(); @@ -180,7 +180,7 @@ bool Magnetize( PCB_EDIT_FRAME* frame, int aCurrentTool, wxSize aGridSize, { if( via != currTrack ) // a via cannot influence itself { - if( !doCheckNet || !currTrack || currTrack->GetNet() == via->GetNet() ) + if( !doCheckNet || !currTrack || currTrack->GetNetCode() == via->GetNetCode() ) { *curpos = via->GetStart(); // D(printf("via hit\n");) @@ -223,7 +223,7 @@ bool Magnetize( PCB_EDIT_FRAME* frame, int aCurrentTool, wxSize aGridSize, if( track->Type() != PCB_TRACE_T ) continue; - if( doCheckNet && currTrack && currTrack->GetNet() != track->GetNet() ) + if( doCheckNet && currTrack && currTrack->GetNetCode() != track->GetNetCode() ) continue; if( m_Pcb->IsLayerVisible( track->GetLayer() ) == false ) diff --git a/pcbnew/menubar_pcbframe.cpp b/pcbnew/menubar_pcbframe.cpp index 81bf1d9fa7..df83d337c9 100644 --- a/pcbnew/menubar_pcbframe.cpp +++ b/pcbnew/menubar_pcbframe.cpp @@ -314,11 +314,6 @@ void PCB_EDIT_FRAME::ReCreateMenuBar() editMenu->AppendSeparator(); - AddMenuItem( editMenu, ID_SELECTION_TOOL, - _( "Select Tool" ), - _( "Interactive selection and drag&drop tool." ), - KiBitmap( tools_xpm ) ); - AddMenuItem( editMenu, ID_PNS_ROUTER_TOOL, _( "Interactive router" ), _( "Interactive router push&shove tool." ), diff --git a/pcbnew/minimun_spanning_tree.cpp b/pcbnew/minimun_spanning_tree.cpp index f107590d6c..8d683f7786 100644 --- a/pcbnew/minimun_spanning_tree.cpp +++ b/pcbnew/minimun_spanning_tree.cpp @@ -69,7 +69,7 @@ MIN_SPAN_TREE::MIN_SPAN_TREE() void MIN_SPAN_TREE::MSP_Init( int aNodesCount ) { - m_Size = aNodesCount; + m_Size = std::max( aNodesCount, 1 ); inTree.clear(); linkedTo.clear(); distTo.clear(); diff --git a/pcbnew/modedit_undo_redo.cpp b/pcbnew/modedit_undo_redo.cpp index 4f273eb3c7..613f4d8d2b 100644 --- a/pcbnew/modedit_undo_redo.cpp +++ b/pcbnew/modedit_undo_redo.cpp @@ -46,7 +46,7 @@ void FOOTPRINT_EDIT_FRAME::SaveCopyInUndoList( BOARD_ITEM* aItem, } -void FOOTPRINT_EDIT_FRAME::SaveCopyInUndoList( PICKED_ITEMS_LIST& aItemsList, +void FOOTPRINT_EDIT_FRAME::SaveCopyInUndoList( const PICKED_ITEMS_LIST& aItemsList, UNDO_REDO_T aTypeCommand, const wxPoint& aTransformPoint ) { diff --git a/pcbnew/module_editor_frame.h b/pcbnew/module_editor_frame.h index 5cb6ea1166..1c2a6128ed 100644 --- a/pcbnew/module_editor_frame.h +++ b/pcbnew/module_editor_frame.h @@ -245,7 +245,7 @@ public: * @param aTransformPoint = the reference point of the transformation, for * commands like move */ - virtual void SaveCopyInUndoList( PICKED_ITEMS_LIST& aItemsList, + virtual void SaveCopyInUndoList( const PICKED_ITEMS_LIST& aItemsList, UNDO_REDO_T aTypeCommand, const wxPoint& aTransformPoint = wxPoint( 0, 0 ) ); diff --git a/pcbnew/modview_frame.h b/pcbnew/modview_frame.h index fd8d017df4..212f687dd8 100644 --- a/pcbnew/modview_frame.h +++ b/pcbnew/modview_frame.h @@ -201,7 +201,7 @@ private: */ void OnLeftDClick( wxDC*, const wxPoint& ) {} void SaveCopyInUndoList( BOARD_ITEM*, UNDO_REDO_T, const wxPoint& ) {} - void SaveCopyInUndoList( PICKED_ITEMS_LIST&, UNDO_REDO_T, const wxPoint &) {} + void SaveCopyInUndoList( const PICKED_ITEMS_LIST&, UNDO_REDO_T, const wxPoint &) {} DECLARE_EVENT_TABLE() diff --git a/pcbnew/move_or_drag_track.cpp b/pcbnew/move_or_drag_track.cpp index 968ea993ec..6525d7abd7 100644 --- a/pcbnew/move_or_drag_track.cpp +++ b/pcbnew/move_or_drag_track.cpp @@ -627,7 +627,7 @@ void PCB_EDIT_FRAME::StartMoveOneNodeOrSegment( TRACK* aTrack, wxDC* aDC, int aC { Collect_TrackSegmentsToDrag( GetBoard(), aTrack->GetStart(), aTrack->GetLayerMask(), - aTrack->GetNet(), aTrack->GetWidth() / 2 ); + aTrack->GetNetCode(), aTrack->GetWidth() / 2 ); } PosInit = aTrack->GetStart(); @@ -647,17 +647,17 @@ void PCB_EDIT_FRAME::StartMoveOneNodeOrSegment( TRACK* aTrack, wxDC* aDC, int aC case ID_POPUP_PCB_DRAG_TRACK_SEGMENT: // drag a segment pos = aTrack->GetStart(); Collect_TrackSegmentsToDrag( GetBoard(), pos, aTrack->GetLayerMask(), - aTrack->GetNet(), aTrack->GetWidth() / 2 ); + aTrack->GetNetCode(), aTrack->GetWidth() / 2 ); pos = aTrack->GetEnd(); aTrack->SetFlags( IS_DRAGGED | ENDPOINT | STARTPOINT ); Collect_TrackSegmentsToDrag( GetBoard(), pos, aTrack->GetLayerMask(), - aTrack->GetNet(), aTrack->GetWidth() / 2 ); + aTrack->GetNetCode(), aTrack->GetWidth() / 2 ); break; case ID_POPUP_PCB_MOVE_TRACK_NODE: // Drag via or move node pos = (diag & STARTPOINT) ? aTrack->GetStart() : aTrack->GetEnd(); Collect_TrackSegmentsToDrag( GetBoard(), pos, aTrack->GetLayerMask(), - aTrack->GetNet(), aTrack->GetWidth() / 2 ); + aTrack->GetNetCode(), aTrack->GetWidth() / 2 ); PosInit = pos; break; } @@ -684,7 +684,7 @@ void PCB_EDIT_FRAME::StartMoveOneNodeOrSegment( TRACK* aTrack, wxDC* aDC, int aC s_LastPos = PosInit; m_canvas->SetMouseCapture( Show_MoveNode, Abort_MoveTrack ); - GetBoard()->SetHighLightNet( aTrack->GetNet() ); + GetBoard()->SetHighLightNet( aTrack->GetNetCode() ); GetBoard()->HighLightON(); GetBoard()->DrawHighLight( m_canvas, aDC, GetBoard()->GetHighLightNetCode() ); @@ -792,7 +792,7 @@ void PCB_EDIT_FRAME::Start_DragTrackSegmentAndKeepSlope( TRACK* track, wxDC* DC s_LastPos = GetCrossHairPosition(); m_canvas->SetMouseCapture( Show_Drag_Track_Segment_With_Cte_Slope, Abort_MoveTrack ); - GetBoard()->SetHighLightNet( track->GetNet() ); + GetBoard()->SetHighLightNet( track->GetNetCode() ); GetBoard()->HighLightON(); GetBoard()->DrawHighLight( m_canvas, DC, GetBoard()->GetHighLightNetCode() ); @@ -828,7 +828,7 @@ bool PCB_EDIT_FRAME::PlaceDraggedOrMovedTrackSegment( TRACK* Track, wxDC* DC ) if( Track == NULL ) return false; - int current_net_code = Track->GetNet(); + int current_net_code = Track->GetNetCode(); // DRC control: if( g_Drc_On ) diff --git a/pcbnew/pad_edition_functions.cpp b/pcbnew/pad_edition_functions.cpp index 7823dfa5b7..57907ad142 100644 --- a/pcbnew/pad_edition_functions.cpp +++ b/pcbnew/pad_edition_functions.cpp @@ -163,7 +163,7 @@ void PCB_BASE_FRAME::AddPad( MODULE* aModule, bool draw ) // Update the pad properties. Import_Pad_Settings( pad, false ); - pad->SetNetname( wxEmptyString ); + pad->SetNetCode( NETINFO_LIST::UNCONNECTED ); pad->SetPosition( GetCrossHairPosition() ); diff --git a/pcbnew/pcad2kicadpcb_plugin/pcb.cpp b/pcbnew/pcad2kicadpcb_plugin/pcb.cpp index 39a65ebf33..6afde99801 100644 --- a/pcbnew/pcad2kicadpcb_plugin/pcb.cpp +++ b/pcbnew/pcad2kicadpcb_plugin/pcb.cpp @@ -914,17 +914,17 @@ void PCB::AddToBoard() m_board->SetCopperLayerCount( m_layersStackup.GetCount() ); - for( i = 0; i < (int) m_pcbComponents.GetCount(); i++ ) - { - m_pcbComponents[i]->AddToBoard(); - } - for( i = 0; i < (int) m_pcbNetlist.GetCount(); i++ ) { net = m_pcbNetlist[i]; m_board->AppendNet( new NETINFO_ITEM( m_board, net->m_name, net->m_netCode ) ); } + + for( i = 0; i < (int) m_pcbComponents.GetCount(); i++ ) + { + m_pcbComponents[i]->AddToBoard(); + } } } // namespace PCAD2KICAD diff --git a/pcbnew/pcad2kicadpcb_plugin/pcb_line.cpp b/pcbnew/pcad2kicadpcb_plugin/pcb_line.cpp index ad18b26748..28112177f9 100644 --- a/pcbnew/pcad2kicadpcb_plugin/pcb_line.cpp +++ b/pcbnew/pcad2kicadpcb_plugin/pcb_line.cpp @@ -147,7 +147,7 @@ void PCB_LINE::AddToBoard() track->SetWidth( m_width ); track->SetLayer( m_KiCadLayer ); - track->SetNet( m_netCode ); + track->SetNetCode( m_netCode ); } else { diff --git a/pcbnew/pcad2kicadpcb_plugin/pcb_pad.cpp b/pcbnew/pcad2kicadpcb_plugin/pcb_pad.cpp index c757d124c2..4985958fc9 100644 --- a/pcbnew/pcad2kicadpcb_plugin/pcb_pad.cpp +++ b/pcbnew/pcad2kicadpcb_plugin/pcb_pad.cpp @@ -273,8 +273,16 @@ void PCB_PAD::AddToModule( MODULE* aModule, int aRotation, bool aEncapsulatedPad pad->SetAttribute( padType ); - pad->SetNet( 0 ); - pad->SetNetname( m_net ); + // Set the proper net code + NETINFO_ITEM* netinfo = m_board->FindNet( m_net ); + if( netinfo == NULL ) // I believe this should not happen, but just in case + { + // It is a new net + netinfo = new NETINFO_ITEM( m_board, m_net ); + m_board->AppendNet( netinfo ); + } + + pad->SetNetCode( netinfo->GetNet() ); } if( !aEncapsulatedPad ) @@ -335,7 +343,7 @@ void PCB_PAD::AddToBoard() via->SetDrill( m_hole ); via->SetLayer( m_KiCadLayer ); - via->SetNet( m_netCode ); + via->SetNetCode( m_netCode ); } } else // pad diff --git a/pcbnew/pcad2kicadpcb_plugin/pcb_polygon.cpp b/pcbnew/pcad2kicadpcb_plugin/pcb_polygon.cpp index d64f626bf9..6d7045fb94 100644 --- a/pcbnew/pcad2kicadpcb_plugin/pcb_polygon.cpp +++ b/pcbnew/pcad2kicadpcb_plugin/pcb_polygon.cpp @@ -171,8 +171,7 @@ void PCB_POLYGON::AddToBoard() zone->SetTimeStamp( m_timestamp ); zone->SetLayer( m_KiCadLayer ); - zone->SetNet( m_netCode ); - zone->SetNetName( m_net ); + zone->SetNetCode( m_netCode ); // add outline int outline_hatch = CPolyLine::DIAGONAL_EDGE; diff --git a/pcbnew/pcb_netlist.h b/pcbnew/pcb_netlist.h index ff9544e10f..58ab9bf17d 100644 --- a/pcbnew/pcb_netlist.h +++ b/pcbnew/pcb_netlist.h @@ -47,16 +47,14 @@ class REPORTER; class COMPONENT_NET { wxString m_pinName; - wxString m_netNumber; wxString m_netName; public: COMPONENT_NET() {} - COMPONENT_NET( const wxString& aPinName, const wxString& aNetName ) + COMPONENT_NET( const wxString& aPinName, const wxString& aNetName ) : + m_pinName( aPinName ), m_netName( aNetName ) { - m_pinName = aPinName; - m_netName = aNetName; } const wxString& GetPinName() const { return m_pinName; } diff --git a/pcbnew/pcb_painter.cpp b/pcbnew/pcb_painter.cpp index 2e0bec81bf..e3f7c7f7c3 100644 --- a/pcbnew/pcb_painter.cpp +++ b/pcbnew/pcb_painter.cpp @@ -34,7 +34,6 @@ #include #include #include -#include #include #include @@ -75,6 +74,7 @@ void PCB_RENDER_SETTINGS::ImportLegacyColors( COLORS_DESIGN_SETTINGS* aSettings m_layerColors[NETNAMES_GAL_LAYER( PADS_NETNAMES_VISIBLE )] = COLOR4D( 0.8, 0.8, 0.8, 0.7 ); m_layerColors[NETNAMES_GAL_LAYER( PAD_FR_NETNAMES_VISIBLE )] = COLOR4D( 0.8, 0.8, 0.8, 0.7 ); m_layerColors[NETNAMES_GAL_LAYER( PAD_BK_NETNAMES_VISIBLE )] = COLOR4D( 0.8, 0.8, 0.8, 0.7 ); + m_layerColors[ITEM_GAL_LAYER( RATSNEST_VISIBLE )] = COLOR4D( 0.4, 0.4, 0.4, 0.7 ); m_layerColors[ITEM_GAL_LAYER( WORKSHEET )] = COLOR4D( 0.5, 0.0, 0.0, 1.0 ); // Netnames for copper layers @@ -152,7 +152,7 @@ const COLOR4D& PCB_RENDER_SETTINGS::GetColor( const VIEW_ITEM* aItem, int aLayer // Try to obtain the netcode for the item const BOARD_CONNECTED_ITEM* item = dynamic_cast( aItem ); if( item ) - netCode = item->GetNet(); + netCode = item->GetNetCode(); } // Return grayish color for non-highlighted layers in the high contrast mode @@ -265,7 +265,7 @@ void PCB_PAINTER::draw( const TRACK* aTrack, int aLayer ) if( m_pcbSettings->m_netNamesOnTracks && IsNetnameLayer( aLayer ) ) { - int netCode = aTrack->GetNet(); + int netCode = aTrack->GetNetCode(); // If there is a net name - display it on the track if( netCode > 0 ) @@ -277,11 +277,11 @@ void PCB_PAINTER::draw( const TRACK* aTrack, int aLayer ) if( length < 10 * width ) return; - NETINFO_ITEM* net = ( (BOARD*) aTrack->GetParent() )->FindNet( netCode ); + NETINFO_ITEM* net = aTrack->GetNet(); if( !net ) return; - wxString netName = net->GetShortNetname(); + const wxString& netName = aTrack->GetShortNetname(); VECTOR2D textPosition = start + line / 2.0; // center of the track double textOrientation = -atan( line.y / line.x ); double textSize = std::min( static_cast( width ), length / netName.length() ); diff --git a/pcbnew/pcb_parser.cpp b/pcbnew/pcb_parser.cpp index 82db9a5aca..8ca4bd4cdc 100644 --- a/pcbnew/pcb_parser.cpp +++ b/pcbnew/pcb_parser.cpp @@ -29,6 +29,7 @@ #include #include +#include #include #include #include @@ -427,11 +428,11 @@ BOARD* PCB_PARSER::parseBOARD() throw( IO_ERROR, PARSE_ERROR ) break; case T_segment: - m_board->m_Track.Append( parseTRACK() ); + m_board->Add( parseTRACK(), ADD_APPEND ); break; case T_via: - m_board->m_Track.Append( parseSEGVIA() ); + m_board->Add( parseSEGVIA(), ADD_APPEND ); break; case T_zone: @@ -1066,9 +1067,7 @@ void PCB_PARSER::parseNETINFO_ITEM() throw( IO_ERROR, PARSE_ERROR ) // (TODO: a better test.) if( number > 0 || m_board->FindNet( 0 ) == NULL ) { - NETINFO_ITEM* net = new NETINFO_ITEM( m_board ); - net->SetNet( number ); - net->SetNetname( name ); + NETINFO_ITEM* net = new NETINFO_ITEM( m_board, name, number ); m_board->AppendNet( net ); } } @@ -1733,7 +1732,7 @@ MODULE* PCB_PARSER::parseMODULE( wxArrayString* aInitialComments ) throw( IO_ERR case T_pad: { - D_PAD* pad = parseD_PAD(); + D_PAD* pad = parseD_PAD( module.get() ); wxPoint pt = pad->GetPos0(); RotatePoint( &pt, module->GetOrientation() ); pad->SetPosition( pt + module->GetPosition() ); @@ -2013,14 +2012,14 @@ EDGE_MODULE* PCB_PARSER::parseEDGE_MODULE() throw( IO_ERROR, PARSE_ERROR ) } -D_PAD* PCB_PARSER::parseD_PAD() throw( IO_ERROR, PARSE_ERROR ) +D_PAD* PCB_PARSER::parseD_PAD( MODULE* aParent ) throw( IO_ERROR, PARSE_ERROR ) { wxCHECK_MSG( CurTok() == T_pad, NULL, wxT( "Cannot parse " ) + GetTokenString( CurTok() ) + wxT( " as D_PAD." ) ); wxSize sz; wxPoint pt; - std::auto_ptr< D_PAD > pad( new D_PAD( NULL ) ); + std::auto_ptr< D_PAD > pad( new D_PAD( aParent ) ); NeedSYMBOLorNUMBER(); pad->SetPadName( FromUTF8() ); @@ -2191,9 +2190,9 @@ D_PAD* PCB_PARSER::parseD_PAD() throw( IO_ERROR, PARSE_ERROR ) break; case T_net: - pad->SetNet( parseInt( "net number" ) ); + pad->SetNetCode( parseInt( "net number" ) ); NeedSYMBOLorNUMBER(); - pad->SetNetname( FromUTF8() ); + assert( FromUTF8() == m_board->FindNet( pad->GetNetCode() )->GetNetname() ); NeedRIGHT(); break; @@ -2289,7 +2288,7 @@ TRACK* PCB_PARSER::parseTRACK() throw( IO_ERROR, PARSE_ERROR ) break; case T_net: - track->SetNet( parseInt( "net number" ) ); + track->SetNetCode( parseInt( "net number" ) ); break; case T_tstamp: @@ -2367,7 +2366,7 @@ SEGVIA* PCB_PARSER::parseSEGVIA() throw( IO_ERROR, PARSE_ERROR ) break; case T_net: - via->SetNet( parseInt( "net number" ) ); + via->SetNetCode( parseInt( "net number" ) ); NeedRIGHT(); break; @@ -2419,13 +2418,19 @@ ZONE_CONTAINER* PCB_PARSER::parseZONE_CONTAINER() throw( IO_ERROR, PARSE_ERROR ) // Init the net code only, not the netname, to be sure // the zone net name is the name read in file. // (When mismatch, the user will be prompted in DRC, to fix the actual name) - zone->BOARD_CONNECTED_ITEM::SetNet( parseInt( "net number" ) ); + zone->SetNetCode( parseInt( "net number" ) ); NeedRIGHT(); break; case T_net_name: NeedSYMBOLorNUMBER(); - zone->SetNetName( FromUTF8() ); + if( zone->GetNet()->GetNetname() != FromUTF8() ) + { + wxString msg = _( "There is a zone that belongs to a not " + "existing net (" ) + FromUTF8() + _("), you should verify it." ); + DisplayError( NULL, msg ); + zone->SetNetCode( NETINFO_LIST::UNCONNECTED ); + } NeedRIGHT(); break; @@ -2689,7 +2694,7 @@ ZONE_CONTAINER* PCB_PARSER::parseZONE_CONTAINER() throw( IO_ERROR, PARSE_ERROR ) if( !zone->IsOnCopperLayer() ) { zone->SetFillMode( 0 ); - zone->SetNet( 0 ); + zone->SetNetCode( NETINFO_LIST::UNCONNECTED ); } // Set hatch here, after outlines corners are read @@ -2701,10 +2706,7 @@ ZONE_CONTAINER* PCB_PARSER::parseZONE_CONTAINER() throw( IO_ERROR, PARSE_ERROR ) // Ensure keepout does not have a net (which have no sense for a keepout zone) if( zone->GetIsKeepout() ) - { - zone->SetNet(0); - zone->SetNetName( wxEmptyString ); - } + zone->SetNetCode( NETINFO_LIST::UNCONNECTED ); return zone.release(); } diff --git a/pcbnew/pcb_parser.h b/pcbnew/pcb_parser.h index 233acb1291..0dfb0bbdc5 100644 --- a/pcbnew/pcb_parser.h +++ b/pcbnew/pcb_parser.h @@ -99,7 +99,7 @@ class PCB_PARSER : public PCB_LEXER MODULE* parseMODULE( wxArrayString* aInitialComments = 0 ) throw( IO_ERROR, PARSE_ERROR ); TEXTE_MODULE* parseTEXTE_MODULE() throw( IO_ERROR, PARSE_ERROR ); EDGE_MODULE* parseEDGE_MODULE() throw( IO_ERROR, PARSE_ERROR ); - D_PAD* parseD_PAD() throw( IO_ERROR, PARSE_ERROR ); + D_PAD* parseD_PAD( MODULE* aParent = NULL ) throw( IO_ERROR, PARSE_ERROR ); TRACK* parseTRACK() throw( IO_ERROR, PARSE_ERROR ); SEGVIA* parseSEGVIA() throw( IO_ERROR, PARSE_ERROR ); ZONE_CONTAINER* parseZONE_CONTAINER() throw( IO_ERROR, PARSE_ERROR ); diff --git a/pcbnew/pcbframe.cpp b/pcbnew/pcbframe.cpp index c2cb9fb4da..25fa22eaa4 100644 --- a/pcbnew/pcbframe.cpp +++ b/pcbnew/pcbframe.cpp @@ -128,8 +128,6 @@ BEGIN_EVENT_TABLE( PCB_EDIT_FRAME, PCB_BASE_FRAME ) // menu Config /* Tom's hacks start */ - EVT_MENU ( ID_SELECTION_TOOL, PCB_EDIT_FRAME::onGenericCommand ) - EVT_TOOL ( ID_SELECTION_TOOL, PCB_EDIT_FRAME::onGenericCommand ) EVT_MENU ( ID_PNS_ROUTER_TOOL, PCB_EDIT_FRAME::onGenericCommand ) EVT_TOOL ( ID_PNS_ROUTER_TOOL, PCB_EDIT_FRAME::onGenericCommand ) /* Tom's hacks end */ @@ -337,16 +335,6 @@ PCB_EDIT_FRAME::PCB_EDIT_FRAME( wxWindow* parent, const wxString& title, SetBoard( new BOARD() ); - if( GetGalCanvas() ) - { - ViewReloadBoard( m_Pcb ); - - // update the tool manager with the new board and its view. - if( m_toolManager ) - m_toolManager->SetEnvironment( m_Pcb, GetGalCanvas()->GetView(), - GetGalCanvas()->GetViewControls(), this ); - } - // Create the PCB_LAYER_WIDGET *after* SetBoard(): wxFont font = wxSystemSettings::GetFont( wxSYS_DEFAULT_GUI_FONT ); @@ -546,8 +534,11 @@ void PCB_EDIT_FRAME::SetBoard( BOARD* aBoard ) // update the tool manager with the new board and its view. if( m_toolManager ) + { m_toolManager->SetEnvironment( aBoard, GetGalCanvas()->GetView(), GetGalCanvas()->GetViewControls(), this ); + m_toolManager->ResetTools( TOOL_BASE::MODEL_RELOAD ); + } } } @@ -608,27 +599,22 @@ void PCB_EDIT_FRAME::ViewReloadBoard( const BOARD* aBoard ) const view->Add( zone ); } - // Add an entry for the worksheet layout - KIGFX::WORKSHEET_VIEWITEM* worksheet = new KIGFX::WORKSHEET_VIEWITEM( - std::string( aBoard->GetFileName().mb_str() ), - std::string( GetScreenDesc().mb_str() ), - &GetPageSettings(), &GetTitleBlock() ); + KIGFX::WORKSHEET_VIEWITEM* worksheet = aBoard->GetWorksheetViewItem(); + worksheet->SetSheetName( std::string( GetScreenDesc().mb_str() ) ); + BASE_SCREEN* screen = GetScreen(); + if( screen != NULL ) { - worksheet->SetSheetNumber( GetScreen()->m_ScreenNumber ); - worksheet->SetSheetCount( GetScreen()->m_NumberOfScreens ); + worksheet->SetSheetNumber( screen->m_ScreenNumber ); + worksheet->SetSheetCount( screen->m_NumberOfScreens ); } view->Add( worksheet ); + view->Add( aBoard->GetRatsnestViewItem() ); - // Add an entry for the ratsnest - RN_DATA* ratsnest = aBoard->GetRatsnest(); - ratsnest->ProcessBoard(); - ratsnest->Recalculate(); - view->Add( new KIGFX::RATSNEST_VIEWITEM( ratsnest ) ); - - view->SetPanBoundary( worksheet->ViewBBox() ); + // Limit panning to the size of worksheet frame + view->SetPanBoundary( aBoard->GetWorksheetViewItem()->ViewBBox() ); view->RecacheAllItems( true ); if( IsGalCanvasActive() ) @@ -751,10 +737,17 @@ void PCB_EDIT_FRAME::UseGalCanvas( bool aEnable ) { EDA_DRAW_FRAME::UseGalCanvas( aEnable ); - m_toolManager->SetEnvironment( m_Pcb, GetGalCanvas()->GetView(), - GetGalCanvas()->GetViewControls(), this ); - ViewReloadBoard( m_Pcb ); + + if( aEnable ) + { + // Update potential changes in the ratsnest + m_Pcb->GetRatsnest()->Recalculate(); + + m_toolManager->SetEnvironment( m_Pcb, GetGalCanvas()->GetView(), + GetGalCanvas()->GetViewControls(), this ); + m_toolManager->ResetTools( TOOL_BASE::GAL_SWITCH ); + } } diff --git a/pcbnew/pcbnew_id.h b/pcbnew/pcbnew_id.h index 85aa832862..608bac920a 100644 --- a/pcbnew/pcbnew_id.h +++ b/pcbnew/pcbnew_id.h @@ -372,7 +372,6 @@ enum pcbnew_ids ID_FOOTPRINT_WIZARD_SELECT_WIZARD, ID_FOOTPRINT_WIZARD_EXPORT_TO_BOARD, - ID_SELECTION_TOOL, ID_PNS_ROUTER_TOOL }; diff --git a/pcbnew/ratsnest.cpp b/pcbnew/ratsnest.cpp index 00cec1cea0..028c632568 100644 --- a/pcbnew/ratsnest.cpp +++ b/pcbnew/ratsnest.cpp @@ -70,8 +70,11 @@ public: void MIN_SPAN_TREE_PADS::AddTreeToRatsnest( std::vector &aRatsnestList ) { - std::vector & padsBuffer = *m_PadsList; - int netcode = padsBuffer[0]->GetNet(); + std::vector& padsBuffer = *m_PadsList; + if( padsBuffer.empty() ) + return; + + int netcode = padsBuffer[0]->GetNetCode(); // Note: to get edges in minimum spanning tree, // the index value 0 is not used: it is just // the entry point of the minimum spanning tree. @@ -179,7 +182,7 @@ void PCB_BASE_FRAME::Compile_Ratsnest( wxDC* aDC, bool aDisplayStatus ) */ static bool sortByNetcode( const D_PAD* const & ref, const D_PAD* const & item ) { - return ref->GetNet() < item->GetNet(); + return ref->GetNetCode() < item->GetNetCode(); } @@ -537,7 +540,7 @@ void PCB_BASE_FRAME::build_ratsnest_module( MODULE* aModule ) // collect active pads of the module: for( pad_ref = aModule->Pads(); pad_ref != NULL; pad_ref = pad_ref->Next() ) { - if( pad_ref->GetNet() == 0 ) + if( pad_ref->GetNetCode() == NETINFO_LIST::UNCONNECTED ) continue; localPadList.push_back( pad_ref ); @@ -559,11 +562,11 @@ void PCB_BASE_FRAME::build_ratsnest_module( MODULE* aModule ) { pad_ref = localPadList[ii]; - if( pad_ref->GetNet() == current_net_code ) + if( pad_ref->GetNetCode() == current_net_code ) continue; // A new net was found, load all pads of others modules members of this net: - NETINFO_ITEM* net = m_Pcb->FindNet( pad_ref->GetNet() ); + NETINFO_ITEM* net = pad_ref->GetNet(); if( net == NULL ) //Should not occur { @@ -594,7 +597,7 @@ void PCB_BASE_FRAME::build_ratsnest_module( MODULE* aModule ) * footprint pads it is therefore not time consuming, and it is made only * once */ - current_net_code = localPadList[0]->GetNet(); + current_net_code = localPadList[0]->GetNetCode(); MIN_SPAN_TREE_PADS min_spanning_tree; std::vector padsBuffer; // contains pads of only one net @@ -608,7 +611,7 @@ void PCB_BASE_FRAME::build_ratsnest_module( MODULE* aModule ) if( jj >= pads_module_count ) break; - if( localPadList[jj]->GetNet() != current_net_code ) + if( localPadList[jj]->GetNetCode() != current_net_code ) break; } @@ -620,7 +623,7 @@ void PCB_BASE_FRAME::build_ratsnest_module( MODULE* aModule ) padsBuffer.clear(); ii = jj; if( ii < localPadList.size() ) - current_net_code = localPadList[ii]->GetNet(); + current_net_code = localPadList[ii]->GetNetCode(); } internalRatsCount = m_Pcb->m_LocalRatsnest.size(); @@ -652,13 +655,13 @@ void PCB_BASE_FRAME::build_ratsnest_module( MODULE* aModule ) m_Pcb->m_LocalRatsnest.erase( m_Pcb->m_LocalRatsnest.begin() + internalRatsCount, m_Pcb->m_LocalRatsnest.end() ); - current_net_code = localPadList[0]->GetNet(); + current_net_code = localPadList[0]->GetNetCode(); for( unsigned ii = 0; ii < pads_module_count; ii++ ) { pad_ref = localPadList[ii]; - if( pad_ref->GetNet() != current_net_code ) + if( pad_ref->GetNetCode() != current_net_code ) { // if needed, creates a new ratsnest for the old net if( addRats ) @@ -667,7 +670,7 @@ void PCB_BASE_FRAME::build_ratsnest_module( MODULE* aModule ) } addRats = false; - current_net_code = pad_ref->GetNet(); + current_net_code = pad_ref->GetNetCode(); local_rats.m_Lenght = INT_MAX; } @@ -679,10 +682,10 @@ void PCB_BASE_FRAME::build_ratsnest_module( MODULE* aModule ) pad_externe = localPadList[jj]; // we search pads having the same net code - if( pad_externe->GetNet() < pad_ref->GetNet() ) + if( pad_externe->GetNetCode() < pad_ref->GetNetCode() ) continue; - if( pad_externe->GetNet() > pad_ref->GetNet() ) // pads are sorted by net code + if( pad_externe->GetNetCode() > pad_ref->GetNetCode() ) // pads are sorted by net code break; distance = abs( pad_externe->GetPosition().x - pad_pos.x ) + @@ -692,7 +695,7 @@ void PCB_BASE_FRAME::build_ratsnest_module( MODULE* aModule ) { local_rats.m_PadStart = pad_ref; local_rats.m_PadEnd = pad_externe; - local_rats.SetNet( pad_ref->GetNet() ); + local_rats.SetNet( pad_ref->GetNetCode() ); local_rats.m_Lenght = distance; local_rats.m_Status = 0; @@ -810,7 +813,7 @@ void PCB_BASE_FRAME::BuildAirWiresTargetsList( BOARD_CONNECTED_ITEM* aItemRef, if( aItemRef == NULL ) return; - int net_code = aItemRef->GetNet(); + int net_code = aItemRef->GetNetCode(); int subnet = aItemRef->GetSubNet(); if( net_code <= 0 ) @@ -841,9 +844,9 @@ void PCB_BASE_FRAME::BuildAirWiresTargetsList( BOARD_CONNECTED_ITEM* aItemRef, // current track: for( TRACK* track = m_Pcb->m_Track; track; track = track->Next() ) { - if( track->GetNet() < net_code ) + if( track->GetNetCode() < net_code ) continue; - if( track->GetNet() > net_code ) + if( track->GetNetCode() > net_code ) break;; if( !track->GetSubNet() || (track->GetSubNet() != subnet) ) diff --git a/pcbnew/ratsnest_data.cpp b/pcbnew/ratsnest_data.cpp index 7bb7fad2a5..6b9d2b043a 100644 --- a/pcbnew/ratsnest_data.cpp +++ b/pcbnew/ratsnest_data.cpp @@ -27,6 +27,10 @@ * @brief Class that computes missing connections on a PCB. */ +#ifdef USE_OPENMP +#include +#endif /* USE_OPENMP */ + #include #include @@ -35,7 +39,6 @@ #include #include -#include #include #include #include @@ -75,10 +78,21 @@ bool sortArea( const RN_POLY& aP1, const RN_POLY& aP2 ) } +bool operator==( const RN_NODE_PTR& aFirst, const RN_NODE_PTR& aSecond ) +{ + return aFirst->GetX() == aSecond->GetX() && aFirst->GetY() == aSecond->GetY(); +} + + +bool operator!=( const RN_NODE_PTR& aFirst, const RN_NODE_PTR& aSecond ) +{ + return aFirst->GetX() != aSecond->GetX() || aFirst->GetY() != aSecond->GetY(); +} + + bool isEdgeConnectingNode( const RN_EDGE_PTR& aEdge, const RN_NODE_PTR& aNode ) { - return ( aEdge->getSourceNode().get() == aNode.get() ) || - ( aEdge->getTargetNode().get() == aNode.get() ); + return aEdge->getSourceNode() == aNode || aEdge->getTargetNode() == aNode; } @@ -126,10 +140,18 @@ std::vector* kruskalMST( RN_LINKS::RN_EDGE_LIST& aEdges, cycles[srcTag].splice( cycles[srcTag].end(), cycles[trgTag] ); if( dt->getWeight() == 0 ) // Skip already existing connections (weight == 0) + { mstExpectedSize--; + } else { - mst->push_back( dt ); + // Do a copy of edge, but make it RN_EDGE_MST. In contrary to RN_EDGE, + // RN_EDGE_MST saves both source and target node and does not require any other + // edges to exist for getting source/target nodes + RN_EDGE_MST_PTR newEdge = boost::make_shared( dt->getSourceNode(), + dt->getTargetNode(), + dt->getWeight() ); + mst->push_back( newEdge ); ++mstSize; } } @@ -201,12 +223,18 @@ const RN_NODE_PTR& RN_LINKS::AddNode( int aX, int aY ) } -void RN_LINKS::RemoveNode( const RN_NODE_PTR& aNode ) +bool RN_LINKS::RemoveNode( const RN_NODE_PTR& aNode ) { aNode->DecRefCount(); // TODO use the shared_ptr use_count if( aNode->GetRefCount() == 0 ) + { m_nodes.erase( aNode ); + + return true; + } + + return false; } @@ -270,6 +298,9 @@ void RN_NET::compute() void RN_NET::clearNode( const RN_NODE_PTR& aNode ) { + if( !m_rnEdges ) + return; + std::vector::iterator newEnd; // Remove all ratsnest edges for associated with the node @@ -391,7 +422,7 @@ void RN_NET::AddItem( const ZONE_CONTAINER* aZone ) // Origin and end of bounding box for a polygon VECTOR2I origin( polyPoints[0].x, polyPoints[0].y ); VECTOR2I end( polyPoints[0].x, polyPoints[0].y ); - int idxStart = 0; + unsigned int idxStart = 0; // Extract polygons from zones for( unsigned int i = 0; i < polyPoints.size(); ++i ) @@ -417,10 +448,14 @@ void RN_NET::AddItem( const ZONE_CONTAINER* aZone ) m_links, BOX2I( origin, end - origin ) ) ); idxStart = i + 1; - origin.x = polyPoints[idxStart].x; - origin.y = polyPoints[idxStart].y; - end.x = polyPoints[idxStart].x; - end.y = polyPoints[idxStart].y; + + if( idxStart < polyPoints.size() ) + { + origin.x = polyPoints[idxStart].x; + origin.y = polyPoints[idxStart].y; + end.x = polyPoints[idxStart].x; + end.y = polyPoints[idxStart].y; + } } } @@ -430,75 +465,97 @@ void RN_NET::AddItem( const ZONE_CONTAINER* aZone ) void RN_NET::RemoveItem( const D_PAD* aPad ) { - RN_NODE_PTR& node = m_pads[aPad]; - if( !node ) - return; + try + { + RN_NODE_PTR node = m_pads.at( aPad ); - // Remove edges associated with the node - clearNode( node ); - m_links.RemoveNode( node ); + if( m_links.RemoveNode( node ) ) + clearNode( node ); - m_pads.erase( aPad ); + m_pads.erase( aPad ); - m_dirty = true; + m_dirty = true; + } + catch( ... ) + { + } } void RN_NET::RemoveItem( const SEGVIA* aVia ) { - RN_NODE_PTR& node = m_vias[aVia]; - if( !node ) - return; + try + { + RN_NODE_PTR node = m_vias.at( aVia ); - // Remove edges associated with the node - clearNode( node ); - m_links.RemoveNode( node ); + if( m_links.RemoveNode( node ) ) + clearNode( node ); - m_vias.erase( aVia ); + m_vias.erase( aVia ); - m_dirty = true; + m_dirty = true; + } + catch( ... ) + { + } } void RN_NET::RemoveItem( const TRACK* aTrack ) { - RN_EDGE_PTR& edge = m_tracks[aTrack]; - if( !edge ) - return; + try + { + RN_EDGE_PTR& edge = m_tracks.at( aTrack ); - // Save nodes, so they can be cleared later - const RN_NODE_PTR& aBegin = edge->getSourceNode(); - const RN_NODE_PTR& aEnd = edge->getTargetNode(); - m_links.RemoveConnection( edge ); + // Save nodes, so they can be cleared later + RN_NODE_PTR aBegin = edge->getSourceNode(); + RN_NODE_PTR aEnd = edge->getTargetNode(); + m_links.RemoveConnection( edge ); - // Remove nodes associated with the edge. It is done in a safe way, there is a check - // if nodes are not used by other edges. - clearNode( aBegin ); - clearNode( aEnd ); - m_links.RemoveNode( aBegin ); - m_links.RemoveNode( aEnd ); + // Remove nodes associated with the edge. It is done in a safe way, there is a check + // if nodes are not used by other edges. + if( m_links.RemoveNode( aBegin ) ) + clearNode( aBegin ); - m_tracks.erase( aTrack ); + if( m_links.RemoveNode( aEnd ) ) + clearNode( aEnd ); - m_dirty = true; + m_tracks.erase( aTrack ); + + m_dirty = true; + } + catch( ... ) + { + } } void RN_NET::RemoveItem( const ZONE_CONTAINER* aZone ) { - // Remove all subpolygons that make the zone - std::deque& polygons = m_zonePolygons[aZone]; - BOOST_FOREACH( RN_POLY& polygon, polygons ) - m_links.RemoveNode( polygon.GetNode() ); - polygons.clear(); + try + { + // Remove all subpolygons that make the zone + std::deque& polygons = m_zonePolygons.at( aZone ); + BOOST_FOREACH( RN_POLY& polygon, polygons ) + { + const RN_NODE_PTR node = polygon.GetNode(); - // Remove all connections added by the zone - std::deque& edges = m_zoneConnections[aZone]; - BOOST_FOREACH( RN_EDGE_PTR& edge, edges ) - m_links.RemoveConnection( edge ); - edges.clear(); + if( m_links.RemoveNode( node ) ) + clearNode( node ); + } + polygons.clear(); - m_dirty = true; + // Remove all connections added by the zone + std::deque& edges = m_zoneConnections.at( aZone ); + BOOST_FOREACH( RN_EDGE_PTR& edge, edges ) + m_links.RemoveConnection( edge ); + edges.clear(); + + m_dirty = true; + } + catch( ... ) + { + } } @@ -512,15 +569,17 @@ const RN_NODE_PTR RN_NET::GetClosestNode( const RN_NODE_PTR& aNode ) const for( it = nodes.begin(), itEnd = nodes.end(); it != itEnd; ++it ) { + RN_NODE_PTR node = *it; + // Obviously the distance between node and itself is the shortest, // that's why we have to skip it - if( *it != aNode ) + if( node != aNode ) { - unsigned int distance = getDistance( *it, aNode ); + unsigned int distance = getDistance( node, aNode ); if( distance < minDistance ) { minDistance = distance; - closest = *it; + closest = node; } } } @@ -540,17 +599,18 @@ const RN_NODE_PTR RN_NET::GetClosestNode( const RN_NODE_PTR& aNode, for( it = nodes.begin(), itEnd = nodes.end(); it != itEnd; ++it ) { - RN_NODE_PTR baseNode = *it; + RN_NODE_PTR node = *it; // Obviously the distance between node and itself is the shortest, // that's why we have to skip it - if( *it != aNode && aFilter( baseNode ) ) + if( node != aNode && aFilter( node ) ) { - unsigned int distance = getDistance( *it, aNode ); + unsigned int distance = getDistance( node, aNode ); + if( distance < minDistance ) { minDistance = distance; - closest = *it; + closest = node; } } } @@ -613,68 +673,114 @@ std::list RN_NET::GetNodes( const BOARD_CONNECTED_ITEM* aItem ) con { std::list nodes; - switch( aItem->Type() ) + try { - case PCB_PAD_T: - { - const D_PAD* pad = static_cast( aItem ); - nodes.push_back( m_pads.at( pad ) ); - } - break; - - case PCB_VIA_T: - { - const SEGVIA* via = static_cast( aItem ); - nodes.push_back( m_vias.at( via ) ); - } - break; - - case PCB_TRACE_T: - { - const TRACK* track = static_cast( aItem ); - RN_EDGE_PTR edge = m_tracks.at( track ); - - nodes.push_back( edge->getSourceNode() ); - nodes.push_back( edge->getTargetNode() ); - } - break; - - default: + switch( aItem->Type() ) + { + case PCB_PAD_T: + { + const D_PAD* pad = static_cast( aItem ); + nodes.push_back( m_pads.at( pad ) ); + } break; + + case PCB_VIA_T: + { + const SEGVIA* via = static_cast( aItem ); + nodes.push_back( m_vias.at( via ) ); + } + break; + + case PCB_TRACE_T: + { + const TRACK* track = static_cast( aItem ); + RN_EDGE_PTR edge = m_tracks.at( track ); + + nodes.push_back( edge->getSourceNode() ); + nodes.push_back( edge->getTargetNode() ); + } + break; + + default: + break; + } + } + catch ( ... ) + { + return nodes; } return nodes; } -void RN_NET::ClearSimple() +void RN_DATA::AddSimple( const BOARD_ITEM* aItem ) { - BOOST_FOREACH( const RN_NODE_PTR& node, m_simpleNodes ) - node->SetFlag( false ); + int net; - m_simpleNodes.clear(); -} + if( aItem->IsConnected() ) + { + const BOARD_CONNECTED_ITEM* item = static_cast( aItem ); + net = item->GetNetCode(); + if( net < 1 ) // do not process unconnected items + return; + + // Add all nodes belonging to the item + BOOST_FOREACH( RN_NODE_PTR node, m_nets[net].GetNodes( item ) ) + m_nets[net].AddSimpleNode( node ); + } + else if( aItem->Type() == PCB_MODULE_T ) + { + const MODULE* module = static_cast( aItem ); + + for( const D_PAD* pad = module->Pads().GetFirst(); pad; pad = pad->Next() ) + AddSimple( pad ); -void RN_DATA::AddSimple( const BOARD_CONNECTED_ITEM* aItem ) -{ - int net = aItem->GetNet(); - if( net < 1 ) // do not process unconnected items return; - - // Get list of nodes responding to the item - std::list nodes = m_nets[net].GetNodes( aItem ); - std::list::iterator it, itEnd; - - for( it = nodes.begin(), itEnd = nodes.end(); it != itEnd; ++it ) - m_nets[net].AddSimpleNode( *it ); + } + else + return; } -void RN_DATA::AddSimple( const MODULE* aModule ) +void RN_DATA::AddBlocked( const BOARD_ITEM* aItem ) { - for( const D_PAD* pad = aModule->Pads().GetFirst(); pad; pad = pad->Next() ) - AddSimple( pad ); + int net; + + if( aItem->IsConnected() ) + { + const BOARD_CONNECTED_ITEM* item = static_cast( aItem ); + net = item->GetNetCode(); + + if( net < 1 ) // do not process unconnected items + return; + + // Block all nodes belonging to the item + BOOST_FOREACH( RN_NODE_PTR node, m_nets[net].GetNodes( item ) ) + m_nets[net].AddBlockedNode( node ); + } + else if( aItem->Type() == PCB_MODULE_T ) + { + const MODULE* module = static_cast( aItem ); + + for( const D_PAD* pad = module->Pads().GetFirst(); pad; pad = pad->Next() ) + AddBlocked( pad ); + + return; + } + else + return; +} + + +void RN_DATA::AddSimple( const VECTOR2I& aPosition, int aNetCode ) +{ + assert( aNetCode > 0 ); + + RN_NODE_PTR newNode = boost::make_shared( aPosition.x, aPosition.y ); + + m_nets[aNetCode].AddSimpleNode( newNode ); } @@ -725,56 +831,58 @@ void RN_NET::processZones() } -void RN_DATA::updateNet( int aNetCode ) +void RN_DATA::Add( const BOARD_ITEM* aItem ) { - assert( aNetCode < (int) m_nets.size() ); - if( aNetCode < 1 ) + int net; + + if( aItem->IsConnected() ) + { + net = static_cast( aItem )->GetNetCode(); + if( net < 1 ) // do not process unconnected items + return; + + // Autoresize + if( net >= (int) m_nets.size() ) + m_nets.resize( net + 1 ); + } + else if( aItem->Type() == PCB_MODULE_T ) + { + const MODULE* module = static_cast( aItem ); + for( const D_PAD* pad = module->Pads().GetFirst(); pad; pad = pad->Next() ) + { + net = pad->GetNetCode(); + if( net < 1 ) // do not process unconnected items + continue; + + // Autoresize + if( net >= (int) m_nets.size() ) + m_nets.resize( net + 1 ); + + m_nets[net].AddItem( pad ); + } + return; - - m_nets[aNetCode].ClearSimple(); - m_nets[aNetCode].Update(); -} - - -void RN_DATA::Update( const BOARD_CONNECTED_ITEM* aItem ) -{ - int net = aItem->GetNet(); - if( net < 1 ) // do not process unconnected items + } + else return; switch( aItem->Type() ) { case PCB_PAD_T: - { - const D_PAD* pad = static_cast( aItem ); - m_nets[net].RemoveItem( pad ); - m_nets[net].AddItem( pad ); - } - break; + m_nets[net].AddItem( static_cast( aItem ) ); + break; case PCB_TRACE_T: - { - const TRACK* track = static_cast( aItem ); - m_nets[net].RemoveItem( track ); - m_nets[net].AddItem( track ); - } - break; + m_nets[net].AddItem( static_cast( aItem ) ); + break; case PCB_VIA_T: - { - const SEGVIA* via = static_cast( aItem ); - m_nets[net].RemoveItem( via ); - m_nets[net].AddItem( via ); - } - break; + m_nets[net].AddItem( static_cast( aItem ) ); + break; case PCB_ZONE_AREA_T: - { - const ZONE_CONTAINER* zone = static_cast( aItem ); - m_nets[net].RemoveItem( zone); - m_nets[net].AddItem( zone ); - } - break; + m_nets[net].AddItem( static_cast( aItem ) ); + break; default: break; @@ -782,18 +890,61 @@ void RN_DATA::Update( const BOARD_CONNECTED_ITEM* aItem ) } -void RN_DATA::Update( const MODULE* aModule ) +void RN_DATA::Remove( const BOARD_ITEM* aItem ) { - for( const D_PAD* pad = aModule->Pads().GetFirst(); pad; pad = pad->Next() ) - { - int net = pad->GetNet(); + int net; - if( net > 0 ) // do not process unconnected items - { - m_nets[net].RemoveItem( pad ); - m_nets[net].AddItem( pad ); - } + if( aItem->IsConnected() ) + { + net = static_cast( aItem )->GetNetCode(); + if( net < 1 ) // do not process unconnected items + return; } + else if( aItem->Type() == PCB_MODULE_T ) + { + const MODULE* module = static_cast( aItem ); + for( const D_PAD* pad = module->Pads().GetFirst(); pad; pad = pad->Next() ) + { + net = pad->GetNetCode(); + if( net < 1 ) // do not process unconnected items + continue; + + m_nets[net].RemoveItem( pad ); + } + + return; + } + else + return; + + switch( aItem->Type() ) + { + case PCB_PAD_T: + m_nets[net].RemoveItem( static_cast( aItem ) ); + break; + + case PCB_TRACE_T: + m_nets[net].RemoveItem( static_cast( aItem ) ); + break; + + case PCB_VIA_T: + m_nets[net].RemoveItem( static_cast( aItem ) ); + break; + + case PCB_ZONE_AREA_T: + m_nets[net].RemoveItem( static_cast( aItem ) ); + break; + + default: + break; + } +} + + +void RN_DATA::Update( const BOARD_ITEM* aItem ) +{ + Remove( aItem ); + Add( aItem ); } @@ -808,7 +959,7 @@ void RN_DATA::ProcessBoard() { for( D_PAD* pad = module->Pads().GetFirst(); pad; pad = pad->Next() ) { - netCode = pad->GetNet(); + netCode = pad->GetNetCode(); if( netCode > 0 ) m_nets[netCode].AddItem( pad ); @@ -817,7 +968,7 @@ void RN_DATA::ProcessBoard() for( TRACK* track = m_board->m_Track; track; track = track->Next() ) { - netCode = track->GetNet(); + netCode = track->GetNetCode(); if( netCode > 0 ) { @@ -831,7 +982,7 @@ void RN_DATA::ProcessBoard() for( int i = 0; i < m_board->GetAreaCount(); ++i ) { ZONE_CONTAINER* zone = m_board->GetArea( i ); - netCode = zone->GetNet(); + netCode = zone->GetNetCode(); if( netCode > 0 ) m_nets[netCode].AddItem( zone ); @@ -843,12 +994,23 @@ void RN_DATA::Recalculate( int aNet ) { if( aNet < 0 ) // Recompute everything { - // Start with net number 1, as 0 stand for not connected - for( unsigned int i = 1; i < m_board->GetNetCount(); ++i ) + unsigned int i, netCount; + netCount = m_board->GetNetCount(); + +#ifdef USE_OPENMP + #pragma omp parallel shared(netCount) private(i) { - if( m_nets[i].IsDirty() ) - updateNet( i ); - } + #pragma omp for schedule(guided, 1) +#else /* USE_OPENMP */ + { +#endif + // Start with net number 1, as 0 stands for not connected + for( i = 1; i < netCount; ++i ) + { + if( m_nets[i].IsDirty() ) + updateNet( i ); + } + } /* end of parallel section */ } else if( aNet > 0 ) // Recompute only specific net { @@ -857,8 +1019,13 @@ void RN_DATA::Recalculate( int aNet ) } -void RN_DATA::ClearSimple() +void RN_DATA::updateNet( int aNetCode ) { - BOOST_FOREACH( RN_NET& net, m_nets ) - net.ClearSimple(); + assert( aNetCode < (int) m_nets.size() ); + + if( aNetCode < 1 ) + return; + + m_nets[aNetCode].ClearSimple(); + m_nets[aNetCode].Update(); } diff --git a/pcbnew/ratsnest_data.h b/pcbnew/ratsnest_data.h index 6d0e7ee896..712909f2fa 100644 --- a/pcbnew/ratsnest_data.h +++ b/pcbnew/ratsnest_data.h @@ -37,6 +37,7 @@ #include #include +#include class BOARD; class BOARD_ITEM; @@ -57,6 +58,9 @@ typedef hed::EdgeMST RN_EDGE_MST; typedef boost::shared_ptr RN_EDGE_MST_PTR; typedef hed::Triangulation TRIANGULATOR; +bool operator==( const RN_NODE_PTR& aFirst, const RN_NODE_PTR& aSecond ); +bool operator!=( const RN_NODE_PTR& aFirst, const RN_NODE_PTR& aSecond ); + ///> General interface for filtering out nodes in search functions. struct RN_NODE_FILTER : public std::unary_function { @@ -83,7 +87,7 @@ struct RN_NODE_COMPARE : std::binary_function { bool operator()( const RN_NODE_PTR& aNode1, const RN_NODE_PTR& aNode2 ) const { - return ( aNode1->GetX() == aNode2->GetX() && aNode1->GetY() == aNode2->GetY() ); + return aNode1 == aNode2; } }; @@ -129,8 +133,9 @@ public: * Function RemoveNode() * Removes a node described by a given node pointer. * @param aNode is a pointer to node to be removed. + * @return True if node was removed, false if there were other references, so it was kept. */ - void RemoveNode( const RN_NODE_PTR& aNode ); + bool RemoveNode( const RN_NODE_PTR& aNode ); /** * Function GetNodes() @@ -279,7 +284,7 @@ public: /** * Function MarkDirty() - * Marks ratsnest for given net as 'dirty', ie. requiring recomputation. + * Marks ratsnest for given net as 'dirty', i.e. requiring recomputation. */ void MarkDirty() { @@ -427,7 +432,7 @@ public: /** * Function GetEdges() * Returns pointer to the vector of edges that makes ratsnest for a given net. - * @return Pointer to the vector of edges that makes ratsnest for a given net + * @return Pointer to the vector of edges that makes ratsnest for a given net. */ const std::vector* GetEdges() const { @@ -436,8 +441,8 @@ public: /** * Function AddSimpleNode() - * Changes drawing mode for a node to simple (ie. one ratsnest line per node). - * @param aNode is a node that changes its drawing mode.. + * Changes drawing mode for a node to simple (i.e. one ratsnest line per node). + * @param aNode is a node that changes its drawing mode. */ void AddSimpleNode( RN_NODE_PTR& aNode ) { @@ -445,9 +450,21 @@ public: aNode->SetFlag( true ); } + /** + * Function AddBlockedNode() + * Specifies a node as not suitable as a ratsnest line target (i.e. ratsnest lines will not + * target the node). The status is cleared after calling ClearSimple(). + * @param aNode is the node that is not going to be used as a ratsnest line target. + */ + void AddBlockedNode( RN_NODE_PTR& aNode ) + { + m_blockedNodes.push_back( aNode ); + aNode->SetFlag( true ); + } + /** * Function GetSimpleNodes() - * Returns list of nodes for which ratsnest is drawn in simple mode (ie. one + * Returns list of nodes for which ratsnest is drawn in simple mode (i.e. one * ratsnest line per node). * @return list of nodes for which ratsnest is drawn in simple mode. */ @@ -460,10 +477,20 @@ public: * Function ClearSimple() * Removes all nodes and edges that are used for displaying ratsnest in simple mode. */ - void ClearSimple(); + void ClearSimple() + { + BOOST_FOREACH( const RN_NODE_PTR& node, m_simpleNodes ) + node->SetFlag( false ); + + BOOST_FOREACH( const RN_NODE_PTR& node, m_blockedNodes ) + node->SetFlag( false ); + + m_simpleNodes.clear(); + m_blockedNodes.clear(); + } protected: - ///> Validates edge, ie. modifies source and target nodes for an edge + ///> Validates edge, i.e. modifies source and target nodes for an edge ///> to make sure that they are not ones with the flag set. void validateEdge( RN_EDGE_PTR& aEdge ); @@ -485,6 +512,9 @@ protected: ///> List of nodes for which ratsnest is drawn in simple mode. std::deque m_simpleNodes; + ///> List of nodes which should be used as ratsnest target nodes.. + std::deque m_blockedNodes; + ///> Flag indicating necessity of recalculation of ratsnest for a net. bool m_dirty; @@ -523,40 +553,61 @@ public: RN_DATA( const BOARD* aBoard ) : m_board( aBoard ) {} /** - * Function UpdateItem() - * Updates ratsnest data for an item. + * Function Add() + * Adds an item to the ratsnest data. + * @param aItem is an item to be added. + */ + void Add( const BOARD_ITEM* aItem ); + + /** + * Function Remove() + * Removes an item from the ratsnest data. * @param aItem is an item to be updated. */ - void Update( const BOARD_CONNECTED_ITEM* aItem ); + void Remove( const BOARD_ITEM* aItem ); /** - * Function UpdateItem() - * Updates ratsnest data for a module. - * @param aItem is a module to be updated. + * Function Update() + * Updates the ratsnest data for an item. + * @param aItem is an item to be updated. */ - void Update( const MODULE* aModule ); + void Update( const BOARD_ITEM* aItem ); /** * Function AddSimple() - * Sets an item to be drawn in simple mode (ie. one line per node, instead of full ratsnest). - * It is used for drawing temporary ratsnest, eg. while moving an item. + * Sets an item to be drawn in simple mode (i.e. one line per node, instead of full ratsnest). + * It is used for drawing quick, temporary ratsnest, eg. while moving an item. * @param aItem is an item to be drawn in simple node. */ - void AddSimple( const BOARD_CONNECTED_ITEM* aItem ); + void AddSimple( const BOARD_ITEM* aItem ); /** * Function AddSimple() - * Sets a module to be drawn in simple mode (ie. one line per node, instead of full ratsnest). - * It is used for drawing temporary ratsnest, eg. while moving a module. - * @param aModule is a module to be drawn in simple node. + * Allows to draw a ratsnest line using a position expressed in world coordinates and a + * net code (so there is no need to have a real BOARD_ITEM to draw ratsnest line). + * It is used for drawing quick, temporary ratsnest, eg. while moving an item. + * @param aPosition is the point for which ratsnest line are going to be drawn. + * @param aNetCode determines the net code for which the ratsnest line are going to be drawn. */ - void AddSimple( const MODULE* aModule ); + void AddSimple( const VECTOR2I& aPosition, int aNetCode ); + + /** + * Function AddBlocked() + * Specifies an item as not suitable as a ratsnest line target (i.e. ratsnest lines will not + * target its node(s)). The status is cleared after calling ClearSimple(). + * @param aItem is the item of which node(s) are not going to be used as a ratsnest line target. + */ + void AddBlocked( const BOARD_ITEM* aItem ); /** * Function ClearSimple() * Clears the list of nodes for which ratsnest is drawn in simple mode (one line per node). */ - void ClearSimple(); + void ClearSimple() + { + BOOST_FOREACH( RN_NET& net, m_nets ) + net.ClearSimple(); + } /** * Function ProcessBoard() @@ -573,13 +624,26 @@ public: void Recalculate( int aNet = -1 ); /** - * Function GetNets() - * Returns ratsnest grouped by net numbers. - * @return Vector of ratsnest grouped by net numbers. + * Function GetNetCount() + * Returns the number of nets handled by the ratsnest. + * @return Number of the nets. */ - const std::vector& GetNets() const + int GetNetCount() const { - return m_nets; + return m_nets.size(); + } + + /** + * Function GetNet() + * Returns ratsnest grouped by net numbers. + * @param aNetCode is the net code. + * @return Ratsnest data for a specified net. + */ + RN_NET& GetNet( int aNetCode ) + { + assert( aNetCode > 0 ); // ratsnest does not handle the unconnected net + + return m_nets[aNetCode]; } protected: diff --git a/pcbnew/ratsnest_viewitem.cpp b/pcbnew/ratsnest_viewitem.cpp index 282c0998a0..5de2527111 100644 --- a/pcbnew/ratsnest_viewitem.cpp +++ b/pcbnew/ratsnest_viewitem.cpp @@ -30,6 +30,7 @@ #include #include #include +#include #include #include @@ -57,33 +58,39 @@ void RATSNEST_VIEWITEM::ViewDraw( int aLayer, GAL* aGal ) const aGal->SetIsStroke( true ); aGal->SetIsFill( false ); aGal->SetLineWidth( 1.0 ); - aGal->SetStrokeColor( COLOR4D( 1.0, 1.0, 1.0, 0.4 ) ); + RENDER_SETTINGS* rs = m_view->GetPainter()->GetSettings(); + COLOR4D color = rs->GetColor( NULL, ITEM_GAL_LAYER( RATSNEST_VISIBLE ) ); - // Draw the temporary ratsnest - BOOST_FOREACH( const RN_NET& net, m_data->GetNets() ) + for( int i = 1; i < m_data->GetNetCount(); ++i ) { + RN_NET& net = m_data->GetNet( i ); + if( !net.IsVisible() ) continue; - // Avoid duplicate destinations for ratsnest lines by storing already used nodes - boost::unordered_set usedDestinations; + // Set brighter color for the temporary ratsnest + aGal->SetStrokeColor( color.Brightened( 0.8 ) ); // Draw the "dynamic" ratsnest (ie. for objects that may be currently being moved) BOOST_FOREACH( const RN_NODE_PTR& node, net.GetSimpleNodes() ) { RN_NODE_PTR dest = net.GetClosestNode( node, WITHOUT_FLAG() ); - if( dest && usedDestinations.find( dest ) == usedDestinations.end() ) + if( dest ) { VECTOR2D origin( node->GetX(), node->GetY() ); VECTOR2D end( dest->GetX(), dest->GetY() ); aGal->DrawLine( origin, end ); - usedDestinations.insert( dest ); + + // Avoid duplicate destinations for ratsnest lines by storing already used nodes + net.AddBlockedNode( dest ); } } // Draw the "static" ratsnest + aGal->SetStrokeColor( color ); // using the default ratsnest color + const std::vector* edges = net.GetUnconnected(); if( edges == NULL ) continue; diff --git a/pcbnew/router/pns_item.h b/pcbnew/router/pns_item.h index e9c856e086..c375a7ada5 100644 --- a/pcbnew/router/pns_item.h +++ b/pcbnew/router/pns_item.h @@ -28,7 +28,7 @@ #include "pns_layerset.h" -class BOARD_ITEM; +class BOARD_CONNECTED_ITEM; class PNS_NODE; /** @@ -94,8 +94,8 @@ public: const std::string GetKindStr() const; ///> Gets/Sets the corresponding parent object in the host application's model (pcbnew) - void SetParent( BOARD_ITEM* aParent ) { m_parent = aParent; } - BOARD_ITEM* GetParent() const { return m_parent; } + void SetParent( BOARD_CONNECTED_ITEM* aParent ) { m_parent = aParent; } + BOARD_CONNECTED_ITEM* GetParent() const { return m_parent; } ///> Net accessors int GetNet() const { return m_net; } @@ -145,7 +145,7 @@ private: protected: PnsKind m_kind; - BOARD_ITEM* m_parent; + BOARD_CONNECTED_ITEM* m_parent; PNS_NODE* m_world; PNS_NODE* m_owner; PNS_LAYERSET m_layers; diff --git a/pcbnew/router/pns_router.cpp b/pcbnew/router/pns_router.cpp index 151b28ffa1..e3cf287596 100644 --- a/pcbnew/router/pns_router.cpp +++ b/pcbnew/router/pns_router.cpp @@ -47,7 +47,7 @@ #include #include -#include +#include #include #include #include @@ -66,6 +66,9 @@ public: for( unsigned int i = 0; i < aBoard->GetNetCount(); i++ ) { NETINFO_ITEM* ni = aBoard->FindNet( i ); + if( ni == NULL ) + continue; + wxString netClassName = ni->GetClassName(); NETCLASS* nc = aBoard->m_NetClasses.Find( netClassName ); int clearance = nc->GetClearance(); @@ -94,12 +97,11 @@ private: PNS_ITEM* PNS_ROUTER::syncPad( D_PAD* aPad ) { - PNS_LAYERSET layers; + PNS_LAYERSET layers( 0, 15 ); switch( aPad->GetAttribute() ) { case PAD_STANDARD: - layers = PNS_LAYERSET( 0, 15 ); break; case PAD_SMD: @@ -127,7 +129,7 @@ PNS_ITEM* PNS_ROUTER::syncPad( D_PAD* aPad ) PNS_SOLID* solid = new PNS_SOLID; solid->SetLayers( layers ); - solid->SetNet( aPad->GetNet() ); + solid->SetNet( aPad->GetNetCode() ); wxPoint wx_c = aPad->GetPosition(); wxSize wx_sz = aPad->GetSize(); @@ -178,7 +180,7 @@ PNS_ITEM* PNS_ROUTER::syncPad( D_PAD* aPad ) PNS_ITEM* PNS_ROUTER::syncTrack( TRACK* aTrack ) { PNS_SEGMENT* s = - new PNS_SEGMENT( SEG( aTrack->GetStart(), aTrack->GetEnd() ), aTrack->GetNet() ); + new PNS_SEGMENT( SEG( aTrack->GetStart(), aTrack->GetEnd() ), aTrack->GetNetCode() ); s->SetWidth( aTrack->GetWidth() ); s->SetLayers( PNS_LAYERSET( aTrack->GetLayer() ) ); @@ -193,7 +195,7 @@ PNS_ITEM* PNS_ROUTER::syncVia( SEGVIA* aVia ) aVia->GetPosition(), PNS_LAYERSET( 0, 15 ), aVia->GetWidth(), - aVia->GetNet() ); + aVia->GetNetCode() ); v->SetParent( aVia ); return v; @@ -241,18 +243,21 @@ void PNS_ROUTER::SyncWorld() ClearWorld(); - m_clearanceFunc = new PCBNEW_CLEARANCE_FUNC( m_board ); m_world = new PNS_NODE(); m_world->SetClearanceFunctor( m_clearanceFunc ); m_world->SetMaxClearance( 1000000 ); // m_board->GetBiggestClearanceValue()); pads = m_board->GetPads(); - BOOST_FOREACH( D_PAD * pad, pads ) { - PNS_ITEM* solid = syncPad( pad ); + for( MODULE* module = m_board->m_Modules; module; module = module->Next() ) + { + for( D_PAD* pad = module->Pads(); pad; pad = pad->Next() ) + { + PNS_ITEM* solid = syncPad( pad ); - if( solid ) - m_world->Add( solid ); + if( solid ) + m_world->Add( solid ); + } } for( TRACK* t = m_board->m_Track; t; t = t->Next() ) @@ -263,7 +268,7 @@ void PNS_ROUTER::SyncWorld() if( type == PCB_TRACE_T ) item = syncTrack( t ); else if( type == PCB_VIA_T ) - item = syncVia( static_cast (t) ); + item = syncVia( static_cast( t ) ); if( item ) m_world->Add( item ); @@ -319,6 +324,9 @@ PNS_ROUTER::~PNS_ROUTER() { ClearWorld(); theRouter = NULL; + + if( m_previewItems ) + delete m_previewItems; } @@ -459,9 +467,10 @@ void PNS_ROUTER::EraseView() } if( m_previewItems ) + { m_previewItems->FreeItems(); - - m_previewItems->ViewUpdate( KIGFX::VIEW_ITEM::GEOMETRY ); + m_previewItems->ViewUpdate( KIGFX::VIEW_ITEM::GEOMETRY ); + } } @@ -576,18 +585,19 @@ void PNS_ROUTER::commitRouting( PNS_NODE* aNode ) for( unsigned int i = 0; i < removed.size(); i++ ) { - BOARD_ITEM* parent = removed[i]->GetParent(); + BOARD_CONNECTED_ITEM* parent = removed[i]->GetParent(); if( parent ) { - m_view->Remove( parent ); + m_undoBuffer.PushItem( ITEM_PICKER( parent, UR_DELETED ) ); m_board->Remove( parent ); + m_view->Remove( parent ); } } BOOST_FOREACH( PNS_ITEM* item, added ) { - BOARD_ITEM* newBI = NULL; + BOARD_CONNECTED_ITEM* newBI = NULL; switch( item->GetKind() ) { @@ -601,7 +611,7 @@ void PNS_ROUTER::commitRouting( PNS_NODE* aNode ) track->SetEnd( wxPoint( s.B.x, s.B.y ) ); track->SetWidth( seg->GetWidth() ); track->SetLayer( seg->GetLayers().Start() ); - track->SetNet( seg->GetNet() ); + track->SetNetCode( seg->GetNet() ); newBI = track; break; } @@ -612,7 +622,7 @@ void PNS_ROUTER::commitRouting( PNS_NODE* aNode ) PNS_VIA* via = static_cast( item ); via_board->SetPosition( wxPoint( via->GetPos().x, via->GetPos().y ) ); via_board->SetWidth( via->GetDiameter() ); - via_board->SetNet( via->GetNet() ); + via_board->SetNetCode( via->GetNet() ); newBI = via_board; break; } @@ -627,7 +637,7 @@ void PNS_ROUTER::commitRouting( PNS_NODE* aNode ) newBI->ClearFlags(); m_view->Add( newBI ); m_board->Add( newBI ); - m_board->GetRatsnest()->Update( static_cast( newBI ) ); + m_undoBuffer.PushItem( ITEM_PICKER( newBI, UR_NEW ) ); newBI->ViewUpdate( KIGFX::VIEW_ITEM::GEOMETRY ); } } @@ -754,13 +764,12 @@ bool PNS_ROUTER::FixRoute( const VECTOR2I& aP, PNS_ITEM* aEndItem ) void PNS_ROUTER::StopRouting() { + // Update the ratsnest with new changes + m_board->GetRatsnest()->Recalculate( m_currentNet ); + if( !RoutingInProgress() ) return; - // highlightCurrent(false); - - // Update the ratsnest - m_board->GetRatsnest()->Recalculate( m_currentNet ); EraseView(); m_state = IDLE; diff --git a/pcbnew/router/pns_router.h b/pcbnew/router/pns_router.h index 0bb882fa25..430f950a37 100644 --- a/pcbnew/router/pns_router.h +++ b/pcbnew/router/pns_router.h @@ -27,6 +27,7 @@ #include #include +#include #include "pns_routing_settings.h" #include "pns_item.h" @@ -137,6 +138,23 @@ public: const PNS_ITEMSET QueryHoverItems( const VECTOR2I& aP ); const VECTOR2I SnapToItem( PNS_ITEM* item, VECTOR2I aP, bool& aSplitsSegment ); + /** + * Returns the last changes introduced by the router (since the last time ClearLastChanges() + * was called or a new track has been started). + */ + const PICKED_ITEMS_LIST& GetLastChanges() const + { + return m_undoBuffer; + } + + /** + * Clears the list of recent changes, saved to be stored in the undo buffer. + */ + void ClearLastChanges() + { + m_undoBuffer.ClearItemsList(); + } + private: void clearViewFlags(); @@ -188,6 +206,9 @@ private: PNS_CLEARANCE_FUNC* m_clearanceFunc; boost::unordered_set m_hiddenItems; + + ///> Stores list of modified items in the current operation + PICKED_ITEMS_LIST m_undoBuffer; }; #endif diff --git a/pcbnew/router/pns_solid.h b/pcbnew/router/pns_solid.h index db52c808c4..b6f38a2851 100644 --- a/pcbnew/router/pns_solid.h +++ b/pcbnew/router/pns_solid.h @@ -32,10 +32,14 @@ class PNS_SOLID : public PNS_ITEM { public: - PNS_SOLID() : PNS_ITEM( SOLID ) + PNS_SOLID() : PNS_ITEM( SOLID ), m_shape( NULL ) { m_movable = false; - m_shape = NULL; + } + + ~PNS_SOLID() + { + delete m_shape; } PNS_ITEM* Clone() const; diff --git a/pcbnew/router/router_tool.cpp b/pcbnew/router/router_tool.cpp index 116e27f316..558b4dfab6 100644 --- a/pcbnew/router/router_tool.cpp +++ b/pcbnew/router/router_tool.cpp @@ -31,7 +31,8 @@ #include #include -#include + +#include #include "router_tool.h" #include "pns_segment.h" @@ -71,7 +72,7 @@ ROUTER_TOOL::~ROUTER_TOOL() } -void ROUTER_TOOL::Reset() +void ROUTER_TOOL::Reset( RESET_REASON aReason ) { if( m_router ) delete m_router; @@ -82,6 +83,7 @@ void ROUTER_TOOL::Reset() m_router->ClearWorld(); m_router->SetBoard( getModel( PCB_T ) ); m_router->SyncWorld(); + m_needsSync = false; if( getView() ) m_router->SetView( getView() ); @@ -138,7 +140,8 @@ PNS_ITEM* ROUTER_TOOL::pickSingleItem( const VECTOR2I& aWhere, int aNet, int aLa if( !IsCopperLayer( item->GetLayers().Start() ) ) continue; - if( item->GetParent() && !item->GetParent()->ViewIsVisible() ) + if( item->GetParent() && !item->GetParent()->ViewIsVisible() && + !item->GetParent()->IsSelected() ) continue; if( aNet < 0 || item->GetNet() == aNet ) @@ -278,10 +281,34 @@ void ROUTER_TOOL::updateEndItem( TOOL_EVENT& aEvent ) else { m_endItem = NULL; - m_endSnapPoint = p; + m_endSnapPoint = getView()->ToWorld( ctls->GetCursorPosition() ); ctls->ForceCursorPosition( false ); } + // Draw ratsnest for the currently routed track + RN_DATA* ratsnest = getModel( PCB_T )->GetRatsnest(); + ratsnest->ClearSimple(); + + if( ( m_endItem == NULL || m_endItem == m_startItem ) && m_startItem->GetNet() > 0 ) + { + // The ending node has to be first, so the line for the track is drawn first + ratsnest->AddSimple( m_endSnapPoint, m_startItem->GetNet() ); + + // Those nodes are added just to force ratsnest not to drawn + // lines to already routed parts of the track + const PICKED_ITEMS_LIST& changes = m_router->GetLastChanges(); + for( unsigned int i = 0; i < changes.GetCount(); ++i ) + { + // Block the new tracks, do not handle tracks that were moved + // (moved tracks are saved in the undo buffer with UR_DELETED status instead) + if( changes.GetPickedItemStatus( i ) == UR_NEW ) + ratsnest->AddBlocked( static_cast( changes.GetPickedItem( i ) ) ); + } + + // Also the origin of the new track should be skipped in the ratsnest shown for the routed track + ratsnest->AddBlocked( static_cast( m_startItem->GetParent() ) ); + } + if( m_endItem ) TRACE( 0, "%s, layer : %d", m_endItem->GetKindStr().c_str() % m_endItem->GetLayers().Start() ); @@ -290,6 +317,7 @@ void ROUTER_TOOL::updateEndItem( TOOL_EVENT& aEvent ) void ROUTER_TOOL::startRouting() { + bool saveUndoBuffer = true; VIEW_CONTROLS* ctls = getViewControls(); int width = getDefaultWidth( m_startItem ? m_startItem->GetNet() : -1 ); @@ -317,6 +345,11 @@ void ROUTER_TOOL::startRouting() { if( evt->IsCancel() ) break; + else if( evt->Action() == TA_UNDO_REDO ) + { + saveUndoBuffer = false; + break; + } else if( evt->IsMotion() ) { updateEndItem( *evt ); @@ -369,8 +402,21 @@ void ROUTER_TOOL::startRouting() } } - if( m_router->RoutingInProgress() ) - m_router->StopRouting(); + m_router->StopRouting(); + + if( saveUndoBuffer ) + { + // Save the recent changes in the undo buffer + getEditFrame()->SaveCopyInUndoList( m_router->GetLastChanges(), + UR_UNSPECIFIED ); + m_router->ClearLastChanges(); + getEditFrame()->OnModify(); + } + else + { + // It was interrupted by TA_UNDO_REDO event, so we have to sync the world now + m_needsSync = true; + } ctls->SetAutoPan( false ); ctls->ForceCursorPosition( false ); @@ -391,8 +437,16 @@ int ROUTER_TOOL::Main( TOOL_EVENT& aEvent ) // Main loop: keep receiving events while( OPT_TOOL_EVENT evt = Wait() ) { + if( m_needsSync ) + { + m_router->SyncWorld(); + m_needsSync = false; + } + if( evt->IsCancel() ) break; // Finish + else if( evt->Action() == TA_UNDO_REDO ) + m_needsSync = true; else if( evt->IsMotion() ) updateStartItem( *evt ); else if( evt->IsClick( BUT_LEFT ) ) @@ -407,6 +461,7 @@ int ROUTER_TOOL::Main( TOOL_EVENT& aEvent ) // Restore the default settings ctls->SetAutoPan( false ); ctls->ShowCursor( false ); + ctls->ForceCursorPosition( false ); return 0; } diff --git a/pcbnew/router/router_tool.h b/pcbnew/router/router_tool.h index da2a36601d..42bbceb19c 100644 --- a/pcbnew/router/router_tool.h +++ b/pcbnew/router/router_tool.h @@ -41,7 +41,7 @@ public: ROUTER_TOOL(); ~ROUTER_TOOL(); - void Reset(); + void Reset( RESET_REASON aReason ); int Main( TOOL_EVENT& aEvent ); private: @@ -72,6 +72,9 @@ private: PNS_ITEM* m_endItem; VECTOR2I m_endSnapPoint; + ///> Flag marking that the router's world needs syncing. + bool m_needsSync; + /*boost::shared_ptr m_menu;*/ CONTEXT_MENU* m_menu; }; diff --git a/pcbnew/router/trace.h b/pcbnew/router/trace.h index b1acfd688f..1f8a3e32c9 100644 --- a/pcbnew/router/trace.h +++ b/pcbnew/router/trace.h @@ -21,7 +21,8 @@ #ifndef __TRACE_H #define __TRACE_H -#ifdef DEBUG +// #ifdef DEBUG +#if 0 #include #include diff --git a/pcbnew/specctra_export.cpp b/pcbnew/specctra_export.cpp index 7f37c5c89d..2ac40ef5af 100644 --- a/pcbnew/specctra_export.cpp +++ b/pcbnew/specctra_export.cpp @@ -692,7 +692,7 @@ IMAGE* SPECCTRA_DB::makeIMAGE( BOARD* aBoard, MODULE* aModule ) pin->pin_id += buf; // append "@1" or "@2", etc. to pin name } - pin->kiNetCode = pad->GetNet(); + pin->kiNetCode = pad->GetNetCode(); image->pins.push_back( pin ); @@ -1556,7 +1556,7 @@ void SPECCTRA_DB::FromBOARD( BOARD* aBoard ) throw( IO_ERROR ) plane->SetShape( mainPolygon ); - plane->name = TO_UTF8( item->GetNetName() ); + plane->name = TO_UTF8( item->GetNetname() ); if( plane->name.size() == 0 ) { @@ -1922,7 +1922,7 @@ void SPECCTRA_DB::FromBOARD( BOARD* aBoard ) throw( IO_ERROR ) { TRACK* track = (TRACK*) items[i]; - int netcode = track->GetNet(); + int netcode = track->GetNetCode(); if( netcode == 0 ) continue; @@ -1981,7 +1981,7 @@ void SPECCTRA_DB::FromBOARD( BOARD* aBoard ) throw( IO_ERROR ) SEGVIA* via = (SEGVIA*) items[i]; wxASSERT( via->Type() == PCB_VIA_T ); - int netcode = via->GetNet(); + int netcode = via->GetNetCode(); if( netcode == 0 ) continue; diff --git a/pcbnew/specctra_import.cpp b/pcbnew/specctra_import.cpp index 9b541d1ed8..06d9a61843 100644 --- a/pcbnew/specctra_import.cpp +++ b/pcbnew/specctra_import.cpp @@ -207,7 +207,7 @@ TRACK* SPECCTRA_DB::makeTRACK( PATH* aPath, int aPointIndex, int aNetcode ) thro track->SetEnd( mapPt( aPath->points[aPointIndex+1], routeResolution ) ); track->SetLayer( pcbLayer2kicad[layerNdx] ); track->SetWidth( scale( aPath->aperture_width, routeResolution ) ); - track->SetNet( aNetcode ); + track->SetNetCode( aNetcode ); return track; } @@ -339,7 +339,7 @@ SEGVIA* SPECCTRA_DB::makeVIA( PADSTACK* aPadstack, const POINT& aPoint, int aNet } if( via ) - via->SetNet( aNetCode ); + via->SetNetCode( aNetCode ); return via; } diff --git a/pcbnew/tools/common_actions.cpp b/pcbnew/tools/common_actions.cpp index a61ebc52b0..f1fb3befd6 100644 --- a/pcbnew/tools/common_actions.cpp +++ b/pcbnew/tools/common_actions.cpp @@ -24,21 +24,35 @@ #include "common_actions.h" #include +#include // Selection tool actions TOOL_ACTION COMMON_ACTIONS::selectionActivate( "pcbnew.InteractiveSelection", - AS_GLOBAL, 'S', - "Selection tool", "Allows to select items" ); + AS_GLOBAL, 0, "", "" ); // No description, it is not supposed to be shown anywhere -// Move tool actions -TOOL_ACTION COMMON_ACTIONS::moveActivate( "pcbnew.InteractiveMove", +TOOL_ACTION COMMON_ACTIONS::selectionSingle( "pcbnew.InteractiveSelection.Single", + AS_GLOBAL, 0, "", "" ); // No description, it is not supposed to be shown anywhere + +TOOL_ACTION COMMON_ACTIONS::selectionClear( "pcbnew.InteractiveSelection.Clear", + AS_GLOBAL, 0, "", "" ); // No description, it is not supposed to be shown anywhere + +// Edit tool actions +TOOL_ACTION COMMON_ACTIONS::editActivate( "pcbnew.InteractiveEdit", AS_GLOBAL, 'M', "Move", "Moves the selected item(s)" ); -TOOL_ACTION COMMON_ACTIONS::rotate( "pcbnew.InteractiveMove.rotate", - AS_CONTEXT, ' ', +TOOL_ACTION COMMON_ACTIONS::rotate( "pcbnew.InteractiveEdit.rotate", + AS_CONTEXT, 'R', "Rotate", "Rotates selected item(s)" ); -TOOL_ACTION COMMON_ACTIONS::flip( "pcbnew.InteractiveMove.flip", +TOOL_ACTION COMMON_ACTIONS::flip( "pcbnew.InteractiveEdit.flip", AS_CONTEXT, 'F', "Flip", "Flips selected item(s)" ); + +TOOL_ACTION COMMON_ACTIONS::remove( "pcbnew.InteractiveEdit.remove", + AS_GLOBAL, WXK_DELETE, + "Remove", "Deletes selected item(s)" ); + +TOOL_ACTION COMMON_ACTIONS::properties( "pcbnew.InteractiveEdit.properties", + AS_GLOBAL, 'E', + "Properties...", "Displays properties window" ); diff --git a/pcbnew/tools/common_actions.h b/pcbnew/tools/common_actions.h index 547b86f814..86aafe5894 100644 --- a/pcbnew/tools/common_actions.h +++ b/pcbnew/tools/common_actions.h @@ -24,26 +24,36 @@ #include -class ACTION_MANAGER; - /** * Class COMMON_ACTIONS * - * Gathers all the actions that are shared by tools. The instance of COMMON_ACTIOSN is created - * inside of ACTION_MANAGER object and registers them. + * Gathers all the actions that are shared by tools. The instance of COMMON_ACTION is created + * inside of ACTION_MANAGER object that registers the actions. */ class COMMON_ACTIONS { public: - /// Activation of the move tool - static TOOL_ACTION moveActivate; - /// Activation of the selection tool static TOOL_ACTION selectionActivate; + /// Select a single item under the cursor position + static TOOL_ACTION selectionSingle; + + /// Clears the current selection + static TOOL_ACTION selectionClear; + + /// Activation of the edit tool + static TOOL_ACTION editActivate; + /// Rotation of selected objects static TOOL_ACTION rotate; /// Flipping of selected objects static TOOL_ACTION flip; + + /// Activation of the edit tool + static TOOL_ACTION properties; + + /// Deleting a BOARD_ITEM + static TOOL_ACTION remove; }; diff --git a/pcbnew/tools/edit_tool.cpp b/pcbnew/tools/edit_tool.cpp new file mode 100644 index 0000000000..f5f1c3b0ff --- /dev/null +++ b/pcbnew/tools/edit_tool.cpp @@ -0,0 +1,478 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2013 CERN + * @author Maciej Suminski + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, you may find one here: + * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html + * or you may search the http://www.gnu.org website for the version 2 license, + * or you may write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "common_actions.h" +#include "selection_tool.h" +#include "edit_tool.h" + +using namespace KIGFX; +using boost::optional; + +EDIT_TOOL::EDIT_TOOL() : + TOOL_INTERACTIVE( "pcbnew.InteractiveEdit" ), m_selectionTool( NULL ) +{ +} + + +bool EDIT_TOOL::Init() +{ + // Find the selection tool, so they can cooperate + m_selectionTool = static_cast( m_toolMgr->FindTool( "pcbnew.InteractiveSelection" ) ); + + if( !m_selectionTool ) + { + DisplayError( NULL, wxT( "pcbnew.InteractiveSelection tool is not available" ) ); + return false; + } + + // Add context menu entries that are displayed when selection tool is active + m_selectionTool->AddMenuItem( COMMON_ACTIONS::editActivate ); + m_selectionTool->AddMenuItem( COMMON_ACTIONS::rotate ); + m_selectionTool->AddMenuItem( COMMON_ACTIONS::flip ); + m_selectionTool->AddMenuItem( COMMON_ACTIONS::remove ); + m_selectionTool->AddMenuItem( COMMON_ACTIONS::properties ); + + setTransitions(); + + return true; +} + + +int EDIT_TOOL::Main( TOOL_EVENT& aEvent ) +{ + const SELECTION_TOOL::SELECTION& selection = m_selectionTool->GetSelection(); + + // Shall the selection be cleared at the end? + bool unselect = selection.Empty(); + + // Be sure that there is at least one item that we can modify + if( !makeSelection( selection ) ) + return 0; + + VECTOR2D dragPosition; // The last position of the cursor while dragging + m_dragging = false; // Are selected items being dragged? + bool restore = false; // Should items' state be restored when finishing the tool? + + // By default, modified items need to update their geometry + m_updateFlag = KIGFX::VIEW_ITEM::GEOMETRY; + + VIEW_CONTROLS* controls = getViewControls(); + PCB_EDIT_FRAME* editFrame = static_cast( m_toolMgr->GetEditFrame() ); + controls->ShowCursor( true ); + controls->SetSnapping( true ); + controls->SetAutoPan( true ); + controls->ForceCursorPosition( false ); + + // Main loop: keep receiving events + while( OPT_TOOL_EVENT evt = Wait() ) + { + if( evt->IsCancel() ) + { + restore = true; // Cancelling the tool means that items have to be restored + break; // Finish + } + + // Dispatch TOOL_ACTIONs + else if( evt->Category() == TC_COMMAND ) + { + if( evt->IsAction( &COMMON_ACTIONS::rotate ) ) + { + Rotate( aEvent ); + } + else if( evt->IsAction( &COMMON_ACTIONS::flip ) ) + { + Flip( aEvent ); + + // Flip causes change of layers + enableUpdateFlag( KIGFX::VIEW_ITEM::LAYERS ); + } + else if( evt->IsAction( &COMMON_ACTIONS::remove ) ) + { + Remove( aEvent ); + + break; // exit the loop, as there is no further processing for removed items + } + } + + else if( evt->IsMotion() || evt->IsDrag( BUT_LEFT ) ) + { + if( m_dragging ) + { + // Drag items to the current cursor position + VECTOR2D movement = ( getView()->ToWorld( controls->GetCursorPosition() ) - + dragPosition ); + for( unsigned int i = 0; i < selection.items.GetCount(); ++i ) + { + BOARD_ITEM* item = static_cast( selection.items.GetPickedItem( i ) ); + item->Move( wxPoint( movement.x, movement.y ) ); + } + + updateRatsnest( true ); + } + else + { + // Prepare to drag - save items, so changes can be undone + editFrame->OnModify(); + editFrame->SaveCopyInUndoList( selection.items, UR_CHANGED ); + + m_dragging = true; + } + + selection.group->ViewUpdate( VIEW_ITEM::GEOMETRY ); + dragPosition = getView()->ToWorld( controls->GetCursorPosition() ); + } + + else if( evt->IsMouseUp( BUT_LEFT ) || evt->IsClick( BUT_LEFT ) ) + break; // Finish + } + + m_dragging = false; + + if( restore ) + { + // Modifications have to be rollbacked, so restore the previous state of items + wxCommandEvent dummy; + editFrame->GetBoardFromUndoList( dummy ); + } + else + { + // Changes are applied, so update the items + selection.group->ItemsViewUpdate( m_updateFlag ); + } + + if( unselect ) + m_toolMgr->RunAction( "pcbnew.InteractiveSelection.Clear" ); + + RN_DATA* ratsnest = getModel( PCB_T )->GetRatsnest(); + ratsnest->ClearSimple(); + ratsnest->Recalculate(); + + controls->ShowCursor( false ); + controls->SetSnapping( false ); + controls->SetAutoPan( false ); + + setTransitions(); + + return 0; +} + + +int EDIT_TOOL::Properties( TOOL_EVENT& aEvent ) +{ + const SELECTION_TOOL::SELECTION& selection = m_selectionTool->GetSelection(); + PCB_EDIT_FRAME* editFrame = static_cast( m_toolMgr->GetEditFrame() ); + + // Shall the selection be cleared at the end? + bool unselect = selection.Empty(); + + if( !makeSelection( selection ) ) + return 0; + + // Properties are displayed when there is only one item selected + if( selection.Size() == 1 ) + { + // Display properties dialog + BOARD_ITEM* item = static_cast( selection.items.GetPickedItem( 0 ) ); + VECTOR2I cursor = getView()->ToWorld( getViewControls()->GetCursorPosition() ); + + // Check if user wants to edit pad or module properties + if( item->Type() == PCB_MODULE_T ) + { + for( D_PAD* pad = static_cast( item )->Pads(); pad; pad = pad->Next() ) + { + if( pad->ViewBBox().Contains( cursor ) ) + { + // Turns out that user wants to edit a pad properties + item = pad; + break; + } + } + } + + editFrame->SaveCopyInUndoList( item, UR_CHANGED ); + editFrame->OnModify(); + editFrame->OnEditItemRequest( NULL, item ); + + item->ViewUpdate( KIGFX::VIEW_ITEM::GEOMETRY ); + + updateRatsnest( true ); + getModel( PCB_T )->GetRatsnest()->Recalculate(); + + if( unselect ) + m_toolMgr->RunAction( "pcbnew.InteractiveSelection.Clear" ); + } + + setTransitions(); + + return 0; +} + + +int EDIT_TOOL::Rotate( TOOL_EVENT& aEvent ) +{ + const SELECTION_TOOL::SELECTION& selection = m_selectionTool->GetSelection(); + PCB_EDIT_FRAME* editFrame = static_cast( m_toolMgr->GetEditFrame() ); + + // Shall the selection be cleared at the end? + bool unselect = selection.Empty(); + + if( !makeSelection( selection ) ) + return 0; + + wxPoint rotatePoint = getModificationPoint( selection ); + + if( !m_dragging ) // If it is being dragged, then it is already saved with UR_CHANGED flag + { + editFrame->OnModify(); + editFrame->SaveCopyInUndoList( selection.items, UR_ROTATED, rotatePoint ); + } + + for( unsigned int i = 0; i < selection.items.GetCount(); ++i ) + { + BOARD_ITEM* item = static_cast( selection.items.GetPickedItem( i ) ); + + item->Rotate( rotatePoint, editFrame->GetRotationAngle() ); + + if( !m_dragging ) + item->ViewUpdate( KIGFX::VIEW_ITEM::GEOMETRY ); + } + + setTransitions(); + updateRatsnest( true ); + + if( m_dragging ) + selection.group->ViewUpdate( KIGFX::VIEW_ITEM::GEOMETRY ); + else + getModel( PCB_T )->GetRatsnest()->Recalculate(); + + if( unselect ) + m_toolMgr->RunAction( "pcbnew.InteractiveSelection.Clear" ); + + return 0; +} + + +int EDIT_TOOL::Flip( TOOL_EVENT& aEvent ) +{ + const SELECTION_TOOL::SELECTION& selection = m_selectionTool->GetSelection(); + PCB_EDIT_FRAME* editFrame = static_cast( m_toolMgr->GetEditFrame() ); + + // Shall the selection be cleared at the end? + bool unselect = selection.Empty(); + + if( !makeSelection( selection ) ) + return 0; + + wxPoint flipPoint = getModificationPoint( selection ); + + if( !m_dragging ) // If it is being dragged, then it is already saved with UR_CHANGED flag + { + editFrame->OnModify(); + editFrame->SaveCopyInUndoList( selection.items, UR_FLIPPED, flipPoint ); + } + + for( unsigned int i = 0; i < selection.items.GetCount(); ++i ) + { + BOARD_ITEM* item = static_cast( selection.items.GetPickedItem( i ) ); + + item->Flip( flipPoint ); + + if( !m_dragging ) + item->ViewUpdate( KIGFX::VIEW_ITEM::LAYERS ); + } + + setTransitions(); + updateRatsnest( true ); + + if( m_dragging ) + selection.group->ViewUpdate( KIGFX::VIEW_ITEM::GEOMETRY ); + else + getModel( PCB_T )->GetRatsnest()->Recalculate(); + + if( unselect ) + m_toolMgr->RunAction( "pcbnew.InteractiveSelection.Clear" ); + + return 0; +} + + +int EDIT_TOOL::Remove( TOOL_EVENT& aEvent ) +{ + const SELECTION_TOOL::SELECTION& selection = m_selectionTool->GetSelection(); + + if( !makeSelection( selection ) ) + return 0; + + // Get a copy of the selected items set + PICKED_ITEMS_LIST selectedItems = selection.items; + PCB_EDIT_FRAME* editFrame = static_cast( m_toolMgr->GetEditFrame() ); + + // As we are about to remove items, they have to be removed from the selection first + m_toolMgr->RunAction( "pcbnew.InteractiveSelection.Clear" ); + + // Save them + for( unsigned int i = 0; i < selectedItems.GetCount(); ++i ) + selectedItems.SetPickedItemStatus( UR_DELETED, i ); + editFrame->OnModify(); + editFrame->SaveCopyInUndoList( selectedItems, UR_DELETED ); + + // And now remove + for( unsigned int i = 0; i < selectedItems.GetCount(); ++i ) + { + BOARD_ITEM* item = static_cast( selectedItems.GetPickedItem( i ) ); + remove( item ); + } + + // Rebuild list of pads and nets if necessary + BOARD* board = getModel( PCB_T ); + if( !( board->m_Status_Pcb & NET_CODES_OK ) ) + board->BuildListOfNets(); + + setTransitions(); + board->GetRatsnest()->Recalculate(); + + return 0; +} + + +void EDIT_TOOL::remove( BOARD_ITEM* aItem ) +{ + BOARD* board = getModel( PCB_T ); + + switch( aItem->Type() ) + { + case PCB_MODULE_T: + { + MODULE* module = static_cast( aItem ); + module->ClearFlags(); + module->RunOnChildren( std::bind1st( std::mem_fun( &KIGFX::VIEW::Remove ), getView() ) ); + + // Module itself is deleted after the switch scope is finished + // list of pads is rebuild by BOARD::BuildListOfNets() + + // Clear flags to indicate, that the ratsnest, list of nets & pads are not valid anymore + board->m_Status_Pcb = 0; + } + break; + + // These are not supposed to be removed + case PCB_PAD_T: + case PCB_MODULE_TEXT_T: + case PCB_MODULE_EDGE_T: + return; + + case PCB_LINE_T: // a segment not on copper layers + case PCB_TEXT_T: // a text on a layer + case PCB_TRACE_T: // a track segment (segment on a copper layer) + case PCB_VIA_T: // a via (like track segment on a copper layer) + case PCB_DIMENSION_T: // a dimension (graphic item) + case PCB_TARGET_T: // a target (graphic item) + case PCB_MARKER_T: // a marker used to show something + case PCB_ZONE_T: // SEG_ZONE items are now deprecated + case PCB_ZONE_AREA_T: + break; + + default: // other types do not need to (or should not) be handled + assert( false ); + return; + break; + } + + getView()->Remove( aItem ); + board->Remove( aItem ); +} + + +void EDIT_TOOL::setTransitions() +{ + Go( &EDIT_TOOL::Main, COMMON_ACTIONS::editActivate.MakeEvent() ); + Go( &EDIT_TOOL::Rotate, COMMON_ACTIONS::rotate.MakeEvent() ); + Go( &EDIT_TOOL::Flip, COMMON_ACTIONS::flip.MakeEvent() ); + Go( &EDIT_TOOL::Remove, COMMON_ACTIONS::remove.MakeEvent() ); + Go( &EDIT_TOOL::Properties, COMMON_ACTIONS::properties.MakeEvent() ); +} + + +void EDIT_TOOL::updateRatsnest( bool aRedraw ) +{ + const SELECTION_TOOL::SELECTION& selection = m_selectionTool->GetSelection(); + RN_DATA* ratsnest = getModel( PCB_T )->GetRatsnest(); + + ratsnest->ClearSimple(); + for( unsigned int i = 0; i < selection.items.GetCount(); ++i ) + { + BOARD_ITEM* item = static_cast( selection.items.GetPickedItem( i ) ); + + ratsnest->Update( item ); + + if( aRedraw ) + ratsnest->AddSimple( item ); + } +} + + +wxPoint EDIT_TOOL::getModificationPoint( const SELECTION_TOOL::SELECTION& aSelection ) +{ + if( aSelection.Size() == 1 ) + { + return static_cast( aSelection.items.GetPickedItem( 0 ) )->GetPosition(); + } + else + { + VECTOR2I cursor = getView()->ToWorld( getViewControls()->GetCursorPosition() ); + return wxPoint( cursor.x, cursor.y ); + } +} + + +bool EDIT_TOOL::makeSelection( const SELECTION_TOOL::SELECTION& aSelection ) +{ + if( aSelection.Empty() ) + { + // Try to find an item that could be modified + m_toolMgr->RunAction( "pcbnew.InteractiveSelection.Single" ); + + if( aSelection.Empty() ) + { + // This is necessary, so later the tool may be activated upon + // reception of the activation event + setTransitions(); + + return false; // Still no items to work with + } + } + + return true; +} diff --git a/pcbnew/tools/edit_tool.h b/pcbnew/tools/edit_tool.h new file mode 100644 index 0000000000..d31b159aa5 --- /dev/null +++ b/pcbnew/tools/edit_tool.h @@ -0,0 +1,128 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2013 CERN + * @author Maciej Suminski + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, you may find one here: + * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html + * or you may search the http://www.gnu.org website for the version 2 license, + * or you may write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#ifndef __EDIT_TOOL_H +#define __EDIT_TOOL_H + +#include +#include +#include + +class BOARD_ITEM; +class SELECTION_TOOL; + +namespace KIGFX +{ +class VIEW_GROUP; +} + +/** + * Class EDIT_TOOL + * + * The interactive edit tool. Allows to move, rotate, flip and change properties of items selected + * using the pcbnew.InteractiveSelection tool. + */ + +class EDIT_TOOL : public TOOL_INTERACTIVE +{ +public: + EDIT_TOOL(); + + /// @copydoc TOOL_INTERACTIVE::Reset() + void Reset( RESET_REASON aReason ) {}; + + /// @copydoc TOOL_INTERACTIVE::Init() + bool Init(); + + /** + * Function Main() + * + * Main loop in which events are handled. + * @param aEvent is the handled event. + */ + int Main( TOOL_EVENT& aEvent ); + + /** + * Function Edit() + * + * Displays properties window for the selected object. + */ + int Properties( TOOL_EVENT& aEvent ); + + /** + * Function Rotate() + * + * Rotates currently selected items. + */ + int Rotate( TOOL_EVENT& aEvent ); + + /** + * Function Flip() + * + * Rotates currently selected items. The rotation point is the current cursor position. + */ + int Flip( TOOL_EVENT& aEvent ); + + /** + * Function Remove() + * + * Deletes currently selected items. The rotation point is the current cursor position. + */ + int Remove( TOOL_EVENT& aEvent ); + +private: + ///> Selection tool used for obtaining selected items + SELECTION_TOOL* m_selectionTool; + + ///> Flag determining if anything is being dragged right now + bool m_dragging; + + ///> Removes and frees a single BOARD_ITEM. + void remove( BOARD_ITEM* aItem ); + + ///> Sets up handlers for various events + void setTransitions(); + + ///> The required update flag for modified items + KIGFX::VIEW_ITEM::VIEW_UPDATE_FLAGS m_updateFlag; + + ///> Enables higher order update flag + void enableUpdateFlag( KIGFX::VIEW_ITEM::VIEW_UPDATE_FLAGS aFlag ) + { + if( m_updateFlag < aFlag ) + m_updateFlag = aFlag; + } + + void updateRatsnest( bool aRedraw ); + + ///> Returns the right modification point (e.g. for rotation), depending on the number of + ///> selected items. + wxPoint getModificationPoint( const SELECTION_TOOL::SELECTION& aSelection ); + + ///> If there are no items currently selected, it tries to choose the item that is under + ///> the cursor or displays a disambiguation menu if there are multpile items. + bool makeSelection( const SELECTION_TOOL::SELECTION& aSelection ); +}; + +#endif diff --git a/pcbnew/tools/item_state.h b/pcbnew/tools/item_state.h deleted file mode 100644 index ed562c623d..0000000000 --- a/pcbnew/tools/item_state.h +++ /dev/null @@ -1,284 +0,0 @@ -/* - * This program source code file is part of KiCad, a free EDA CAD application. - * - * Copyright (C) 2013 CERN - * @author Maciej Suminski - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, you may find one here: - * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html - * or you may search the http://www.gnu.org website for the version 2 license, - * or you may write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA - */ - -#ifndef ITEM_STATE_H_ -#define ITEM_STATE_H_ - -#include -#include - -/** - * Class ITEM_STATE - * - * Provides means for modifying properties of groups of items and gives possibility of rolling back - * the introduced changes. Does not take ownership of modified items, neither takes care of - * refreshing. - */ -class ITEM_STATE -{ -public: - ITEM_STATE() : - m_movement( 0.0, 0.0 ), m_flips( 0 ), m_rotation( 0.0 ) - { -#ifdef __WXDEBUG__ - m_canSave = true; -#endif - } - - /** - * Function Save() - * - * Adds an item and saves it's state. - * @param aItem is the item to be added. - */ - void Save( BOARD_ITEM* aItem ) - { -#ifdef __WXDEBUG__ - wxASSERT_MSG( m_canSave, wxT( "You cannot save items after issuing commands. You have " - "either RestoreAll() or Apply() before adding items!" ) ); -#endif - m_items.push_back( aItem ); - } - - /** - * Function RestoreAll() - * - * Rollbacks all the changes to the initial state. - */ - void RestoreAll() - { - // Check if there is a not saved movement command - saveMovement(); - - std::deque::iterator it, it_end; - std::deque::iterator cmd, cmd_end; - - for( it = m_items.begin(), it_end = m_items.end(); it != it_end; ++it ) - { - for( cmd = m_commands.begin(), cmd_end = m_commands.end(); cmd != cmd_end; ++cmd ) - cmd->Revert( *it ); - } - - reset(); - } - - /** - * Function Apply() - * - * Resets the state, clears the list of items & changes, so the object can be reused for - * other items. - */ - void Apply() - { - reset(); - } - - /** - * Function Move() - * - * Moves stored items by a given vector. - * @param aMovement is the movement vector. - */ - void Move( const VECTOR2D& aMovement ) - { -#ifdef __WXDEBUG__ - m_canSave = false; -#endif - std::deque::iterator it, it_end; - - for( it = m_items.begin(), it_end = m_items.end(); it != it_end; ++it ) - (*it)->Move( wxPoint( aMovement.x, aMovement.y ) ); - - m_movement += aMovement; - } - - /** - * Function Rotate() - * - * Rotates stored items by a given angle. - * @param aAngle is the angle (in decidegrees). - */ - void Rotate( const VECTOR2D& aPoint, double aAngle ) - { -#ifdef __WXDEBUG__ - m_canSave = false; -#endif - saveMovement(); - m_commands.push_front( COMMAND( COMMAND::ROTATE, aPoint, aAngle ) ); - - std::deque::iterator it, it_end; - - for( it = m_items.begin(), it_end = m_items.end(); it != it_end; ++it ) - (*it)->Rotate( wxPoint( aPoint.x, aPoint.y ), aAngle ); - - m_rotation += aAngle; - } - - /** - * Function Flip() - * - * Changes the board side for stored items. - * @param aPoint is the rotation point. - */ - void Flip( const VECTOR2D& aPoint ) - { -#ifdef __WXDEBUG__ - m_canSave = false; -#endif - saveMovement(); - m_commands.push_front( COMMAND( COMMAND::FLIP, aPoint ) ); - - std::deque::iterator it, it_end; - - for( it = m_items.begin(), it_end = m_items.end(); it != it_end; ++it ) - (*it)->Flip( wxPoint( aPoint.x, aPoint.y ) ); - - m_flips++; - } - - /** - * Function ToggleVisibility() - * - * Switches the visibility property of stored items. - */ - void ToggleVisibility() - { -#ifdef __WXDEBUG__ - m_canSave = false; -#endif - m_commands.push_front( COMMAND( COMMAND::VISIBILITY ) ); - - std::deque::iterator it, it_end; - - for( it = m_items.begin(), it_end = m_items.end(); it != it_end; ++it ) - (*it)->ViewSetVisible( !(*it)->ViewIsVisible() ); - } - - /** - * Function GetUpdateFlag() - * - * Returns information on what kind of update should be applied to items in order to display - * them properly. - * @return Flag required to refresh items. - */ - KIGFX::VIEW_ITEM::VIEW_UPDATE_FLAGS GetUpdateFlag() const - { - if( m_flips % 2 == 1 ) // If number of flips is odd, then we need to change layers - return KIGFX::VIEW_ITEM::LAYERS; - else if( m_movement.x != 0.0 || m_movement.y != 0.0 || m_rotation != 0.0 ) - return KIGFX::VIEW_ITEM::GEOMETRY; - - return KIGFX::VIEW_ITEM::APPEARANCE; - } - -private: - /// COMMAND stores modifications that were done to items - struct COMMAND - { - /// Type of command - enum TYPE { MOVE, ROTATE, FLIP, VISIBILITY }; - TYPE m_type; - - /// Point where flip/rotation occurred or movement vector - VECTOR2D m_point; - - /// Used only for rotation - double m_angle; - - COMMAND( TYPE aType, VECTOR2D aPoint = VECTOR2D( 0.0, 0.0 ), double aAngle = 0.0 ) : - m_type( aType ), m_point( aPoint ), m_angle( aAngle ) {}; - - void Revert( BOARD_ITEM* aItem ) - { - switch( m_type ) - { - case MOVE: - aItem->Move( wxPoint( -m_point.x, -m_point.y ) ); - break; - - case ROTATE: - aItem->Rotate( wxPoint( m_point.x, m_point.y ), -m_angle ); - break; - - case FLIP: - aItem->Flip( wxPoint( m_point.x, m_point.y ) ); - break; - - case VISIBILITY: - aItem->ViewSetVisible( !aItem->ViewIsVisible() ); - break; - } - } - }; - - /// Adds a MOVEMENT command basing on the current movement vector - void saveMovement() - { - if( m_movement.x != 0.0 || m_movement.y != 0.0 ) - { - m_commands.push_front( COMMAND( COMMAND::MOVE, m_movement ) ); - - m_movement.x = 0.0; - m_movement.y = 0.0; - } - } - - /// Restores the initial state - void reset() - { - m_movement.x = 0.0; - m_movement.y = 0.0; - m_flips = 0; - m_rotation = 0.0; - - m_items.clear(); - m_commands.clear(); - -#ifdef __WXDEBUG__ - m_canSave = true; -#endif - } - - /// List of issued commands - std::deque m_items; - - /// List of items that are affected by commands - std::deque m_commands; - - /// Current movement vector (updated by Move() command) - VECTOR2D m_movement; - - /// Number of flips applied to items - unsigned int m_flips; - - /// Total rotation applied to items - double m_rotation; - -#ifdef __WXDEBUG__ - /// Debug flag assuring that functions are called in proper order - bool m_canSave; -#endif -}; - -#endif /* ITEM_STATE_H_ */ diff --git a/pcbnew/tools/move_tool.cpp b/pcbnew/tools/move_tool.cpp deleted file mode 100644 index 2cc3b0752e..0000000000 --- a/pcbnew/tools/move_tool.cpp +++ /dev/null @@ -1,204 +0,0 @@ -/* - * This program source code file is part of KiCad, a free EDA CAD application. - * - * Copyright (C) 2013 CERN - * @author Maciej Suminski - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, you may find one here: - * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html - * or you may search the http://www.gnu.org website for the version 2 license, - * or you may write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA - */ - -#include -#include -#include -#include -#include -#include - -#include - -#include "common_actions.h" -#include "selection_tool.h" -#include "move_tool.h" - -using namespace KIGFX; -using boost::optional; - -MOVE_TOOL::MOVE_TOOL() : - TOOL_INTERACTIVE( "pcbnew.InteractiveMove" ), m_selectionTool( NULL ) -{ -} - - -void MOVE_TOOL::Reset() -{ - // The tool launches upon reception of action event ("pcbnew.InteractiveMove") - Go( &MOVE_TOOL::Main, COMMON_ACTIONS::moveActivate.MakeEvent() ); -} - - -bool MOVE_TOOL::Init() -{ - // Find the selection tool, so they can cooperate - TOOL_BASE* selectionTool = m_toolMgr->FindTool( "pcbnew.InteractiveSelection" ); - - if( selectionTool ) - { - m_selectionTool = static_cast( selectionTool ); - - // Add context menu entries that are displayed when selection tool is active - m_selectionTool->AddMenuItem( COMMON_ACTIONS::moveActivate ); - m_selectionTool->AddMenuItem( COMMON_ACTIONS::rotate ); - m_selectionTool->AddMenuItem( COMMON_ACTIONS::flip ); - } - else - { - DisplayError( NULL, wxT( "pcbnew.InteractiveSelection tool is not available" ) ); - return false; - } - - return true; -} - - -int MOVE_TOOL::Main( TOOL_EVENT& aEvent ) -{ - const SELECTION_TOOL::SELECTION& selection = m_selectionTool->GetSelection(); - - if( selection.Empty() ) - return 0; // there are no items to operate on - - VECTOR2D dragPosition; - bool dragging = false; - bool restore = false; // Should items' state be restored when finishing the tool? - - VIEW_CONTROLS* controls = getViewControls(); - controls->ShowCursor( true ); - controls->SetSnapping( true ); - controls->SetAutoPan( true ); - - // Main loop: keep receiving events - while( OPT_TOOL_EVENT evt = Wait() ) - { - if( evt->IsCancel() ) - { - restore = true; // Cancelling the tool means that items have to be restored - break; // Finish - } - - // Dispatch TOOL_ACTIONs - else if( evt->Category() == TC_COMMAND ) - { - VECTOR2D cursorPos = getView()->ToWorld( getViewControls()->GetCursorPosition() ); - - if( evt->IsAction( &COMMON_ACTIONS::rotate ) ) // got rotation event? - { - m_state.Rotate( cursorPos, 900.0 ); - selection.group->ViewUpdate( VIEW_ITEM::GEOMETRY ); - updateRatsnest( true ); - } - else if( evt->IsAction( &COMMON_ACTIONS::flip ) ) // got flip event? - { - m_state.Flip( cursorPos ); - selection.group->ViewUpdate( VIEW_ITEM::GEOMETRY ); - updateRatsnest( true ); - } - } - - else if( evt->IsMotion() || evt->IsDrag( BUT_LEFT ) ) - { - if( dragging ) - { - // Drag items to the current cursor position - VECTOR2D movement = ( evt->Position() - dragPosition ); - m_state.Move( movement ); - - updateRatsnest( true ); - } - else - { - // Prepare to drag - std::set::iterator it; - - for( it = selection.items.begin(); it != selection.items.end(); ++it ) - { - // Save the state of the selected items, in case it has to be restored - m_state.Save( *it ); - } - - dragging = true; - } - - selection.group->ViewUpdate( VIEW_ITEM::GEOMETRY ); - dragPosition = evt->Position(); - } - else if( evt->IsMouseUp( BUT_LEFT ) || evt->IsClick( BUT_LEFT ) ) - break; // Finish - } - - if( restore ) - { - // Modifications has to be rollbacked, so restore the previous state of items - selection.group->ItemsViewUpdate( VIEW_ITEM::APPEARANCE ); - m_state.RestoreAll(); - - updateRatsnest( false ); - } - else - { - // Changes are applied, so update the items - selection.group->ItemsViewUpdate( m_state.GetUpdateFlag() ); - m_state.Apply(); - - } - - RN_DATA* ratsnest = static_cast( m_toolMgr->GetModel() )->GetRatsnest(); - ratsnest->Recalculate(); - - controls->ShowCursor( false ); - controls->SetSnapping( false ); - controls->SetAutoPan( false ); - - return 0; -} - - -void MOVE_TOOL::updateRatsnest( bool aRedraw ) -{ - const SELECTION_TOOL::SELECTION& selection = m_selectionTool->GetSelection(); - RN_DATA* ratsnest = static_cast( m_toolMgr->GetModel() )->GetRatsnest(); - - ratsnest->ClearSimple(); - BOOST_FOREACH( BOARD_ITEM* item, selection.items ) - { - if( item->Type() == PCB_PAD_T || item->Type() == PCB_TRACE_T || - item->Type() == PCB_VIA_T || item->Type() == PCB_ZONE_AREA_T ) - { - ratsnest->Update( static_cast( item ) ); - - if( aRedraw ) - ratsnest->AddSimple( static_cast( item ) ); - } - else if( item->Type() == PCB_MODULE_T ) - { - ratsnest->Update( static_cast( item ) ); - - if( aRedraw ) - ratsnest->AddSimple( static_cast( item ) ); - } - } -} diff --git a/pcbnew/tools/move_tool.h b/pcbnew/tools/move_tool.h deleted file mode 100644 index 10783a5ed4..0000000000 --- a/pcbnew/tools/move_tool.h +++ /dev/null @@ -1,76 +0,0 @@ -/* - * This program source code file is part of KiCad, a free EDA CAD application. - * - * Copyright (C) 2013 CERN - * @author Maciej Suminski - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, you may find one here: - * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html - * or you may search the http://www.gnu.org website for the version 2 license, - * or you may write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA - */ - -#ifndef __MOVE_TOOL_H -#define __MOVE_TOOL_H - -#include -#include -#include -#include "item_state.h" - -class BOARD_ITEM; -class SELECTION_TOOL; - -namespace KIGFX -{ -class VIEW_GROUP; -} - -/** - * Class MOVE_TOOL - * - * Our sample move tool. Allows to move, rotate and flip items selected by - * pcbnew.InteractiveSelection tool. - */ - -class MOVE_TOOL : public TOOL_INTERACTIVE -{ -public: - MOVE_TOOL(); - - /// @copydoc TOOL_INTERACTIVE::Reset() - void Reset(); - - /// @copydoc TOOL_INTERACTIVE::Init() - bool Init(); - - /** - * Function Main() - * - * Main loop in which events are handled. - */ - int Main( TOOL_EVENT& aEvent ); - -private: - void updateRatsnest( bool aRedraw ); - - /// Saves the state of items and allows to restore them - ITEM_STATE m_state; - - /// Selection tool used for obtaining selected items - SELECTION_TOOL* m_selectionTool; -}; - -#endif diff --git a/pcbnew/tools/pcb_tools.cpp b/pcbnew/tools/pcb_tools.cpp index e8e0568587..a4b4f21a24 100644 --- a/pcbnew/tools/pcb_tools.cpp +++ b/pcbnew/tools/pcb_tools.cpp @@ -35,7 +35,7 @@ #include #include "selection_tool.h" -#include "move_tool.h" +#include "edit_tool.h" #include "common_actions.h" #include @@ -47,27 +47,32 @@ void PCB_EDIT_FRAME::setupTools() GetGalCanvas()->SetEventDispatcher( m_toolDispatcher ); // Register tool actions - m_toolManager->RegisterAction( &COMMON_ACTIONS::moveActivate ); - m_toolManager->RegisterAction( &COMMON_ACTIONS::selectionActivate ); + m_toolManager->RegisterAction( &COMMON_ACTIONS::selectionSingle ); + m_toolManager->RegisterAction( &COMMON_ACTIONS::selectionClear ); + m_toolManager->RegisterAction( &COMMON_ACTIONS::editActivate ); m_toolManager->RegisterAction( &COMMON_ACTIONS::rotate ); m_toolManager->RegisterAction( &COMMON_ACTIONS::flip ); + m_toolManager->RegisterAction( &COMMON_ACTIONS::remove ); + m_toolManager->RegisterAction( &COMMON_ACTIONS::properties ); // Register tools m_toolManager->RegisterTool( new SELECTION_TOOL ); m_toolManager->RegisterTool( new ROUTER_TOOL ); - m_toolManager->RegisterTool( new MOVE_TOOL ); + m_toolManager->RegisterTool( new EDIT_TOOL ); + + m_toolManager->SetEnvironment( NULL, GetGalCanvas()->GetView(), + GetGalCanvas()->GetViewControls(), this ); + m_toolManager->ResetTools( TOOL_BASE::RUN ); + + // Run the selection tool, it is supposed to be always active + m_toolManager->InvokeTool( "pcbnew.InteractiveSelection" ); } void PCB_EDIT_FRAME::destroyTools() { - m_toolManager->UnregisterAction( &COMMON_ACTIONS::moveActivate ); - m_toolManager->UnregisterAction( &COMMON_ACTIONS::selectionActivate ); - m_toolManager->UnregisterAction( &COMMON_ACTIONS::rotate ); - m_toolManager->UnregisterAction( &COMMON_ACTIONS::flip ); - - delete m_toolDispatcher; delete m_toolManager; + delete m_toolDispatcher; } diff --git a/pcbnew/tools/selection_tool.cpp b/pcbnew/tools/selection_tool.cpp index fbd2aee6f6..2a4f167671 100644 --- a/pcbnew/tools/selection_tool.cpp +++ b/pcbnew/tools/selection_tool.cpp @@ -47,11 +47,10 @@ #include "bright_box.h" #include "common_actions.h" -using namespace KIGFX; using boost::optional; SELECTION_TOOL::SELECTION_TOOL() : - TOOL_INTERACTIVE( "pcbnew.InteractiveSelection" ), m_multiple( false ) + TOOL_INTERACTIVE( "pcbnew.InteractiveSelection" ), m_additive( false ), m_multiple( false ) { m_selArea = new SELECTION_AREA; m_selection.group = new KIGFX::VIEW_GROUP; @@ -65,8 +64,16 @@ SELECTION_TOOL::~SELECTION_TOOL() } -void SELECTION_TOOL::Reset() +void SELECTION_TOOL::Reset( RESET_REASON aReason ) { + if( aReason == TOOL_BASE::MODEL_RELOAD ) + // Remove pointers to the selected items from containers + // without changing their properties (as they are already deleted) + m_selection.clear(); + else + // Restore previous properties of selected items and remove them from containers + clearSelection(); + // Reinsert the VIEW_GROUP, in case it was removed from the VIEW getView()->Remove( m_selection.group ); getView()->Add( m_selection.group ); @@ -78,12 +85,6 @@ void SELECTION_TOOL::Reset() int SELECTION_TOOL::Main( TOOL_EVENT& aEvent ) { - VIEW* view = getView(); - - assert( getModel( PCB_T ) != NULL ); - - view->Add( m_selection.group ); - // Main loop: keep receiving events while( OPT_TOOL_EVENT evt = Wait() ) { @@ -91,20 +92,47 @@ int SELECTION_TOOL::Main( TOOL_EVENT& aEvent ) // become the new selection (discarding previously selected items) m_additive = evt->Modifier( MD_SHIFT ); - if( evt->IsCancel() ) + if( evt->IsAction( &COMMON_ACTIONS::selectionSingle ) ) { - if( !m_selection.Empty() ) // Cancel event deselects items... - clearSelection(); - else // ...unless there is nothing selected - break; // then exit the tool + selectSingle( getView()->ToWorld( getViewControls()->GetMousePosition() ) ); + } + + else if( evt->IsCancel() || evt->Action() == TA_UNDO_REDO || + evt->IsAction( &COMMON_ACTIONS::selectionClear ) ) + { + clearSelection(); } // single click? Select single object - if( evt->IsClick( BUT_LEFT ) ) + else if( evt->IsClick( BUT_LEFT ) ) + { + if( !m_additive ) + clearSelection(); + selectSingle( evt->Position() ); + } + + // right click? if there is any object - show the context menu + else if( evt->IsClick( BUT_RIGHT ) ) + { + if( m_selection.Empty() ) + selectSingle( evt->Position() ); + + if( !m_selection.Empty() ) + SetContextMenu( &m_menu, CMENU_NOW ); + } + + // double click? Display the properties window + else if( evt->IsDblClick( BUT_LEFT ) ) + { + if( m_selection.Empty() ) + selectSingle( evt->Position() ); + + m_toolMgr->RunAction( "pcbnew.InteractiveEdit.properties" ); + } // drag with LMB? Select multiple objects (or at least draw a selection box) or drag them - if( evt->IsDrag( BUT_LEFT ) ) + else if( evt->IsDrag( BUT_LEFT ) ) { if( m_selection.Empty() || m_additive ) { @@ -118,7 +146,7 @@ int SELECTION_TOOL::Main( TOOL_EVENT& aEvent ) if( containsSelected( evt->Position() ) ) { // Yes -> run the move tool and wait till it finishes - m_toolMgr->InvokeTool( "pcbnew.InteractiveMove" ); + m_toolMgr->InvokeTool( "pcbnew.InteractiveEdit" ); } else { @@ -129,8 +157,8 @@ int SELECTION_TOOL::Main( TOOL_EVENT& aEvent ) } } - m_selection.group->Clear(); - view->Remove( m_selection.group ); + // This tool is supposed to be active forever + assert( false ); return 0; } @@ -146,13 +174,9 @@ void SELECTION_TOOL::AddMenuItem( const TOOL_ACTION& aAction ) void SELECTION_TOOL::toggleSelection( BOARD_ITEM* aItem ) { - if( m_selection.items.find( aItem ) != m_selection.items.end() ) + if( aItem->IsSelected() ) { - deselectItem( aItem ); - - // If there is nothing selected, disable the context menu - if( m_selection.Empty() ) - SetContextMenu( &m_menu, CMENU_OFF ); + deselect( aItem ); } else { @@ -161,36 +185,11 @@ void SELECTION_TOOL::toggleSelection( BOARD_ITEM* aItem ) // Prevent selection of invisible or inactive items if( selectable( aItem ) ) - { - selectItem( aItem ); - - // Now the context menu should be enabled - SetContextMenu( &m_menu, CMENU_BUTTON ); - } + select( aItem ); } } -void SELECTION_TOOL::clearSelection() -{ - VIEW_GROUP::const_iter it, it_end; - - for( it = m_selection.group->Begin(), it_end = m_selection.group->End(); it != it_end; ++it ) - { - BOARD_ITEM* item = static_cast( *it ); - - item->ViewSetVisible( true ); - item->ClearSelected(); - } - - m_selection.group->Clear(); - m_selection.items.clear(); - - // Do not show the context menu when there is nothing selected - SetContextMenu( &m_menu, CMENU_OFF ); -} - - void SELECTION_TOOL::selectSingle( const VECTOR2I& aWhere ) { BOARD* pcb = getModel( PCB_T ); @@ -206,7 +205,6 @@ void SELECTION_TOOL::selectSingle( const VECTOR2I& aWhere ) case 0: if( !m_additive ) clearSelection(); - break; case 1: @@ -214,13 +212,10 @@ void SELECTION_TOOL::selectSingle( const VECTOR2I& aWhere ) break; default: - // Remove modules, they have to be selected by clicking on area that does not - // contain anything but module footprint and not selectable items + // Remove unselectable items for( int i = collector.GetCount() - 1; i >= 0 ; --i ) { - BOARD_ITEM* boardItem = ( collector )[i]; - - if( boardItem->Type() == PCB_MODULE_T || !selectable( boardItem ) ) + if( !selectable( collector[i] ) ) collector.Remove( i ); } @@ -242,48 +237,11 @@ void SELECTION_TOOL::selectSingle( const VECTOR2I& aWhere ) } -BOARD_ITEM* SELECTION_TOOL::pickSmallestComponent( GENERAL_COLLECTOR* aCollector ) -{ - int count = aCollector->GetPrimaryCount(); // try to use preferred layer - - if( 0 == count ) - count = aCollector->GetCount(); - - for( int i = 0; i < count; ++i ) - { - if( ( *aCollector )[i]->Type() != PCB_MODULE_T ) - return NULL; - } - - // All are modules, now find smallest MODULE - int minDim = 0x7FFFFFFF; - int minNdx = 0; - - for( int i = 0; i < count; ++i ) - { - MODULE* module = (MODULE*) ( *aCollector )[i]; - - int lx = module->GetBoundingBox().GetWidth(); - int ly = module->GetBoundingBox().GetHeight(); - - int lmin = std::min( lx, ly ); - - if( lmin < minDim ) - { - minDim = lmin; - minNdx = i; - } - } - - return (*aCollector)[minNdx]; -} - - bool SELECTION_TOOL::selectMultiple() { bool cancelled = false; // Was the tool cancelled while it was running? m_multiple = true; // Multiple selection mode is active - VIEW* view = getView(); + KIGFX::VIEW* view = getView(); getViewControls()->SetAutoPan( true ); view->Add( m_selArea ); @@ -305,7 +263,7 @@ bool SELECTION_TOOL::selectMultiple() m_selArea->SetOrigin( evt->DragOrigin() ); m_selArea->SetEnd( evt->Position() ); m_selArea->ViewSetVisible( true ); - m_selArea->ViewUpdate( VIEW_ITEM::GEOMETRY ); + m_selArea->ViewUpdate( KIGFX::VIEW_ITEM::GEOMETRY ); } if( evt->IsMouseUp( BUT_LEFT ) ) @@ -314,26 +272,25 @@ bool SELECTION_TOOL::selectMultiple() m_selArea->ViewSetVisible( false ); // Mark items within the selection box as selected - std::vector selectedItems; + std::vector selectedItems; BOX2I selectionBox = m_selArea->ViewBBox(); view->Query( selectionBox, selectedItems ); // Get the list of selected items - std::vector::iterator it, it_end; + std::vector::iterator it, it_end; for( it = selectedItems.begin(), it_end = selectedItems.end(); it != it_end; ++it ) { BOARD_ITEM* item = static_cast( it->first ); // Add only those items that are visible and fully within the selection box - if( selectable( item ) && selectionBox.Contains( item->ViewBBox() ) ) - selectItem( item ); + if( !item->IsSelected() && selectable( item ) && selectionBox.Contains( item->ViewBBox() ) ) + select( item ); } - // Now the context menu should be enabled - if( !m_selection.Empty() ) - SetContextMenu( &m_menu, CMENU_BUTTON ); + // Do not display information about selected item,as there is more than one + getEditFrame()->SetCurItem( NULL ); - break; + break; // Stop waiting for events } } @@ -345,6 +302,27 @@ bool SELECTION_TOOL::selectMultiple() } +void SELECTION_TOOL::clearSelection() +{ + if( m_selection.Empty() ) + return; + + KIGFX::VIEW_GROUP::const_iter it, it_end; + + // Restore the initial properties + for( it = m_selection.group->Begin(), it_end = m_selection.group->End(); it != it_end; ++it ) + { + BOARD_ITEM* item = static_cast( *it ); + + item->ViewSetVisible( true ); + item->ClearSelected(); + } + m_selection.clear(); + + getEditFrame()->SetCurItem( NULL ); +} + + BOARD_ITEM* SELECTION_TOOL::disambiguationMenu( GENERAL_COLLECTOR* aCollector ) { BOARD_ITEM* current = NULL; @@ -402,15 +380,49 @@ BOARD_ITEM* SELECTION_TOOL::disambiguationMenu( GENERAL_COLLECTOR* aCollector ) } // Removes possible brighten mark - getView()->MarkTargetDirty( TARGET_OVERLAY ); - - // Restore the original menu - SetContextMenu( &m_menu, CMENU_BUTTON ); + getView()->MarkTargetDirty( KIGFX::TARGET_OVERLAY ); return current; } +BOARD_ITEM* SELECTION_TOOL::pickSmallestComponent( GENERAL_COLLECTOR* aCollector ) +{ + int count = aCollector->GetPrimaryCount(); // try to use preferred layer + + if( 0 == count ) + count = aCollector->GetCount(); + + for( int i = 0; i < count; ++i ) + { + if( ( *aCollector )[i]->Type() != PCB_MODULE_T ) + return NULL; + } + + // All are modules, now find smallest MODULE + int minDim = 0x7FFFFFFF; + int minNdx = 0; + + for( int i = 0; i < count; ++i ) + { + MODULE* module = (MODULE*) ( *aCollector )[i]; + + int lx = module->GetBoundingBox().GetWidth(); + int ly = module->GetBoundingBox().GetHeight(); + + int lmin = std::min( lx, ly ); + + if( lmin < minDim ) + { + minDim = lmin; + minNdx = i; + } + } + + return (*aCollector)[minNdx]; +} + + bool SELECTION_TOOL::selectable( const BOARD_ITEM* aItem ) const { // Is high contrast mode enabled? @@ -453,33 +465,25 @@ bool SELECTION_TOOL::selectable( const BOARD_ITEM* aItem ) const } break; - case PCB_PAD_T: - { - // Pads are not selectable in multiple selection mode - if( m_multiple ) - return false; - - // Pads are supposed to be on top, bottom or both at the same time (THT) - if( aItem->IsOnLayer( LAYER_N_FRONT ) && board->IsLayerVisible( LAYER_N_FRONT ) ) + case PCB_MODULE_T: + if( aItem->IsOnLayer( LAYER_N_FRONT ) && board->IsElementVisible( MOD_FR_VISIBLE ) ) return true; - if( aItem->IsOnLayer( LAYER_N_BACK ) && board->IsLayerVisible( LAYER_N_BACK ) ) + if( aItem->IsOnLayer( LAYER_N_BACK ) && board->IsElementVisible( MOD_BK_VISIBLE ) ) return true; return false; - } - break; - - case PCB_MODULE_TEXT_T: - // Module texts are not selectable in multiple selection mode - if( m_multiple ) - return false; break; - // These are not selectable, otherwise silkscreen drawings would be easily destroyed + case PCB_MODULE_TEXT_T: + if( m_multiple ) + return false; + break; + + // These are not selectable case PCB_MODULE_EDGE_T: - // and some other stuff that should be selected + case PCB_PAD_T: case NOT_USED: case TYPE_NOT_INIT: return false; @@ -493,102 +497,87 @@ bool SELECTION_TOOL::selectable( const BOARD_ITEM* aItem ) const } -void SELECTION_TOOL::selectItem( BOARD_ITEM* aItem ) +void SELECTION_TOOL::select( BOARD_ITEM* aItem ) { - /// Selecting an item needs a few operations, so they are wrapped in a functor - class selectBase_ - { - SELECTION& s; - - public: - selectBase_( SELECTION& s_ ) : s( s_ ) {} - - void operator()( BOARD_ITEM* item ) - { - s.group->Add( item ); - // Hide the original item, so it is shown only on overlay - item->ViewSetVisible( false ); - item->SetSelected(); - } - } selectBase( m_selection ); - - // Modules are treated in a special way - when they are moved, we have to - // move all the parts that make the module, not the module itself + // Modules are treated in a special way - when they are selected, we have to mark + // all the parts that make the module as selected if( aItem->Type() == PCB_MODULE_T ) { MODULE* module = static_cast( aItem ); - - // Add everything that belongs to the module (besides the module itself) - for( D_PAD* pad = module->Pads().GetFirst(); pad; pad = pad->Next() ) - selectBase( pad ); - - for( BOARD_ITEM* drawing = module->GraphicalItems().GetFirst(); drawing; - drawing = drawing->Next() ) - selectBase( drawing ); - - selectBase( &module->Reference() ); - selectBase( &module->Value() ); + module->RunOnChildren( std::bind1st( std::mem_fun( &SELECTION_TOOL::selectVisually ), this ) ); } - // Add items to the VIEW_GROUP, so they will be displayed on the overlay - selectBase( aItem ); - m_selection.items.insert( aItem ); + selectVisually( aItem ); + ITEM_PICKER picker( aItem ); + m_selection.items.PushItem( picker ); + + // It is enough to do it only for the first selected item + if( m_selection.Size() == 1 ) + { + // Set as the current item, so the information about selection is displayed + getEditFrame()->SetCurItem( aItem, true ); + } + else if( m_selection.Size() == 2 ) // Check only for 2, so it will not be + { // called for every next selected item + // If multiple items are selected, do not show the information about the selected item + getEditFrame()->SetCurItem( NULL, true ); + } } -void SELECTION_TOOL::deselectItem( BOARD_ITEM* aItem ) +void SELECTION_TOOL::deselect( BOARD_ITEM* aItem ) { - /// Deselecting an item needs a few operations, so they are wrapped in a functor - class deselectBase_ - { - SELECTION& s; - - public: - deselectBase_( SELECTION& s_ ) : s( s_ ) {} - - void operator()( BOARD_ITEM* item ) - { - s.group->Remove( item ); - // Restore original item visibility - item->ViewSetVisible( true ); - item->ClearSelected(); - } - } deselectBase( m_selection ); - - // Modules are treated in a special way - when they are moved, we have to - // move all the parts that make the module, not the module itself + // Modules are treated in a special way - when they are selected, we have to + // deselect all the parts that make the module, not the module itself if( aItem->Type() == PCB_MODULE_T ) { MODULE* module = static_cast( aItem ); - - // Add everything that belongs to the module (besides the module itself) - for( D_PAD* pad = module->Pads().GetFirst(); pad; pad = pad->Next() ) - deselectBase( pad ); - - for( BOARD_ITEM* drawing = module->GraphicalItems().GetFirst(); drawing; - drawing = drawing->Next() ) - deselectBase( drawing ); - - deselectBase( &module->Reference() ); - deselectBase( &module->Value() ); + module->RunOnChildren( std::bind1st( std::mem_fun( &SELECTION_TOOL::deselectVisually ), this ) ); } - deselectBase( aItem ); - m_selection.items.erase( aItem ); + deselectVisually( aItem ); + + int itemIdx = m_selection.items.FindItem( aItem ); + if( itemIdx >= 0 ) + m_selection.items.RemovePicker( itemIdx ); + + // If there is nothing selected, disable the context menu + if( m_selection.Empty() ) + getEditFrame()->SetCurItem( NULL ); +} + + +void SELECTION_TOOL::selectVisually( BOARD_ITEM* aItem ) const +{ + m_selection.group->Add( aItem ); + + // Hide the original item, so it is shown only on overlay + aItem->ViewSetVisible( false ); + aItem->SetSelected(); +} + + +void SELECTION_TOOL::deselectVisually( BOARD_ITEM* aItem ) const +{ + m_selection.group->Remove( aItem ); + + // Restore original item visibility + aItem->ViewSetVisible( true ); + aItem->ClearSelected(); } bool SELECTION_TOOL::containsSelected( const VECTOR2I& aPoint ) const { - const unsigned GRIP_MARGIN = 500000; + const unsigned GRIP_MARGIN = 20; + VECTOR2D margin = getView()->ToWorld( VECTOR2D( GRIP_MARGIN, GRIP_MARGIN ), false ); // Check if the point is located within any of the currently selected items bounding boxes - std::set::iterator it, it_end; - - for( it = m_selection.items.begin(), it_end = m_selection.items.end(); it != it_end; ++it ) + for( unsigned int i = 0; i < m_selection.items.GetCount(); ++i ) { - BOX2I itemBox = (*it)->ViewBBox(); - itemBox.Inflate( GRIP_MARGIN ); // Give some margin for gripping an item + BOARD_ITEM* item = static_cast( m_selection.items.GetPickedItem( i ) ); + BOX2I itemBox = item->ViewBBox(); + itemBox.Inflate( margin.x, margin.y ); // Give some margin for gripping an item if( itemBox.Contains( aPoint ) ) return true; @@ -596,3 +585,10 @@ bool SELECTION_TOOL::containsSelected( const VECTOR2I& aPoint ) const return false; } + + +void SELECTION_TOOL::SELECTION::clear() +{ + items.ClearItemsList(); + group->Clear(); +} diff --git a/pcbnew/tools/selection_tool.h b/pcbnew/tools/selection_tool.h index ee8cf45003..4c5e4b2d9a 100644 --- a/pcbnew/tools/selection_tool.h +++ b/pcbnew/tools/selection_tool.h @@ -26,11 +26,10 @@ #ifndef __SELECTION_TOOL_H #define __SELECTION_TOOL_H -#include - #include #include #include +#include class SELECTION_AREA; class BOARD_ITEM; @@ -50,7 +49,7 @@ class VIEW_GROUP; * - draw selection box (drag LMB) * - handles MODULEs properly (ie. selects either MODULE or its PADs, TEXTs, etc.) * - takes into account high-contrast & layer visibility settings - * - invokes InteractiveMove tool when user starts to drag selected items + * - invokes InteractiveEdit tool when user starts to drag selected items */ class SELECTION_TOOL : public TOOL_INTERACTIVE @@ -62,17 +61,33 @@ public: struct SELECTION { /// Set of selected items - std::set items; + PICKED_ITEMS_LIST items; /// VIEW_GROUP that holds currently selected items KIGFX::VIEW_GROUP* group; /// Checks if there is anything selected - bool Empty() const { return items.empty(); } + bool Empty() const + { + return ( items.GetCount() == 0 ); + } + + /// Returns the number of selected parts + int Size() const + { + return items.GetCount(); + } + + private: + /// Clears both the VIEW_GROUP and set of selected items. Please note that it does not + /// change properties of selected items (e.g. selection flag). + void clear(); + + friend class SELECTION_TOOL; }; /// @copydoc TOOL_INTERACTIVE::Reset() - void Reset(); + void Reset( RESET_REASON aReason ); /** * Function Main() @@ -92,7 +107,7 @@ public: } /** - * Function AddAction() + * Function AddMenuItem() * * Adds a menu entry to run a TOOL_ACTION on selected items. * @param aAction is a menu entry to be added. @@ -117,6 +132,12 @@ private: */ bool selectMultiple(); + /** + * Function ClearSelection() + * Clears the current selection. + */ + void clearSelection(); + /** * Function disambiguationMenu() * Handles the menu that allows to select one of many items in case there is more than one @@ -142,12 +163,6 @@ private: */ void toggleSelection( BOARD_ITEM* aItem ); - /** - * Function clearSelection() - * Clears selections of currently selected items. - */ - void clearSelection(); - /** * Function selectable() * Checks conditions for an item to be selected. @@ -162,7 +177,7 @@ private: * * @param aItem is an item to be selected. */ - void selectItem( BOARD_ITEM* aItem ); + void select( BOARD_ITEM* aItem ); /** * Function deselectItem() @@ -170,7 +185,21 @@ private: * * @param aItem is an item to be deselected. */ - void deselectItem( BOARD_ITEM* aItem ); + void deselect( BOARD_ITEM* aItem ); + + /** + * Function deselectVisually() + * Marks item as selected, but does not add it to the ITEMS_PICKED_LIST. + * @param aItem is an item to be be marked. + */ + void selectVisually( BOARD_ITEM* aItem ) const; + + /** + * Function deselectVisually() + * Marks item as selected, but does not add it to the ITEMS_PICKED_LIST. + * @param aItem is an item to be be marked. + */ + void deselectVisually( BOARD_ITEM* aItem ) const; /** * Function containsSelected() diff --git a/pcbnew/tr_modif.cpp b/pcbnew/tr_modif.cpp index d4aa7eb5a6..59c0f042fb 100644 --- a/pcbnew/tr_modif.cpp +++ b/pcbnew/tr_modif.cpp @@ -72,7 +72,7 @@ int PCB_EDIT_FRAME::EraseRedundantTrack( wxDC* aDC, wxPoint end; LAYER_MSK startmasklayer, endmasklayer; - int netcode = aNewTrack->GetNet(); + int netcode = aNewTrack->GetNetCode(); /* Reconstruct the complete track (the new track has to start on a segment of track). */ diff --git a/pcbnew/tracepcb.cpp b/pcbnew/tracepcb.cpp index ccd092fcca..06ffe75859 100644 --- a/pcbnew/tracepcb.cpp +++ b/pcbnew/tracepcb.cpp @@ -250,7 +250,7 @@ void BOARD::DrawHighLight( EDA_DRAW_PANEL* am_canvas, wxDC* DC, int aNetCode ) for( BOARD::ZONE_CONTAINERS::iterator zc = zones.begin(); zc!=zones.end(); ++zc ) { - if( (*zc)->GetNet() == aNetCode ) + if( (*zc)->GetNetCode() == aNetCode ) { (*zc)->Draw( am_canvas, DC, draw_mode ); } @@ -261,7 +261,7 @@ void BOARD::DrawHighLight( EDA_DRAW_PANEL* am_canvas, wxDC* DC, int aNetCode ) { for( D_PAD* pad = module->Pads(); pad; pad = pad->Next() ) { - if( pad->GetNet() == aNetCode ) + if( pad->GetNetCode() == aNetCode ) { pad->Draw( am_canvas, DC, draw_mode ); } @@ -271,7 +271,7 @@ void BOARD::DrawHighLight( EDA_DRAW_PANEL* am_canvas, wxDC* DC, int aNetCode ) // Redraw track and vias that have aNetCode for( TRACK* seg = m_Track; seg; seg = seg->Next() ) { - if( seg->GetNet() == aNetCode ) + if( seg->GetNetCode() == aNetCode ) { seg->Draw( am_canvas, DC, draw_mode ); } diff --git a/pcbnew/xchgmod.cpp b/pcbnew/xchgmod.cpp index babfc4818f..74b5a58e0c 100644 --- a/pcbnew/xchgmod.cpp +++ b/pcbnew/xchgmod.cpp @@ -455,17 +455,13 @@ void PCB_EDIT_FRAME::Exchange_Module( MODULE* aOldModule, // Update pad netnames ( when possible) for( D_PAD* pad = aNewModule->Pads(); pad != NULL; pad = pad->Next() ) { - pad->SetNetname( wxEmptyString ); - pad->SetNet( 0 ); + pad->SetNetCode( NETINFO_LIST::UNCONNECTED ); D_PAD* old_pad = aOldModule->Pads(); for( ; old_pad != NULL; old_pad = old_pad->Next() ) { if( pad->PadNameEqual( old_pad ) ) - { - pad->SetNetname( old_pad->GetNetname() ); - pad->SetNet( old_pad->GetNet() ); - } + pad->SetNetCode( old_pad->GetNetCode() ); } } diff --git a/pcbnew/zones_by_polygon.cpp b/pcbnew/zones_by_polygon.cpp index 19dcfe5f2a..838bf67bb7 100644 --- a/pcbnew/zones_by_polygon.cpp +++ b/pcbnew/zones_by_polygon.cpp @@ -130,7 +130,7 @@ void PCB_EDIT_FRAME::duplicateZone( wxDC* aDC, ZONE_CONTAINER* aZone ) s_AuxiliaryList.ClearListAndDeleteItems(); s_PickedList.ClearListAndDeleteItems(); - SaveCopyOfZones( s_PickedList, GetBoard(), newZone->GetNet(), newZone->GetLayer() ); + SaveCopyOfZones( s_PickedList, GetBoard(), newZone->GetNetCode(), newZone->GetLayer() ); GetBoard()->Add( newZone ); ITEM_PICKER picker( newZone, UR_NEW ); @@ -227,10 +227,10 @@ void PCB_EDIT_FRAME::Start_Move_Zone_Corner( wxDC* DC, ZONE_CONTAINER* aZone, } ZONE_SETTINGS zoneInfo = GetZoneSettings(); - zoneInfo.m_NetcodeSelection = aZone->GetNet(); + zoneInfo.m_NetcodeSelection = aZone->GetNetCode(); SetZoneSettings( zoneInfo ); - GetBoard()->SetHighLightNet( aZone->GetNet() ); + GetBoard()->SetHighLightNet( aZone->GetNetCode() ); if( DC ) HighLight( DC ); @@ -248,8 +248,7 @@ void PCB_EDIT_FRAME::Start_Move_Zone_Corner( wxDC* DC, ZONE_CONTAINER* aZone, s_AuxiliaryList.ClearListAndDeleteItems(); s_PickedList.ClearListAndDeleteItems(); - SaveCopyOfZones( s_PickedList, GetBoard(), aZone->GetNet(), - aZone->GetLayer() ); + SaveCopyOfZones( s_PickedList, GetBoard(), aZone->GetNetCode(), aZone->GetLayer() ); if ( IsNewCorner ) aZone->Outline()->InsertCorner(corner_id-1, cx, cy ); @@ -278,8 +277,7 @@ void PCB_EDIT_FRAME::Start_Move_Zone_Drag_Outline_Edge( wxDC* DC, s_PickedList.ClearListAndDeleteItems(); s_AuxiliaryList.ClearListAndDeleteItems(); - SaveCopyOfZones( s_PickedList, GetBoard(), aZone->GetNet(), - aZone->GetLayer() ); + SaveCopyOfZones( s_PickedList, GetBoard(), aZone->GetNetCode(), aZone->GetLayer() ); } @@ -294,17 +292,16 @@ void PCB_EDIT_FRAME::Start_Move_Zone_Outlines( wxDC* DC, ZONE_CONTAINER* aZone ) } ZONE_SETTINGS zoneInfo = GetZoneSettings(); - zoneInfo.m_NetcodeSelection = aZone->GetNet(); + zoneInfo.m_NetcodeSelection = aZone->GetNetCode(); SetZoneSettings( zoneInfo ); - GetBoard()->SetHighLightNet( aZone->GetNet() ); + GetBoard()->SetHighLightNet( aZone->GetNetCode() ); HighLight( DC ); } s_PickedList.ClearListAndDeleteItems(); s_AuxiliaryList.ClearListAndDeleteItems(); - SaveCopyOfZones( s_PickedList, GetBoard(), aZone->GetNet(), - aZone->GetLayer() ); + SaveCopyOfZones( s_PickedList, GetBoard(), aZone->GetNetCode(), aZone->GetLayer() ); aZone->SetFlags( IS_MOVED ); m_canvas->SetMouseCapture( Show_Zone_Corner_Or_Outline_While_Move_Mouse, @@ -382,7 +379,7 @@ void PCB_EDIT_FRAME::Remove_Zone_Corner( wxDC* DC, ZONE_CONTAINER* aZone ) s_AuxiliaryList.ClearListAndDeleteItems(); s_PickedList. ClearListAndDeleteItems(); - SaveCopyOfZones( s_PickedList, GetBoard(), aZone->GetNet(), aZone->GetLayer() ); + SaveCopyOfZones( s_PickedList, GetBoard(), aZone->GetNetCode(), aZone->GetLayer() ); aZone->Outline()->DeleteCorner( aZone->GetSelectedCorner() ); // modify zones outlines according to the new aZone shape @@ -549,8 +546,7 @@ int PCB_EDIT_FRAME::Begin_Zone( wxDC* DC ) { zoneInfo.m_NetcodeSelection = GetBoard()->GetHighLightNetCode(); - zone->SetNet( zoneInfo.m_NetcodeSelection ); - zone->SetNetNameFromNetCode( ); + zone->SetNetCode( zoneInfo.m_NetcodeSelection ); } double tmp = ZONE_THERMAL_RELIEF_GAP_MIL; wxGetApp().GetSettings()->Read( ZONE_THERMAL_RELIEF_GAP_STRING_KEY, &tmp ); @@ -578,8 +574,7 @@ int PCB_EDIT_FRAME::Begin_Zone( wxDC* DC ) zoneInfo.SetIsKeepout( true ); // Netcode and netname are irrelevant, // so ensure they are cleared - zone->SetNet( 0 ); - zone->SetNetName( wxEmptyString ); + zone->SetNetCode( NETINFO_LIST::UNCONNECTED ); edited = InvokeKeepoutAreaEditor( this, &zoneInfo ); } else @@ -625,7 +620,7 @@ int PCB_EDIT_FRAME::Begin_Zone( wxDC* DC ) { if( s_CurrentZone ) { - zoneInfo.m_NetcodeSelection = s_CurrentZone->GetNet(); + zoneInfo.m_NetcodeSelection = s_CurrentZone->GetNetCode(); GetBoard()->SetZoneSettings( zoneInfo ); } @@ -746,7 +741,7 @@ bool PCB_EDIT_FRAME::End_Zone( wxDC* DC ) // Save initial zones configuration, for undo/redo, before adding new zone s_AuxiliaryList.ClearListAndDeleteItems(); s_PickedList.ClearListAndDeleteItems(); - SaveCopyOfZones(s_PickedList, GetBoard(), zone->GetNet(), zone->GetLayer() ); + SaveCopyOfZones(s_PickedList, GetBoard(), zone->GetNetCode(), zone->GetLayer() ); // Put new zone in list if( !s_CurrentZone ) @@ -904,7 +899,7 @@ void PCB_EDIT_FRAME::Edit_Zone_Params( wxDC* DC, ZONE_CONTAINER* aZone ) NETINFO_ITEM* net = GetBoard()->FindNet( zoneInfo.m_NetcodeSelection ); if( net ) // net == NULL should not occur - aZone->SetNetName( net->GetNetname() ); + aZone->SetNetCode( net->GetNet() ); // Combine zones if possible GetBoard()->OnAreaPolygonModified( &s_AuxiliaryList, aZone ); diff --git a/pcbnew/zones_by_polygon_fill_functions.cpp b/pcbnew/zones_by_polygon_fill_functions.cpp index 61324cb6c7..3146786a6b 100644 --- a/pcbnew/zones_by_polygon_fill_functions.cpp +++ b/pcbnew/zones_by_polygon_fill_functions.cpp @@ -100,10 +100,10 @@ int PCB_EDIT_FRAME::Fill_Zone( ZONE_CONTAINER* aZone ) // Shows the net ZONE_SETTINGS zoneInfo = GetZoneSettings(); - zoneInfo.m_NetcodeSelection = aZone->GetNet(); + zoneInfo.m_NetcodeSelection = aZone->GetNetCode(); SetZoneSettings( zoneInfo ); - msg = aZone->GetNetName(); + msg = aZone->GetNetname(); if( msg.IsEmpty() ) msg = wxT( "No net" ); @@ -150,7 +150,7 @@ int PCB_EDIT_FRAME::Fill_All_Zones( wxWindow * aActiveWindow, bool aVerbose ) if( zoneContainer->GetIsKeepout() ) continue; - msg.Printf( FORMAT_STRING, ii+1, areaCount, GetChars( zoneContainer->GetNetName() ) ); + msg.Printf( FORMAT_STRING, ii + 1, areaCount, GetChars( zoneContainer->GetNetname() ) ); if( progressDialog ) { diff --git a/pcbnew/zones_convert_brd_items_to_polygons_with_Boost.cpp b/pcbnew/zones_convert_brd_items_to_polygons_with_Boost.cpp index eaef234893..c51da1fc1c 100644 --- a/pcbnew/zones_convert_brd_items_to_polygons_with_Boost.cpp +++ b/pcbnew/zones_convert_brd_items_to_polygons_with_Boost.cpp @@ -228,7 +228,7 @@ void ZONE_CONTAINER::AddClearanceAreasPolygonsToPolysList( BOARD* aPcb ) pad = &dummypad; } - if( pad->GetNet() != GetNet() ) + if( pad->GetNetCode() != GetNetCode() ) { item_clearance = pad->GetClearance() + margin; item_boundingbox = pad->GetBoundingBox(); @@ -249,7 +249,7 @@ void ZONE_CONTAINER::AddClearanceAreasPolygonsToPolysList( BOARD* aPcb ) int gap = zone_clearance; if( ( GetPadConnection( pad ) == PAD_NOT_IN_ZONE ) - || ( GetNet() == 0 ) || ( pad->GetShape() == PAD_TRAPEZOID ) ) + || ( GetNetCode() == 0 ) || ( pad->GetShape() == PAD_TRAPEZOID ) ) // PAD_TRAPEZOID shapes are not in zones because they are used in microwave apps // and i think it is good that shapes are not changed by thermal pads or others @@ -275,7 +275,7 @@ void ZONE_CONTAINER::AddClearanceAreasPolygonsToPolysList( BOARD* aPcb ) if( !track->IsOnLayer( GetLayer() ) ) continue; - if( track->GetNet() == GetNet() && (GetNet() != 0) ) + if( track->GetNetCode() == GetNetCode() && (GetNetCode() != 0) ) continue; item_clearance = track->GetClearance() + margin; @@ -363,7 +363,7 @@ void ZONE_CONTAINER::AddClearanceAreasPolygonsToPolysList( BOARD* aPcb ) // do not add clearance. // the zone will be connected to the current zone, but filled areas // will use different parameters (clearance, thermal shapes ) - bool addclearance = GetNet() != zone->GetNet(); + bool addclearance = GetNetCode() != zone->GetNetCode(); int clearance = zone_clearance; if( zone->GetIsKeepout() ) @@ -394,7 +394,7 @@ void ZONE_CONTAINER::AddClearanceAreasPolygonsToPolysList( BOARD* aPcb ) if( !pad->IsOnLayer( GetLayer() ) ) continue; - if( pad->GetNet() != GetNet() ) + if( pad->GetNetCode() != GetNetCode() ) continue; item_boundingbox = pad->GetBoundingBox(); int thermalGap = GetThermalReliefGap( pad ); @@ -428,7 +428,7 @@ void ZONE_CONTAINER::AddClearanceAreasPolygonsToPolysList( BOARD* aPcb ) CopyPolygonsFromKiPolygonListToFilledPolysList( polyset_zone_solid_areas ); // Remove insulated islands: - if( GetNet() > 0 ) + if( GetNetCode() > 0 ) TestForCopperIslandAndRemoveInsulatedIslands( aPcb ); // Now we remove all unused thermal stubs. @@ -436,7 +436,7 @@ void ZONE_CONTAINER::AddClearanceAreasPolygonsToPolysList( BOARD* aPcb ) // Test thermal stubs connections and add polygons to remove unconnected stubs. // (this is a refinement for thermal relief shapes) - if( GetNet() > 0 ) + if( GetNetCode() > 0 ) BuildUnconnectedThermalStubsPolygonList( cornerBufferPolysToSubstract, aPcb, this, s_Correction, s_thermalRot ); @@ -453,7 +453,7 @@ void ZONE_CONTAINER::AddClearanceAreasPolygonsToPolysList( BOARD* aPcb ) m_FilledPolysList.RemoveAllContours(); CopyPolygonsFromKiPolygonListToFilledPolysList( polyset_zone_solid_areas ); - if( GetNet() > 0 ) + if( GetNetCode() > 0 ) TestForCopperIslandAndRemoveInsulatedIslands( aPcb ); } diff --git a/pcbnew/zones_convert_to_polygons_aux_functions.cpp b/pcbnew/zones_convert_to_polygons_aux_functions.cpp index f570ebdd4b..16549b2ed4 100644 --- a/pcbnew/zones_convert_to_polygons_aux_functions.cpp +++ b/pcbnew/zones_convert_to_polygons_aux_functions.cpp @@ -162,7 +162,7 @@ void BuildUnconnectedThermalStubsPolygonList( CPOLYGONS_LIST& aCornerBuffer, if( !pad->IsOnLayer( aZone->GetLayer() ) ) continue; - if( pad->GetNet() != aZone->GetNet() ) + if( pad->GetNetCode() != aZone->GetNetCode() ) continue; // Calculate thermal bridge half width diff --git a/pcbnew/zones_functions_for_undo_redo.cpp b/pcbnew/zones_functions_for_undo_redo.cpp index 52166bc5db..5710937208 100644 --- a/pcbnew/zones_functions_for_undo_redo.cpp +++ b/pcbnew/zones_functions_for_undo_redo.cpp @@ -67,7 +67,7 @@ bool ZONE_CONTAINER::IsSame( const ZONE_CONTAINER& aZoneToCompare ) if( GetLayer() != aZoneToCompare.GetLayer() ) return false; - if( m_Netname != aZoneToCompare.m_Netname ) + if( GetNetCode() != aZoneToCompare.GetNetCode() ) return false; if( GetPriority() != aZoneToCompare.GetPriority() ) @@ -146,7 +146,7 @@ int SaveCopyOfZones( PICKED_ITEMS_LIST& aPickList, BOARD* aPcb, int aNetCode, LA if( zone == NULL ) // End of list break; - if( aNetCode >= 0 && aNetCode != zone->GetNet() ) + if( aNetCode >= 0 && aNetCode != zone->GetNetCode() ) continue; if( aLayer >= 0 && aLayer != zone->GetLayer() ) diff --git a/pcbnew/zones_polygons_insulated_copper_islands.cpp b/pcbnew/zones_polygons_insulated_copper_islands.cpp index c2154ae5dc..5e72a64497 100644 --- a/pcbnew/zones_polygons_insulated_copper_islands.cpp +++ b/pcbnew/zones_polygons_insulated_copper_islands.cpp @@ -54,7 +54,7 @@ void ZONE_CONTAINER::TestForCopperIslandAndRemoveInsulatedIslands( BOARD* aPcb ) if( !pad->IsOnLayer( GetLayer() ) ) continue; - if( pad->GetNet() != GetNet() ) + if( pad->GetNetCode() != GetNetCode() ) continue; listPointsCandidates.push_back( pad->GetPosition() ); @@ -66,7 +66,7 @@ void ZONE_CONTAINER::TestForCopperIslandAndRemoveInsulatedIslands( BOARD* aPcb ) if( !track->IsOnLayer( GetLayer() ) ) continue; - if( track->GetNet() != GetNet() ) + if( track->GetNetCode() != GetNetCode() ) continue; listPointsCandidates.push_back( track->GetStart() ); diff --git a/pcbnew/zones_polygons_test_connections.cpp b/pcbnew/zones_polygons_test_connections.cpp index ccc91634e2..fd277f2a63 100644 --- a/pcbnew/zones_polygons_test_connections.cpp +++ b/pcbnew/zones_polygons_test_connections.cpp @@ -50,11 +50,11 @@ void Merge_SubNets_Connected_By_CopperAreas( BOARD* aPcb, int aNetcode ); // zone size = size of the m_FilledPolysList buffer bool sort_areas( const ZONE_CONTAINER* ref, const ZONE_CONTAINER* tst ) { - if( ref->GetNet() == tst->GetNet() ) + if( ref->GetNetCode() == tst->GetNetCode() ) return ref->GetFilledPolysList().GetCornersCount() < tst->GetFilledPolysList().GetCornersCount(); else - return ref->GetNet() < tst->GetNet(); + return ref->GetNetCode() < tst->GetNetCode(); } /** @@ -72,14 +72,14 @@ void BOARD::Test_Connections_To_Copper_Areas( int aNetcode ) for( MODULE* module = m_Modules; module; module = module->Next() ) { for( D_PAD* pad = module->Pads(); pad != NULL; pad = pad->Next() ) - if( (aNetcode < 0) || ( aNetcode == pad->GetNet() ) ) + if( (aNetcode < 0) || ( aNetcode == pad->GetNetCode() ) ) pad->SetZoneSubNet( 0 ); } // clear .m_ZoneSubnet parameter for tracks and vias for( TRACK* track = m_Track; track; track = track->Next() ) { - if( (aNetcode < 0) || ( aNetcode == track->GetNet() ) ) + if( (aNetcode < 0) || ( aNetcode == track->GetNetCode() ) ) track->SetZoneSubNet( 0 ); } @@ -93,7 +93,7 @@ void BOARD::Test_Connections_To_Copper_Areas( int aNetcode ) ZONE_CONTAINER* curr_zone = GetArea( index ); if( !curr_zone->IsOnCopperLayer() ) continue; - if( (aNetcode >= 0) && ( aNetcode != curr_zone->GetNet() ) ) + if( (aNetcode >= 0) && ( aNetcode != curr_zone->GetNetCode() ) ) continue; if( curr_zone->GetFilledPolysList().GetCornersCount() == 0 ) continue; @@ -112,7 +112,7 @@ void BOARD::Test_Connections_To_Copper_Areas( int aNetcode ) { ZONE_CONTAINER* curr_zone = zones_candidates[idx]; - int netcode = curr_zone->GetNet(); + int netcode = curr_zone->GetNetCode(); // Build a list of candidates connected to the net: // At this point, layers are not considered, because areas on different layers can @@ -136,7 +136,7 @@ void BOARD::Test_Connections_To_Copper_Areas( int aNetcode ) TRACK* track = m_Track.GetFirst()->GetStartNetCode( netcode ); for( ; track; track = track->Next() ) { - if( track->GetNet() != netcode ) + if( track->GetNetCode() != netcode ) break; candidates.push_back( track ); } @@ -255,10 +255,10 @@ void Merge_SubNets_Connected_By_CopperAreas( BOARD* aPcb ) if ( ! curr_zone->IsOnCopperLayer() ) continue; - if ( curr_zone->GetNet() <= 0 ) + if ( curr_zone->GetNetCode() <= 0 ) continue; - Merge_SubNets_Connected_By_CopperAreas( aPcb, curr_zone->GetNet() ); + Merge_SubNets_Connected_By_CopperAreas( aPcb, curr_zone->GetNetCode() ); } } @@ -284,7 +284,7 @@ void Merge_SubNets_Connected_By_CopperAreas( BOARD* aPcb, int aNetcode ) { ZONE_CONTAINER* curr_zone = aPcb->GetArea( index ); - if( aNetcode == curr_zone->GetNet() ) + if( aNetcode == curr_zone->GetNetCode() ) { found = true; break; @@ -311,7 +311,7 @@ void Merge_SubNets_Connected_By_CopperAreas( BOARD* aPcb, int aNetcode ) track = aPcb->m_Track.GetFirst()->GetStartNetCode( aNetcode ); for( ; track; track = track->Next() ) { - if( track->GetNet() != aNetcode ) + if( track->GetNetCode() != aNetcode ) break; Candidates.push_back( track ); } diff --git a/pcbnew/zones_test_and_combine_areas.cpp b/pcbnew/zones_test_and_combine_areas.cpp index 362d469daa..b35c1be122 100644 --- a/pcbnew/zones_test_and_combine_areas.cpp +++ b/pcbnew/zones_test_and_combine_areas.cpp @@ -59,7 +59,7 @@ bool BOARD::OnAreaPolygonModified( PICKED_ITEMS_LIST* aModifiedZonesList, if( bCheckAllAreas ) { modified = true; - CombineAllAreasInNet( aModifiedZonesList, modified_area->GetNet(), true ); + CombineAllAreasInNet( aModifiedZonesList, modified_area->GetNetCode(), true ); } if( !IsCopperLayer( layer ) ) // Refill non copper zones on this layer @@ -98,7 +98,7 @@ bool BOARD::CombineAllAreasInNet( PICKED_ITEMS_LIST* aDeletedList, int aNetCode, { ZONE_CONTAINER* curr_area = m_ZoneDescriptorList[ia1]; - if( curr_area->GetNet() != aNetCode ) + if( curr_area->GetNetCode() != aNetCode ) continue; // legal polygon @@ -109,7 +109,7 @@ bool BOARD::CombineAllAreasInNet( PICKED_ITEMS_LIST* aDeletedList, int aNetCode, { ZONE_CONTAINER* area2 = m_ZoneDescriptorList[ia2]; - if( area2->GetNet() != aNetCode ) + if( area2->GetNetCode() != aNetCode ) continue; if( curr_area->GetPriority() != area2->GetPriority() ) @@ -158,7 +158,7 @@ bool BOARD::TestAreaIntersections( ZONE_CONTAINER* area_to_test ) { ZONE_CONTAINER* area2 = m_ZoneDescriptorList[ia2]; - if( area_to_test->GetNet() != area2->GetNet() ) + if( area_to_test->GetNetCode() != area2->GetNetCode() ) continue; if( area_to_test == area2 ) @@ -390,7 +390,7 @@ int BOARD::Test_Drc_Areas_Outlines_To_Areas_Outlines( ZONE_CONTAINER* aArea_To_E continue; // Test for same net - if( Area_Ref->GetNet() == area_to_test->GetNet() && Area_Ref->GetNet() >= 0 ) + if( Area_Ref->GetNetCode() == area_to_test->GetNetCode() && Area_Ref->GetNetCode() >= 0 ) continue; // test for different priorities @@ -586,7 +586,7 @@ bool DRC::doEdgeZoneDrc( ZONE_CONTAINER* aArea, int aCornerIndex ) continue; // Test for same net - if( ( aArea->GetNet() == area_to_test->GetNet() ) && (aArea->GetNet() >= 0) ) + if( ( aArea->GetNetCode() == area_to_test->GetNetCode() ) && (aArea->GetNetCode() >= 0) ) continue; // test for same priority