From 1f5fb979b9e9de06c336988e10d9064768b1c5f4 Mon Sep 17 00:00:00 2001 From: Seth Hillbrand Date: Tue, 28 Jul 2020 10:17:56 -0700 Subject: [PATCH] Keep PNS item RTree on layer-by-layer Rather than extra splitting of the RTree that we use for collision detection on types and direction, we limit this to checks on layer-by-layer basis. This also allows for layer expansion by using deque of RTrees rather than fixed index This fixes the missing layernumbers and keeps the layers in a deque to prevent re-allocation on expansion. Replaces ad94b6205 --- pcbnew/router/pns_index.cpp | 95 +++++-------------------------------- pcbnew/router/pns_index.h | 78 +++++------------------------- 2 files changed, 26 insertions(+), 147 deletions(-) diff --git a/pcbnew/router/pns_index.cpp b/pcbnew/router/pns_index.cpp index 97885b0c35..88b096b815 100644 --- a/pcbnew/router/pns_index.cpp +++ b/pcbnew/router/pns_index.cpp @@ -23,91 +23,35 @@ namespace PNS { -INDEX::INDEX() -{ - memset( m_subIndices, 0, sizeof( m_subIndices ) ); -} - - -INDEX::~INDEX() -{ - Clear(); -} - - -INDEX::ITEM_SHAPE_INDEX* INDEX::getSubindex( const ITEM* aItem ) -{ - int idx_n = -1; - - const LAYER_RANGE& l = aItem->Layers(); - - switch( aItem->Kind() ) - { - case ITEM::VIA_T: - idx_n = SI_Multilayer; - break; - - case ITEM::SOLID_T: - { - if( l.IsMultilayer() ) - idx_n = SI_Multilayer; - else if( l.Start() == B_Cu ) // fixme: use kicad layer codes - idx_n = SI_PadsTop; - else if( l.Start() == F_Cu ) - idx_n = SI_PadsBottom; - else - idx_n = SI_Traces + 2 * l.Start() + SI_SegStraight; - } - break; - - case ITEM::ARC_T: - case ITEM::SEGMENT_T: - case ITEM::LINE_T: - idx_n = SI_Traces + 2 * l.Start() + SI_SegStraight; - break; - - default: - break; - } - - if( idx_n < 0 || idx_n >= MaxSubIndices ) - { - wxASSERT( idx_n >= 0 ); - wxASSERT( idx_n < MaxSubIndices ); - return nullptr; - } - - if( !m_subIndices[idx_n] ) - m_subIndices[idx_n] = new ITEM_SHAPE_INDEX; - - return m_subIndices[idx_n]; -} void INDEX::Add( ITEM* aItem ) { - ITEM_SHAPE_INDEX* idx = getSubindex( aItem ); + const LAYER_RANGE& range = aItem->Layers(); - if( !idx ) - return; + if( m_subIndices.size() <= static_cast( range.End() ) ) + m_subIndices.resize( 2 * range.End() + 1 ); // +1 handles the 0 case + + for( int i = range.Start(); i <= range.End(); ++i ) + m_subIndices[i].Add( aItem ); - idx->Add( aItem ); m_allItems.insert( aItem ); int net = aItem->Net(); if( net >= 0 ) - { m_netMap[net].push_back( aItem ); - } } + void INDEX::Remove( ITEM* aItem ) { - ITEM_SHAPE_INDEX* idx = getSubindex( aItem ); + const LAYER_RANGE& range = aItem->Layers(); - if( !idx ) + if( m_subIndices.size() <= static_cast( range.End() ) ) return; - idx->Remove( aItem ); + for( int i = range.Start(); i < range.End(); ++i ) + m_subIndices[i].Remove( aItem ); + m_allItems.erase( aItem ); int net = aItem->Net(); @@ -115,6 +59,7 @@ void INDEX::Remove( ITEM* aItem ) m_netMap[net].remove( aItem ); } + void INDEX::Replace( ITEM* aOldItem, ITEM* aNewItem ) { Remove( aOldItem ); @@ -122,20 +67,6 @@ void INDEX::Replace( ITEM* aOldItem, ITEM* aNewItem ) } -void INDEX::Clear() -{ - for( int i = 0; i < MaxSubIndices; ++i ) - { - ITEM_SHAPE_INDEX* idx = m_subIndices[i]; - - if( idx ) - delete idx; - - m_subIndices[i] = NULL; - } -} - - INDEX::NET_ITEMS_LIST* INDEX::GetItemsForNet( int aNet ) { if( m_netMap.find( aNet ) == m_netMap.end() ) diff --git a/pcbnew/router/pns_index.h b/pcbnew/router/pns_index.h index 28da0107a6..f87caa9ad8 100644 --- a/pcbnew/router/pns_index.h +++ b/pcbnew/router/pns_index.h @@ -2,7 +2,7 @@ * KiRouter - a push-and-(sometimes-)shove PCB router * * Copyright (C) 2013-2014 CERN - * Copyright (C) 2016 KiCad Developers, see AUTHORS.txt for contributors. + * Copyright (C) 2016-2020 KiCad Developers, see AUTHORS.txt for contributors. * Author: Tomasz Wlostowski * * This program is free software: you can redistribute it and/or modify it @@ -22,13 +22,12 @@ #ifndef __PNS_INDEX_H #define __PNS_INDEX_H -#include +#include +#include #include #include -#include - -#include +#include #include #include "pns_item.h" @@ -50,33 +49,24 @@ public: typedef SHAPE_INDEX ITEM_SHAPE_INDEX; typedef std::unordered_set ITEM_SET; - INDEX(); - ~INDEX(); + INDEX(){}; /** - * Function Add() - * * Adds item to the spatial index. */ void Add( ITEM* aItem ); /** - * Function Remove() - * * Removes an item from the spatial index. */ void Remove( ITEM* aItem ); /** - * Function Add() - * * Replaces one item with another. */ void Replace( ITEM* aOldItem, ITEM* aNewItem ); /** - * Function Query() - * * Searches items in the index that are in proximity of aItem. * For each item, function object aVisitor is called. Only items on * overlapping layers are considered. @@ -91,8 +81,6 @@ public: int Query( const ITEM* aItem, int aMinDistance, Visitor& aVisitor ); /** - * Function Query() - * * Searches items in the index that are in proximity of aShape. * For each item, function object aVisitor is called. Treats all * layers as colliding. @@ -107,15 +95,6 @@ public: int Query( const SHAPE* aShape, int aMinDistance, Visitor& aVisitor ); /** - * Function Clear() - * - * Removes all items from the index. - */ - void Clear(); - - /** - * Function GetItemsForNet() - * * Returns list of all items in a given net. */ NET_ITEMS_LIST* GetItemsForNet( int aNet ); @@ -131,8 +110,6 @@ public: } /** - * Function Size() - * * Returns number of items stored in the index. */ int Size() const { return m_allItems.size(); } @@ -141,63 +118,34 @@ public: ITEM_SET::iterator end() { return m_allItems.end(); } private: - static const int MaxSubIndices = 128; - static const int SI_Multilayer = 2; - static const int SI_SegDiagonal = 0; - static const int SI_SegStraight = 1; - static const int SI_Traces = 3; - static const int SI_PadsTop = 0; - static const int SI_PadsBottom = 1; template - int querySingle( int index, const SHAPE* aShape, int aMinDistance, Visitor& aVisitor ); + int querySingle( std::size_t aIndex, const SHAPE* aShape, int aMinDistance, Visitor& aVisitor ); - ITEM_SHAPE_INDEX* getSubindex( const ITEM* aItem ); - - ITEM_SHAPE_INDEX* m_subIndices[MaxSubIndices]; + std::deque m_subIndices; std::map m_netMap; ITEM_SET m_allItems; }; template -int INDEX::querySingle( int index, const SHAPE* aShape, int aMinDistance, Visitor& aVisitor ) +int INDEX::querySingle( std::size_t aIndex, const SHAPE* aShape, int aMinDistance, Visitor& aVisitor ) { - if( !m_subIndices[index] ) + if( aIndex >= m_subIndices.size() ) return 0; - return m_subIndices[index]->Query( aShape, aMinDistance, aVisitor, false ); + return m_subIndices[aIndex].Query( aShape, aMinDistance, aVisitor, false ); } template int INDEX::Query( const ITEM* aItem, int aMinDistance, Visitor& aVisitor ) { - const SHAPE* shape = aItem->Shape(); int total = 0; - total += querySingle( SI_Multilayer, shape, aMinDistance, aVisitor ); - const LAYER_RANGE& layers = aItem->Layers(); - if( layers.IsMultilayer() ) - { - total += querySingle( SI_PadsTop, shape, aMinDistance, aVisitor ); - total += querySingle( SI_PadsBottom, shape, aMinDistance, aVisitor ); - - for( int i = layers.Start(); i <= layers.End(); ++i ) - total += querySingle( SI_Traces + 2 * i + SI_SegStraight, shape, aMinDistance, aVisitor ); - } - else - { - int l = layers.Start(); - - if( l == B_Cu ) - total += querySingle( SI_PadsTop, shape, aMinDistance, aVisitor ); - else if( l == F_Cu ) - total += querySingle( SI_PadsBottom, shape, aMinDistance, aVisitor ); - - total += querySingle( SI_Traces + 2 * l + SI_SegStraight, shape, aMinDistance, aVisitor ); - } + for( int i = layers.Start(); i <= layers.End(); ++i ) + total += querySingle( i, aItem->Shape(), aMinDistance, aVisitor ); return total; } @@ -207,7 +155,7 @@ int INDEX::Query( const SHAPE* aShape, int aMinDistance, Visitor& aVisitor ) { int total = 0; - for( int i = 0; i < MaxSubIndices; i++ ) + for( std::size_t i = 0; i < m_subIndices.size(); ++i ) total += querySingle( i, aShape, aMinDistance, aVisitor ); return total;