mirror of https://github.com/KLayout/klayout.git
Merge remote-tracking branch 'remotes/origin/master' into pymod
Provides fixes for issue #166 and #172.
This commit is contained in:
commit
6795de1dbb
|
|
@ -112,7 +112,7 @@ struct cut_polygon_edge
|
|||
{
|
||||
typedef typename PointType::coord_type coord_type;
|
||||
typedef typename db::edge<coord_type> edge_type;
|
||||
typedef typename db::coord_traits<coord_type>::area_type projection_type;
|
||||
typedef double projection_type;
|
||||
|
||||
cut_polygon_edge ()
|
||||
: contour (-1), index (0), projected (0), point (), last_point ()
|
||||
|
|
@ -179,7 +179,7 @@ public:
|
|||
|
||||
bool operator< (const loose_end_struct<CuttingEdgeType> &other) const
|
||||
{
|
||||
if (proj () != other.proj ()) {
|
||||
if (! db::coord_traits<double>::equal (proj (), other.proj ())) {
|
||||
return proj () < other.proj ();
|
||||
} else {
|
||||
return db::vprod_sign (edge (), other.edge ()) > 0;
|
||||
|
|
@ -196,13 +196,13 @@ static bool _cut_polygon_internal (const PolygonType &input, const Edge &line, C
|
|||
typedef db::edge<coord_type> edge_type;
|
||||
typedef cut_polygon_edge<point_type> cut_polygon_edge_type;
|
||||
typedef cut_polygon_segment<cut_polygon_edge_type> cutting_segment_type;
|
||||
typedef typename db::coord_traits<coord_type>::area_type projection_type;
|
||||
|
||||
bool do_hole_assignment = (input.holes () > 0);
|
||||
std::vector <PolygonType> hull_polygons;
|
||||
std::vector <PolygonType> hole_polygons;
|
||||
|
||||
std::vector<cutting_segment_type> cutting_segments;
|
||||
double line_length = line.double_length ();
|
||||
|
||||
for (unsigned int nc = 0; nc < input.holes () + 1; ++nc) {
|
||||
|
||||
|
|
@ -229,7 +229,7 @@ static bool _cut_polygon_internal (const PolygonType &input, const Edge &line, C
|
|||
int s1 = line.side_of (e.p1 ());
|
||||
int s2 = line.side_of (e.p2 ());
|
||||
|
||||
projection_type p = db::sprod (ip.second - line.p1 (), line.p2 () - line.p1 ());
|
||||
double p = line_length * double (db::vprod (e.p1 () - line.p1 (), e.d ())) / double (db::vprod (line.d (), e.d ()));
|
||||
|
||||
if (s1 < 0 && s2 >= 0) {
|
||||
// right -> left or on edge
|
||||
|
|
|
|||
|
|
@ -2241,3 +2241,20 @@ TEST(403)
|
|||
EXPECT_EQ (right_of.size (), size_t (0));
|
||||
}
|
||||
}
|
||||
|
||||
// issue 166
|
||||
TEST(404)
|
||||
{
|
||||
db::Polygon poly;
|
||||
std::string s ("(390,0;438,936;176,874;0,832;438,937;541,961;821,102)");
|
||||
tl::Extractor ex (s.c_str ());
|
||||
ex.read (poly);
|
||||
|
||||
std::vector<db::Polygon> sp;
|
||||
db::split_polygon (poly, sp);
|
||||
EXPECT_EQ (sp.size (), size_t (2));
|
||||
if (sp.size () >= 2) {
|
||||
EXPECT_EQ (sp[0].to_string (), "(390,0;438,936;390,925;438,937;541,961;821,102)");
|
||||
EXPECT_EQ (sp[1].to_string (), "(0,832;176,874;390,925)");
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1145,3 +1145,11 @@ TEST(121)
|
|||
opt.max_vertex_count = 4;
|
||||
run_test (_this, "t121.oas.gz", "t121_au.gds.gz", true, opt);
|
||||
}
|
||||
|
||||
// Extreme fracturing by max. points
|
||||
TEST(166)
|
||||
{
|
||||
db::GDS2WriterOptions opt;
|
||||
opt.max_vertex_count = 4;
|
||||
run_test (_this, "t166.oas.gz", "t166_au.gds.gz", false, opt);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -70,17 +70,6 @@ DEFImporter::get_orient (bool optional)
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief A structure describing a via
|
||||
*/
|
||||
struct ViaDesc
|
||||
{
|
||||
ViaDesc () : cell (0) { }
|
||||
|
||||
db::Cell *cell;
|
||||
std::string m1, m2;
|
||||
};
|
||||
|
||||
void
|
||||
DEFImporter::read_polygon (db::Polygon &poly, double scale)
|
||||
{
|
||||
|
|
@ -153,7 +142,7 @@ DEFImporter::do_read (db::Layout &layout)
|
|||
double dbu_mic = 1000.0;
|
||||
double scale = 1.0 / (dbu_mic * layout.dbu ());
|
||||
std::map<int, db::Polygon> styles;
|
||||
std::map<std::string, ViaDesc> via_desc;
|
||||
std::map<std::string, ViaDesc> via_desc = m_lef_importer.vias ();
|
||||
std::map<std::string, std::vector<db::Polygon> > regions;
|
||||
std::list<Group> groups;
|
||||
std::list<std::pair<std::string, db::CellInstArray> > instances;
|
||||
|
|
|
|||
|
|
@ -533,6 +533,24 @@ private:
|
|||
const LEFDEFReaderOptions *mp_tech_comp;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief A structure describing a via
|
||||
*/
|
||||
struct EXT_PUBLIC ViaDesc
|
||||
{
|
||||
ViaDesc () : cell (0) { }
|
||||
|
||||
/**
|
||||
* @brief The cell representing the via
|
||||
*/
|
||||
db::Cell *cell;
|
||||
|
||||
/**
|
||||
* @brief The names of bottom and top metal respectively
|
||||
*/
|
||||
std::string m1, m2;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief The LEF importer object
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -458,6 +458,9 @@ LEFImporter::do_read (db::Layout &layout)
|
|||
std::string cellname = "VIA_" + n;
|
||||
db::Cell &cell = layout.cell (layout.add_cell (cellname.c_str ()));
|
||||
|
||||
ViaDesc &via_desc = m_vias[n];
|
||||
via_desc.cell = &cell;
|
||||
|
||||
while (test ("DEFAULT") || test ("TOPOFSTACKONLY"))
|
||||
;
|
||||
test (";");
|
||||
|
|
@ -543,9 +546,9 @@ LEFImporter::do_read (db::Layout &layout)
|
|||
|
||||
} else if (test ("LAYERS")) {
|
||||
|
||||
geometry[0].first = get ();
|
||||
via_desc.m1 = geometry[0].first = get ();
|
||||
geometry[1].first = get ();
|
||||
geometry[2].first = get ();
|
||||
via_desc.m2 = geometry[2].first = get ();
|
||||
|
||||
test (";");
|
||||
|
||||
|
|
|
|||
|
|
@ -86,6 +86,16 @@ public:
|
|||
*/
|
||||
double layer_ext (const std::string &layer, double def_ext = 0.0) const;
|
||||
|
||||
/**
|
||||
* @brief Gets a map of the vias defined in this LEF file
|
||||
*
|
||||
* The map maps the via name to the via description.
|
||||
*/
|
||||
const std::map<std::string, ViaDesc> &vias () const
|
||||
{
|
||||
return m_vias;
|
||||
}
|
||||
|
||||
protected:
|
||||
void do_read (db::Layout &layout);
|
||||
|
||||
|
|
@ -95,6 +105,7 @@ private:
|
|||
std::map<std::string, double> m_default_ext;
|
||||
std::map<std::string, db::Cell *> m_macros_by_name;
|
||||
std::map<std::string, db::Box> m_macro_bboxes_by_name;
|
||||
std::map<std::string, ViaDesc> m_vias;
|
||||
|
||||
std::vector <db::Trans> get_iteration (db::Layout &layout);
|
||||
void read_geometries (db::Layout &layout, db::Cell &cell, LayerPurpose purpose, std::map<std::string, db::Box> *collect_bboxes = 0);
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@
|
|||
|
||||
#include <cstdlib>
|
||||
|
||||
static void run_test (tl::TestBase *_this, const char *lef_dir, const char *filename, const char *au)
|
||||
static void run_test (tl::TestBase *_this, const char *lef_dir, const char *filename, const char *au, bool priv = true)
|
||||
{
|
||||
db::LEFDEFReaderOptions tc;
|
||||
tc.set_via_geometry_datatype (0);
|
||||
|
|
@ -60,7 +60,7 @@ static void run_test (tl::TestBase *_this, const char *lef_dir, const char *file
|
|||
|
||||
if (ex.test ("def:")) {
|
||||
|
||||
std::string fn (tl::testsrc_private ());
|
||||
std::string fn (priv ? tl::testsrc_private () : tl::testsrc ());
|
||||
fn += "/testdata/lefdef/";
|
||||
fn += lef_dir;
|
||||
fn += "/";
|
||||
|
|
@ -73,7 +73,7 @@ static void run_test (tl::TestBase *_this, const char *lef_dir, const char *file
|
|||
|
||||
} else if (ex.test ("lef:")) {
|
||||
|
||||
std::string fn (tl::testsrc_private ());
|
||||
std::string fn (priv ? tl::testsrc_private () : tl::testsrc ());
|
||||
fn += "/testdata/lefdef/";
|
||||
fn += lef_dir;
|
||||
fn += "/";
|
||||
|
|
@ -118,7 +118,7 @@ static void run_test (tl::TestBase *_this, const char *lef_dir, const char *file
|
|||
|
||||
if (au) {
|
||||
|
||||
std::string fn (tl::testsrc_private ());
|
||||
std::string fn (priv ? tl::testsrc_private () : tl::testsrc ());
|
||||
fn += "/testdata/lefdef/";
|
||||
fn += lef_dir;
|
||||
fn += "/";
|
||||
|
|
@ -233,3 +233,8 @@ TEST(19)
|
|||
run_test (_this, "def10", "def:in.def", "au.oas.gz");
|
||||
}
|
||||
|
||||
TEST(20)
|
||||
{
|
||||
run_test (_this, "issue-172", "lef:in.lef+def:in.def", "au.oas.gz", false);
|
||||
}
|
||||
|
||||
|
|
|
|||
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
|
@ -0,0 +1,16 @@
|
|||
VERSION 5.6 ;
|
||||
NAMESCASESENSITIVE ON ;
|
||||
DIVIDERCHAR "/" ;
|
||||
BUSBITCHARS "<>" ;
|
||||
DESIGN SMALL ;
|
||||
UNITS DISTANCE MICRONS 100 ;
|
||||
|
||||
DIEAREA ( -30 -30 ) ( 1030 1030 ) ;
|
||||
|
||||
NETS 1 ;
|
||||
- TOP
|
||||
+ ROUTED M1 ( 0 0 ) ( 1000 * ) M2_M1
|
||||
NEW M2 ( 1000 0 ) ( 1000 1000 ) ;
|
||||
END NETS
|
||||
|
||||
END DESIGN
|
||||
|
|
@ -0,0 +1,40 @@
|
|||
VERSION 5.7 ;
|
||||
NAMESCASESENSITIVE ON ;
|
||||
BUSBITCHARS "[]" ;
|
||||
DIVIDERCHAR "/" ;
|
||||
UNITS
|
||||
DATABASE MICRONS 1000 ;
|
||||
END UNITS
|
||||
|
||||
USEMINSPACING OBS ON ;
|
||||
USEMINSPACING PIN OFF ;
|
||||
CLEARANCEMEASURE EUCLIDEAN ;
|
||||
|
||||
MANUFACTURINGGRID 0.05 ;
|
||||
|
||||
LAYER M1
|
||||
TYPE ROUTING ;
|
||||
DIRECTION HORIZONTAL ;
|
||||
WIDTH 0.2 ;
|
||||
END M1
|
||||
|
||||
LAYER V2
|
||||
TYPE CUT ;
|
||||
END V2
|
||||
|
||||
LAYER M2
|
||||
TYPE ROUTING ;
|
||||
DIRECTION VERTICAL ;
|
||||
WIDTH 0.2 ;
|
||||
END M2
|
||||
|
||||
VIA M2_M1 DEFAULT
|
||||
LAYER M1 ;
|
||||
RECT -0.300 -0.300 0.300 0.300 ;
|
||||
LAYER V2 ;
|
||||
RECT -0.200 -0.200 0.200 0.200 ;
|
||||
LAYER M2 ;
|
||||
RECT -0.300 -0.300 0.300 0.300 ;
|
||||
END M2_M1
|
||||
|
||||
END LIBRARY
|
||||
|
|
@ -150,7 +150,7 @@ class DBTransTests(unittest.TestCase):
|
|||
self.assertEqual( c.is_mirror(), True )
|
||||
self.assertEqual( c.rot(), pya.DCplxTrans.M135.rot() )
|
||||
self.assertEqual( str(c.s_trans()), "m135 0,0" )
|
||||
self.assertEqual( c.angle, 270 )
|
||||
self.assertAlmostEqual( c.angle, 270 )
|
||||
|
||||
self.assertEqual( str(c.trans( pya.Edge(0, 1, 2, 3) )), "(-1,0;-3,-2)" )
|
||||
self.assertEqual( str(( c * pya.Edge(0, 1, 2, 3) )), "(-1,0;-3,-2)" )
|
||||
|
|
@ -174,7 +174,7 @@ class DBTransTests(unittest.TestCase):
|
|||
self.assertEqual( c.is_mirror(), False )
|
||||
self.assertEqual( c.rot(), pya.DCplxTrans.R0.rot() )
|
||||
self.assertEqual( str(c.s_trans()), "r0 0,0" )
|
||||
self.assertEqual( c.angle, 0 )
|
||||
self.assertAlmostEqual( c.angle, 0 )
|
||||
|
||||
c = pya.DCplxTrans( 0.75, 45, True, 2.5, -12.5 )
|
||||
self.assertEqual( str(c), "m22.5 *0.75 2.5,-12.5" )
|
||||
|
|
@ -185,7 +185,7 @@ class DBTransTests(unittest.TestCase):
|
|||
self.assertEqual( c.is_mag(), True )
|
||||
self.assertEqual( c.rot(), pya.DCplxTrans.M0.rot() )
|
||||
self.assertEqual( str(c.s_trans()), "m0 2.5,-12.5" )
|
||||
self.assertEqual( c.angle, 45 )
|
||||
self.assertAlmostEqual( c.angle, 45 )
|
||||
|
||||
self.assertEqual( str(c.ctrans( 5 )), "3.75" )
|
||||
self.assertEqual( str(c.trans( pya.DPoint( 12, 16 ) )), "17.3492424049,-14.6213203436" )
|
||||
|
|
@ -335,7 +335,7 @@ class DBTransTests(unittest.TestCase):
|
|||
self.assertEqual( c.is_mirror(), True )
|
||||
self.assertEqual( c.rot(), pya.CplxTrans.M135.rot() )
|
||||
self.assertEqual( str(c.s_trans()), "m135 0,0" )
|
||||
self.assertEqual( c.angle, 270 )
|
||||
self.assertAlmostEqual( c.angle, 270 )
|
||||
|
||||
c = pya.CplxTrans.from_dtrans( pya.DCplxTrans.M135 )
|
||||
self.assertEqual( str(c), "m135 *1 0,0" )
|
||||
|
|
@ -348,7 +348,7 @@ class DBTransTests(unittest.TestCase):
|
|||
self.assertEqual( c.is_mirror(), False )
|
||||
self.assertEqual( c.rot(), pya.CplxTrans.R0.rot() )
|
||||
self.assertEqual( str(c.s_trans()), "r0 0,0" )
|
||||
self.assertEqual( c.angle, 0 )
|
||||
self.assertAlmostEqual( c.angle, 0 )
|
||||
|
||||
c = pya.CplxTrans( 0.75, 45, True, 2.5, -12.5 )
|
||||
self.assertEqual( str(c), "m22.5 *0.75 2.5,-12.5" )
|
||||
|
|
@ -360,7 +360,7 @@ class DBTransTests(unittest.TestCase):
|
|||
self.assertEqual( c.is_mag(), True )
|
||||
self.assertEqual( c.rot(), pya.CplxTrans.M0.rot() )
|
||||
self.assertEqual( str(c.s_trans()), "m0 3,-13" )
|
||||
self.assertEqual( c.angle, 45 )
|
||||
self.assertAlmostEqual( c.angle, 45 )
|
||||
|
||||
self.assertEqual( str(c.ctrans( 5 )), "3.75" )
|
||||
self.assertEqual( str(c.trans( pya.Point( 12, 16 ) )), "17.3492424049,-14.6213203436" )
|
||||
|
|
@ -517,7 +517,7 @@ class DBTransTests(unittest.TestCase):
|
|||
self.assertEqual(t1 < t4, True)
|
||||
self.assertEqual(t4 < t1, False)
|
||||
|
||||
# Hash values
|
||||
# Hash values
|
||||
def test_5_Trans_Hash(self):
|
||||
|
||||
t1 = pya.DTrans( pya.DTrans.M135, pya.DPoint( 17, 5 ))
|
||||
|
|
|
|||
|
|
@ -471,9 +471,11 @@ class QtBindingTest(unittest.TestCase):
|
|||
|
||||
pya.QApplication.processEvents()
|
||||
|
||||
s1 = "QKeyEvent: ShortcutOverride (51)\nQKeyEvent: KeyPress (6)\nQKeyEvent: ShortcutOverride (51)\nQKeyEvent: KeyPress (6)\nQKeyEvent: ShortcutOverride (51)\nQKeyEvent: KeyPress (6)"
|
||||
s2 = "QKeyEvent: KeyPress (6)\nQKeyEvent: KeyPress (6)\nQKeyEvent: KeyPress (6)"
|
||||
self.assertEqual("\n".join(ef.log()) == s1 or "\n".join(ef.log()) == s2, True)
|
||||
s1 = "QKeyEvent: ShortcutOverride (51)\nQKeyEvent: KeyPress (6)\nQKeyEvent: ShortcutOverride (51)\nQKeyEvent: KeyPress (6)\nQKeyEvent: ShortcutOverride (51)\nQKeyEvent: KeyPress (6)"
|
||||
s2 = "QKeyEvent: KeyPress (6)\nQKeyEvent: KeyPress (6)\nQKeyEvent: KeyPress (6)"
|
||||
s3 = "QKeyEvent_Native: ShortcutOverride (51)\nQKeyEvent: KeyPress (6)\nQKeyEvent_Native: ShortcutOverride (51)\nQKeyEvent: KeyPress (6)\nQKeyEvent_Native: ShortcutOverride (51)\nQKeyEvent: KeyPress (6)"
|
||||
self.assertIn("\n".join(ef.log()), (s1, s2, s3))
|
||||
|
||||
ef = None
|
||||
|
||||
self.assertEqual(widget.text, "ABCpO")
|
||||
|
|
|
|||
|
|
@ -534,7 +534,10 @@ class QtBinding_TestClass < TestBase
|
|||
|
||||
GC.start
|
||||
|
||||
assert_equal(ef.log.select { |s| s !~ /RBA::QKeyEvent: ShortcutOverride/ }.join("\n"), "RBA::QKeyEvent: KeyPress (6)\nRBA::QKeyEvent: KeyPress (6)\nRBA::QKeyEvent: KeyPress (6)")
|
||||
assert_equal(ef.log.select { |s| s !~ /RBA::QKeyEvent: ShortcutOverride/ }.join("\n"), "RBA::QKeyEvent: KeyPress (6)\nRBA::QKeyEvent: KeyPress (6)\nRBA::QKeyEvent: KeyPress (6)")
|
||||
|
||||
# TODO: on macOS 10.13, ef.log yields "RBA::QKeyEvent_Native: ShortcutOverride (51)\nRBA::QKeyEvent: KeyPress (6)\nRBA::QKeyEvent_Native: ShortcutOverride (51)\nRBA::QKeyEvent: KeyPress (6)\nRBA::QKeyEvent_Native: ShortcutOverride (51)\nRBA::QKeyEvent: KeyPress (6)", causing this test to fail.
|
||||
|
||||
ef = nil
|
||||
ef = EventFilter::new
|
||||
GC.start
|
||||
|
|
|
|||
Loading…
Reference in New Issue