mirror of https://github.com/KLayout/klayout.git
Shape#hash and Shape#< allow using Shape objects as hash keys
This commit is contained in:
parent
69423e37ac
commit
c43b70b783
|
|
@ -43,6 +43,7 @@
|
|||
using them to select edges.
|
||||
* Enhancement: New RBA/pya Features
|
||||
- Main window title: MainWindow#title (property)
|
||||
- MainWindow#synchronous (getter added)
|
||||
- LayoutView#is_dirty?
|
||||
- Triangulation: Region#delaunay
|
||||
- Quality rasterizer: Region#rasterize
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@
|
|||
#include "dbShape.h"
|
||||
#include "dbBoxConvert.h"
|
||||
#include "dbPolygonTools.h"
|
||||
#include "dbHash.h"
|
||||
#include "tlCpp.h"
|
||||
|
||||
namespace db
|
||||
|
|
@ -862,6 +863,24 @@ Shape::box_type Shape::rectangle () const
|
|||
return box_type ();
|
||||
}
|
||||
|
||||
size_t
|
||||
Shape::hash_value () const
|
||||
{
|
||||
size_t h = size_t (m_type);
|
||||
h = std::hcombine (h, std::hfunc (m_trans));
|
||||
|
||||
if (m_stable) {
|
||||
// Use the bytes of the iterator binary pattern (see operator<)
|
||||
for (unsigned int i = 0; i < sizeof (tl::reuse_vector<box_type>::const_iterator); ++i) {
|
||||
h = std::hcombine (h, size_t (m_generic.iter[i]));
|
||||
}
|
||||
} else {
|
||||
h = std::hcombine (h, size_t (m_generic.any));
|
||||
}
|
||||
|
||||
return h;
|
||||
}
|
||||
|
||||
std::string
|
||||
Shape::to_string () const
|
||||
{
|
||||
|
|
|
|||
|
|
@ -2769,6 +2769,11 @@ public:
|
|||
return m_trans < d.m_trans;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Hash value
|
||||
*/
|
||||
size_t hash_value () const;
|
||||
|
||||
/**
|
||||
* @brief Convert to a string
|
||||
*/
|
||||
|
|
@ -2837,6 +2842,21 @@ public:
|
|||
};
|
||||
|
||||
} // namespace db
|
||||
|
||||
namespace std
|
||||
{
|
||||
|
||||
// provide a template specialization for std::hash<T>
|
||||
template <>
|
||||
struct hash <db::Shape>
|
||||
{
|
||||
size_t operator() (const db::Shape &s) const
|
||||
{
|
||||
return s.hash_value ();
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace std
|
||||
|
||||
#endif
|
||||
|
||||
|
|
|
|||
|
|
@ -2131,6 +2131,21 @@ Class<db::Shape> decl_Shape ("db", "Shape",
|
|||
"Equality of shapes is not specified by the identity of the objects but by the\n"
|
||||
"identity of the pointers - both shapes must refer to the same object.\n"
|
||||
) +
|
||||
gsi::method ("<", &db::Shape::operator<, gsi::arg ("other"),
|
||||
"@brief Less operator\n"
|
||||
"\n"
|
||||
"The less operator implementation is based on pointers and not strictly reproducible."
|
||||
"However, it is good enough so Shape objects can serve as keys in hashes (see also \\hash).\n"
|
||||
"\n"
|
||||
"This method has been introduced in version 0.29."
|
||||
) +
|
||||
gsi::method ("hash", &db::Shape::hash_value,
|
||||
"@brief Hash function\n"
|
||||
"\n"
|
||||
"The hash function enables Shape objects as keys in hashes.\n"
|
||||
"\n"
|
||||
"This method has been introduced in version 0.29."
|
||||
) +
|
||||
gsi::method ("to_s", &db::Shape::to_string,
|
||||
"@brief Create a string showing the contents of the reference\n"
|
||||
"\n"
|
||||
|
|
|
|||
|
|
@ -99,6 +99,7 @@ void run_pythontest (tl::TestBase *_this, const std::string &fn)
|
|||
PYTHONTEST (kwargs, "kwargs.py")
|
||||
PYTHONTEST (dbLayoutTest, "dbLayoutTest.py")
|
||||
PYTHONTEST (dbRegionTest, "dbRegionTest.py")
|
||||
PYTHONTEST (dbShapesTest, "dbShapesTest.py")
|
||||
PYTHONTEST (dbReaders, "dbReaders.py")
|
||||
PYTHONTEST (dbPCellsTest, "dbPCells.py")
|
||||
PYTHONTEST (dbPolygonTest, "dbPolygonTest.py")
|
||||
|
|
|
|||
|
|
@ -0,0 +1,59 @@
|
|||
# KLayout Layout Viewer
|
||||
# Copyright (C) 2006-2024 Matthias Koefferlein
|
||||
#
|
||||
# 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, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
|
||||
import pya
|
||||
import unittest
|
||||
import sys
|
||||
import os
|
||||
|
||||
class DBShapesTest(unittest.TestCase):
|
||||
|
||||
# Shape objects as hashes
|
||||
def test_12(self):
|
||||
|
||||
s = pya.Shapes()
|
||||
s1 = s.insert(pya.Box(1, 2, 3, 4))
|
||||
s2 = s.insert(pya.Polygon(pya.Box(1, 2, 3, 4)))
|
||||
s3 = s.insert(pya.SimplePolygon(pya.Box(1, 2, 3, 4)))
|
||||
|
||||
self.assertEqual(s1.hash != s2.hash, True) # let's hope so ...
|
||||
self.assertEqual(s1.hash != s3.hash, True)
|
||||
self.assertEqual(s2.hash != s3.hash, True)
|
||||
|
||||
self.assertEqual(s1 < s2 or s2 < s1, True)
|
||||
self.assertEqual(s1 < s3 or s3 < s1, True)
|
||||
self.assertEqual(s2 < s3 or s3 < s2, True)
|
||||
|
||||
h = {}
|
||||
h[s1] = 1
|
||||
h[s2] = 2
|
||||
h[s3] = 3
|
||||
|
||||
self.assertEqual(len(h), 3)
|
||||
|
||||
self.assertEqual(h[s1], 1)
|
||||
self.assertEqual(h[s2], 2)
|
||||
self.assertEqual(h[s3], 3)
|
||||
|
||||
# run unit tests
|
||||
if __name__ == '__main__':
|
||||
suite = unittest.TestLoader().loadTestsFromTestCase(DBShapesTest)
|
||||
|
||||
if not unittest.TextTestRunner(verbosity = 1).run(suite).wasSuccessful():
|
||||
sys.exit(1)
|
||||
|
||||
|
|
@ -1627,6 +1627,35 @@ class DBShapes_TestClass < TestBase
|
|||
|
||||
end
|
||||
|
||||
# Shape objects as hashes
|
||||
def test_12
|
||||
|
||||
s = RBA::Shapes::new
|
||||
s1 = s.insert(RBA::Box::new(1, 2, 3, 4))
|
||||
s2 = s.insert(RBA::Polygon::new(RBA::Box::new(1, 2, 3, 4)))
|
||||
s3 = s.insert(RBA::SimplePolygon::new(RBA::Box::new(1, 2, 3, 4)))
|
||||
|
||||
assert_equal(s1.hash != s2.hash, true) # let's hope so ...
|
||||
assert_equal(s1.hash != s3.hash, true)
|
||||
assert_equal(s2.hash != s3.hash, true)
|
||||
|
||||
assert_equal(s1 < s2 || s2 < s1, true)
|
||||
assert_equal(s1 < s3 || s3 < s1, true)
|
||||
assert_equal(s2 < s3 || s3 < s2, true)
|
||||
|
||||
h = {}
|
||||
h[s1] = 1
|
||||
h[s2] = 2
|
||||
h[s3] = 3
|
||||
|
||||
assert_equal(h.size, 3)
|
||||
|
||||
assert_equal(h[s1], 1)
|
||||
assert_equal(h[s2], 2)
|
||||
assert_equal(h[s3], 3)
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
load("test_epilogue.rb")
|
||||
|
|
|
|||
Loading…
Reference in New Issue