Commit 190af5d9 authored by Maciej Suminski's avatar Maciej Suminski
Browse files

Added functions to resolve connectivity queries in ratsnest (GAL).

parent e6a10faa
Loading
Loading
Loading
Loading
+63 −43
Original line number Original line Diff line number Diff line
@@ -100,6 +100,9 @@ protected:
    /// Node coordinates
    /// Node coordinates
    int m_x, m_y;
    int m_x, m_y;


    /// Tag for quick connection resolution
    int m_tag;

    /// Reference count
    /// Reference count
    unsigned int m_refCount;
    unsigned int m_refCount;


@@ -112,7 +115,7 @@ public:
#ifdef TTL_USE_NODE_ID
#ifdef TTL_USE_NODE_ID
        m_id( id_count++ ),
        m_id( id_count++ ),
#endif
#endif
        m_x( aX ), m_y( aY ), m_refCount( 0 )
        m_x( aX ), m_y( aY ), m_tag( -1 ), m_refCount( 0 )
    {
    {
    }
    }


@@ -120,20 +123,32 @@ public:
    ~NODE() {}
    ~NODE() {}


    /// Returns the x-coordinate
    /// Returns the x-coordinate
    int GetX() const
    inline int GetX() const
    {
    {
        return m_x;
        return m_x;
    }
    }


    /// Returns the y-coordinate
    /// Returns the y-coordinate
    int GetY() const
    inline int GetY() const
    {
    {
        return m_y;
        return m_y;
    }
    }


    /// Returns tag, common identifier for connected nodes
    inline int GetTag() const
    {
        return m_tag;
    }

    /// Sets tag, common identifier for connected nodes
    inline void SetTag( int aTag )
    {
        m_tag = aTag;
    }

#ifdef TTL_USE_NODE_ID
#ifdef TTL_USE_NODE_ID
    /// Returns the id (TTL_USE_NODE_ID must be defined)
    /// Returns the id (TTL_USE_NODE_ID must be defined)
    int Id() const
    inline int Id() const
    {
    {
        return m_id;
        return m_id;
    }
    }
@@ -141,29 +156,29 @@ public:


#ifdef TTL_USE_NODE_FLAG
#ifdef TTL_USE_NODE_FLAG
    /// Sets the flag (TTL_USE_NODE_FLAG must be defined)
    /// Sets the flag (TTL_USE_NODE_FLAG must be defined)
    void SetFlag( bool aFlag )
    inline void SetFlag( bool aFlag )
    {
    {
        m_flag = aFlag;
        m_flag = aFlag;
    }
    }


    /// Returns the flag (TTL_USE_NODE_FLAG must be defined)
    /// Returns the flag (TTL_USE_NODE_FLAG must be defined)
    const bool& GetFlag() const
    inline const bool& GetFlag() const
    {
    {
        return m_flag;
        return m_flag;
    }
    }
#endif
#endif


    void IncRefCount()
    inline void IncRefCount()
    {
    {
        m_refCount++;
        m_refCount++;
    }
    }


    void DecRefCount()
    inline void DecRefCount()
    {
    {
        m_refCount--;
        m_refCount--;
    }
    }


    unsigned int GetRefCount() const
    inline unsigned int GetRefCount() const
    {
    {
        return m_refCount;
        return m_refCount;
    }
    }
@@ -187,55 +202,65 @@ public:
    {
    {
    }
    }


    /// Returns tag, common identifier for connected nodes
    inline int GetTag() const
    {
        int tag = GetSourceNode()->GetTag();
        if( tag >= 0 )
            return tag;

        return GetTargetNode()->GetTag();
    }

    /// Sets the source node
    /// Sets the source node
    void SetSourceNode( const NODE_PTR& aNode )
    inline void SetSourceNode( const NODE_PTR& aNode )
    {
    {
        m_sourceNode = aNode;
        m_sourceNode = aNode;
    }
    }


    /// Sets the next edge in face
    /// Sets the next edge in face
    void SetNextEdgeInFace( const EDGE_PTR& aEdge )
    inline void SetNextEdgeInFace( const EDGE_PTR& aEdge )
    {
    {
        m_nextEdgeInFace = aEdge;
        m_nextEdgeInFace = aEdge;
    }
    }


    /// Sets the twin edge
    /// Sets the twin edge
    void SetTwinEdge( const EDGE_PTR& aEdge )
    inline void SetTwinEdge( const EDGE_PTR& aEdge )
    {
    {
        m_twinEdge = aEdge;
        m_twinEdge = aEdge;
    }
    }


    /// Sets the edge as a leading edge
    /// Sets the edge as a leading edge
    void SetAsLeadingEdge( bool aLeading = true )
    inline void SetAsLeadingEdge( bool aLeading = true )
    {
    {
        m_isLeadingEdge = aLeading;
        m_isLeadingEdge = aLeading;
    }
    }


    /// Checks if an edge is a leading edge
    /// Checks if an edge is a leading edge
    bool IsLeadingEdge() const
    inline bool IsLeadingEdge() const
    {
    {
        return m_isLeadingEdge;
        return m_isLeadingEdge;
    }
    }


    /// Returns the twin edge
    /// Returns the twin edge
    EDGE_PTR GetTwinEdge() const
    inline EDGE_PTR GetTwinEdge() const
    {
    {
        return m_twinEdge.lock();
        return m_twinEdge.lock();
    }
    }


    void ClearTwinEdge()
    inline void ClearTwinEdge()
    {
    {
        m_twinEdge.reset();
        m_twinEdge.reset();
    }
    }


    /// Returns the next edge in face
    /// Returns the next edge in face
    const EDGE_PTR& GetNextEdgeInFace() const
    inline const EDGE_PTR& GetNextEdgeInFace() const
    {
    {
        return m_nextEdgeInFace;
        return m_nextEdgeInFace;
    }
    }


    /// Retuns the source node
    /// Retuns the source node
    const NODE_PTR& GetSourceNode() const
    inline const NODE_PTR& GetSourceNode() const
    {
    {
        return m_sourceNode;
        return m_sourceNode;
    }
    }
@@ -246,12 +271,12 @@ public:
        return m_nextEdgeInFace->GetSourceNode();
        return m_nextEdgeInFace->GetSourceNode();
    }
    }


    void SetWeight( unsigned int weight )
    inline void SetWeight( unsigned int weight )
    {
    {
        m_weight = weight;
        m_weight = weight;
    }
    }


    unsigned int GetWeight() const
    inline unsigned int GetWeight() const
    {
    {
        return m_weight;
        return m_weight;
    }
    }
@@ -294,22 +319,17 @@ public:
        m_weight = aWeight;
        m_weight = aWeight;
    }
    }


    EDGE_MST( const EDGE& edge )
    {
        m_sourceNode = edge.GetSourceNode();
        m_target = edge.GetTargetNode();
        m_weight = edge.GetWeight();
    }

    ~EDGE_MST()
    {
    }

    /// @copydoc Edge::setSourceNode()
    /// @copydoc Edge::setSourceNode()
    virtual const NODE_PTR& GetTargetNode() const
    virtual const NODE_PTR& GetTargetNode() const
    {
    {
        return m_target;
        return m_target;
    }
    }

private:
    EDGE_MST( const EDGE& aEdge )
    {
        assert( false );
    }
};
};


class DART; // Forward declaration (class in this namespace)
class DART; // Forward declaration (class in this namespace)
+159 −38
Original line number Original line Diff line number Diff line
/*
/*
 * This program source code file is part of KICAD, a free EDA CAD application.
 * This program source code file is part of KICAD, a free EDA CAD application.
 *
 *
 * Copyright (C) 2013 CERN
 * Copyright (C) 2013-2015 CERN
 * @author Maciej Suminski <maciej.suminski@cern.ch>
 * @author Maciej Suminski <maciej.suminski@cern.ch>
 *
 *
 * This program is free software; you can redistribute it and/or
 * This program is free software; you can redistribute it and/or
@@ -96,22 +96,26 @@ bool isEdgeConnectingNode( const RN_EDGE_PTR& aEdge, const RN_NODE_PTR& aNode )
}
}




std::vector<RN_EDGE_PTR>* kruskalMST( RN_LINKS::RN_EDGE_LIST& aEdges,
static std::vector<RN_EDGE_MST_PTR>* kruskalMST( RN_LINKS::RN_EDGE_LIST& aEdges,
                                      const std::vector<RN_NODE_PTR>& aNodes )
                                                 std::vector<RN_NODE_PTR>& aNodes )
{
{
    unsigned int nodeNumber = aNodes.size();
    unsigned int nodeNumber = aNodes.size();
    unsigned int mstExpectedSize = nodeNumber - 1;
    unsigned int mstExpectedSize = nodeNumber - 1;
    unsigned int mstSize = 0;
    unsigned int mstSize = 0;
    bool ratsnestLines = false;


    // The output
    // The output
    std::vector<RN_EDGE_PTR>* mst = new std::vector<RN_EDGE_PTR>;
    std::vector<RN_EDGE_MST_PTR>* mst = new std::vector<RN_EDGE_MST_PTR>;
    mst->reserve( mstExpectedSize );
    mst->reserve( mstExpectedSize );


    // Set tags for marking cycles
    // Set tags for marking cycles
    boost::unordered_map<RN_NODE_PTR, int> tags;
    boost::unordered_map<RN_NODE_PTR, int> tags;
    unsigned int tag = 0;
    unsigned int tag = 0;
    BOOST_FOREACH( const RN_NODE_PTR& node, aNodes )
    BOOST_FOREACH( RN_NODE_PTR& node, aNodes )
    {
        node->SetTag( tag );
        tags[node] = tag++;
        tags[node] = tag++;
    }


    // Lists of nodes connected together (subtrees) to detect cycles in the graph
    // Lists of nodes connected together (subtrees) to detect cycles in the graph
    std::vector<std::list<int> > cycles( nodeNumber );
    std::vector<std::list<int> > cycles( nodeNumber );
@@ -123,27 +127,40 @@ std::vector<RN_EDGE_PTR>* kruskalMST( RN_LINKS::RN_EDGE_LIST& aEdges,


    while( mstSize < mstExpectedSize && !aEdges.empty() )
    while( mstSize < mstExpectedSize && !aEdges.empty() )
    {
    {
        RN_EDGE_PTR& dt = *aEdges.begin();
        RN_EDGE_PTR& dt = aEdges.front();


        int srcTag = tags[dt->GetSourceNode()];
        int srcTag = tags[dt->GetSourceNode()];
        int trgTag = tags[dt->GetTargetNode()];
        int trgTag = tags[dt->GetTargetNode()];


        // Because edges are sorted by their weight, first we always process connected
        // items (weight == 0). Once we stumble upon an edge with non-zero weight,
        // it means that the rest of the lines are ratsnest.
        if( !ratsnestLines && dt->GetWeight() != 0 )
            ratsnestLines = true;

        // Check if by adding this edge we are going to join two different forests
        // Check if by adding this edge we are going to join two different forests
        if( srcTag != trgTag )
        if( srcTag != trgTag )
        {
        {
            // Update tags
            // Update tags
            std::list<int>::iterator it, itEnd;
            std::list<int>::iterator it, itEnd;

            if( ratsnestLines )
            {
                for( it = cycles[trgTag].begin(), itEnd = cycles[trgTag].end(); it != itEnd; ++it )
                for( it = cycles[trgTag].begin(), itEnd = cycles[trgTag].end(); it != itEnd; ++it )
                    tags[aNodes[*it]] = srcTag;
                    tags[aNodes[*it]] = srcTag;
            }
            else
            {
                for( it = cycles[trgTag].begin(), itEnd = cycles[trgTag].end(); it != itEnd; ++it ) {
                    tags[aNodes[*it]] = srcTag;
                    aNodes[*it]->SetTag( srcTag );
                }
            }


            // Move nodes that were marked with old tag to the list marked with the new tag
            // Move nodes that were marked with old tag to the list marked with the new tag
            cycles[srcTag].splice( cycles[srcTag].end(), cycles[trgTag] );
            cycles[srcTag].splice( cycles[srcTag].end(), cycles[trgTag] );


            if( dt->GetWeight() == 0 )      // Skip already existing connections (weight == 0)
            if( ratsnestLines )
            {
                mstExpectedSize--;
            }
            else
            {
            {
                // Do a copy of edge, but make it RN_EDGE_MST. In contrary to RN_EDGE,
                // Do a copy of edge, but make it RN_EDGE_MST. In contrary to RN_EDGE,
                // RN_EDGE_MST saves both source and target node and does not require any other
                // RN_EDGE_MST saves both source and target node and does not require any other
@@ -154,6 +171,11 @@ std::vector<RN_EDGE_PTR>* kruskalMST( RN_LINKS::RN_EDGE_LIST& aEdges,
                mst->push_back( newEdge );
                mst->push_back( newEdge );
                ++mstSize;
                ++mstSize;
            }
            }
            else
            {
                // Processing a connection, decrease the expected size of the ratsnest MST
                --mstExpectedSize;
            }
        }
        }


        // Remove the edge that was just processed
        // Remove the edge that was just processed
@@ -167,7 +189,7 @@ std::vector<RN_EDGE_PTR>* kruskalMST( RN_LINKS::RN_EDGE_LIST& aEdges,
}
}




void RN_NET::validateEdge( RN_EDGE_PTR& aEdge )
void RN_NET::validateEdge( RN_EDGE_MST_PTR& aEdge )
{
{
    RN_NODE_PTR source = aEdge->GetSourceNode();
    RN_NODE_PTR source = aEdge->GetSourceNode();
    RN_NODE_PTR target = aEdge->GetTargetNode();
    RN_NODE_PTR target = aEdge->GetTargetNode();
@@ -238,12 +260,13 @@ bool RN_LINKS::RemoveNode( const RN_NODE_PTR& aNode )
}
}




const RN_EDGE_PTR& RN_LINKS::AddConnection( const RN_NODE_PTR& aNode1, const RN_NODE_PTR& aNode2,
RN_EDGE_MST_PTR RN_LINKS::AddConnection( const RN_NODE_PTR& aNode1, const RN_NODE_PTR& aNode2,
                                          unsigned int aDistance )
                                          unsigned int aDistance )
{
{
    m_edges.push_back( boost::make_shared<RN_EDGE_MST>( aNode1, aNode2, aDistance ) );
    RN_EDGE_MST_PTR edge = boost::make_shared<RN_EDGE_MST>( aNode1, aNode2, aDistance );
    m_edges.push_back( edge );


    return m_edges.back();
    return edge;
}
}




@@ -252,10 +275,10 @@ void RN_NET::compute()
    const RN_LINKS::RN_NODE_SET& boardNodes = m_links.GetNodes();
    const RN_LINKS::RN_NODE_SET& boardNodes = m_links.GetNodes();
    const RN_LINKS::RN_EDGE_LIST& boardEdges = m_links.GetConnections();
    const RN_LINKS::RN_EDGE_LIST& boardEdges = m_links.GetConnections();


    // Special case that does need so complicated algorithm
    // Special cases that does need so complicated algorithm
    if( boardNodes.size() == 2 )
    if( boardNodes.size() <= 2 )
    {
    {
        m_rnEdges.reset( new std::vector<RN_EDGE_PTR>( 0 ) );
        m_rnEdges.reset( new std::vector<RN_EDGE_MST_PTR>( 0 ) );


        // Check if the only possible connection exists
        // Check if the only possible connection exists
        if( boardEdges.size() == 0 )
        if( boardEdges.size() == 0 )
@@ -268,12 +291,6 @@ void RN_NET::compute()


        return;
        return;
    }
    }
    else if( boardNodes.size() <= 1 )   // This case is even simpler
    {
        m_rnEdges.reset( new std::vector<RN_EDGE_PTR>( 0 ) );

        return;
    }


    // Move and sort (sorting speeds up) all nodes to a vector for the Delaunay triangulation
    // Move and sort (sorting speeds up) all nodes to a vector for the Delaunay triangulation
    std::vector<RN_NODE_PTR> nodes( boardNodes.size() );
    std::vector<RN_NODE_PTR> nodes( boardNodes.size() );
@@ -301,7 +318,7 @@ void RN_NET::clearNode( const RN_NODE_PTR& aNode )
    if( !m_rnEdges )
    if( !m_rnEdges )
        return;
        return;


    std::vector<RN_EDGE_PTR>::iterator newEnd;
    std::vector<RN_EDGE_MST_PTR>::iterator newEnd;


    // Remove all ratsnest edges for associated with the node
    // Remove all ratsnest edges for associated with the node
    newEnd = std::remove_if( m_rnEdges->begin(), m_rnEdges->end(),
    newEnd = std::remove_if( m_rnEdges->begin(), m_rnEdges->end(),
@@ -377,7 +394,7 @@ void RN_NET::Update()


    compute();
    compute();


    BOOST_FOREACH( RN_EDGE_PTR& edge, *m_rnEdges )
    BOOST_FOREACH( RN_EDGE_MST_PTR& edge, *m_rnEdges )
        validateEdge( edge );
        validateEdge( edge );


    m_dirty = false;
    m_dirty = false;
@@ -386,8 +403,7 @@ void RN_NET::Update()


void RN_NET::AddItem( const D_PAD* aPad )
void RN_NET::AddItem( const D_PAD* aPad )
{
{
    RN_NODE_PTR nodePtr = m_links.AddNode( aPad->GetPosition().x, aPad->GetPosition().y );
    m_pads[aPad] = m_links.AddNode( aPad->GetPosition().x, aPad->GetPosition().y );
    m_pads[aPad] = nodePtr;


    m_dirty = true;
    m_dirty = true;
}
}
@@ -505,7 +521,7 @@ void RN_NET::RemoveItem( const TRACK* aTrack )
{
{
    try
    try
    {
    {
        RN_EDGE_PTR& edge = m_tracks.at( aTrack );
        RN_EDGE_MST_PTR& edge = m_tracks.at( aTrack );


        // Save nodes, so they can be cleared later
        // Save nodes, so they can be cleared later
        RN_NODE_PTR aBegin = edge->GetSourceNode();
        RN_NODE_PTR aBegin = edge->GetSourceNode();
@@ -546,8 +562,8 @@ void RN_NET::RemoveItem( const ZONE_CONTAINER* aZone )
        polygons.clear();
        polygons.clear();


        // Remove all connections added by the zone
        // Remove all connections added by the zone
        std::deque<RN_EDGE_PTR>& edges = m_zoneConnections.at( aZone );
        std::deque<RN_EDGE_MST_PTR>& edges = m_zoneConnections.at( aZone );
        BOOST_FOREACH( RN_EDGE_PTR& edge, edges )
        BOOST_FOREACH( RN_EDGE_PTR edge, edges )
            m_links.RemoveConnection( edge );
            m_links.RemoveConnection( edge );
        edges.clear();
        edges.clear();


@@ -694,7 +710,7 @@ std::list<RN_NODE_PTR> RN_NET::GetNodes( const BOARD_CONNECTED_ITEM* aItem ) con
        case PCB_TRACE_T:
        case PCB_TRACE_T:
        {
        {
            const TRACK* track = static_cast<const TRACK*>( aItem );
            const TRACK* track = static_cast<const TRACK*>( aItem );
            RN_EDGE_PTR edge = m_tracks.at( track );
            const RN_EDGE_MST_PTR& edge = m_tracks.at( track );


            nodes.push_back( edge->GetSourceNode() );
            nodes.push_back( edge->GetSourceNode() );
            nodes.push_back( edge->GetTargetNode() );
            nodes.push_back( edge->GetTargetNode() );
@@ -714,6 +730,76 @@ std::list<RN_NODE_PTR> RN_NET::GetNodes( const BOARD_CONNECTED_ITEM* aItem ) con
}
}




void RN_NET::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();
}


void RN_NET::GetConnectedItems( const BOARD_CONNECTED_ITEM* aItem,
                                std::list<BOARD_CONNECTED_ITEM*>& aOutput,
                                RN_ITEM_TYPES aTypes ) const
{
    std::list<RN_NODE_PTR> nodes = GetNodes( aItem );
    assert( !nodes.empty() );

    int tag = nodes.front()->GetTag();
    assert( tag >= 0 );

    if( aTypes & RN_PADS )
    {
        for( PAD_NODE_MAP::const_iterator it = m_pads.begin(); it != m_pads.end(); ++it )
        {
            if( it->second->GetTag() == tag )
                aOutput.push_back( const_cast<D_PAD*>( it->first ) );
        }
    }

    if( aTypes & RN_VIAS )
    {
        for( VIA_NODE_MAP::const_iterator it = m_vias.begin(); it != m_vias.end(); ++it )
        {
            if( it->second->GetTag() == tag )
                aOutput.push_back( const_cast<VIA*>( it->first ) );
        }
    }

    if( aTypes & RN_TRACKS )
    {
        for( TRACK_EDGE_MAP::const_iterator it = m_tracks.begin(); it != m_tracks.end(); ++it )
        {
            if( it->second->GetTag() == tag )
                aOutput.push_back( const_cast<TRACK*>( it->first ) );
        }
    }

    if( aTypes & RN_ZONES )
    {
        for( ZONE_EDGE_MAP::const_iterator it = m_zoneConnections.begin();
                it != m_zoneConnections.end(); ++it )
        {
            const std::deque<RN_EDGE_MST_PTR>& edges = it->second;

            BOOST_FOREACH( const RN_EDGE_MST_PTR& edge, edges )
            {
                if( edge->GetTag() == tag )
                {
                    aOutput.push_back( const_cast<ZONE_CONTAINER*>( it->first ) );
                    break;
                }
            }
        }
    }
}


void RN_DATA::AddSimple( const BOARD_ITEM* aItem )
void RN_DATA::AddSimple( const BOARD_ITEM* aItem )
{
{
    int net;
    int net;
@@ -784,11 +870,46 @@ void RN_DATA::AddSimple( const VECTOR2I& aPosition, int aNetCode )
}
}




void RN_DATA::GetConnectedItems( const BOARD_CONNECTED_ITEM* aItem,
                                 std::list<BOARD_CONNECTED_ITEM*>& aOutput,
                                 RN_ITEM_TYPES aTypes ) const
{
    int net = aItem->GetNetCode();

    if( net < 1 )
        return;

    assert( net < (int) m_nets.size() );

    m_nets[net].GetConnectedItems( aItem, aOutput, aTypes );
}


bool RN_DATA::AreConnected( const BOARD_CONNECTED_ITEM* aItem, const BOARD_CONNECTED_ITEM* aOther )
{
    int net1 = aItem->GetNetCode();
    int net2 = aOther->GetNetCode();

    if( net1 < 1 || net2 < 1 || net1 != net2 )
        return false;

    assert( net1 < (int) m_nets.size() && net2 < (int) m_nets.size() );

    // net1 == net2
    std::list<RN_NODE_PTR> items1 = m_nets[net1].GetNodes( aItem );
    std::list<RN_NODE_PTR> items2 = m_nets[net1].GetNodes( aOther );

    assert( !items1.empty() && !items2.empty() );

    return ( items1.front()->GetTag() == items2.front()->GetTag() );
}


void RN_NET::processZones()
void RN_NET::processZones()
{
{
    BOOST_FOREACH( std::deque<RN_EDGE_PTR>& edges, m_zoneConnections | boost::adaptors::map_values )
    BOOST_FOREACH( std::deque<RN_EDGE_MST_PTR>& edges, m_zoneConnections | boost::adaptors::map_values )
    {
    {
        BOOST_FOREACH( RN_EDGE_PTR& edge, edges )
        BOOST_FOREACH( RN_EDGE_MST_PTR edge, edges )
            m_links.RemoveConnection( edge );
            m_links.RemoveConnection( edge );


        edges.clear();
        edges.clear();
@@ -814,7 +935,7 @@ void RN_NET::processZones()
            {
            {
                if( poly->HitTest( *point ) )
                if( poly->HitTest( *point ) )
                {
                {
                    const RN_EDGE_PTR& connection = m_links.AddConnection( poly->GetNode(), *point );
                    RN_EDGE_MST_PTR connection = m_links.AddConnection( poly->GetNode(), *point );
                    m_zoneConnections[poly->GetParent()].push_back( connection );
                    m_zoneConnections[poly->GetParent()].push_back( connection );


                    // This point already belongs to a polygon, we do not need to check it anymore
                    // This point already belongs to a polygon, we do not need to check it anymore
+65 −39
Original line number Original line Diff line number Diff line
/*
/*
 * This program source code file is part of KICAD, a free EDA CAD application.
 * This program source code file is part of KICAD, a free EDA CAD application.
 *
 *
 * Copyright (C) 2013 CERN
 * Copyright (C) 2013-2015 CERN
 * @author Maciej Suminski <maciej.suminski@cern.ch>
 * @author Maciej Suminski <maciej.suminski@cern.ch>
 *
 *
 * This program is free software; you can redistribute it and/or
 * This program is free software; you can redistribute it and/or
@@ -49,6 +49,16 @@ class TRACK;
class ZONE_CONTAINER;
class ZONE_CONTAINER;
class CPolyPt;
class CPolyPt;


///> Types of items that are handled by the class
enum RN_ITEM_TYPES
{
    RN_PADS    = 0x01,
    RN_VIAS    = 0x02,
    RN_TRACKS  = 0x04,
    RN_ZONES   = 0x08,
    RN_ALL     = 0xFF
};

// Preserve KiCad coding style policy
// Preserve KiCad coding style policy
typedef hed::NODE           RN_NODE;
typedef hed::NODE           RN_NODE;
typedef hed::NODE_PTR       RN_NODE_PTR;
typedef hed::NODE_PTR       RN_NODE_PTR;
@@ -157,7 +167,7 @@ public:
     * @param aDistance is the distance of the connection (0 means that nodes are actually
     * @param aDistance is the distance of the connection (0 means that nodes are actually
     * connected, >0 means a missing connection).
     * connected, >0 means a missing connection).
     */
     */
    const RN_EDGE_PTR& AddConnection( const RN_NODE_PTR& aNode1, const RN_NODE_PTR& aNode2,
    RN_EDGE_MST_PTR AddConnection( const RN_NODE_PTR& aNode1, const RN_NODE_PTR& aNode2,
                                    unsigned int aDistance = 0 );
                                    unsigned int aDistance = 0 );


    /**
    /**
@@ -181,7 +191,7 @@ public:
    }
    }


protected:
protected:
    ///> Set of nodes that are used are expected to be connected together.
    ///> Set of nodes that are expected to be connected together (vias, tracks, pads).
    RN_NODE_SET m_nodes;
    RN_NODE_SET m_nodes;


    ///> List of edges that currently connect nodes.
    ///> List of edges that currently connect nodes.
@@ -210,7 +220,6 @@ public:
        return m_node;
        return m_node;
    }
    }



    /**
    /**
     * Function GetParent()
     * Function GetParent()
     * Returns pointer to zone that is the owner of subpolygon.
     * Returns pointer to zone that is the owner of subpolygon.
@@ -307,7 +316,7 @@ public:
     * Returns pointer to a vector of edges that makes ratsnest for a given net.
     * Returns pointer to a vector of edges that makes ratsnest for a given net.
     * @return Pointer to a vector of edges that makes ratsnest for a given net.
     * @return Pointer to a vector of edges that makes ratsnest for a given net.
     */
     */
    const std::vector<RN_EDGE_PTR>* GetUnconnected() const
    const std::vector<RN_EDGE_MST_PTR>* GetUnconnected() const
    {
    {
        return m_rnEdges.get();
        return m_rnEdges.get();
    }
    }
@@ -429,22 +438,12 @@ public:
    std::list<RN_NODE_PTR> GetClosestNodes( const RN_NODE_PTR& aNode,
    std::list<RN_NODE_PTR> GetClosestNodes( const RN_NODE_PTR& aNode,
                                            const RN_NODE_FILTER& aFilter, int aNumber = -1 ) const;
                                            const RN_NODE_FILTER& aFilter, int aNumber = -1 ) const;


    /**
     * 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.
     */
    const std::vector<RN_EDGE_PTR>* GetEdges() const
    {
        return m_rnEdges.get();
    }

    /**
    /**
     * Function AddSimpleNode()
     * Function AddSimpleNode()
     * Changes drawing mode for a node to simple (i.e. one ratsnest line per node).
     * 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.
     * @param aNode is a node that changes its drawing mode.
     */
     */
    void AddSimpleNode( RN_NODE_PTR& aNode )
    inline void AddSimpleNode( RN_NODE_PTR& aNode )
    {
    {
        m_simpleNodes.push_back( aNode );
        m_simpleNodes.push_back( aNode );
        aNode->SetFlag( true );
        aNode->SetFlag( true );
@@ -456,7 +455,7 @@ public:
     * target the node). The status is cleared after calling ClearSimple().
     * 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.
     * @param aNode is the node that is not going to be used as a ratsnest line target.
     */
     */
    void AddBlockedNode( RN_NODE_PTR& aNode )
    inline void AddBlockedNode( RN_NODE_PTR& aNode )
    {
    {
        m_blockedNodes.push_back( aNode );
        m_blockedNodes.push_back( aNode );
        aNode->SetFlag( true );
        aNode->SetFlag( true );
@@ -468,7 +467,7 @@ public:
     * ratsnest line per node).
     * ratsnest line per node).
     * @return list of nodes for which ratsnest is drawn in simple mode.
     * @return list of nodes for which ratsnest is drawn in simple mode.
     */
     */
    const std::deque<RN_NODE_PTR>& GetSimpleNodes() const
    inline const std::deque<RN_NODE_PTR>& GetSimpleNodes() const
    {
    {
        return m_simpleNodes;
        return m_simpleNodes;
    }
    }
@@ -477,22 +476,23 @@ public:
     * Function ClearSimple()
     * Function ClearSimple()
     * Removes all nodes and edges that are used for displaying ratsnest in simple mode.
     * 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();
     * Function GetConnectedItems()
    }
     * Adds items that are connected together to a list.
     * @param aItem is the reference item to find other connected items.
     * @param aOutput is the list that will contain found items.
     * @param aTypes allows to filter by item types.
     */
    void GetConnectedItems( const BOARD_CONNECTED_ITEM* aItem,
                            std::list<BOARD_CONNECTED_ITEM*>& aOutput,
                            RN_ITEM_TYPES aTypes = RN_ALL) const;


protected:
protected:
    ///> Validates edge, i.e. 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.
    ///> to make sure that they are not ones with the flag set.
    void validateEdge( RN_EDGE_PTR& aEdge );
    void validateEdge( RN_EDGE_MST_PTR& aEdge );


    ///> Removes all ratsnest edges for a given node.
    ///> Removes all ratsnest edges for a given node.
    void clearNode( const RN_NODE_PTR& aNode );
    void clearNode( const RN_NODE_PTR& aNode );
@@ -507,31 +507,37 @@ protected:
    RN_LINKS m_links;
    RN_LINKS m_links;


    ///> Vector of edges that makes ratsnest for a given net.
    ///> Vector of edges that makes ratsnest for a given net.
    boost::shared_ptr< std::vector<RN_EDGE_PTR> > m_rnEdges;
    boost::shared_ptr< std::vector<RN_EDGE_MST_PTR> > m_rnEdges;


    ///> List of nodes for which ratsnest is drawn in simple mode.
    ///> List of nodes for which ratsnest is drawn in simple mode.
    std::deque<RN_NODE_PTR> m_simpleNodes;
    std::deque<RN_NODE_PTR> m_simpleNodes;


    ///> List of nodes which should be used as ratsnest target nodes..
    ///> List of nodes which will not be used as ratsnest target nodes.
    std::deque<RN_NODE_PTR> m_blockedNodes;
    std::deque<RN_NODE_PTR> m_blockedNodes;


    ///> Flag indicating necessity of recalculation of ratsnest for a net.
    ///> Flag indicating necessity of recalculation of ratsnest for a net.
    bool m_dirty;
    bool m_dirty;


    ///> Helper typedefs
    typedef boost::unordered_map<const D_PAD*, RN_NODE_PTR> PAD_NODE_MAP;
    typedef boost::unordered_map<const VIA*, RN_NODE_PTR> VIA_NODE_MAP;
    typedef boost::unordered_map<const TRACK*, RN_EDGE_MST_PTR> TRACK_EDGE_MAP;
    typedef boost::unordered_map<const ZONE_CONTAINER*, std::deque<RN_POLY> > ZONE_POLY_MAP;
    typedef boost::unordered_map<const ZONE_CONTAINER*, std::deque<RN_EDGE_MST_PTR> > ZONE_EDGE_MAP;
    ///> Map that associates nodes in the ratsnest model to respective nodes.
    ///> Map that associates nodes in the ratsnest model to respective nodes.
    boost::unordered_map<const D_PAD*, RN_NODE_PTR> m_pads;
    PAD_NODE_MAP m_pads;


    ///> Map that associates nodes in the ratsnest model to respective vias.
    ///> Map that associates nodes in the ratsnest model to respective vias.
    boost::unordered_map<const VIA*, RN_NODE_PTR> m_vias;
    VIA_NODE_MAP m_vias;


    ///> Map that associates edges in the ratsnest model to respective tracks.
    ///> Map that associates edges in the ratsnest model to respective tracks.
    boost::unordered_map<const TRACK*, RN_EDGE_PTR> m_tracks;
    TRACK_EDGE_MAP m_tracks;


    ///> Map that associates groups of subpolygons in the ratsnest model to their respective zones.
    ///> Map that associates groups of subpolygons in the ratsnest model to respective zones.
    boost::unordered_map<const ZONE_CONTAINER*, std::deque<RN_POLY> > m_zonePolygons;
    ZONE_POLY_MAP m_zonePolygons;


    ///> Map that associates groups of edges in the ratsnest model to their respective zones.
    ///> Map that associates groups of edges in the ratsnest model to respective zones.
    boost::unordered_map<const ZONE_CONTAINER*, std::deque<RN_EDGE_PTR> > m_zoneConnections;
    ZONE_EDGE_MAP m_zoneConnections;


    ///> Visibility flag.
    ///> Visibility flag.
    bool m_visible;
    bool m_visible;
@@ -646,6 +652,26 @@ public:
        return m_nets[aNetCode];
        return m_nets[aNetCode];
    }
    }


    /**
     * Function GetConnectedItems()
     * Adds items that are connected together to a list.
     * @param aItem is the reference item to find other connected items.
     * @param aOutput is the list that will contain found items.
     * @param aTypes allows to filter by item types.
     */
    void GetConnectedItems( const BOARD_CONNECTED_ITEM* aItem,
                            std::list<BOARD_CONNECTED_ITEM*>& aOutput,
                            RN_ITEM_TYPES aTypes = RN_ALL ) const;

    /**
     * Function AreConnected()
     * Checks if two items are connected with copper.
     * @param aThis is the first item.
     * @param aOther is the second item.
     * @return True if they are connected, false otherwise.
     */
    bool AreConnected( const BOARD_CONNECTED_ITEM* aItem, const BOARD_CONNECTED_ITEM* aOther );

protected:
protected:
    /**
    /**
     * Function updateNet()
     * Function updateNet()
+4 −3
Original line number Original line Diff line number Diff line
@@ -72,7 +72,7 @@ void RATSNEST_VIEWITEM::ViewDraw( int aLayer, GAL* aGal ) const
        // Set brighter color for the temporary ratsnest
        // Set brighter color for the temporary ratsnest
        aGal->SetStrokeColor( color.Brightened( 0.8 ) );
        aGal->SetStrokeColor( color.Brightened( 0.8 ) );


        // Draw the "dynamic" ratsnest (ie. for objects that may be currently being moved)
        // Draw the "dynamic" ratsnest (i.e. for objects that may be currently being moved)
        BOOST_FOREACH( const RN_NODE_PTR& node, net.GetSimpleNodes() )
        BOOST_FOREACH( const RN_NODE_PTR& node, net.GetSimpleNodes() )
        {
        {
            RN_NODE_PTR dest = net.GetClosestNode( node, WITHOUT_FLAG() );
            RN_NODE_PTR dest = net.GetClosestNode( node, WITHOUT_FLAG() );
@@ -93,11 +93,12 @@ void RATSNEST_VIEWITEM::ViewDraw( int aLayer, GAL* aGal ) const
        if( i != highlightedNet )
        if( i != highlightedNet )
            aGal->SetStrokeColor( color );  // using the default ratsnest color for not highlighted
            aGal->SetStrokeColor( color );  // using the default ratsnest color for not highlighted


        const std::vector<RN_EDGE_PTR>* edges = net.GetUnconnected();
        const std::vector<RN_EDGE_MST_PTR>* edges = net.GetUnconnected();

        if( edges == NULL )
        if( edges == NULL )
            continue;
            continue;


        BOOST_FOREACH( const RN_EDGE_PTR& edge, *edges )
        BOOST_FOREACH( const RN_EDGE_MST_PTR& edge, *edges )
        {
        {
            const RN_NODE_PTR& sourceNode = edge->GetSourceNode();
            const RN_NODE_PTR& sourceNode = edge->GetSourceNode();
            const RN_NODE_PTR& targetNode = edge->GetTargetNode();
            const RN_NODE_PTR& targetNode = edge->GetTargetNode();