summaryrefslogtreecommitdiff
path: root/include/geometry/shape_index_list.h
diff options
context:
space:
mode:
Diffstat (limited to 'include/geometry/shape_index_list.h')
-rw-r--r--include/geometry/shape_index_list.h291
1 files changed, 291 insertions, 0 deletions
diff --git a/include/geometry/shape_index_list.h b/include/geometry/shape_index_list.h
new file mode 100644
index 0000000..194ae5f
--- /dev/null
+++ b/include/geometry/shape_index_list.h
@@ -0,0 +1,291 @@
+/*
+ * This program source code file is part of KiCad, a free EDA CAD application.
+ *
+ * Copyright (C) 2013 CERN
+ * @author Tomasz Wlostowski <tomasz.wlostowski@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 __SHAPE_INDEX_LIST_H
+#define __SHAPE_INDEX_LIST_H
+
+#include <boost/unordered_map.hpp>
+
+template <class T>
+const SHAPE* defaultShapeFunctor( const T aItem )
+{
+ return aItem->Shape();
+}
+
+template <class T, const SHAPE* (ShapeFunctor) (const T) = defaultShapeFunctor<T> >
+class SHAPE_INDEX_LIST
+{
+ struct SHAPE_ENTRY
+ {
+ SHAPE_ENTRY( T aParent )
+ {
+ shape = ShapeFunctor( aParent );
+ bbox = shape->BBox( 0 );
+ parent = aParent;
+ }
+
+ ~SHAPE_ENTRY()
+ {
+ }
+
+ T parent;
+ const SHAPE* shape;
+ BOX2I bbox;
+ };
+
+ typedef std::vector<SHAPE_ENTRY> SHAPE_VEC;
+ typedef typename std::vector<SHAPE_ENTRY>::iterator SHAPE_VEC_ITER;
+
+public:
+ // "Normal" iterator interface, for STL algorithms.
+ class iterator
+ {
+ public:
+ iterator()
+ {}
+
+ iterator( SHAPE_VEC_ITER aCurrent ) :
+ m_current( aCurrent )
+ {}
+
+ iterator( const iterator& aB ) :
+ m_current( aB.m_current )
+ {}
+
+ T operator*() const
+ {
+ return (*m_current).parent;
+ }
+
+ void operator++()
+ {
+ ++m_current;
+ }
+
+ iterator& operator++( int aDummy )
+ {
+ ++m_current;
+ return *this;
+ }
+
+ bool operator==( const iterator& aRhs ) const
+ {
+ return m_current == aRhs.m_current;
+ }
+
+ bool operator!=( const iterator& aRhs ) const
+ {
+ return m_current != aRhs.m_current;
+ }
+
+ const iterator& operator=( const iterator& aRhs )
+ {
+ m_current = aRhs.m_current;
+ return *this;
+ }
+
+ private:
+ SHAPE_VEC_ITER m_current;
+ };
+
+ // "Query" iterator, for iterating over a set of spatially matching shapes.
+ class query_iterator
+ {
+ public:
+ query_iterator()
+ {
+ }
+
+ query_iterator( SHAPE_VEC_ITER aCurrent, SHAPE_VEC_ITER aEnd, SHAPE* aShape,
+ int aMinDistance, bool aExact ) :
+ m_end( aEnd ),
+ m_current( aCurrent ),
+ m_shape( aShape ),
+ m_minDistance( aMinDistance ),
+ m_exact( aExact )
+ {
+ if( aShape )
+ {
+ m_refBBox = aShape->BBox();
+ next();
+ }
+ }
+
+ query_iterator( const query_iterator& aB ) :
+ m_end( aB.m_end ),
+ m_current( aB.m_current ),
+ m_shape( aB.m_shape ),
+ m_minDistance( aB.m_minDistance ),
+ m_exact( aB.m_exact ),
+ m_refBBox( aB.m_refBBox )
+ {
+ }
+
+ T operator*() const
+ {
+ return (*m_current).parent;
+ }
+
+ query_iterator& operator++()
+ {
+ ++m_current;
+ next();
+ return *this;
+ }
+
+ query_iterator& operator++( int aDummy )
+ {
+ ++m_current;
+ next();
+ return *this;
+ }
+
+ bool operator==( const query_iterator& aRhs ) const
+ {
+ return m_current == aRhs.m_current;
+ }
+
+ bool operator!=( const query_iterator& aRhs ) const
+ {
+ return m_current != aRhs.m_current;
+ }
+
+ const query_iterator& operator=( const query_iterator& aRhs )
+ {
+ m_end = aRhs.m_end;
+ m_current = aRhs.m_current;
+ m_shape = aRhs.m_shape;
+ m_minDistance = aRhs.m_minDistance;
+ m_exact = aRhs.m_exact;
+ m_refBBox = aRhs.m_refBBox;
+ return *this;
+ }
+
+ private:
+ void next()
+ {
+ while( m_current != m_end )
+ {
+ if( m_refBBox.Distance( m_current->bbox ) <= m_minDistance )
+ {
+ if( !m_exact || m_current->shape->Collide( m_shape, m_minDistance ) )
+ return;
+ }
+
+ ++m_current;
+ }
+ }
+
+ SHAPE_VEC_ITER m_end;
+ SHAPE_VEC_ITER m_current;
+ BOX2I m_refBBox;
+ bool m_exact;
+ SHAPE* m_shape;
+ int m_minDistance;
+ };
+
+ void Add( T aItem )
+ {
+ SHAPE_ENTRY s( aItem );
+
+ m_shapes.push_back( s );
+ }
+
+ void Remove( const T aItem )
+ {
+ SHAPE_VEC_ITER i;
+
+ for( i = m_shapes.begin(); i != m_shapes.end(); ++i )
+ {
+ if( i->parent == aItem )
+ break;
+ }
+
+ if( i == m_shapes.end() )
+ return;
+
+ m_shapes.erase( i );
+ }
+
+ int Size() const
+ {
+ return m_shapes.size();
+ }
+
+ template <class Visitor>
+ int Query( const SHAPE* aShape, int aMinDistance, Visitor& aV, bool aExact = true ) // const
+ {
+ SHAPE_VEC_ITER i;
+ int n = 0;
+ VECTOR2I::extended_type minDistSq = (VECTOR2I::extended_type) aMinDistance * aMinDistance;
+
+ BOX2I refBBox = aShape->BBox();
+
+ for( i = m_shapes.begin(); i != m_shapes.end(); ++i )
+ {
+ if( refBBox.SquaredDistance( i->bbox ) <= minDistSq )
+ {
+ if( !aExact || i->shape->Collide( aShape, aMinDistance ) )
+ {
+ n++;
+
+ if( !aV( i->parent ) )
+ return n;
+ }
+ }
+ }
+
+ return n;
+ }
+
+ void Clear()
+ {
+ m_shapes.clear();
+ }
+
+ query_iterator qbegin( SHAPE* aShape, int aMinDistance, bool aExact )
+ {
+ return query_iterator( m_shapes.begin(), m_shapes.end(), aShape, aMinDistance, aExact );
+ }
+
+ const query_iterator qend()
+ {
+ return query_iterator( m_shapes.end(), m_shapes.end(), NULL, 0, false );
+ }
+
+ iterator begin()
+ {
+ return iterator( m_shapes.begin() );
+ }
+
+ iterator end()
+ {
+ return iterator( m_shapes.end() );
+ }
+
+private:
+ SHAPE_VEC m_shapes;
+};
+
+#endif