diff --git a/src/db/db/dbHierProcessor.cc b/src/db/db/dbHierProcessor.cc index ea5ddabd0..595ad3ff6 100644 --- a/src/db/db/dbHierProcessor.cc +++ b/src/db/db/dbHierProcessor.cc @@ -1655,6 +1655,13 @@ struct scan_shape2shape_same_layer scanner.process (rec, dist, db::box_convert (), db::box_convert ()); } + + void + operator () (const db::Shapes *, unsigned int, unsigned int, shape_interactions &, db::Coord) const + { + // cannot have different types on the same layer + tl_assert (false); + } }; template @@ -1679,13 +1686,28 @@ struct scan_shape2shape_same_layer scanner.process (rec, dist, db::box_convert ()); } + + void + operator () (const db::Shapes *shapes, unsigned int subject_id0, unsigned int intruder_layer, shape_interactions &interactions, db::Coord dist) const + { + db::box_scanner scanner; + interaction_registration_shape1 rec (&interactions, intruder_layer); + + unsigned int id = subject_id0; + for (db::Shapes::shape_iterator i = shapes->begin (shape_flags ()); !i.at_end (); ++i) { + const T *ref = i->basic_ptr (typename T::tag ()); + scanner.insert (ref, id++); + } + + scanner.process (rec, dist, db::box_convert ()); + } }; template struct scan_shape2shape_different_layers { void - operator () (db::Layout *layout, const db::Shapes *subject_shapes, const db::Shapes *intruder_shapes, unsigned int subject_id0, const std::set &intruders, unsigned int intruder_layer, shape_interactions &interactions, db::Coord dist) + operator () (db::Layout *layout, const db::Shapes *subject_shapes, const db::Shapes *intruder_shapes, unsigned int subject_id0, const std::set *intruders, unsigned int intruder_layer, shape_interactions &interactions, db::Coord dist) const { db::box_scanner2 scanner; interaction_registration_shape2shape rec (layout, &interactions, intruder_layer); @@ -1697,8 +1719,10 @@ struct scan_shape2shape_different_layers } // TODO: can we confine this search to the subject's (sized) bounding box? - for (typename std::set::const_iterator i = intruders.begin (); i != intruders.end (); ++i) { - scanner.insert2 (i.operator-> (), interactions.next_id ()); + if (intruders) { + for (typename std::set::const_iterator i = intruders->begin (); i != intruders->end (); ++i) { + scanner.insert2 (i.operator-> (), interactions.next_id ()); + } } if (intruder_shapes) { @@ -1763,7 +1787,7 @@ local_processor::compute_local_cell (const db::local_processor_conte } else { db::Layout *target_layout = (mp_subject_layout == mp_intruder_layout ? 0 : mp_subject_layout); - scan_shape2shape_different_layers () (target_layout, subject_shapes, intruder_shapes, subject_id0, ipl == intruders.second.end () ? empty_intruders : ipl->second, *il, interactions, op->dist ()); + scan_shape2shape_different_layers () (target_layout, subject_shapes, intruder_shapes, subject_id0, &(ipl == intruders.second.end () ? empty_intruders : ipl->second), *il, interactions, op->dist ()); } @@ -1825,6 +1849,88 @@ local_processor::compute_local_cell (const db::local_processor_conte } } +template +void +local_processor::run_flat (const db::Shapes *subject_shapes, const db::Shapes *intruders, const local_operation *op, db::Shapes *result_shapes) const +{ + std::vector is; + is.push_back (intruders); + + std::vector os; + os.push_back (result_shapes); + + run_flat (subject_shapes, is, op, os); +} + +template +void +local_processor::run_flat (const db::Shapes *subject_shapes, const std::vector &intruders, const local_operation *op, const std::vector &result_shapes) const +{ + tl_assert (mp_subject_top == 0); + tl_assert (mp_intruder_top == 0); + + shape_interactions interactions; + + for (std::vector::const_iterator il = intruders.begin (); il != intruders.end (); ++il) { + + const db::Shapes *intruder_shapes = *il; + + // insert dummy interactions to accommodate subject vs. nothing and assign an ID + // range for the subject shapes. + unsigned int subject_id0 = 0; + for (db::Shapes::shape_iterator i = subject_shapes->begin (shape_flags ()); !i.at_end (); ++i) { + + unsigned int id = interactions.next_id (); + if (subject_id0 == 0) { + subject_id0 = id; + } + + if (op->on_empty_intruder_hint () != local_operation::Drop) { + const TS *ref = i->basic_ptr (typename TS::tag ()); + interactions.add_subject (id, *ref); + } + + } + + static std::set empty_intruders; + + if (! subject_shapes->empty () && intruder_shapes) { + + if (intruder_shapes == subject_shapes) { + scan_shape2shape_same_layer () (subject_shapes, subject_id0, (unsigned int) (il - intruders.begin ()), interactions, op->dist ()); + } else { + scan_shape2shape_different_layers () (0 /*layout*/, subject_shapes, intruder_shapes, subject_id0, 0 /*ext. intruders*/, (unsigned int) (il - intruders.begin ()), interactions, op->dist ()); + } + + } + + } + + if (interactions.begin () != interactions.end ()) { + + if (interactions.begin_intruders () == interactions.end_intruders ()) { + + typename local_operation::on_empty_intruder_mode eh = op->on_empty_intruder_hint (); + if (eh == local_operation::Drop) { + return; + } + + } + + std::vector > result; + result.resize (result_shapes.size ()); + op->compute_local (mp_subject_layout, interactions, result, m_max_vertex_count, m_area_ratio); + + for (std::vector::const_iterator r = result_shapes.begin (); r != result_shapes.end (); ++r) { + if (*r) { + const std::unordered_set rs = result [r - result_shapes.begin ()]; + (*r)->insert (rs.begin (), rs.end ()); + } + } + + } +} + template class DB_PUBLIC local_processor; template class DB_PUBLIC local_processor; template class DB_PUBLIC local_processor; diff --git a/src/db/db/dbHierProcessor.h b/src/db/db/dbHierProcessor.h index f5044af15..33a75eeac 100644 --- a/src/db/db/dbHierProcessor.h +++ b/src/db/db/dbHierProcessor.h @@ -375,7 +375,7 @@ template class DB_PUBLIC local_processor { public: - local_processor (db::Layout *layout, db::Cell *top, const std::set *breakout_cells = 0); + local_processor (db::Layout *layout = 0, db::Cell *top = 0, const std::set *breakout_cells = 0); local_processor (db::Layout *subject_layout, db::Cell *subject_top, const db::Layout *intruder_layout, const db::Cell *intruder_cell, const std::set *subject_breakout_cells = 0, const std::set *intruder_breakout_cells = 0); void run (local_operation *op, unsigned int subject_layer, unsigned int intruder_layer, unsigned int output_layers); void run (local_operation *op, unsigned int subject_layer, const std::vector &intruder_layers, const std::vector &output_layers); @@ -383,6 +383,9 @@ public: void compute_contexts (local_processor_contexts &contexts, const local_operation *op, unsigned int subject_layer, const std::vector &intruder_layers) const; void compute_results (local_processor_contexts &contexts, const local_operation *op, const std::vector &output_layers) const; + void run_flat (const db::Shapes *subject_shapes, const db::Shapes *intruders, const local_operation *op, db::Shapes *result_shapes) const; + void run_flat (const db::Shapes *subjects, const std::vector &intruders, const local_operation *op, const std::vector &result_shapes) const; + void set_description (const std::string &d) { m_description = d; diff --git a/src/db/unit_tests/dbHierProcessorTests.cc b/src/db/unit_tests/dbHierProcessorTests.cc index 05ac5b94f..11f3bb68a 100644 --- a/src/db/unit_tests/dbHierProcessorTests.cc +++ b/src/db/unit_tests/dbHierProcessorTests.cc @@ -323,6 +323,110 @@ static void run_test_bool22 (tl::TestBase *_this, const char *file, TestMode mod run_test_bool_gen (_this, file, mode, out_layer_num1, out_layer_num2, context_doc, false, 0, nthreads); } +static void run_test_bool_gen_flat (tl::TestBase *_this, const char *file, TestMode mode, int out_layer_num1, int out_layer_num2, db::Coord dist) +{ + db::Layout layout_org; + + unsigned int l1 = 0, l2 = 0, lout1 = 0, lout2 = 0; + db::LayerMap lmap; + bool swap = (mode == TMAndSwapped || mode == TMNotSwapped); + + { + tl::InputStream stream (testdata (file)); + db::Reader reader (stream); + + db::LayerProperties p; + + p.layer = swap ? 2 : 1; + p.datatype = 0; + lmap.map (db::LDPair (p.layer, p.datatype), l1 = layout_org.insert_layer ()); + layout_org.set_properties (l1, p); + + p.layer = swap ? 1 : 2; + p.datatype = 0; + if (mode == TMSelfOverlap) { + lmap.map (db::LDPair (p.layer, p.datatype), l2 = l1); + } else { + lmap.map (db::LDPair (p.layer, p.datatype), l2 = layout_org.insert_layer ()); + layout_org.set_properties (l2, p); + } + + p.layer = out_layer_num1; + p.datatype = 0; + lmap.map (db::LDPair (out_layer_num1, 0), lout1 = layout_org.insert_layer ()); + layout_org.set_properties (lout1, p); + + if (out_layer_num2 >= 0) { + p.layer = out_layer_num2; + p.datatype = 0; + lmap.map (db::LDPair (out_layer_num2, 0), lout2 = layout_org.insert_layer ()); + layout_org.set_properties (lout2, p); + } + + db::LoadLayoutOptions options; + options.get_options ().layer_map = lmap; + options.get_options ().create_other_layers = false; + reader.read (layout_org, options); + } + + db::Cell &top_cell = layout_org.cell (*layout_org.begin_top_down ()); + layout_org.flatten (top_cell, -1, true); + + layout_org.clear_layer (lout1); + if (out_layer_num2 >= 0) { + layout_org.clear_layer (lout2); + } + normalize_layer (layout_org, l1); + if (l1 != l2) { + normalize_layer (layout_org, l2); + } + + db::local_operation *lop = 0; + db::BoolAndOrNotLocalOperation bool_op (mode == TMAnd || mode == TMAndSwapped); + db::SelfOverlapMergeLocalOperation self_intersect_op (2); + BoolAndOrNotWithSizedLocalOperation sized_bool_op (mode == TMAnd || mode == TMAndSwapped, dist); + SelfOverlapWithSizedLocalOperation sized_self_intersect_op (2, dist); + db::TwoBoolAndNotLocalOperation andnot; + + if (mode == TMAndNot) { + lop = &andnot; + } else if (mode == TMSelfOverlap) { + if (dist > 0) { + lop = &sized_self_intersect_op; + } else { + lop = &self_intersect_op; + } + } else { + if (dist > 0) { + lop = &sized_bool_op; + } else { + lop = &bool_op; + } + } + + std::vector ilv; + std::vector olv; + ilv.push_back (&top_cell.shapes (l2)); + olv.push_back (&top_cell.shapes (lout1)); + if (out_layer_num2 >= 0) { + olv.push_back (&top_cell.shapes (lout2)); + } + + db::local_processor proc (&layout_org); + proc.set_area_ratio (3.0); + proc.set_max_vertex_count (16); + + proc.run_flat (&top_cell.shapes (l1), ilv, lop, olv); + + db::compare_layouts (_this, layout_org, testdata (file), lmap, false /*skip other layers*/, db::AsPolygons); +} + +static void run_test_bool22_flat (tl::TestBase *_this, const char *file, TestMode mode, int out_layer_num1, int out_layer_num2) +{ + run_test_bool_gen_flat (_this, file, mode, out_layer_num1, out_layer_num2, 0); +} + + TEST(BasicAnd1) { // Simple flat AND @@ -1167,3 +1271,9 @@ TEST(MultipleOutputs) run_test_bool22 (_this, "hlp17.oas", TMAndNot, 100, 101); } +TEST(FlatOperation) +{ + // Redundant hierarchy, NOT + run_test_bool22_flat (_this, "hlp17_flat.oas", TMAndNot, 100, 101); +} + diff --git a/testdata/algo/hlp17_flat.oas b/testdata/algo/hlp17_flat.oas new file mode 100644 index 000000000..aecbf21a0 Binary files /dev/null and b/testdata/algo/hlp17_flat.oas differ