Merged the lp:~cern-kicad/kicad/selection_tool branch.
This commit is contained in:
commit
5c9e7d9b9b
|
@ -144,6 +144,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" )
|
||||
|
||||
|
|
|
@ -214,6 +214,7 @@ set( PCB_COMMON_SRCS
|
|||
../pcbnew/class_zone.cpp
|
||||
../pcbnew/class_zone_settings.cpp
|
||||
../pcbnew/classpcb.cpp
|
||||
../pcbnew/ratsnest_data.cpp
|
||||
../pcbnew/collectors.cpp
|
||||
../pcbnew/netlist_reader.cpp
|
||||
../pcbnew/legacy_netlist_reader.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();
|
||||
|
|
|
@ -81,10 +81,13 @@ EDA_DRAW_PANEL_GAL::EDA_DRAW_PANEL_GAL( wxWindow* aParentWindow, wxWindowID aWin
|
|||
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 );
|
||||
|
|
|
@ -60,10 +60,13 @@ CAIRO_GAL::CAIRO_GAL( wxWindow* aParent, wxEvtHandler* aMouseListener,
|
|||
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 ) );
|
||||
#endif
|
||||
|
|
|
@ -34,11 +34,11 @@
|
|||
#include <typeinfo>
|
||||
#include <wx/msgdlg.h>
|
||||
#include <confirm.h>
|
||||
#ifdef __WXDEBUG__
|
||||
#ifdef PROFILE
|
||||
#include <profile.h>
|
||||
#include <wx/debug.h>
|
||||
#include <wx/log.h>
|
||||
#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 */
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -73,10 +73,13 @@ OPENGL_GAL::OPENGL_GAL( wxWindow* aParent, wxEvtHandler* aMouseListener,
|
|||
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 ) );
|
||||
#endif
|
||||
|
|
|
@ -51,8 +51,6 @@ using namespace hed;
|
|||
using namespace std;
|
||||
|
||||
|
||||
Triangulation* TTLtraits::triang_ = NULL;
|
||||
|
||||
#ifdef TTL_USE_NODE_ID
|
||||
int Node::id_count = 0;
|
||||
#endif
|
||||
|
@ -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<TTLtraits>(d_iter, *it);
|
||||
helper->insertNode<TTLtraits>(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<TTLtraits>(dc);
|
||||
helper->removeRectangularBoundary<TTLtraits>(dc);
|
||||
}
|
||||
|
||||
|
||||
|
@ -206,8 +223,8 @@ 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();
|
||||
EdgePtr e2(e1->getNextEdgeInFace());
|
||||
EdgePtr e3(e2->getNextEdgeInFace());
|
||||
|
||||
if (e1->getTwinEdge())
|
||||
e1->getTwinEdge()->setTwinEdge(EdgePtr());
|
||||
|
@ -223,15 +240,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 +256,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)
|
||||
|
@ -269,7 +286,7 @@ cout << "Iterate boundary 2" << endl;
|
|||
|
||||
Dart dart_iter = dart;
|
||||
do {
|
||||
if (ttl::isBoundaryEdge(dart_iter))
|
||||
if (helper->isBoundaryEdge(dart_iter))
|
||||
dart_iter.alpha0().alpha1();
|
||||
else
|
||||
dart_iter.alpha2().alpha1();
|
||||
|
@ -305,14 +322,11 @@ bool Triangulation::removeLeadingEdgeFromList(EdgePtr& leadingEdge) {
|
|||
edge->setAsLeadingEdge(false);
|
||||
it = leadingEdges_.erase(it);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (it == leadingEdges_.end())
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
@ -322,6 +336,31 @@ void Triangulation::cleanAll() {
|
|||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void Triangulation::swapEdge(Dart& dart) {
|
||||
if (!dart.getEdge()->isConstrained()) swapEdge(dart.getEdge());
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void Triangulation::splitTriangle(Dart& dart, 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());
|
||||
}
|
||||
|
||||
|
||||
#ifdef TTL_USE_NODE_FLAG
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
// This is a "template" for accessing all nodes (but multiple tests)
|
||||
|
@ -409,14 +448,14 @@ 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);
|
||||
|
@ -447,7 +486,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,19 +496,15 @@ 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);
|
||||
|
||||
addLeadingEdge(e1_n);
|
||||
addLeadingEdge(e2_n);
|
||||
addLeadingEdge(e3_n);
|
||||
|
@ -486,20 +520,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 +547,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 +597,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<TTLtraits>(dart)) {
|
||||
if (helper->swapTestDelaunay<TTLtraits>(dart)) {
|
||||
noNotDelaunay++;
|
||||
|
||||
//printEdge(dart,os); os << "\n";
|
||||
|
@ -610,7 +640,7 @@ void Triangulation::optimizeDelaunay() {
|
|||
|
||||
Dart dart(edge);
|
||||
// Constrained edges should not be swapped
|
||||
if (!edge->isConstrained() && ttl::swapTestDelaunay<TTLtraits>(dart, cycling_check)) {
|
||||
if (!edge->isConstrained() && helper->swapTestDelaunay<TTLtraits>(dart, cycling_check)) {
|
||||
optimal = false;
|
||||
swapEdge(edge);
|
||||
}
|
||||
|
@ -632,7 +662,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 +673,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();
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -29,7 +29,7 @@
|
|||
#include <cassert>
|
||||
|
||||
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 )
|
||||
{
|
||||
|
|
|
@ -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<wxMouseEvent>( static_cast<wxMouseEvent*>( &aEvent ) );
|
||||
int args = st->button | mods;
|
||||
|
@ -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,17 +216,18 @@ 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 )
|
||||
{
|
||||
wxMouseEvent* me = static_cast<wxMouseEvent*>( &aEvent );
|
||||
int mods = decodeModifiers<wxMouseEvent>( me );
|
||||
|
||||
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;
|
||||
|
@ -270,11 +283,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
|
||||
|
|
|
@ -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, "" }
|
||||
};
|
||||
|
|
|
@ -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,11 +138,10 @@ void TOOL_MANAGER::RegisterTool( TOOL_BASE* aTool )
|
|||
|
||||
aTool->m_toolMgr = this;
|
||||
|
||||
if( aTool->GetType() == INTERACTIVE )
|
||||
if( !aTool->Init() )
|
||||
{
|
||||
if( !static_cast<TOOL_INTERACTIVE*>( 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() ) );
|
||||
|
||||
|
@ -150,7 +153,6 @@ void TOOL_MANAGER::RegisterTool( TOOL_BASE* 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<TOOL_INTERACTIVE*>( 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<TOOL_ID>::iterator it, it_end;
|
||||
std::deque<TOOL_ID>::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<CONTEXT_MENU> menu( new CONTEXT_MENU( *st->contextMenu ) );
|
||||
GetEditFrame()->PopupMenu( menu->GetMenu() );
|
||||
|
||||
//
|
||||
// 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,6 +474,7 @@ bool TOOL_MANAGER::ProcessEvent( TOOL_EVENT& aEvent )
|
|||
if( m_view->IsDirty() )
|
||||
{
|
||||
PCB_EDIT_FRAME* f = static_cast<PCB_EDIT_FRAME*>( GetEditFrame() );
|
||||
if( f->IsGalCanvasActive() )
|
||||
f->GetGalCanvas()->Refresh(); // fixme: ugly hack, provide a method in TOOL_DISPATCHER.
|
||||
}
|
||||
|
||||
|
@ -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_INTERACTIVE*>( 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();
|
||||
}
|
||||
|
|
|
@ -34,9 +34,9 @@
|
|||
#include <gal/graphics_abstraction_layer.h>
|
||||
#include <painter.h>
|
||||
|
||||
#ifdef __WXDEBUG__
|
||||
#ifdef PROFILE
|
||||
#include <profile.h>
|
||||
#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 */
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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 );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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 ) )
|
||||
{
|
||||
|
|
|
@ -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 )
|
||||
{
|
||||
|
|
|
@ -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 ) )
|
||||
{
|
||||
|
|
|
@ -82,8 +82,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 )
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -93,6 +92,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.
|
||||
*/
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
{
|
||||
|
|
|
@ -98,6 +98,24 @@ struct fnv_1a
|
|||
};
|
||||
|
||||
|
||||
/// Hash function for wxString, counterpart of std::string hash
|
||||
struct WXSTRING_HASH : std::unary_function<wxString, std::size_t>
|
||||
{
|
||||
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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -56,37 +56,44 @@ 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_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 );
|
||||
|
@ -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;
|
||||
|
|
|
@ -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()
|
||||
*
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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.<br>
|
||||
*
|
||||
* \note
|
||||
* This function is also present in the TTL as ttl::swapTestDelaunay.<br>
|
||||
* Thus, the function can be implemented simply as:
|
||||
* \code
|
||||
* { return ttl::swapTestDelaunay<TTLtraits>(dart); }
|
||||
* \endcode
|
||||
*/
|
||||
//static bool swapTestDelaunay(const Dart& dart) {
|
||||
// return ttl::swapTestDelaunay<TTLtraits>(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<TTLtraits>(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.
|
||||
*
|
||||
* <center>
|
||||
* \image html swapEdge.gif
|
||||
* </center>
|
||||
*
|
||||
* \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.
|
||||
*
|
||||
* <center>
|
||||
* \image html splitTriangle.gif
|
||||
* </center>
|
||||
*
|
||||
* \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.
|
||||
*
|
||||
* <center>
|
||||
* \image html reverse_splitTriangle.gif
|
||||
* </center>
|
||||
*/
|
||||
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
|
||||
|
|
|
@ -51,10 +51,13 @@
|
|||
#include <vector>
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <ttl/ttl.h>
|
||||
#include <ttl/ttl_util.h>
|
||||
#include <boost/shared_ptr.hpp>
|
||||
|
||||
namespace ttl {
|
||||
class TriangulationHelper;
|
||||
};
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
// The half-edge data structure
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
|
@ -242,26 +245,75 @@ public:
|
|||
class Triangulation {
|
||||
|
||||
protected:
|
||||
list<EdgePtr> leadingEdges_; // one half-edge for each arc
|
||||
std::list<EdgePtr> 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.
|
||||
*
|
||||
* <center>
|
||||
* \image html swapEdge.gif
|
||||
* </center>
|
||||
*
|
||||
* \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.
|
||||
*
|
||||
* <center>
|
||||
* \image html splitTriangle.gif
|
||||
* </center>
|
||||
*
|
||||
* \param dart
|
||||
* Output: A CCW dart incident with the new node; see the figure.
|
||||
*/
|
||||
void splitTriangle(Dart& dart, 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.
|
||||
*
|
||||
* <center>
|
||||
* \image html reverse_splitTriangle.gif
|
||||
* </center>
|
||||
*/
|
||||
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,
|
||||
|
@ -295,20 +347,20 @@ public:
|
|||
Dart createDart();
|
||||
|
||||
/// Returns a list of "triangles" (one leading half-edge for each triangle)
|
||||
const list<EdgePtr>& getLeadingEdges() const { return leadingEdges_; }
|
||||
const std::list<EdgePtr>& getLeadingEdges() const { return leadingEdges_; }
|
||||
|
||||
/// Returns the number of triangles
|
||||
int noTriangles() const { return (int)leadingEdges_.size(); }
|
||||
|
||||
/// Returns a list of half-edges (one half-edge for each arc)
|
||||
list<EdgePtr>* getEdges(bool skip_boundary_edges = false) const;
|
||||
std::list<EdgePtr>* 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<NodePtr>* getNodes() const;
|
||||
std::list<NodePtr>* getNodes() const;
|
||||
#endif
|
||||
|
||||
/// Swaps edges until the triangulation is Delaunay (constrained edges are not swapped)
|
||||
|
@ -320,12 +372,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
|
||||
|
||||
|
||||
|
|
|
@ -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,14 +113,14 @@
|
|||
|
||||
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
|
||||
// ----------------------
|
||||
|
@ -145,55 +143,55 @@ namespace ttl {
|
|||
// Topological and Geometric Queries
|
||||
// ---------------------------------
|
||||
template<class TraitsType, class PointType, class DartType>
|
||||
bool locateFaceSimplest(const PointType& point, DartType& dart);
|
||||
static bool locateFaceSimplest(const PointType& point, DartType& dart);
|
||||
|
||||
template<class TraitsType, class PointType, class DartType>
|
||||
bool locateTriangle(const PointType& point, DartType& dart);
|
||||
static bool locateTriangle(const PointType& point, DartType& dart);
|
||||
|
||||
template<class TraitsType, class PointType, class DartType>
|
||||
bool inTriangleSimplest(const PointType& point, const DartType& dart);
|
||||
static bool inTriangleSimplest(const PointType& point, const DartType& dart);
|
||||
|
||||
template<class TraitsType, class PointType, class DartType>
|
||||
bool inTriangle(const PointType& point, const DartType& dart);
|
||||
static bool inTriangle(const PointType& point, const DartType& dart);
|
||||
|
||||
template<class DartType, class DartListType>
|
||||
void getBoundary(const DartType& dart, DartListType& boundary);
|
||||
static void getBoundary(const DartType& dart, DartListType& boundary);
|
||||
|
||||
template<class DartType>
|
||||
bool isBoundaryEdge(const DartType& dart);
|
||||
static bool isBoundaryEdge(const DartType& dart);
|
||||
|
||||
template<class DartType>
|
||||
bool isBoundaryFace(const DartType& dart);
|
||||
static bool isBoundaryFace(const DartType& dart);
|
||||
|
||||
template<class DartType>
|
||||
bool isBoundaryNode(const DartType& dart);
|
||||
static bool isBoundaryNode(const DartType& dart);
|
||||
|
||||
template<class DartType>
|
||||
int getDegreeOfNode(const DartType& dart);
|
||||
static int getDegreeOfNode(const DartType& dart);
|
||||
|
||||
template<class DartType, class DartListType>
|
||||
void get_0_orbit_interior(const DartType& dart, DartListType& orbit);
|
||||
static void get_0_orbit_interior(const DartType& dart, DartListType& orbit);
|
||||
|
||||
template<class DartType, class DartListType>
|
||||
void get_0_orbit_boundary(const DartType& dart, DartListType& orbit);
|
||||
static void get_0_orbit_boundary(const DartType& dart, DartListType& orbit);
|
||||
|
||||
template<class DartType>
|
||||
bool same_0_orbit(const DartType& d1, const DartType& d2);
|
||||
static bool same_0_orbit(const DartType& d1, const DartType& d2);
|
||||
|
||||
template<class DartType>
|
||||
bool same_1_orbit(const DartType& d1, const DartType& d2);
|
||||
static bool same_1_orbit(const DartType& d1, const DartType& d2);
|
||||
|
||||
template<class DartType>
|
||||
bool same_2_orbit(const DartType& d1, const DartType& d2);
|
||||
static bool same_2_orbit(const DartType& d1, const DartType& d2);
|
||||
|
||||
template <class TraitsType, class DartType>
|
||||
bool swappableEdge(const DartType& dart, bool allowDegeneracy = false);
|
||||
static bool swappableEdge(const DartType& dart, bool allowDegeneracy = false);
|
||||
|
||||
template<class DartType>
|
||||
void positionAtNextBoundaryEdge(DartType& dart);
|
||||
static void positionAtNextBoundaryEdge(DartType& dart);
|
||||
|
||||
template<class TraitsType, class DartType>
|
||||
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<class TraitsType, class DartType>
|
||||
bool swapTestDelaunay(const DartType& dart, bool cycling_check = false);
|
||||
bool swapTestDelaunay(const DartType& dart, bool cycling_check = false) const;
|
||||
|
||||
template<class TraitsType, class DartType>
|
||||
void recSwapDelaunay(DartType& diagonal);
|
||||
|
@ -223,9 +221,29 @@ namespace ttl {
|
|||
// Constrained Triangulation
|
||||
// -------------------------
|
||||
template<class TraitsType, class DartType>
|
||||
DartType insertConstraint(DartType& dstart, DartType& dend, bool optimize_delaunay);
|
||||
static DartType insertConstraint(DartType& dstart, DartType& dend, bool optimize_delaunay);
|
||||
|
||||
#endif
|
||||
private:
|
||||
hed::Triangulation& triangulation;
|
||||
|
||||
template <class TraitsType, class ForwardIterator, class DartType>
|
||||
void insertNodes(ForwardIterator first, ForwardIterator last, DartType& dart);
|
||||
|
||||
template <class TopologyElementType, class DartType>
|
||||
static bool isMemberOfFace(const TopologyElementType& topologyElement, const DartType& dart);
|
||||
|
||||
template <class TraitsType, class NodeType, class DartType>
|
||||
static bool locateFaceWithNode(const NodeType& node, DartType& dart_iter);
|
||||
|
||||
template <class DartType>
|
||||
static void getAdjacentTriangles(const DartType& dart, DartType& t1, DartType& t2, DartType& t3);
|
||||
|
||||
template <class DartType>
|
||||
static void getNeighborNodes(const DartType& dart, std::list<DartType>& node_list, bool& boundary);
|
||||
|
||||
template <class TraitsType, class DartType>
|
||||
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 <class TraitsType, class DartType, class PointType>
|
||||
bool insertNode(DartType& dart, PointType& point) {
|
||||
bool TriangulationHelper::insertNode(DartType& dart, PointType& point) {
|
||||
|
||||
bool found = ttl::locateTriangle<TraitsType>(point, dart);
|
||||
bool found = locateTriangle<TraitsType>(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<TraitsType>(d1);
|
||||
}
|
||||
|
||||
//if (!TraitsType::fixedEdge(d2) && !ttl::isBoundaryEdge(d2)) {
|
||||
if (!ttl::isBoundaryEdge(d2)) {
|
||||
//if (!TraitsType::fixedEdge(d2) && !isBoundaryEdge(d2)) {
|
||||
if (!isBoundaryEdge(d2)) {
|
||||
d2.alpha2();
|
||||
recSwapDelaunay<TraitsType>(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<TraitsType>(d3);
|
||||
}
|
||||
|
@ -332,7 +350,7 @@ namespace ttl {
|
|||
//------------------------------------------------------------------------------------------------
|
||||
// Private/Hidden function (might change later)
|
||||
template <class TraitsType, class ForwardIterator, class DartType>
|
||||
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 <class TraitsType, class DartType>
|
||||
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<TraitsType>(d_iter);
|
||||
positionAtNextBoundaryEdge(d_next);
|
||||
removeBoundaryNode<TraitsType>(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 <class TraitsType, class DartType>
|
||||
void removeNode(DartType& dart) {
|
||||
void TriangulationHelper::removeNode(DartType& dart) {
|
||||
|
||||
if (ttl::isBoundaryNode(dart))
|
||||
ttl::removeBoundaryNode<TraitsType>(dart);
|
||||
if (isBoundaryNode(dart))
|
||||
removeBoundaryNode<TraitsType>(dart);
|
||||
else
|
||||
ttl::removeInteriorNode<TraitsType>(dart);
|
||||
removeInteriorNode<TraitsType>(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 <class TraitsType, class DartType>
|
||||
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<DartType> swapped_edges;
|
||||
ttl::swapEdgesAwayFromBoundaryNode<TraitsType>(dart, swapped_edges);
|
||||
std::list<DartType> swapped_edges;
|
||||
swapEdgesAwayFromBoundaryNode<TraitsType>(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<DartType>::iterator it;
|
||||
typename std::list<DartType>::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<DartType> DartListType;
|
||||
ttl::optimizeDelaunay<TraitsType, DartType, DartListType>(swapped_edges);
|
||||
typedef std::list<DartType> DartListType;
|
||||
optimizeDelaunay<TraitsType, DartType, DartListType>(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 <class TraitsType, class DartType>
|
||||
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<DartType> swapped_edges;
|
||||
ttl::swapEdgesAwayFromInteriorNode<TraitsType>(dart, swapped_edges);
|
||||
std::list<DartType> swapped_edges;
|
||||
swapEdgesAwayFromInteriorNode<TraitsType>(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<TraitsType, DartType>(swapped_edges);
|
||||
optimizeDelaunay<TraitsType, DartType>(swapped_edges);
|
||||
}
|
||||
|
||||
//@} // End of Delaunay Triangulation Group
|
||||
|
@ -527,7 +545,7 @@ namespace ttl {
|
|||
//------------------------------------------------------------------------------------------------
|
||||
// Private/Hidden function (might change later)
|
||||
template <class TopologyElementType, class DartType>
|
||||
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 <class TraitsType, class NodeType, class DartType>
|
||||
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 <class TraitsType, class PointType, class DartType>
|
||||
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 <class TraitsType, class PointType, class DartType>
|
||||
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 <class TraitsType, class PointType, class DartType>
|
||||
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 <class TraitsType, class PointType, class DartType>
|
||||
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 <class DartType>
|
||||
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 <class DartType, class DartListType>
|
||||
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 <class DartType>
|
||||
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 <class DartType>
|
||||
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 <class DartType>
|
||||
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 <class DartType>
|
||||
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 <class DartType>
|
||||
void getNeighborNodes(const DartType& dart, std::list<DartType>& node_list, bool& boundary) {
|
||||
void TriangulationHelper::getNeighborNodes(const DartType& dart,
|
||||
std::list<DartType>& 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 <class DartType, class DartListType>
|
||||
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 <class DartType, class DartListType>
|
||||
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 <class DartType>
|
||||
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 <class DartType>
|
||||
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 <class DartType>
|
||||
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 <class TraitsType, class DartType>
|
||||
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 <class TraitsType, class DartType>
|
||||
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 <class DartType>
|
||||
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 <class TraitsType, class DartType>
|
||||
bool convexBoundary(const DartType& dart) {
|
||||
bool TriangulationHelper::convexBoundary(const DartType& dart) {
|
||||
|
||||
list<DartType> blist;
|
||||
ttl::getBoundary(dart, blist);
|
||||
std::list<DartType> blist;
|
||||
getBoundary(dart, blist);
|
||||
|
||||
int no;
|
||||
no = (int)blist.size();
|
||||
typename list<DartType>::const_iterator bit = blist.begin();
|
||||
typename std::list<DartType>::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 <class TraitsType, class DartType, class DartListType>
|
||||
void optimizeDelaunay(DartListType& elist) {
|
||||
void TriangulationHelper::optimizeDelaunay(DartListType& elist) {
|
||||
optimizeDelaunay<TraitsType, DartType, DartListType>(elist, elist.end());
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------------------------
|
||||
template <class TraitsType, class DartType, class DartListType>
|
||||
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<TraitsType>(*it, cycling_check)) {
|
||||
if (swapTestDelaunay<TraitsType>(*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<TraitsType, DartType>(it, elist);
|
||||
swapEdgeInList<TraitsType, DartType>(it, elist);
|
||||
|
||||
optimal = false;
|
||||
} // end if should swap
|
||||
|
@ -1513,9 +1532,9 @@ namespace ttl {
|
|||
*/
|
||||
template <class TraitsType, class DartType>
|
||||
#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 <class TraitsType, class DartType>
|
||||
void recSwapDelaunay(DartType& diagonal) {
|
||||
void TriangulationHelper::recSwapDelaunay(DartType& diagonal) {
|
||||
|
||||
if (!ttl::swapTestDelaunay<TraitsType>(diagonal))
|
||||
// ??? ttl::swapTestDelaunay also checks if boundary, so this can be optimized
|
||||
if (!swapTestDelaunay<TraitsType>(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<TraitsType>(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 <class TraitsType, class DartType, class ListType>
|
||||
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<TraitsType>(d_iter, allowDegeneracy)) {
|
||||
TraitsType::swapEdge(d_iter); // swap the edge away
|
||||
if (swappableEdge<TraitsType>(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 <class TraitsType, class DartType, class ListType>
|
||||
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<TraitsType>(d_iter, allowDegeneracy)) {
|
||||
TraitsType::swapEdge(d_iter);
|
||||
if (swappableEdge<TraitsType>(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 <class TraitsType, class DartType, class DartListType>
|
||||
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;
|
||||
|
||||
|
|
|
@ -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
|
||||
* <EFBFBD>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 <class DartType>
|
||||
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 <class TraitsType, class DartType>
|
||||
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 <class TraitsType, class DartType>
|
||||
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 <class TraitsType, class DartType, class ListType>
|
||||
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<TraitsType>(dstart, dend);
|
||||
DartType my_end = getAtSmallestAngle<TraitsType>(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 <class TraitsType, class DartType>
|
||||
void transformToConstraint(DartType& dstart, DartType& dend, std::list<DartType>& elist) {
|
||||
void transformToConstraint(ttl::TriangulationHelper helper, DartType& dstart, DartType& dend,
|
||||
std::list<DartType>& elist) const {
|
||||
|
||||
typename list<DartType>::iterator it, used;
|
||||
typename std::list<DartType>::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<TraitsType, DartType>(*it, true)) {
|
||||
if (ttl::TriangulationHelper::swappableEdge<TraitsType, DartType>(*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<TraitsType, DartType>(it,elist);
|
||||
helper.swapEdgeInList<TraitsType, DartType>(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 <class TraitsType, class DartType>
|
||||
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<DartType> elist;
|
||||
DartType next_start = ttl_constr::findCrossingEdges<TraitsType>(dstart, dend, elist);
|
||||
std::list<DartType> elist;
|
||||
DartType next_start = ttl_constr::ConstrainedTriangulation::findCrossingEdges<TraitsType>(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<TraitsType>(dstart, next_start, elist);
|
||||
ttl_constr::ConstrainedTriangulation::transformToConstraint<TraitsType>(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<DartType>::iterator end_opt = elist.end();
|
||||
typename std::list<DartType>::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<TraitsType, DartType>(elist, end_opt);
|
||||
optimizeDelaunay<TraitsType, DartType>(elist, end_opt);
|
||||
}
|
||||
|
||||
if(elist.size() == 0) // by Thomas Sevaldrud
|
||||
|
|
|
@ -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();
|
||||
|
||||
|
|
|
@ -84,7 +84,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 +112,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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -1088,7 +1088,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 ) );
|
||||
|
||||
|
|
|
@ -679,7 +679,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 ) );
|
||||
|
||||
|
@ -704,7 +704,7 @@ public:
|
|||
* - Get an old version of the board from Redo list
|
||||
* @return none
|
||||
*/
|
||||
void GetBoardFromRedoList( wxCommandEvent& event );
|
||||
void GetBoardFromRedoList( wxCommandEvent& aEvent );
|
||||
|
||||
/**
|
||||
* Function GetBoardFromUndoList
|
||||
|
@ -713,7 +713,7 @@ public:
|
|||
* - Get an old version of the board from Undo list
|
||||
* @return none
|
||||
*/
|
||||
void GetBoardFromUndoList( wxCommandEvent& event );
|
||||
void GetBoardFromUndoList( wxCommandEvent& aEvent );
|
||||
|
||||
/* Block operations: */
|
||||
|
||||
|
|
|
@ -222,7 +222,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
|
||||
|
@ -252,7 +251,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
|
||||
)
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
|
||||
#include <fctsys.h>
|
||||
#include <class_drawpanel.h>
|
||||
#include <class_drawpanel_gal.h>
|
||||
#include <macros.h>
|
||||
|
||||
#include <pcbnew.h>
|
||||
|
@ -40,6 +41,10 @@
|
|||
#include <class_zone.h>
|
||||
#include <class_edge_mod.h>
|
||||
|
||||
#include <ratsnest_data.h>
|
||||
|
||||
#include <tools/selection_tool.h>
|
||||
#include <tool/tool_manager.h>
|
||||
|
||||
/* 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<MODULE*>( 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<MODULE*>( 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<MODULE*>( 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<MODULE*>( 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 )
|
||||
{
|
||||
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();
|
||||
|
|
|
@ -206,7 +206,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 +842,8 @@ void BOARD::Add( BOARD_ITEM* aBoardItem, int aControl )
|
|||
}
|
||||
break;
|
||||
}
|
||||
|
||||
m_ratsnest->Add( aBoardItem );
|
||||
}
|
||||
|
||||
|
||||
|
@ -905,6 +907,8 @@ BOARD_ITEM* BOARD::Remove( BOARD_ITEM* aBoardItem )
|
|||
wxFAIL_MSG( wxT( "BOARD::Remove() needs more ::Type() support" ) );
|
||||
}
|
||||
|
||||
m_ratsnest->Remove( aBoardItem );
|
||||
|
||||
return aBoardItem;
|
||||
}
|
||||
|
||||
|
@ -1355,79 +1359,7 @@ NETINFO_ITEM* BOARD::FindNet( int aNetcode ) const
|
|||
|
||||
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 +1444,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
|
||||
|
@ -1601,13 +1534,13 @@ int BOARD::SetAreasNetCodesFromNetNames( void )
|
|||
{
|
||||
if( !GetArea( ii )->IsOnCopperLayer() )
|
||||
{
|
||||
GetArea( ii )->SetNet( 0 );
|
||||
GetArea( ii )->SetNet( NETINFO_LIST::UNCONNECTED );
|
||||
continue;
|
||||
}
|
||||
|
||||
if( GetArea( ii )->GetNet() != 0 ) // i.e. if this zone is connected to a net
|
||||
{
|
||||
const NETINFO_ITEM* net = FindNet( GetArea( ii )->GetNetName() );
|
||||
const NETINFO_ITEM* net = FindNet( GetArea( ii )->GetNetname() );
|
||||
|
||||
if( net )
|
||||
{
|
||||
|
@ -2618,7 +2551,7 @@ void BOARD::ReplaceNetlist( NETLIST& aNetlist, bool aDeleteSinglePadNets,
|
|||
}
|
||||
|
||||
if( !aNetlist.IsDryRun() )
|
||||
pad->SetNetname( wxEmptyString );
|
||||
pad->SetNet( NETINFO_LIST::UNCONNECTED );
|
||||
}
|
||||
}
|
||||
else // Footprint pad has a net.
|
||||
|
@ -2638,7 +2571,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->SetNet( netinfo->GetNet() );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2710,7 +2653,8 @@ void BOARD::ReplaceNetlist( NETLIST& aNetlist, bool aDeleteSinglePadNets,
|
|||
GetChars( previouspad->GetPadName() ) );
|
||||
aReporter->Report( msg );
|
||||
}
|
||||
previouspad->SetNetname( wxEmptyString );
|
||||
|
||||
previouspad->SetNet( NETINFO_LIST::UNCONNECTED );
|
||||
}
|
||||
netname = pad->GetNetname();
|
||||
count = 1;
|
||||
|
@ -2723,7 +2667,7 @@ void BOARD::ReplaceNetlist( NETLIST& aNetlist, bool aDeleteSinglePadNets,
|
|||
|
||||
// Examine last pad
|
||||
if( pad && count == 1 )
|
||||
pad->SetNetname( wxEmptyString );
|
||||
pad->SetNet( NETINFO_LIST::UNCONNECTED );
|
||||
}
|
||||
|
||||
// Last step: Some tests:
|
||||
|
@ -2760,31 +2704,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
|
||||
|
|
|
@ -845,6 +845,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)
|
||||
|
|
|
@ -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 <fctsys.h>
|
||||
#include <pcbnew.h>
|
||||
|
||||
#include <class_board.h>
|
||||
#include <class_board_item.h>
|
||||
|
||||
|
||||
BOARD_CONNECTED_ITEM::BOARD_CONNECTED_ITEM( BOARD_ITEM* aParent, KICAD_T idtype ) :
|
||||
BOARD_ITEM( aParent, idtype )
|
||||
BOARD_ITEM( aParent, idtype ), m_Subnet( 0 ), m_ZoneSubnet( 0 ),
|
||||
m_netinfo( &NETINFO_LIST::ORPHANED )
|
||||
{
|
||||
m_NetCode = 0;
|
||||
m_Subnet = 0;
|
||||
m_ZoneSubnet = 0;
|
||||
// The unconnected is set only in case the item belongs to a BOARD
|
||||
SetNet( NETINFO_LIST::UNCONNECTED );
|
||||
}
|
||||
|
||||
|
||||
BOARD_CONNECTED_ITEM::BOARD_CONNECTED_ITEM( const BOARD_CONNECTED_ITEM& aItem ) :
|
||||
BOARD_ITEM( aItem )
|
||||
BOARD_ITEM( aItem ), m_Subnet( aItem.m_Subnet ), m_ZoneSubnet( aItem.m_ZoneSubnet ),
|
||||
m_netinfo( aItem.m_netinfo )
|
||||
{
|
||||
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
|
||||
{
|
||||
return m_NetCode;
|
||||
return m_netinfo->GetNet();
|
||||
}
|
||||
|
||||
|
||||
void BOARD_CONNECTED_ITEM::SetNet( 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.
|
||||
|
@ -176,10 +157,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;
|
||||
|
|
|
@ -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 <dick@softplc.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_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_board_item.h>
|
||||
|
||||
class NETINFO_ITEM;
|
||||
class NETCLASS;
|
||||
class TRACK;
|
||||
class D_PAD;
|
||||
|
@ -30,8 +55,6 @@ public:
|
|||
std::vector<D_PAD*> 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)
|
||||
*/
|
||||
|
@ -39,31 +62,73 @@ private:
|
|||
int m_ZoneSubnet; // used in rastnest computations : for the current net,
|
||||
// handle cluster number in zone connection
|
||||
|
||||
/// Stores all informations about the net that item belongs to
|
||||
const NETINFO_ITEM* m_netinfo;
|
||||
|
||||
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
|
||||
* @return int - the net code.
|
||||
*/
|
||||
int GetNet() const;
|
||||
virtual void SetNet( int aNetCode );
|
||||
|
||||
/**
|
||||
* Function SetNet
|
||||
* 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 SetNet( 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,6 +149,10 @@ 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;
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -728,6 +728,41 @@ EDA_ITEM* MODULE::Clone() const
|
|||
}
|
||||
|
||||
|
||||
void MODULE::RunOnChildren( boost::function<void (BOARD_ITEM*)> aFunction )
|
||||
{
|
||||
for( D_PAD* pad = m_Pads.GetFirst(); pad; pad = pad->Next() )
|
||||
aFunction( static_cast<BOARD_ITEM*>( pad ) );
|
||||
|
||||
for( BOARD_ITEM* drawing = m_Drawings.GetFirst(); drawing; drawing = drawing->Next() )
|
||||
aFunction( drawing );
|
||||
|
||||
aFunction( static_cast<BOARD_ITEM*>( m_Reference ) );
|
||||
aFunction( static_cast<BOARD_ITEM*>( 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
|
||||
|
|
|
@ -41,6 +41,7 @@
|
|||
#include <PolyLine.h>
|
||||
#include "zones.h"
|
||||
|
||||
#include <boost/function.hpp>
|
||||
|
||||
class LINE_READER;
|
||||
class EDA_3D_CANVAS;
|
||||
|
@ -447,6 +448,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<void (BOARD_ITEM*)> aFunction );
|
||||
|
||||
/// @copydoc VIEW_ITEM::ViewUpdate()
|
||||
void ViewUpdate( int aUpdateFlags );
|
||||
|
||||
/**
|
||||
* Function CopyNetlistSettings
|
||||
* copies the netlist settings to \a aModule.
|
||||
|
|
|
@ -203,11 +203,9 @@ 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; i<count; ++i )
|
||||
for( NETINFO_LIST::iterator net( m_NetInfo.begin() ), netEnd( m_NetInfo.end() );
|
||||
net != netEnd; ++net )
|
||||
{
|
||||
NETINFO_ITEM* net = FindNet( i );
|
||||
if( net )
|
||||
net->SetClass( m_NetClasses.GetDefault() );
|
||||
}
|
||||
|
||||
|
@ -248,10 +246,8 @@ void BOARD::SynchronizeNetsAndNetClasses()
|
|||
|
||||
m_NetClasses.GetDefault()->Clear();
|
||||
|
||||
for( int i=0; i<count; ++i )
|
||||
{
|
||||
NETINFO_ITEM* net = FindNet( i );
|
||||
if( net )
|
||||
for( NETINFO_LIST::iterator net( m_NetInfo.begin() ), netEnd( m_NetInfo.end() );
|
||||
net != netEnd; ++net )
|
||||
{
|
||||
const wxString& classname = net->GetClassName();
|
||||
|
||||
|
@ -263,7 +259,6 @@ void BOARD::SynchronizeNetsAndNetClasses()
|
|||
|
||||
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 )
|
||||
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" );
|
||||
}
|
||||
|
|
|
@ -34,9 +34,10 @@
|
|||
#define __CLASSES_NETINFO__
|
||||
|
||||
|
||||
#include <vector>
|
||||
#include <gr_basic.h>
|
||||
#include <class_netclass.h>
|
||||
#include <boost/unordered_map.hpp>
|
||||
#include <hashtables.h>
|
||||
|
||||
|
||||
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<int/wxString, NETINFO_ITEM*>
|
||||
class iterator
|
||||
{
|
||||
public:
|
||||
iterator( std::map<int, int>::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<int, int>::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<int, int> 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
|
||||
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;
|
||||
return m_NetBuffer[aNetcode];
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -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 const NETINFO_ITEM ORPHANED;
|
||||
|
||||
#if defined(DEBUG)
|
||||
void Show() const;
|
||||
#endif
|
||||
|
||||
private:
|
||||
typedef boost::unordered_map<const wxString, NETINFO_ITEM*, WXSTRING_HASH> NETNAMES_MAP;
|
||||
typedef boost::unordered_map<const int, NETINFO_ITEM*> NETCODES_MAP;
|
||||
|
||||
///> Wrapper class, so you can iterate through NETINFO_ITEM*s, not
|
||||
///> std::pair<int/wxString, NETINFO_ITEM*>
|
||||
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,8 +413,16 @@ private:
|
|||
*/
|
||||
void buildPadsFullList();
|
||||
|
||||
/**
|
||||
* Function getFreeNetCode
|
||||
* returns the first available net code that is not used by any other net.
|
||||
*/
|
||||
int getFreeNetCode() const;
|
||||
|
||||
BOARD* m_Parent;
|
||||
std::vector<NETINFO_ITEM*> m_NetBuffer; ///< net list (name, design constraints ..)
|
||||
|
||||
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<D_PAD*> m_PadsFullList; ///< contains all pads, sorted by pad's netname.
|
||||
///< can be used in ratsnest calculations.
|
||||
|
@ -227,14 +435,16 @@ 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
|
||||
const wxString m_ShortNetname; // short net name, like vout from
|
||||
// /mysheet/mysubsheet/vout
|
||||
|
||||
wxString m_NetClassName; // Net Class name. if void this is equivalent
|
||||
|
@ -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 <D_PAD*> 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 );
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -49,18 +49,10 @@
|
|||
/* 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
|
||||
|
@ -77,17 +69,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)
|
||||
*/
|
||||
|
|
|
@ -11,13 +11,17 @@
|
|||
|
||||
#include <class_board.h>
|
||||
#include <class_module.h>
|
||||
#include <class_pad.h>
|
||||
#include <class_track.h>
|
||||
#include <class_zone.h>
|
||||
#include <class_netinfo.h>
|
||||
|
||||
|
||||
// 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 +33,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<int&>( 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 +88,26 @@ 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->GetNet() == 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
|
||||
GetNetItem( pad->GetNet() )->m_PadInNetList.push_back( pad );
|
||||
|
||||
pad->SetNet( netcode );
|
||||
net_item->m_PadInNetList.push_back( pad );
|
||||
|
||||
nodes_count++;
|
||||
|
||||
last_pad = pad;
|
||||
++nodes_count;
|
||||
}
|
||||
|
||||
m_Parent->SetNodeCount( nodes_count );
|
||||
|
@ -129,18 +117,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 +171,83 @@ 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<int, int>::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<int> 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 )->GetNet() );
|
||||
|
||||
// Tracks
|
||||
for( TRACK* track = m_board->m_Track; track; track = track->Next() )
|
||||
nets.insert( track->GetNet() );
|
||||
|
||||
// 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->GetNet() );
|
||||
}
|
||||
}
|
||||
|
||||
// Segzones
|
||||
for( SEGZONE* zone = m_board->m_Zone; zone; zone = zone->Next() )
|
||||
nets.insert( zone->GetNet() );
|
||||
|
||||
// Prepare the new mapping
|
||||
m_netMapping.clear();
|
||||
|
||||
// Now the nets variable stores all the used net codes (not only for pads)
|
||||
int newNetCode = 0;
|
||||
for( std::set<int>::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 NETINFO_ITEM NETINFO_LIST::ORPHANED = NETINFO_ITEM( NULL, wxString::FromUTF8( "orphaned" ), -1 );
|
||||
const int NETINFO_LIST::UNCONNECTED = 0;
|
||||
|
|
|
@ -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 )
|
||||
|
@ -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->SetNet( GetNet() );
|
||||
|
||||
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 */
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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( GetNet() == 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 );
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -690,7 +690,7 @@ 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( GetNet() == NETINFO_LIST::UNCONNECTED )
|
||||
return;
|
||||
|
||||
NETINFO_ITEM* net = ( (BOARD*) GetParent() )->FindNet( GetNet() );
|
||||
|
@ -952,7 +952,7 @@ void SEGVIA::Draw( EDA_DRAW_PANEL* panel, wxDC* aDC, GR_DRAWMODE aDrawMode,
|
|||
}
|
||||
|
||||
// Display the short netname:
|
||||
if( GetNet() == 0 )
|
||||
if( GetNet() == NETINFO_LIST::UNCONNECTED )
|
||||
return;
|
||||
|
||||
if( DisplayOpt.DisplayNetNamesMode == 0 || DisplayOpt.DisplayNetNamesMode == 1 )
|
||||
|
|
|
@ -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
|
||||
|
@ -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 )
|
||||
{
|
||||
|
@ -658,7 +632,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( ">" );
|
||||
}
|
||||
|
||||
|
@ -849,20 +823,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 )
|
||||
|
@ -928,7 +888,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( ">" );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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->SetNet( NETINFO_LIST::UNCONNECTED );
|
||||
}
|
||||
|
||||
// If no pad, reset pointers and netcode, and do nothing else
|
||||
|
|
|
@ -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 );
|
||||
|
@ -809,26 +810,17 @@ 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.GetNet() == 0 )
|
||||
{
|
||||
rastnestIsChanged = true;
|
||||
m_currentPad->SetNet( 0 );
|
||||
m_currentPad->SetNetname( wxEmptyString );
|
||||
}
|
||||
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" ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
rastnestIsChanged = true;
|
||||
m_currentPad->SetNet( m_padMaster.GetNet() );
|
||||
}
|
||||
}
|
||||
|
||||
m_currentPad->SetLocalClearance( m_padMaster.GetLocalClearance() );
|
||||
|
@ -986,7 +978,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->SetNet( netinfo->GetNet() );
|
||||
else
|
||||
aPad->SetNet( 0 );
|
||||
|
||||
// Clear some values, according to the pad type and shape
|
||||
switch( aPad->GetShape() )
|
||||
|
@ -1034,7 +1032,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->SetNet( 0 );
|
||||
break;
|
||||
|
||||
default:
|
||||
|
|
|
@ -1493,7 +1493,7 @@ void EAGLE_PLUGIN::loadPlain( CPTREE& aGraphics )
|
|||
|
||||
zone->SetTimeStamp( timeStamp( gr->second ) );
|
||||
zone->SetLayer( layer );
|
||||
zone->SetNet( 0 );
|
||||
zone->SetNet( NETINFO_LIST::UNCONNECTED );
|
||||
|
||||
CPolyLine::HATCH_STYLE outline_hatch = CPolyLine::DIAGONAL_EDGE;
|
||||
|
||||
|
@ -1696,7 +1696,6 @@ 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 );
|
||||
}
|
||||
}
|
||||
|
@ -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<MODULE> m( new MODULE( NULL ) );
|
||||
std::auto_ptr<MODULE> 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<string>( "<xmlattr>.name" );
|
||||
wxString netName = FROM_UTF8( nname.c_str() );
|
||||
m_board->AppendNet( new NETINFO_ITEM( m_board, netName, netCode ) );
|
||||
|
||||
m_xpath->Value( nname.c_str() );
|
||||
|
||||
|
@ -2497,7 +2496,6 @@ void EAGLE_PLUGIN::loadSignals( CPTREE& aSignals )
|
|||
zone->SetTimeStamp( timeStamp( it->second ) );
|
||||
zone->SetLayer( layer );
|
||||
zone->SetNet( netCode );
|
||||
zone->SetNetName( netName );
|
||||
|
||||
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)->SetNet( 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"
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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,13 +657,12 @@ 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_mapping->Translate( net->GetNet() ),
|
||||
m_out->Quotew( net->GetNetname() ).c_str() );
|
||||
}
|
||||
|
||||
|
@ -1229,7 +1231,8 @@ void PCB_IO::format( D_PAD* aPad, int aNestLevel ) const
|
|||
|
||||
// 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() );
|
||||
StrPrintf( &output, " (net %d %s)", m_mapping->Translate( aPad->GetNet() ),
|
||||
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->GetNet() ) );
|
||||
|
||||
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->GetNet() ),
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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:
|
|||
|
||||
//-----</PLUGIN API>--------------------------------------------------------
|
||||
|
||||
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 );
|
||||
|
|
|
@ -1303,7 +1303,7 @@ void LEGACY_PLUGIN::loadPAD( MODULE* aModule )
|
|||
|
||||
// read Netname
|
||||
ReadDelimitedText( buf, data, sizeof(buf) );
|
||||
pad->SetNetname( FROM_UTF8( StrPurge( buf ) ) );
|
||||
assert( m_board->FindNet( netcode )->GetNetname() == FROM_UTF8( StrPurge( buf ) ) );
|
||||
}
|
||||
|
||||
else if( TESTLINE( "Po" ) ) // (Po)sition
|
||||
|
@ -1811,7 +1811,7 @@ void LEGACY_PLUGIN::loadNETINFO_ITEM()
|
|||
{
|
||||
char buf[1024];
|
||||
|
||||
NETINFO_ITEM* net = new NETINFO_ITEM( m_board );
|
||||
NETINFO_ITEM* net;
|
||||
char* line;
|
||||
|
||||
while( ( line = READLINE( m_reader ) ) != NULL )
|
||||
|
@ -1822,11 +1822,10 @@ 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" ) )
|
||||
|
@ -2239,7 +2238,6 @@ void LEGACY_PLUGIN::loadZONE_CONTAINER()
|
|||
// 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
|
||||
}
|
||||
|
||||
else if( TESTLINE( "ZLayer" ) ) // layer found
|
||||
|
@ -2256,7 +2254,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 +2265,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 +2282,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 +2357,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 +2421,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->SetNet( 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 +2431,7 @@ void LEGACY_PLUGIN::loadZONE_CONTAINER()
|
|||
if( !zc->IsOnCopperLayer() )
|
||||
{
|
||||
zc->SetFillMode( 0 );
|
||||
zc->SetNet( 0 );
|
||||
zc->SetNet( NETINFO_LIST::UNCONNECTED );
|
||||
}
|
||||
|
||||
// Hatch here, after outlines corners are read
|
||||
|
@ -2904,6 +2899,8 @@ do { \
|
|||
|
||||
void LEGACY_PLUGIN::SaveBOARD( const BOARD* aBoard ) const
|
||||
{
|
||||
m_mapping->SetBoard( aBoard );
|
||||
|
||||
saveGENERAL( aBoard );
|
||||
|
||||
saveSHEET( aBoard );
|
||||
|
@ -2952,7 +2949,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 +3090,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 +3152,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" );
|
||||
|
||||
|
@ -3645,7 +3645,7 @@ void LEGACY_PLUGIN::saveZONE_CONTAINER( const ZONE_CONTAINER* me ) const
|
|||
fprintf( m_fp, "ZInfo %lX %d %s\n",
|
||||
me->GetTimeStamp(),
|
||||
me->GetIsKeepout() ? 0 : me->GetNet(),
|
||||
EscapedUTF8( me->GetIsKeepout() ? wxT("") : me->GetNetName() ).c_str() );
|
||||
EscapedUTF8( me->GetIsKeepout() ? wxT("") : me->GetNetname() ).c_str() );
|
||||
|
||||
// Save the outline layer info
|
||||
fprintf( m_fp, "ZLayer %d\n", me->GetLayer() );
|
||||
|
@ -4422,7 +4422,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 +4432,5 @@ LEGACY_PLUGIN::LEGACY_PLUGIN() :
|
|||
LEGACY_PLUGIN::~LEGACY_PLUGIN()
|
||||
{
|
||||
delete m_cache;
|
||||
delete m_mapping;
|
||||
}
|
||||
|
|
|
@ -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 );
|
||||
|
||||
|
|
|
@ -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 drag&drop tool." ),
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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 )
|
||||
{
|
||||
|
|
|
@ -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 ) );
|
||||
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -141,7 +141,7 @@ void PCB_BASE_FRAME::AddPad( MODULE* aModule, bool draw )
|
|||
|
||||
// Update the pad properties.
|
||||
Import_Pad_Settings( pad, false );
|
||||
pad->SetNetname( wxEmptyString );
|
||||
pad->SetNet( NETINFO_LIST::UNCONNECTED );
|
||||
|
||||
pad->SetPosition( GetCrossHairPosition() );
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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->SetNet( netinfo->GetNet() );
|
||||
}
|
||||
|
||||
if( !aEncapsulatedPad )
|
||||
|
|
|
@ -172,7 +172,6 @@ void PCB_POLYGON::AddToBoard()
|
|||
zone->SetTimeStamp( m_timestamp );
|
||||
zone->SetLayer( m_KiCadLayer );
|
||||
zone->SetNet( m_netCode );
|
||||
zone->SetNetName( m_net );
|
||||
|
||||
// add outline
|
||||
int outline_hatch = CPolyLine::DIAGONAL_EDGE;
|
||||
|
|
|
@ -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; }
|
||||
|
|
|
@ -34,7 +34,6 @@
|
|||
#include <class_marker_pcb.h>
|
||||
#include <class_dimension.h>
|
||||
#include <class_mire.h>
|
||||
#include <class_netinfo.h>
|
||||
#include <pcbstruct.h>
|
||||
|
||||
#include <view/view.h>
|
||||
|
@ -75,6 +74,7 @@ void PCB_RENDER_SETTINGS::ImportLegacyColors( COLORS_DESIGN_SETTINGS* aSettings
|
|||
m_layerColors[ITEM_GAL_LAYER( PADS_NETNAMES_VISIBLE )] = COLOR4D( 0.8, 0.8, 0.8, 0.7 );
|
||||
m_layerColors[ITEM_GAL_LAYER( PAD_FR_NETNAMES_VISIBLE )] = COLOR4D( 0.8, 0.8, 0.8, 0.7 );
|
||||
m_layerColors[ITEM_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
|
||||
|
@ -280,7 +280,7 @@ void PCB_PAINTER::draw( const TRACK* aTrack, int aLayer )
|
|||
if( !net )
|
||||
return;
|
||||
|
||||
std::wstring netName = std::wstring( net->GetShortNetname().wc_str() );
|
||||
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<double>( width ), length / netName.length() );
|
||||
|
|
|
@ -29,6 +29,7 @@
|
|||
|
||||
#include <errno.h>
|
||||
#include <common.h>
|
||||
#include <confirm.h>
|
||||
#include <macros.h>
|
||||
#include <convert_from_iu.h>
|
||||
#include <trigo.h>
|
||||
|
@ -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() );
|
||||
|
@ -2193,7 +2192,7 @@ D_PAD* PCB_PARSER::parseD_PAD() throw( IO_ERROR, PARSE_ERROR )
|
|||
case T_net:
|
||||
pad->SetNet( parseInt( "net number" ) );
|
||||
NeedSYMBOLorNUMBER();
|
||||
pad->SetNetname( FromUTF8() );
|
||||
assert( FromUTF8() == m_board->FindNet( pad->GetNet() )->GetNetname() );
|
||||
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->SetNet( parseInt( "net number" ) );
|
||||
NeedRIGHT();
|
||||
break;
|
||||
|
||||
case T_net_name:
|
||||
NeedSYMBOLorNUMBER();
|
||||
zone->SetNetName( FromUTF8() );
|
||||
if( m_board->FindNet( 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->SetNet( 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->SetNet( 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->SetNet( NETINFO_LIST::UNCONNECTED );
|
||||
|
||||
return zone.release();
|
||||
}
|
||||
|
|
|
@ -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 );
|
||||
|
|
|
@ -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 */
|
||||
|
@ -334,16 +332,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 );
|
||||
|
@ -543,8 +531,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 );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -621,7 +612,6 @@ void PCB_EDIT_FRAME::ViewReloadBoard( const BOARD* aBoard ) const
|
|||
|
||||
// Add an entry for the ratsnest
|
||||
RN_DATA* ratsnest = aBoard->GetRatsnest();
|
||||
ratsnest->ProcessBoard();
|
||||
ratsnest->Recalculate();
|
||||
view->Add( new KIGFX::RATSNEST_VIEWITEM( ratsnest ) );
|
||||
|
||||
|
@ -748,10 +738,17 @@ void PCB_EDIT_FRAME::UseGalCanvas( bool aEnable )
|
|||
{
|
||||
EDA_DRAW_FRAME::UseGalCanvas( aEnable );
|
||||
|
||||
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 );
|
||||
|
||||
ViewReloadBoard( m_Pcb );
|
||||
m_toolManager->ResetTools( TOOL_BASE::GAL_SWITCH );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -371,7 +371,6 @@ enum pcbnew_ids
|
|||
ID_FOOTPRINT_WIZARD_SELECT_WIZARD,
|
||||
ID_FOOTPRINT_WIZARD_EXPORT_TO_BOARD,
|
||||
|
||||
ID_SELECTION_TOOL,
|
||||
ID_PNS_ROUTER_TOOL
|
||||
};
|
||||
|
||||
|
|
|
@ -70,7 +70,10 @@ public:
|
|||
|
||||
void MIN_SPAN_TREE_PADS::AddTreeToRatsnest( std::vector<RATSNEST_ITEM> &aRatsnestList )
|
||||
{
|
||||
std::vector<D_PAD*> & padsBuffer = *m_PadsList;
|
||||
std::vector<D_PAD*>& padsBuffer = *m_PadsList;
|
||||
if( padsBuffer.empty() )
|
||||
return;
|
||||
|
||||
int netcode = padsBuffer[0]->GetNet();
|
||||
// Note: to get edges in minimum spanning tree,
|
||||
// the index value 0 is not used: it is just
|
||||
|
@ -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->GetNet() == NETINFO_LIST::UNCONNECTED )
|
||||
continue;
|
||||
|
||||
localPadList.push_back( pad_ref );
|
||||
|
|
|
@ -27,6 +27,10 @@
|
|||
* @brief Class that computes missing connections on a PCB.
|
||||
*/
|
||||
|
||||
#ifdef USE_OPENMP
|
||||
#include <omp.h>
|
||||
#endif /* USE_OPENMP */
|
||||
|
||||
#include <ratsnest_data.h>
|
||||
|
||||
#include <class_board.h>
|
||||
|
@ -35,7 +39,6 @@
|
|||
#include <class_track.h>
|
||||
#include <class_zone.h>
|
||||
|
||||
#include <boost/foreach.hpp>
|
||||
#include <boost/range/adaptor/map.hpp>
|
||||
#include <boost/scoped_ptr.hpp>
|
||||
#include <boost/make_shared.hpp>
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
@ -201,12 +215,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 +290,9 @@ void RN_NET::compute()
|
|||
|
||||
void RN_NET::clearNode( const RN_NODE_PTR& aNode )
|
||||
{
|
||||
if( !m_rnEdges )
|
||||
return;
|
||||
|
||||
std::vector<RN_EDGE_PTR>::iterator newEnd;
|
||||
|
||||
// Remove all ratsnest edges for associated with the node
|
||||
|
@ -430,75 +453,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
|
||||
if( m_links.RemoveNode( node ) )
|
||||
clearNode( node );
|
||||
m_links.RemoveNode( node );
|
||||
|
||||
m_pads.erase( aPad );
|
||||
|
||||
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
|
||||
if( m_links.RemoveNode( node ) )
|
||||
clearNode( node );
|
||||
m_links.RemoveNode( node );
|
||||
|
||||
m_vias.erase( aVia );
|
||||
|
||||
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();
|
||||
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.
|
||||
if( m_links.RemoveNode( aBegin ) )
|
||||
clearNode( aBegin );
|
||||
|
||||
if( m_links.RemoveNode( aEnd ) )
|
||||
clearNode( aEnd );
|
||||
m_links.RemoveNode( aBegin );
|
||||
m_links.RemoveNode( aEnd );
|
||||
|
||||
m_tracks.erase( aTrack );
|
||||
|
||||
m_dirty = true;
|
||||
}
|
||||
catch( ... )
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void RN_NET::RemoveItem( const ZONE_CONTAINER* aZone )
|
||||
{
|
||||
try
|
||||
{
|
||||
// Remove all subpolygons that make the zone
|
||||
std::deque<RN_POLY>& polygons = m_zonePolygons[aZone];
|
||||
std::deque<RN_POLY>& polygons = m_zonePolygons.at( aZone );
|
||||
BOOST_FOREACH( RN_POLY& polygon, polygons )
|
||||
m_links.RemoveNode( polygon.GetNode() );
|
||||
{
|
||||
const RN_NODE_PTR node = polygon.GetNode();
|
||||
|
||||
if( m_links.RemoveNode( node ) )
|
||||
clearNode( node );
|
||||
}
|
||||
polygons.clear();
|
||||
|
||||
// Remove all connections added by the zone
|
||||
std::deque<RN_EDGE_PTR>& edges = m_zoneConnections[aZone];
|
||||
std::deque<RN_EDGE_PTR>& edges = m_zoneConnections.at( aZone );
|
||||
BOOST_FOREACH( RN_EDGE_PTR& edge, edges )
|
||||
m_links.RemoveConnection( edge );
|
||||
edges.clear();
|
||||
|
||||
m_dirty = true;
|
||||
}
|
||||
catch( ... )
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -512,15 +557,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 +587,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,6 +661,8 @@ std::list<RN_NODE_PTR> RN_NET::GetNodes( const BOARD_CONNECTED_ITEM* aItem ) con
|
|||
{
|
||||
std::list<RN_NODE_PTR> nodes;
|
||||
|
||||
try
|
||||
{
|
||||
switch( aItem->Type() )
|
||||
{
|
||||
case PCB_PAD_T:
|
||||
|
@ -642,39 +692,83 @@ std::list<RN_NODE_PTR> RN_NET::GetNodes( const BOARD_CONNECTED_ITEM* aItem ) con
|
|||
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<const BOARD_CONNECTED_ITEM*>( aItem );
|
||||
net = item->GetNet();
|
||||
|
||||
|
||||
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<RN_NODE_PTR> nodes = m_nets[net].GetNodes( aItem );
|
||||
std::list<RN_NODE_PTR>::iterator it, itEnd;
|
||||
// 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<const MODULE*>( aItem );
|
||||
|
||||
for( it = nodes.begin(), itEnd = nodes.end(); it != itEnd; ++it )
|
||||
m_nets[net].AddSimpleNode( *it );
|
||||
for( const D_PAD* pad = module->Pads().GetFirst(); pad; pad = pad->Next() )
|
||||
AddSimple( pad );
|
||||
|
||||
return;
|
||||
}
|
||||
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<const BOARD_CONNECTED_ITEM*>( aItem );
|
||||
net = item->GetNet();
|
||||
|
||||
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<const MODULE*>( 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<RN_NODE>( aPosition.x, aPosition.y );
|
||||
|
||||
m_nets[aNetCode].AddSimpleNode( newNode );
|
||||
}
|
||||
|
||||
|
||||
|
@ -725,55 +819,57 @@ 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<const BOARD_CONNECTED_ITEM*>( aItem )->GetNet();
|
||||
if( net < 1 ) // do not process unconnected items
|
||||
return;
|
||||
|
||||
m_nets[aNetCode].ClearSimple();
|
||||
m_nets[aNetCode].Update();
|
||||
}
|
||||
|
||||
|
||||
void RN_DATA::Update( const BOARD_CONNECTED_ITEM* aItem )
|
||||
{
|
||||
int net = aItem->GetNet();
|
||||
// Autoresize
|
||||
if( net >= (int) m_nets.size() )
|
||||
m_nets.resize( net + 1 );
|
||||
}
|
||||
else if( aItem->Type() == PCB_MODULE_T )
|
||||
{
|
||||
const MODULE* module = static_cast<const MODULE*>( aItem );
|
||||
for( const D_PAD* pad = module->Pads().GetFirst(); pad; pad = pad->Next() )
|
||||
{
|
||||
net = pad->GetNet();
|
||||
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;
|
||||
}
|
||||
else
|
||||
return;
|
||||
|
||||
switch( aItem->Type() )
|
||||
{
|
||||
case PCB_PAD_T:
|
||||
{
|
||||
const D_PAD* pad = static_cast<const D_PAD*>( aItem );
|
||||
m_nets[net].RemoveItem( pad );
|
||||
m_nets[net].AddItem( pad );
|
||||
}
|
||||
m_nets[net].AddItem( static_cast<const D_PAD*>( aItem ) );
|
||||
break;
|
||||
|
||||
case PCB_TRACE_T:
|
||||
{
|
||||
const TRACK* track = static_cast<const TRACK*>( aItem );
|
||||
m_nets[net].RemoveItem( track );
|
||||
m_nets[net].AddItem( track );
|
||||
}
|
||||
m_nets[net].AddItem( static_cast<const TRACK*>( aItem ) );
|
||||
break;
|
||||
|
||||
case PCB_VIA_T:
|
||||
{
|
||||
const SEGVIA* via = static_cast<const SEGVIA*>( aItem );
|
||||
m_nets[net].RemoveItem( via );
|
||||
m_nets[net].AddItem( via );
|
||||
}
|
||||
m_nets[net].AddItem( static_cast<const SEGVIA*>( aItem ) );
|
||||
break;
|
||||
|
||||
case PCB_ZONE_AREA_T:
|
||||
{
|
||||
const ZONE_CONTAINER* zone = static_cast<const ZONE_CONTAINER*>( aItem );
|
||||
m_nets[net].RemoveItem( zone);
|
||||
m_nets[net].AddItem( zone );
|
||||
}
|
||||
m_nets[net].AddItem( static_cast<const ZONE_CONTAINER*>( aItem ) );
|
||||
break;
|
||||
|
||||
default:
|
||||
|
@ -782,18 +878,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
|
||||
if( aItem->IsConnected() )
|
||||
{
|
||||
net = static_cast<const BOARD_CONNECTED_ITEM*>( aItem )->GetNet();
|
||||
if( net < 1 ) // do not process unconnected items
|
||||
return;
|
||||
}
|
||||
else if( aItem->Type() == PCB_MODULE_T )
|
||||
{
|
||||
const MODULE* module = static_cast<const MODULE*>( aItem );
|
||||
for( const D_PAD* pad = module->Pads().GetFirst(); pad; pad = pad->Next() )
|
||||
{
|
||||
net = pad->GetNet();
|
||||
if( net < 1 ) // do not process unconnected items
|
||||
continue;
|
||||
|
||||
m_nets[net].RemoveItem( pad );
|
||||
m_nets[net].AddItem( pad );
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
else
|
||||
return;
|
||||
|
||||
switch( aItem->Type() )
|
||||
{
|
||||
case PCB_PAD_T:
|
||||
m_nets[net].RemoveItem( static_cast<const D_PAD*>( aItem ) );
|
||||
break;
|
||||
|
||||
case PCB_TRACE_T:
|
||||
m_nets[net].RemoveItem( static_cast<const TRACK*>( aItem ) );
|
||||
break;
|
||||
|
||||
case PCB_VIA_T:
|
||||
m_nets[net].RemoveItem( static_cast<const SEGVIA*>( aItem ) );
|
||||
break;
|
||||
|
||||
case PCB_ZONE_AREA_T:
|
||||
m_nets[net].RemoveItem( static_cast<const ZONE_CONTAINER*>( aItem ) );
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void RN_DATA::Update( const BOARD_ITEM* aItem )
|
||||
{
|
||||
Remove( aItem );
|
||||
Add( aItem );
|
||||
}
|
||||
|
||||
|
||||
|
@ -829,12 +968,25 @@ void RN_DATA::Recalculate( int aNet )
|
|||
{
|
||||
if( aNet < 0 ) // Recompute everything
|
||||
{
|
||||
unsigned int tid, i, chunk, netCount;
|
||||
netCount = m_board->GetNetCount();
|
||||
chunk = 1;
|
||||
|
||||
#ifdef USE_OPENMP
|
||||
#pragma omp parallel shared(chunk, netCount) private(i, tid)
|
||||
{
|
||||
tid = omp_get_thread_num();
|
||||
#pragma omp for schedule(guided, chunk)
|
||||
#else /* USE_OPENMP */
|
||||
{
|
||||
#endif
|
||||
// Start with net number 1, as 0 stand for not connected
|
||||
for( unsigned int i = 1; i < m_board->GetNetCount(); ++i )
|
||||
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
|
||||
{
|
||||
|
@ -843,8 +995,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();
|
||||
}
|
||||
|
|
|
@ -37,6 +37,7 @@
|
|||
|
||||
#include <boost/unordered_set.hpp>
|
||||
#include <boost/unordered_map.hpp>
|
||||
#include <boost/foreach.hpp>
|
||||
|
||||
class BOARD;
|
||||
class BOARD_ITEM;
|
||||
|
@ -57,6 +58,9 @@ typedef hed::EdgeMST RN_EDGE_MST;
|
|||
typedef boost::shared_ptr<hed::EdgeMST> 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<const RN_NODE_PTR&, bool>
|
||||
{
|
||||
|
@ -83,7 +87,7 @@ struct RN_NODE_COMPARE : std::binary_function<RN_NODE_PTR, RN_NODE_PTR, bool>
|
|||
{
|
||||
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<RN_EDGE_PTR>* 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<RN_NODE_PTR> m_simpleNodes;
|
||||
|
||||
///> List of nodes which should be used as ratsnest target nodes..
|
||||
std::deque<RN_NODE_PTR> 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<RN_NET>& 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:
|
||||
|
|
|
@ -30,6 +30,7 @@
|
|||
#include <ratsnest_viewitem.h>
|
||||
#include <ratsnest_data.h>
|
||||
#include <gal/graphics_abstraction_layer.h>
|
||||
#include <pcb_painter.h>
|
||||
#include <layers_id_colors_and_visibility.h>
|
||||
|
||||
#include <boost/foreach.hpp>
|
||||
|
@ -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<RN_NODE_PTR> 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<RN_EDGE_PTR>* edges = net.GetUnconnected();
|
||||
if( edges == NULL )
|
||||
continue;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -47,7 +47,7 @@
|
|||
|
||||
#include <class_board.h>
|
||||
#include <class_board_item.h>
|
||||
#include <class_pad.h>
|
||||
#include <class_module.h>
|
||||
#include <class_track.h>
|
||||
#include <ratsnest_data.h>
|
||||
#include <layers_id_colors_and_visibility.h>
|
||||
|
@ -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();
|
||||
|
@ -241,19 +244,22 @@ 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 ) {
|
||||
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 );
|
||||
}
|
||||
}
|
||||
|
||||
for( TRACK* t = m_board->m_Track; t; t = t->Next() )
|
||||
{
|
||||
|
@ -263,7 +269,7 @@ void PNS_ROUTER::SyncWorld()
|
|||
if( type == PCB_TRACE_T )
|
||||
item = syncTrack( t );
|
||||
else if( type == PCB_VIA_T )
|
||||
item = syncVia( static_cast <SEGVIA*>(t) );
|
||||
item = syncVia( static_cast<SEGVIA*>( t ) );
|
||||
|
||||
if( item )
|
||||
m_world->Add( item );
|
||||
|
@ -576,18 +582,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() )
|
||||
{
|
||||
|
@ -627,7 +634,7 @@ void PNS_ROUTER::commitRouting( PNS_NODE* aNode )
|
|||
newBI->ClearFlags();
|
||||
m_view->Add( newBI );
|
||||
m_board->Add( newBI );
|
||||
m_board->GetRatsnest()->Update( static_cast<BOARD_CONNECTED_ITEM*>( newBI ) );
|
||||
m_undoBuffer.PushItem( ITEM_PICKER( newBI, UR_NEW ) );
|
||||
newBI->ViewUpdate( KIGFX::VIEW_ITEM::GEOMETRY );
|
||||
}
|
||||
}
|
||||
|
@ -754,13 +761,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;
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
#include <boost/unordered_set.hpp>
|
||||
|
||||
#include <geometry/shape_line_chain.h>
|
||||
#include <class_undoredo_container.h>
|
||||
|
||||
#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<BOARD_ITEM*> m_hiddenItems;
|
||||
|
||||
///> Stores list of modified items in the current operation
|
||||
PICKED_ITEMS_LIST m_undoBuffer;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -31,7 +31,8 @@
|
|||
#include <pcb_painter.h>
|
||||
|
||||
#include <tool/context_menu.h>
|
||||
#include <tool/tool_action.h>
|
||||
|
||||
#include <ratsnest_data.h>
|
||||
|
||||
#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<BOARD>( 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<BOARD>( 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<BOARD_CONNECTED_ITEM*>( 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<BOARD_ITEM*>( 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,9 +402,22 @@ void ROUTER_TOOL::startRouting()
|
|||
}
|
||||
}
|
||||
|
||||
if( m_router->RoutingInProgress() )
|
||||
m_router->StopRouting();
|
||||
|
||||
if( saveUndoBuffer )
|
||||
{
|
||||
// Save the recent changes in the undo buffer
|
||||
getEditFrame<PCB_EDIT_FRAME>()->SaveCopyInUndoList( m_router->GetLastChanges(),
|
||||
UR_UNSPECIFIED );
|
||||
m_router->ClearLastChanges();
|
||||
getEditFrame<PCB_EDIT_FRAME>()->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 );
|
||||
highlightNet( 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;
|
||||
}
|
||||
|
|
|
@ -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<CONTEXT_MENU> m_menu;*/
|
||||
CONTEXT_MENU* m_menu;
|
||||
};
|
||||
|
|
|
@ -21,7 +21,8 @@
|
|||
#ifndef __TRACE_H
|
||||
#define __TRACE_H
|
||||
|
||||
#ifdef DEBUG
|
||||
// #ifdef DEBUG
|
||||
#if 0
|
||||
|
||||
#include <string>
|
||||
#include <iostream>
|
||||
|
|
|
@ -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 )
|
||||
{
|
||||
|
|
|
@ -24,21 +24,35 @@
|
|||
|
||||
#include "common_actions.h"
|
||||
#include <tool/action_manager.h>
|
||||
#include <wx/defs.h>
|
||||
|
||||
// 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" );
|
||||
|
|
|
@ -24,26 +24,36 @@
|
|||
|
||||
#include <tool/tool_action.h>
|
||||
|
||||
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;
|
||||
};
|
||||
|
|
|
@ -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 <maciej.suminski@cern.ch>
|
||||
*
|
||||
* 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 <class_board.h>
|
||||
#include <class_module.h>
|
||||
#include <class_zone.h>
|
||||
#include <wxPcbStruct.h>
|
||||
#include <tool/tool_manager.h>
|
||||
#include <view/view_controls.h>
|
||||
#include <ratsnest_data.h>
|
||||
#include <confirm.h>
|
||||
#include <cassert>
|
||||
#include <boost/foreach.hpp>
|
||||
|
||||
#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<SELECTION_TOOL*>( 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<PCB_EDIT_FRAME*>( 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<BOARD_ITEM*>( 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<BOARD>( 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<PCB_EDIT_FRAME*>( 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<BOARD_ITEM*>( 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<MODULE*>( 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<BOARD>( 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<PCB_EDIT_FRAME*>( 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<BOARD_ITEM*>( 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<BOARD>( 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<PCB_EDIT_FRAME*>( 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<BOARD_ITEM*>( 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<BOARD>( 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<PCB_EDIT_FRAME*>( 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<BOARD_ITEM*>( selectedItems.GetPickedItem( i ) );
|
||||
remove( item );
|
||||
}
|
||||
|
||||
// Rebuild list of pads and nets if necessary
|
||||
BOARD* board = getModel<BOARD>( 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<BOARD>( PCB_T );
|
||||
|
||||
switch( aItem->Type() )
|
||||
{
|
||||
case PCB_MODULE_T:
|
||||
{
|
||||
MODULE* module = static_cast<MODULE*>( 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<BOARD>( PCB_T )->GetRatsnest();
|
||||
|
||||
ratsnest->ClearSimple();
|
||||
for( unsigned int i = 0; i < selection.items.GetCount(); ++i )
|
||||
{
|
||||
BOARD_ITEM* item = static_cast<BOARD_ITEM*>( 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<BOARD_ITEM*>( 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;
|
||||
}
|
|
@ -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 <maciej.suminski@cern.ch>
|
||||
*
|
||||
* 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 <math/vector2d.h>
|
||||
#include <tool/tool_interactive.h>
|
||||
#include <view/view_group.h>
|
||||
|
||||
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
|
|
@ -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 <maciej.suminski@cern.ch>
|
||||
*
|
||||
* 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 <deque>
|
||||
#include <class_board_item.h>
|
||||
|
||||
/**
|
||||
* 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<BOARD_ITEM*>::iterator it, it_end;
|
||||
std::deque<COMMAND>::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<BOARD_ITEM*>::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<BOARD_ITEM*>::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<BOARD_ITEM*>::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<BOARD_ITEM*>::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<BOARD_ITEM*> m_items;
|
||||
|
||||
/// List of items that are affected by commands
|
||||
std::deque<COMMAND> 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_ */
|
|
@ -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 <maciej.suminski@cern.ch>
|
||||
*
|
||||
* 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 <class_board.h>
|
||||
#include <class_module.h>
|
||||
#include <tool/tool_manager.h>
|
||||
#include <view/view_controls.h>
|
||||
#include <ratsnest_data.h>
|
||||
#include <confirm.h>
|
||||
|
||||
#include <boost/foreach.hpp>
|
||||
|
||||
#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<SELECTION_TOOL*>( 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<BOARD_ITEM*>::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<BOARD*>( 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<BOARD*>( 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<BOARD_CONNECTED_ITEM*>( item ) );
|
||||
|
||||
if( aRedraw )
|
||||
ratsnest->AddSimple( static_cast<BOARD_CONNECTED_ITEM*>( item ) );
|
||||
}
|
||||
else if( item->Type() == PCB_MODULE_T )
|
||||
{
|
||||
ratsnest->Update( static_cast<MODULE*>( item ) );
|
||||
|
||||
if( aRedraw )
|
||||
ratsnest->AddSimple( static_cast<MODULE*>( item ) );
|
||||
}
|
||||
}
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue