mirror of https://github.com/KLayout/klayout.git
Implemented solution for #570 (deep Edges::extents)
While doing this, it was discovered that the problem also persists for EdgePairs and Texts. In order to provide a more generic solution, some refactoring was applied.
This commit is contained in:
parent
eacd67df1c
commit
759f07ee4d
|
|
@ -196,7 +196,8 @@ SOURCES = \
|
|||
dbOriginalLayerTexts.cc \
|
||||
dbNetShape.cc \
|
||||
dbShapeCollection.cc \
|
||||
gsiDeclDbShapeCollection.cc
|
||||
gsiDeclDbShapeCollection.cc \
|
||||
dbShapeCollectionUtils.cc
|
||||
|
||||
HEADERS = \
|
||||
dbArray.h \
|
||||
|
|
@ -353,7 +354,8 @@ HEADERS = \
|
|||
dbTextsUtils.h \
|
||||
dbOriginalLayerTexts.h \
|
||||
dbNetShape.h \
|
||||
dbShapeCollection.h
|
||||
dbShapeCollection.h \
|
||||
dbShapeCollectionUtils.h
|
||||
|
||||
!equals(HAVE_QT, "0") {
|
||||
|
||||
|
|
|
|||
|
|
@ -125,6 +125,28 @@ void AsIfFlatEdgePairs::invalidate_bbox ()
|
|||
m_bbox_valid = false;
|
||||
}
|
||||
|
||||
RegionDelegate *
|
||||
AsIfFlatEdgePairs::processed_to_polygons (const EdgePairToPolygonProcessorBase &filter) const
|
||||
{
|
||||
std::auto_ptr<FlatRegion> region (new FlatRegion ());
|
||||
|
||||
if (filter.result_must_not_be_merged ()) {
|
||||
region->set_merged_semantics (false);
|
||||
}
|
||||
|
||||
std::vector<db::Polygon> res_polygons;
|
||||
|
||||
for (EdgePairsIterator e (begin ()); ! e.at_end (); ++e) {
|
||||
res_polygons.clear ();
|
||||
filter.process (*e, res_polygons);
|
||||
for (std::vector<db::Polygon>::const_iterator pr = res_polygons.begin (); pr != res_polygons.end (); ++pr) {
|
||||
region->insert (*pr);
|
||||
}
|
||||
}
|
||||
|
||||
return region.release ();
|
||||
}
|
||||
|
||||
EdgePairsDelegate *
|
||||
AsIfFlatEdgePairs::filtered (const EdgePairFilterBase &filter) const
|
||||
{
|
||||
|
|
|
|||
|
|
@ -51,6 +51,8 @@ public:
|
|||
|
||||
virtual EdgePairsDelegate *filtered (const EdgePairFilterBase &) const;
|
||||
|
||||
virtual RegionDelegate *processed_to_polygons (const EdgePairToPolygonProcessorBase &filter) const;
|
||||
|
||||
virtual EdgePairsDelegate *add_in_place (const EdgePairs &other)
|
||||
{
|
||||
return add (other);
|
||||
|
|
|
|||
|
|
@ -152,6 +152,28 @@ AsIfFlatTexts::filtered (const TextFilterBase &filter) const
|
|||
return new_texts.release ();
|
||||
}
|
||||
|
||||
RegionDelegate *
|
||||
AsIfFlatTexts::processed_to_polygons (const TextToPolygonProcessorBase &filter) const
|
||||
{
|
||||
std::auto_ptr<FlatRegion> region (new FlatRegion ());
|
||||
|
||||
if (filter.result_must_not_be_merged ()) {
|
||||
region->set_merged_semantics (false);
|
||||
}
|
||||
|
||||
std::vector<db::Polygon> res_polygons;
|
||||
|
||||
for (TextsIterator e (begin ()); ! e.at_end (); ++e) {
|
||||
res_polygons.clear ();
|
||||
filter.process (*e, res_polygons);
|
||||
for (std::vector<db::Polygon>::const_iterator pr = res_polygons.begin (); pr != res_polygons.end (); ++pr) {
|
||||
region->insert (*pr);
|
||||
}
|
||||
}
|
||||
|
||||
return region.release ();
|
||||
}
|
||||
|
||||
RegionDelegate *
|
||||
AsIfFlatTexts::polygons (db::Coord e) const
|
||||
{
|
||||
|
|
|
|||
|
|
@ -53,6 +53,8 @@ public:
|
|||
|
||||
virtual TextsDelegate *filtered (const TextFilterBase &) const;
|
||||
|
||||
virtual RegionDelegate *processed_to_polygons (const TextToPolygonProcessorBase &filter) const;
|
||||
|
||||
virtual TextsDelegate *add_in_place (const Texts &other)
|
||||
{
|
||||
return add (other);
|
||||
|
|
|
|||
|
|
@ -57,6 +57,22 @@ db::Trans MagnificationReducer::reduce (const db::Trans &) const
|
|||
|
||||
// ------------------------------------------------------------------------------------------
|
||||
|
||||
db::ICplxTrans XYAnisotropyAndMagnificationReducer::reduce (const db::ICplxTrans &trans) const
|
||||
{
|
||||
double a = trans.angle ();
|
||||
if (a > 180.0 - db::epsilon) {
|
||||
a -= 180.0;
|
||||
}
|
||||
return db::ICplxTrans (trans.mag (), a, false, db::Vector ());
|
||||
}
|
||||
|
||||
db::Trans XYAnisotropyAndMagnificationReducer::reduce (const db::Trans &trans) const
|
||||
{
|
||||
return db::Trans (trans.angle () % 2, false, db::Vector ());
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------
|
||||
|
||||
db::ICplxTrans MagnificationAndOrientationReducer::reduce (const db::ICplxTrans &trans) const
|
||||
{
|
||||
db::ICplxTrans res (trans);
|
||||
|
|
|
|||
|
|
@ -81,6 +81,18 @@ struct DB_PUBLIC MagnificationReducer
|
|||
db::Trans reduce (const db::Trans &) const;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief A reducer for magnification and XYAnisotropy
|
||||
*
|
||||
* This reducer is used for cases where an x and y-value is given, e.g. anisotropic size.
|
||||
*/
|
||||
struct DB_PUBLIC XYAnisotropyAndMagnificationReducer
|
||||
: public TransformationReducer
|
||||
{
|
||||
db::ICplxTrans reduce (const db::ICplxTrans &trans) const;
|
||||
db::Trans reduce (const db::Trans &trans) const;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief A magnification and orientation reducer
|
||||
*
|
||||
|
|
|
|||
|
|
@ -240,6 +240,12 @@ EdgePairsDelegate *DeepEdgePairs::filtered (const EdgePairFilterBase &filter) co
|
|||
return AsIfFlatEdgePairs::filtered (filter);
|
||||
}
|
||||
|
||||
RegionDelegate *
|
||||
DeepEdgePairs::processed_to_polygons (const EdgePairToPolygonProcessorBase &filter) const
|
||||
{
|
||||
return shape_collection_processed_impl<db::EdgePair, db::Polygon, db::DeepRegion> (deep_layer (), filter);
|
||||
}
|
||||
|
||||
RegionDelegate *DeepEdgePairs::polygons (db::Coord e) const
|
||||
{
|
||||
db::DeepLayer new_layer = deep_layer ().derived ();
|
||||
|
|
|
|||
|
|
@ -63,6 +63,7 @@ public:
|
|||
|
||||
virtual EdgePairsDelegate *filter_in_place (const EdgePairFilterBase &filter);
|
||||
virtual EdgePairsDelegate *filtered (const EdgePairFilterBase &) const;
|
||||
virtual RegionDelegate *processed_to_polygons (const EdgePairToPolygonProcessorBase &filter) const;
|
||||
|
||||
virtual EdgePairsDelegate *add_in_place (const EdgePairs &other);
|
||||
virtual EdgePairsDelegate *add (const EdgePairs &other) const;
|
||||
|
|
|
|||
|
|
@ -525,146 +525,19 @@ EdgesDelegate *DeepEdges::process_in_place (const EdgeProcessorBase &filter)
|
|||
EdgesDelegate *
|
||||
DeepEdges::processed (const EdgeProcessorBase &filter) const
|
||||
{
|
||||
return processed_impl<db::Edge, db::DeepEdges> (filter);
|
||||
return shape_collection_processed_impl<db::Edge, db::Edge, db::DeepEdges> (filter.requires_raw_input () ? deep_layer () : merged_deep_layer (), filter);
|
||||
}
|
||||
|
||||
EdgePairsDelegate *
|
||||
DeepEdges::processed_to_edge_pairs (const EdgeToEdgePairProcessorBase &filter) const
|
||||
{
|
||||
return processed_impl<db::EdgePair, db::DeepEdgePairs> (filter);
|
||||
return shape_collection_processed_impl<db::Edge, db::EdgePair, db::DeepEdgePairs> (filter.requires_raw_input () ? deep_layer () : merged_deep_layer (), filter);
|
||||
}
|
||||
|
||||
RegionDelegate *
|
||||
DeepEdges::processed_to_polygons (const EdgeToPolygonProcessorBase &filter) const
|
||||
{
|
||||
return processed_impl<db::Polygon, db::DeepRegion> (filter);
|
||||
}
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
template <class Result> struct delivery;
|
||||
|
||||
template <>
|
||||
struct delivery<db::Polygon>
|
||||
{
|
||||
delivery (db::Layout *layout, db::Shapes *shapes)
|
||||
: mp_layout (layout), mp_shapes (shapes)
|
||||
{ }
|
||||
|
||||
void put (const db::Polygon &result)
|
||||
{
|
||||
tl::MutexLocker locker (&mp_layout->lock ());
|
||||
mp_shapes->insert (db::PolygonRef (result, mp_layout->shape_repository ()));
|
||||
}
|
||||
|
||||
private:
|
||||
db::Layout *mp_layout;
|
||||
db::Shapes *mp_shapes;
|
||||
};
|
||||
|
||||
template <class Result>
|
||||
struct delivery
|
||||
{
|
||||
delivery (db::Layout *, db::Shapes *shapes)
|
||||
: mp_shapes (shapes)
|
||||
{ }
|
||||
|
||||
void put (const Result &result)
|
||||
{
|
||||
mp_shapes->insert (result);
|
||||
}
|
||||
|
||||
private:
|
||||
db::Shapes *mp_shapes;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
template <class Result, class OutputContainer>
|
||||
OutputContainer *
|
||||
DeepEdges::processed_impl (const edge_processor<Result> &filter) const
|
||||
{
|
||||
const db::DeepLayer &edges = filter.requires_raw_input () ? deep_layer () : merged_deep_layer ();
|
||||
|
||||
std::auto_ptr<VariantsCollectorBase> vars;
|
||||
if (filter.vars ()) {
|
||||
|
||||
vars.reset (new db::VariantsCollectorBase (filter.vars ()));
|
||||
|
||||
vars->collect (edges.layout (), edges.initial_cell ());
|
||||
|
||||
if (filter.wants_variants ()) {
|
||||
const_cast<db::DeepLayer &> (edges).separate_variants (*vars);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
db::Layout &layout = const_cast<db::Layout &> (edges.layout ());
|
||||
|
||||
std::vector<Result> heap;
|
||||
std::map<db::cell_index_type, std::map<db::ICplxTrans, db::Shapes> > to_commit;
|
||||
|
||||
std::auto_ptr<OutputContainer> res (new OutputContainer (edges.derived ()));
|
||||
if (filter.result_must_not_be_merged ()) {
|
||||
res->set_merged_semantics (false);
|
||||
}
|
||||
|
||||
for (db::Layout::iterator c = layout.begin (); c != layout.end (); ++c) {
|
||||
|
||||
const db::Shapes &s = c->shapes (filter.requires_raw_input () ? edges.layer () : edges.layer ());
|
||||
|
||||
if (vars.get ()) {
|
||||
|
||||
const std::map<db::ICplxTrans, size_t> &vv = vars->variants (c->cell_index ());
|
||||
for (std::map<db::ICplxTrans, size_t>::const_iterator v = vv.begin (); v != vv.end (); ++v) {
|
||||
|
||||
db::Shapes *st;
|
||||
if (vv.size () == 1) {
|
||||
st = & c->shapes (res->deep_layer ().layer ());
|
||||
} else {
|
||||
st = & to_commit [c->cell_index ()] [v->first];
|
||||
}
|
||||
|
||||
delivery<Result> delivery (&layout, st);
|
||||
|
||||
const db::ICplxTrans &tr = v->first;
|
||||
db::ICplxTrans trinv = tr.inverted ();
|
||||
|
||||
for (db::Shapes::shape_iterator si = s.begin (db::ShapeIterator::Edges); ! si.at_end (); ++si) {
|
||||
heap.clear ();
|
||||
filter.process (si->edge ().transformed (tr), heap);
|
||||
for (typename std::vector<Result>::const_iterator i = heap.begin (); i != heap.end (); ++i) {
|
||||
delivery.put (i->transformed (trinv));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
db::Shapes &st = c->shapes (res->deep_layer ().layer ());
|
||||
delivery<Result> delivery (&layout, &st);
|
||||
|
||||
for (db::Shapes::shape_iterator si = s.begin (db::ShapeIterator::Edges); ! si.at_end (); ++si) {
|
||||
filter.process (si->edge (), heap);
|
||||
for (typename std::vector<Result>::const_iterator i = heap.begin (); i != heap.end (); ++i) {
|
||||
delivery.put (*i);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (! to_commit.empty () && vars.get ()) {
|
||||
res->deep_layer ().commit_shapes (*vars, to_commit);
|
||||
}
|
||||
|
||||
if (filter.result_is_merged ()) {
|
||||
res->set_is_merged (true);
|
||||
}
|
||||
return res.release ();
|
||||
return shape_collection_processed_impl<db::Edge, db::Polygon, db::DeepRegion> (filter.requires_raw_input () ? deep_layer () : merged_deep_layer (), filter);
|
||||
}
|
||||
|
||||
EdgesDelegate *
|
||||
|
|
|
|||
|
|
@ -149,9 +149,10 @@ public:
|
|||
return this;
|
||||
}
|
||||
|
||||
void set_is_merged (bool f);
|
||||
|
||||
protected:
|
||||
virtual void merged_semantics_changed ();
|
||||
void set_is_merged (bool f);
|
||||
|
||||
private:
|
||||
friend class DeepRegion;
|
||||
|
|
|
|||
|
|
@ -955,152 +955,19 @@ DeepRegion::process_in_place (const PolygonProcessorBase &filter)
|
|||
EdgesDelegate *
|
||||
DeepRegion::processed_to_edges (const PolygonToEdgeProcessorBase &filter) const
|
||||
{
|
||||
return processed_impl<db::Edge, db::DeepEdges> (filter);
|
||||
return shape_collection_processed_impl<db::Polygon, db::Edge, db::DeepEdges> (filter.requires_raw_input () ? deep_layer () : merged_deep_layer (), filter);
|
||||
}
|
||||
|
||||
EdgePairsDelegate *
|
||||
DeepRegion::processed_to_edge_pairs (const PolygonToEdgePairProcessorBase &filter) const
|
||||
{
|
||||
return processed_impl<db::EdgePair, db::DeepEdgePairs> (filter);
|
||||
return shape_collection_processed_impl<db::Polygon, db::EdgePair, db::DeepEdgePairs> (filter.requires_raw_input () ? deep_layer () : merged_deep_layer (), filter);
|
||||
}
|
||||
|
||||
RegionDelegate *
|
||||
DeepRegion::processed (const PolygonProcessorBase &filter) const
|
||||
{
|
||||
return processed_impl<db::Polygon, db::DeepRegion> (filter);
|
||||
}
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
template <class Result> struct delivery;
|
||||
|
||||
template <>
|
||||
struct delivery<db::Polygon>
|
||||
{
|
||||
delivery (db::Layout *layout, db::Shapes *shapes)
|
||||
: mp_layout (layout), mp_shapes (shapes)
|
||||
{ }
|
||||
|
||||
void put (const db::Polygon &result)
|
||||
{
|
||||
tl::MutexLocker locker (&mp_layout->lock ());
|
||||
mp_shapes->insert (db::PolygonRef (result, mp_layout->shape_repository ()));
|
||||
}
|
||||
|
||||
private:
|
||||
db::Layout *mp_layout;
|
||||
db::Shapes *mp_shapes;
|
||||
};
|
||||
|
||||
template <class Result>
|
||||
struct delivery
|
||||
{
|
||||
delivery (db::Layout *, db::Shapes *shapes)
|
||||
: mp_shapes (shapes)
|
||||
{ }
|
||||
|
||||
void put (const Result &result)
|
||||
{
|
||||
mp_shapes->insert (result);
|
||||
}
|
||||
|
||||
private:
|
||||
db::Shapes *mp_shapes;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
template <class Result, class OutputContainer>
|
||||
OutputContainer *
|
||||
DeepRegion::processed_impl (const polygon_processor<Result> &filter) const
|
||||
{
|
||||
const db::DeepLayer &polygons = filter.requires_raw_input () ? deep_layer () : merged_deep_layer ();
|
||||
|
||||
std::auto_ptr<VariantsCollectorBase> vars;
|
||||
if (filter.vars ()) {
|
||||
|
||||
vars.reset (new db::VariantsCollectorBase (filter.vars ()));
|
||||
|
||||
vars->collect (polygons.layout (), polygons.initial_cell ());
|
||||
|
||||
if (filter.wants_variants ()) {
|
||||
const_cast<db::DeepLayer &> (polygons).separate_variants (*vars);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
db::Layout &layout = const_cast<db::Layout &> (polygons.layout ());
|
||||
|
||||
std::vector<Result> heap;
|
||||
std::map<db::cell_index_type, std::map<db::ICplxTrans, db::Shapes> > to_commit;
|
||||
|
||||
std::auto_ptr<OutputContainer> res (new OutputContainer (polygons.derived ()));
|
||||
if (filter.result_must_not_be_merged ()) {
|
||||
res->set_merged_semantics (false);
|
||||
}
|
||||
|
||||
for (db::Layout::iterator c = layout.begin (); c != layout.end (); ++c) {
|
||||
|
||||
const db::Shapes &s = c->shapes (polygons.layer ());
|
||||
|
||||
if (vars.get ()) {
|
||||
|
||||
const std::map<db::ICplxTrans, size_t> &vv = vars->variants (c->cell_index ());
|
||||
for (std::map<db::ICplxTrans, size_t>::const_iterator v = vv.begin (); v != vv.end (); ++v) {
|
||||
|
||||
db::Shapes *st;
|
||||
if (vv.size () == 1) {
|
||||
st = & c->shapes (res->deep_layer ().layer ());
|
||||
} else {
|
||||
st = & to_commit [c->cell_index ()] [v->first];
|
||||
}
|
||||
|
||||
delivery<Result> delivery (&layout, st);
|
||||
|
||||
const db::ICplxTrans &tr = v->first;
|
||||
db::ICplxTrans trinv = tr.inverted ();
|
||||
|
||||
for (db::Shapes::shape_iterator si = s.begin (db::ShapeIterator::All); ! si.at_end (); ++si) {
|
||||
db::Polygon poly;
|
||||
si->polygon (poly);
|
||||
poly.transform (tr);
|
||||
heap.clear ();
|
||||
filter.process (poly, heap);
|
||||
for (typename std::vector<Result>::const_iterator i = heap.begin (); i != heap.end (); ++i) {
|
||||
delivery.put (i->transformed (trinv));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
db::Shapes &st = c->shapes (res->deep_layer ().layer ());
|
||||
delivery<Result> delivery (&layout, &st);
|
||||
|
||||
for (db::Shapes::shape_iterator si = s.begin (db::ShapeIterator::All); ! si.at_end (); ++si) {
|
||||
db::Polygon poly;
|
||||
si->polygon (poly);
|
||||
heap.clear ();
|
||||
filter.process (poly, heap);
|
||||
for (typename std::vector<Result>::const_iterator i = heap.begin (); i != heap.end (); ++i) {
|
||||
delivery.put (*i);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (! to_commit.empty () && vars.get ()) {
|
||||
res->deep_layer ().commit_shapes (*vars, to_commit);
|
||||
}
|
||||
|
||||
if (filter.result_is_merged ()) {
|
||||
res->set_is_merged (true);
|
||||
}
|
||||
return res.release ();
|
||||
return shape_collection_processed_impl<db::Polygon, db::Polygon, db::DeepRegion> (filter.requires_raw_input () ? deep_layer () : merged_deep_layer (), filter);
|
||||
}
|
||||
|
||||
RegionDelegate *
|
||||
|
|
@ -1318,29 +1185,6 @@ DeepRegion::sized (coord_type d, unsigned int mode) const
|
|||
return res.release ();
|
||||
}
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
struct XYAnisotropyAndMagnificationReducer
|
||||
: public db::TransformationReducer
|
||||
{
|
||||
db::ICplxTrans reduce (const db::ICplxTrans &trans) const
|
||||
{
|
||||
double a = trans.angle ();
|
||||
if (a > 180.0 - db::epsilon) {
|
||||
a -= 180.0;
|
||||
}
|
||||
return db::ICplxTrans (trans.mag (), a, false, db::Vector ());
|
||||
}
|
||||
|
||||
db::Trans reduce (const db::Trans &trans) const
|
||||
{
|
||||
return db::Trans (trans.angle () % 2, false, db::Vector ());
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
RegionDelegate *
|
||||
DeepRegion::sized (coord_type dx, coord_type dy, unsigned int mode) const
|
||||
{
|
||||
|
|
|
|||
|
|
@ -164,10 +164,11 @@ public:
|
|||
return this;
|
||||
}
|
||||
|
||||
void set_is_merged (bool f);
|
||||
|
||||
protected:
|
||||
virtual void merged_semantics_changed ();
|
||||
virtual void min_coherence_changed ();
|
||||
void set_is_merged (bool f);
|
||||
|
||||
private:
|
||||
friend class DeepEdges;
|
||||
|
|
|
|||
|
|
@ -333,6 +333,12 @@ DeepTexts *DeepTexts::apply_filter (const TextFilterBase &filter) const
|
|||
return res.release ();
|
||||
}
|
||||
|
||||
RegionDelegate *
|
||||
DeepTexts::processed_to_polygons (const TextToPolygonProcessorBase &filter) const
|
||||
{
|
||||
return shape_collection_processed_impl<db::Text, db::Polygon, db::DeepRegion> (deep_layer (), filter);
|
||||
}
|
||||
|
||||
RegionDelegate *DeepTexts::polygons (db::Coord e) const
|
||||
{
|
||||
db::DeepLayer new_layer = deep_layer ().derived ();
|
||||
|
|
|
|||
|
|
@ -65,6 +65,8 @@ public:
|
|||
virtual TextsDelegate *filter_in_place (const TextFilterBase &filter);
|
||||
virtual TextsDelegate *filtered (const TextFilterBase &) const;
|
||||
|
||||
virtual RegionDelegate *processed_to_polygons (const TextToPolygonProcessorBase &filter) const;
|
||||
|
||||
virtual TextsDelegate *add_in_place (const Texts &other);
|
||||
virtual TextsDelegate *add (const Texts &other) const;
|
||||
|
||||
|
|
|
|||
|
|
@ -143,6 +143,11 @@ EdgePairs::iter () const
|
|||
return *(i ? i : &def_iter);
|
||||
}
|
||||
|
||||
void EdgePairs::processed (Region &output, const EdgePairToPolygonProcessorBase &filter) const
|
||||
{
|
||||
output = Region (mp_delegate->processed_to_polygons (filter));
|
||||
}
|
||||
|
||||
void EdgePairs::polygons (Region &output, db::Coord e) const
|
||||
{
|
||||
output.set_delegate (mp_delegate->polygons (e));
|
||||
|
|
|
|||
|
|
@ -465,6 +465,14 @@ public:
|
|||
return EdgePairs (mp_delegate->filtered (filter));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Processes the edge pairs into polygons
|
||||
*
|
||||
* This method will run the processor over all edge pairs and return a region
|
||||
* with the outputs of the processor.
|
||||
*/
|
||||
void processed (Region &output, const EdgePairToPolygonProcessorBase &filter) const;
|
||||
|
||||
/**
|
||||
* @brief Transforms the edge pair set
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@
|
|||
#include "dbCommon.h"
|
||||
#include "dbEdgePair.h"
|
||||
#include "dbShapeCollection.h"
|
||||
#include "dbShapeCollectionUtils.h"
|
||||
|
||||
namespace db {
|
||||
|
||||
|
|
@ -37,6 +38,8 @@ class RegionDelegate;
|
|||
class EdgesDelegate;
|
||||
class Layout;
|
||||
|
||||
typedef shape_collection_processor<db::EdgePair, db::Polygon> EdgePairToPolygonProcessorBase;
|
||||
|
||||
/**
|
||||
* @brief The edge pair set iterator delegate
|
||||
*/
|
||||
|
|
@ -97,6 +100,7 @@ public:
|
|||
|
||||
virtual EdgePairsDelegate *filter_in_place (const EdgePairFilterBase &filter) = 0;
|
||||
virtual EdgePairsDelegate *filtered (const EdgePairFilterBase &filter) const = 0;
|
||||
virtual RegionDelegate *processed_to_polygons (const EdgePairToPolygonProcessorBase &filter) const = 0;
|
||||
|
||||
virtual RegionDelegate *polygons (db::Coord e) const = 0;
|
||||
virtual EdgesDelegate *edges () const = 0;
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@
|
|||
#include "dbEdgePairs.h"
|
||||
#include "dbEdgePairRelations.h"
|
||||
#include "dbShapeCollection.h"
|
||||
#include "dbShapeCollectionUtils.h"
|
||||
|
||||
#include <list>
|
||||
|
||||
|
|
@ -128,32 +129,9 @@ public:
|
|||
virtual bool wants_variants () const = 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief A edge processor base class
|
||||
*/
|
||||
class DB_PUBLIC EdgeProcessorBase
|
||||
: public edge_processor<db::Edge>
|
||||
{
|
||||
// .. nothing yet ..
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief An edge-to-polygon processor base class
|
||||
*/
|
||||
class DB_PUBLIC EdgeToPolygonProcessorBase
|
||||
: public edge_processor<db::Polygon>
|
||||
{
|
||||
// .. nothing yet ..
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief An edge-to-edge pair processor base class
|
||||
*/
|
||||
class DB_PUBLIC EdgeToEdgePairProcessorBase
|
||||
: public edge_processor<db::EdgePair>
|
||||
{
|
||||
// .. nothing yet ..
|
||||
};
|
||||
typedef shape_collection_processor<db::Edge, db::Edge> EdgeProcessorBase;
|
||||
typedef shape_collection_processor<db::Edge, db::Polygon> EdgeToPolygonProcessorBase;
|
||||
typedef shape_collection_processor<db::Edge, db::EdgePair> EdgeToEdgePairProcessorBase;
|
||||
|
||||
class RecursiveShapeIterator;
|
||||
class EdgeFilterBase;
|
||||
|
|
|
|||
|
|
@ -53,6 +53,12 @@ EmptyEdgePairs::polygons (db::Coord) const
|
|||
return new EmptyRegion ();
|
||||
}
|
||||
|
||||
RegionDelegate *
|
||||
EmptyEdgePairs::processed_to_polygons (const EdgePairToPolygonProcessorBase &) const
|
||||
{
|
||||
return new EmptyRegion ();
|
||||
}
|
||||
|
||||
EdgesDelegate *
|
||||
EmptyEdgePairs::edges () const
|
||||
{
|
||||
|
|
|
|||
|
|
@ -55,6 +55,7 @@ public:
|
|||
|
||||
virtual EdgePairsDelegate *filter_in_place (const EdgePairFilterBase &) { return this; }
|
||||
virtual EdgePairsDelegate *filtered (const EdgePairFilterBase &) const { return new EmptyEdgePairs (); }
|
||||
virtual RegionDelegate *processed_to_polygons (const EdgePairToPolygonProcessorBase &filter) const;
|
||||
|
||||
virtual RegionDelegate *polygons (db::Coord e) const;
|
||||
virtual EdgesDelegate *edges () const;
|
||||
|
|
|
|||
|
|
@ -54,6 +54,12 @@ EmptyTexts::polygons (db::Coord) const
|
|||
return new EmptyRegion ();
|
||||
}
|
||||
|
||||
RegionDelegate *
|
||||
EmptyTexts::processed_to_polygons (const TextToPolygonProcessorBase &) const
|
||||
{
|
||||
return new EmptyRegion ();
|
||||
}
|
||||
|
||||
EdgesDelegate *
|
||||
EmptyTexts::edges () const
|
||||
{
|
||||
|
|
|
|||
|
|
@ -56,6 +56,8 @@ public:
|
|||
virtual TextsDelegate *filter_in_place (const TextFilterBase &) { return this; }
|
||||
virtual TextsDelegate *filtered (const TextFilterBase &) const { return new EmptyTexts (); }
|
||||
|
||||
virtual RegionDelegate *processed_to_polygons (const TextToPolygonProcessorBase &) const;
|
||||
|
||||
virtual RegionDelegate *polygons (db::Coord e) const;
|
||||
virtual EdgesDelegate *edges () const;
|
||||
|
||||
|
|
|
|||
|
|
@ -135,32 +135,9 @@ public:
|
|||
virtual bool wants_variants () const = 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief A polygon-to-polygon processor base class
|
||||
*/
|
||||
class DB_PUBLIC PolygonProcessorBase
|
||||
: public polygon_processor<db::Polygon>
|
||||
{
|
||||
// .. nothing yet ..
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief A polygon-to-edge processor base class
|
||||
*/
|
||||
class DB_PUBLIC PolygonToEdgeProcessorBase
|
||||
: public polygon_processor<db::Edge>
|
||||
{
|
||||
// .. nothing yet ..
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief A polygon-to-edge pair processor base class
|
||||
*/
|
||||
class DB_PUBLIC PolygonToEdgePairProcessorBase
|
||||
: public polygon_processor<db::EdgePair>
|
||||
{
|
||||
// .. nothing yet ..
|
||||
};
|
||||
typedef shape_collection_processor<db::Polygon, db::Polygon> PolygonProcessorBase;
|
||||
typedef shape_collection_processor<db::Polygon, db::Edge> PolygonToEdgeProcessorBase;
|
||||
typedef shape_collection_processor<db::Polygon, db::EdgePair> PolygonToEdgePairProcessorBase;
|
||||
|
||||
/**
|
||||
* @brief The region iterator delegate
|
||||
|
|
|
|||
|
|
@ -87,28 +87,6 @@ void CornerDetectorCore::detect_corners (const db::Polygon &poly, const CornerPo
|
|||
}
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------------
|
||||
// Extents implementation
|
||||
|
||||
void Extents::process (const db::Polygon &poly, std::vector<db::Polygon> &result) const
|
||||
{
|
||||
db::Box box = poly.box ().enlarged (db::Vector (m_dx, m_dy));
|
||||
if (! box.empty ()) {
|
||||
result.push_back (db::Polygon (box));
|
||||
}
|
||||
}
|
||||
|
||||
const TransformationReducer *Extents::vars () const
|
||||
{
|
||||
if (m_dx == 0 && m_dy == 0) {
|
||||
return 0;
|
||||
} else if (m_dx == m_dy) {
|
||||
return & m_isotropic_reducer;
|
||||
} else {
|
||||
return & m_anisotropic_reducer;
|
||||
}
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------------
|
||||
// RelativeExtents implementation
|
||||
|
||||
|
|
|
|||
|
|
@ -158,34 +158,6 @@ public:
|
|||
// -----------------------------------------------------------------------------------
|
||||
// Extents
|
||||
|
||||
/**
|
||||
* @brief A processor delivering the extents (bounding box) of the merged polygons
|
||||
* This processor allows over- or undersizing of the resulting box by a given amount
|
||||
*/
|
||||
class DB_PUBLIC Extents
|
||||
: public db::PolygonProcessorBase
|
||||
{
|
||||
public:
|
||||
Extents (db::Coord dx, db::Coord dy)
|
||||
: m_dx (dx), m_dy (dy)
|
||||
{
|
||||
// .. nothing yet ..
|
||||
}
|
||||
|
||||
void process (const db::Polygon &poly, std::vector<db::Polygon> &result) const;
|
||||
|
||||
virtual const TransformationReducer *vars () const;
|
||||
virtual bool result_is_merged () const { return false; }
|
||||
virtual bool result_must_not_be_merged () const { return false; }
|
||||
virtual bool requires_raw_input () const { return false; }
|
||||
virtual bool wants_variants () const { return true; }
|
||||
|
||||
private:
|
||||
db::Coord m_dx, m_dy;
|
||||
db::MagnificationAndOrientationReducer m_anisotropic_reducer;
|
||||
db::MagnificationReducer m_isotropic_reducer;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief A processor delivering the relative extents (bounding box) of the merged polygons
|
||||
* This processor allows over- or undersizing of the resulting box by a given amount and delivery
|
||||
|
|
|
|||
|
|
@ -0,0 +1,23 @@
|
|||
|
||||
/*
|
||||
|
||||
KLayout Layout Viewer
|
||||
Copyright (C) 2006-2020 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
|
||||
|
||||
*/
|
||||
|
||||
#include "dbShapeCollectionUtils.h"
|
||||
|
|
@ -0,0 +1,302 @@
|
|||
|
||||
/*
|
||||
|
||||
KLayout Layout Viewer
|
||||
Copyright (C) 2006-2020 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
|
||||
|
||||
*/
|
||||
|
||||
|
||||
#ifndef HDR_dbShapeCollectionUtils
|
||||
#define HDR_dbShapeCollectionUtils
|
||||
|
||||
#include "dbCommon.h"
|
||||
|
||||
#include "dbShape.h"
|
||||
#include "dbShapes.h"
|
||||
#include "dbLayout.h"
|
||||
#include "dbCellVariants.h"
|
||||
#include "dbShapeCollection.h"
|
||||
#include "dbDeepShapeStore.h"
|
||||
|
||||
#include <list>
|
||||
|
||||
namespace db {
|
||||
|
||||
/**
|
||||
* @brief A template base class for edge processors
|
||||
*
|
||||
* A polygon processor can turn a edge into something else.
|
||||
*/
|
||||
template <class Shape, class Result>
|
||||
class DB_PUBLIC_TEMPLATE shape_collection_processor
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* @brief Constructor
|
||||
*/
|
||||
shape_collection_processor () { }
|
||||
|
||||
/**
|
||||
* @brief Destructor
|
||||
*/
|
||||
virtual ~shape_collection_processor () { }
|
||||
|
||||
/**
|
||||
* @brief Performs the actual processing
|
||||
* This method will take the input edge from "edge" and puts the results into "res".
|
||||
* "res" can be empty - in this case, the edge will be skipped.
|
||||
*/
|
||||
virtual void process (const Shape &shape, std::vector<Result> &res) const = 0;
|
||||
|
||||
/**
|
||||
* @brief Returns the transformation reducer for building cell variants
|
||||
* This method may return 0. In this case, not cell variants are built.
|
||||
*/
|
||||
virtual const TransformationReducer *vars () const = 0;
|
||||
|
||||
/**
|
||||
* @brief Returns true, if the result of this operation can be regarded "merged" always.
|
||||
*/
|
||||
virtual bool result_is_merged () const = 0;
|
||||
|
||||
/**
|
||||
* @brief Returns true, if the result of this operation must not be merged.
|
||||
* This feature can be used, if the result represents "degenerated" objects such
|
||||
* as point-like edges. These must not be merged. Otherwise they disappear.
|
||||
*/
|
||||
virtual bool result_must_not_be_merged () const = 0;
|
||||
|
||||
/**
|
||||
* @brief Returns true, if the processor wants raw (not merged) input
|
||||
*/
|
||||
virtual bool requires_raw_input () const = 0;
|
||||
|
||||
/**
|
||||
* @brief Returns true, if the processor wants to build variants
|
||||
* If not true, the processor accepts shape propagation as variant resolution.
|
||||
*/
|
||||
virtual bool wants_variants () const = 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief A shape delivery class for the shape collection processor
|
||||
*/
|
||||
template <class Result> struct shape_collection_processor_delivery;
|
||||
|
||||
/**
|
||||
* @brief A shape delivery implementation for polygons
|
||||
*/
|
||||
template <>
|
||||
struct DB_PUBLIC shape_collection_processor_delivery<db::Polygon>
|
||||
{
|
||||
shape_collection_processor_delivery (db::Layout *layout, db::Shapes *shapes)
|
||||
: mp_layout (layout), mp_shapes (shapes)
|
||||
{ }
|
||||
|
||||
void put (const db::Polygon &result)
|
||||
{
|
||||
tl::MutexLocker locker (&mp_layout->lock ());
|
||||
mp_shapes->insert (db::PolygonRef (result, mp_layout->shape_repository ()));
|
||||
}
|
||||
|
||||
private:
|
||||
db::Layout *mp_layout;
|
||||
db::Shapes *mp_shapes;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief A shape delivery implementation for texts
|
||||
*/
|
||||
template <>
|
||||
struct DB_PUBLIC shape_collection_processor_delivery<db::Text>
|
||||
{
|
||||
shape_collection_processor_delivery (db::Layout *layout, db::Shapes *shapes)
|
||||
: mp_layout (layout), mp_shapes (shapes)
|
||||
{ }
|
||||
|
||||
void put (const db::Text &result)
|
||||
{
|
||||
tl::MutexLocker locker (&mp_layout->lock ());
|
||||
mp_shapes->insert (db::TextRef (result, mp_layout->shape_repository ()));
|
||||
}
|
||||
|
||||
private:
|
||||
db::Layout *mp_layout;
|
||||
db::Shapes *mp_shapes;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief A generic delivery
|
||||
*/
|
||||
template <class Result>
|
||||
struct DB_PUBLIC shape_collection_processor_delivery
|
||||
{
|
||||
shape_collection_processor_delivery (db::Layout *, db::Shapes *shapes)
|
||||
: mp_shapes (shapes)
|
||||
{ }
|
||||
|
||||
void put (const Result &result)
|
||||
{
|
||||
mp_shapes->insert (result);
|
||||
}
|
||||
|
||||
private:
|
||||
db::Shapes *mp_shapes;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Provides a generic implementation of the shape collection processor
|
||||
*/
|
||||
template <class Shape, class Result, class OutputContainer>
|
||||
DB_PUBLIC_TEMPLATE
|
||||
OutputContainer *
|
||||
shape_collection_processed_impl (const db::DeepLayer &input, const shape_collection_processor<Shape, Result> &filter)
|
||||
{
|
||||
std::auto_ptr<VariantsCollectorBase> vars;
|
||||
if (filter.vars ()) {
|
||||
|
||||
vars.reset (new db::VariantsCollectorBase (filter.vars ()));
|
||||
|
||||
vars->collect (input.layout (), input.initial_cell ());
|
||||
|
||||
if (filter.wants_variants ()) {
|
||||
const_cast<db::DeepLayer &> (input).separate_variants (*vars);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
db::Layout &layout = const_cast<db::Layout &> (input.layout ());
|
||||
|
||||
std::vector<Result> heap;
|
||||
std::map<db::cell_index_type, std::map<db::ICplxTrans, db::Shapes> > to_commit;
|
||||
|
||||
std::auto_ptr<OutputContainer> res (new OutputContainer (input.derived ()));
|
||||
if (filter.result_must_not_be_merged ()) {
|
||||
res->set_merged_semantics (false);
|
||||
}
|
||||
|
||||
for (db::Layout::iterator c = layout.begin (); c != layout.end (); ++c) {
|
||||
|
||||
const db::Shapes &s = c->shapes (input.layer ());
|
||||
|
||||
if (vars.get ()) {
|
||||
|
||||
const std::map<db::ICplxTrans, size_t> &vv = vars->variants (c->cell_index ());
|
||||
for (std::map<db::ICplxTrans, size_t>::const_iterator v = vv.begin (); v != vv.end (); ++v) {
|
||||
|
||||
db::Shapes *st;
|
||||
if (vv.size () == 1) {
|
||||
st = & c->shapes (res->deep_layer ().layer ());
|
||||
} else {
|
||||
st = & to_commit [c->cell_index ()] [v->first];
|
||||
}
|
||||
|
||||
shape_collection_processor_delivery<Result> delivery (&layout, st);
|
||||
|
||||
const db::ICplxTrans &tr = v->first;
|
||||
db::ICplxTrans trinv = tr.inverted ();
|
||||
|
||||
for (db::Shapes::shape_iterator si = s.begin (db::ShapeIterator::All); ! si.at_end (); ++si) {
|
||||
Shape s;
|
||||
si->instantiate (s);
|
||||
s.transform (tr);
|
||||
heap.clear ();
|
||||
filter.process (s, heap);
|
||||
for (typename std::vector<Result>::const_iterator i = heap.begin (); i != heap.end (); ++i) {
|
||||
delivery.put (i->transformed (trinv));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
db::Shapes &st = c->shapes (res->deep_layer ().layer ());
|
||||
shape_collection_processor_delivery<Result> delivery (&layout, &st);
|
||||
|
||||
for (db::Shapes::shape_iterator si = s.begin (db::ShapeIterator::All); ! si.at_end (); ++si) {
|
||||
Shape s;
|
||||
si->instantiate (s);
|
||||
heap.clear ();
|
||||
filter.process (s, heap);
|
||||
for (typename std::vector<Result>::const_iterator i = heap.begin (); i != heap.end (); ++i) {
|
||||
delivery.put (*i);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (! to_commit.empty () && vars.get ()) {
|
||||
res->deep_layer ().commit_shapes (*vars, to_commit);
|
||||
}
|
||||
|
||||
if (filter.result_is_merged ()) {
|
||||
res->set_is_merged (true);
|
||||
}
|
||||
return res.release ();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief A generic processor to compute the extents of an object
|
||||
*/
|
||||
template <class Shape>
|
||||
class extents_processor
|
||||
: public db::shape_collection_processor<Shape, db::Polygon>
|
||||
{
|
||||
public:
|
||||
extents_processor (db::Coord dx, db::Coord dy)
|
||||
: m_dx (dx), m_dy (dy)
|
||||
{ }
|
||||
|
||||
virtual void process (const Shape &s, std::vector<db::Polygon> &res) const
|
||||
{
|
||||
db::box_convert<Shape> bc;
|
||||
db::Box box = bc (s).enlarged (db::Vector (m_dx, m_dy));
|
||||
if (! box.empty ()) {
|
||||
res.push_back (db::Polygon (box));
|
||||
}
|
||||
}
|
||||
|
||||
virtual const db::TransformationReducer *vars () const
|
||||
{
|
||||
if (m_dx == 0 && m_dy == 0) {
|
||||
return 0;
|
||||
} else if (m_dx == m_dy) {
|
||||
return & m_isotropic_reducer;
|
||||
} else {
|
||||
return & m_anisotropic_reducer;
|
||||
}
|
||||
}
|
||||
|
||||
virtual bool result_is_merged () const { return false; }
|
||||
virtual bool requires_raw_input () const { return false; }
|
||||
virtual bool result_must_not_be_merged () const { return false; }
|
||||
virtual bool wants_variants () const { return true; }
|
||||
|
||||
private:
|
||||
db::XYAnisotropyAndMagnificationReducer m_anisotropic_reducer;
|
||||
db::MagnificationReducer m_isotropic_reducer;
|
||||
db::Coord m_dx, m_dy;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
|
@ -176,6 +176,11 @@ FlatTexts *Texts::flat_texts ()
|
|||
return texts;
|
||||
}
|
||||
|
||||
void Texts::processed (Region &output, const TextToPolygonProcessorBase &filter) const
|
||||
{
|
||||
output = Region (mp_delegate->processed_to_polygons (filter));
|
||||
}
|
||||
|
||||
void Texts::pull_interacting (Region &output, const Region &other) const
|
||||
{
|
||||
output = Region (mp_delegate->pull_interacting (other));
|
||||
|
|
|
|||
|
|
@ -454,6 +454,14 @@ public:
|
|||
return Texts (mp_delegate->filtered (filter));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Processes the edges into polygons
|
||||
*
|
||||
* This method will run the processor over all edges and return a region
|
||||
* with the outputs of the processor.
|
||||
*/
|
||||
void processed (Region &output, const TextToPolygonProcessorBase &filter) const;
|
||||
|
||||
/**
|
||||
* @brief Selects all polygons of the other region set which include the texts of this text collection
|
||||
*
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@
|
|||
|
||||
#include "dbCommon.h"
|
||||
#include "dbShapeCollection.h"
|
||||
#include "dbShapeCollectionUtils.h"
|
||||
#include "dbText.h"
|
||||
|
||||
namespace db {
|
||||
|
|
@ -38,6 +39,8 @@ class RegionDelegate;
|
|||
class EdgesDelegate;
|
||||
class Layout;
|
||||
|
||||
typedef shape_collection_processor<db::Text, db::Polygon> TextToPolygonProcessorBase;
|
||||
|
||||
/**
|
||||
* @brief The edge pair set iterator delegate
|
||||
*/
|
||||
|
|
@ -98,6 +101,7 @@ public:
|
|||
|
||||
virtual TextsDelegate *filter_in_place (const TextFilterBase &filter) = 0;
|
||||
virtual TextsDelegate *filtered (const TextFilterBase &filter) const = 0;
|
||||
virtual RegionDelegate *processed_to_polygons (const TextToPolygonProcessorBase &filter) const = 0;
|
||||
|
||||
virtual RegionDelegate *polygons (db::Coord e) const = 0;
|
||||
virtual EdgesDelegate *edges () const = 0;
|
||||
|
|
|
|||
|
|
@ -123,12 +123,9 @@ static db::Region polygons2 (const db::EdgePairs *e, db::Coord d)
|
|||
|
||||
static db::Region extents2 (const db::EdgePairs *r, db::Coord dx, db::Coord dy)
|
||||
{
|
||||
db::Region e;
|
||||
e.reserve (r->size ());
|
||||
for (db::EdgePairs::const_iterator i = r->begin (); ! i.at_end (); ++i) {
|
||||
e.insert (i->bbox ().enlarged (db::Vector (dx, dy)));
|
||||
}
|
||||
return e;
|
||||
db::Region output;
|
||||
r->processed (output, db::extents_processor<db::EdgePair> (dx, dy));
|
||||
return output;
|
||||
}
|
||||
|
||||
static db::Region extents1 (const db::EdgePairs *r, db::Coord d)
|
||||
|
|
|
|||
|
|
@ -325,12 +325,9 @@ static db::Region pull_interacting (const db::Edges *r, const db::Region &other)
|
|||
|
||||
static db::Region extents2 (const db::Edges *r, db::Coord dx, db::Coord dy)
|
||||
{
|
||||
db::Region e;
|
||||
e.reserve (r->size ());
|
||||
for (db::Edges::const_iterator i = r->begin (); ! i.at_end (); ++i) {
|
||||
e.insert (i->bbox ().enlarged (db::Vector (dx, dy)));
|
||||
}
|
||||
return e;
|
||||
db::Region output;
|
||||
r->processed (output, db::extents_processor<db::Edge> (dx, dy));
|
||||
return output;
|
||||
}
|
||||
|
||||
static db::Region extents1 (const db::Edges *r, db::Coord d)
|
||||
|
|
|
|||
|
|
@ -259,7 +259,7 @@ static db::Region moved_xy (const db::Region *r, db::Coord x, db::Coord y)
|
|||
|
||||
static db::Region extents2 (const db::Region *r, db::Coord dx, db::Coord dy)
|
||||
{
|
||||
return r->processed (db::Extents (dx, dy));
|
||||
return r->processed (db::extents_processor<db::Polygon> (dx, dy));
|
||||
}
|
||||
|
||||
static db::Region extents1 (const db::Region *r, db::Coord d)
|
||||
|
|
|
|||
|
|
@ -116,12 +116,9 @@ static db::Region polygons0 (const db::Texts *e, db::Coord d)
|
|||
|
||||
static db::Region extents1 (const db::Texts *r, db::Coord dx, db::Coord dy)
|
||||
{
|
||||
db::Region e;
|
||||
e.reserve (r->size ());
|
||||
for (db::Texts::const_iterator i = r->begin (); ! i.at_end (); ++i) {
|
||||
e.insert (i->box ().enlarged (db::Vector (dx, dy)));
|
||||
}
|
||||
return e;
|
||||
db::Region output;
|
||||
r->processed (output, db::extents_processor<db::Text> (dx, dy));
|
||||
return output;
|
||||
}
|
||||
|
||||
static db::Region extents0 (const db::Texts *r, db::Coord d)
|
||||
|
|
|
|||
|
|
@ -1176,8 +1176,8 @@ TEST(21_Processors)
|
|||
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (13, 0)), r1.processed (db::CornersAsRectangles (-180.0, 180.0, 2000)));
|
||||
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (14, 0)), r1.processed (db::CornersAsRectangles (0.0, 180.0, 2000)));
|
||||
|
||||
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (20, 0)), r1.processed (db::Extents (0, 0)));
|
||||
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (21, 0)), r1.processed (db::Extents (1000, 2000)));
|
||||
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (20, 0)), r1.processed (db::extents_processor<db::Polygon> (0, 0)));
|
||||
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (21, 0)), r1.processed (db::extents_processor<db::Polygon> (1000, 2000)));
|
||||
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (22, 0)), r1.processed (db::RelativeExtents (0, 0, 1.0, 1.0, 0, 0)));
|
||||
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (23, 0)), r1.processed (db::RelativeExtents (0.25, 0.4, 0.75, 0.6, 1000, 2000)));
|
||||
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (24, 0)), r1.processed (db::RelativeExtentsAsEdges (0, 0, 1.0, 1.0)));
|
||||
|
|
|
|||
|
|
@ -1589,8 +1589,8 @@ TEST(100_Processors)
|
|||
EXPECT_EQ (r.processed (db::CornersAsRectangles (-180.0, 180.0, 2)).to_string (), "(98,-2;98,2;102,2;102,-2);(-2,-2;-2,2;2,2;2,-2);(-2,198;-2,202;2,202;2,198);(98,198;98,202;102,202;102,198);(198,298;198,302;202,302;202,298);(-2,298;-2,302;2,302;2,298);(-2,398;-2,402;2,402;2,398);(98,398;98,402;102,402;102,398);(98,498;98,502;102,502;102,498);(198,498;198,502;202,502;202,498)");
|
||||
EXPECT_EQ (r.processed (db::CornersAsRectangles (0.0, 180.0, 2)).to_string (), "(98,398;98,402;102,402;102,398)");
|
||||
|
||||
EXPECT_EQ (r.processed (db::Extents (0, 0)).to_string (), "(0,0;0,200;100,200;100,0);(0,300;0,500;200,500;200,300)");
|
||||
EXPECT_EQ (r.processed (db::Extents (10, 20)).to_string (), "(-10,-20;-10,220;110,220;110,-20);(-10,280;-10,520;210,520;210,280)");
|
||||
EXPECT_EQ (r.processed (db::extents_processor<db::Polygon> (0, 0)).to_string (), "(0,0;0,200;100,200;100,0);(0,300;0,500;200,500;200,300)");
|
||||
EXPECT_EQ (r.processed (db::extents_processor<db::Polygon> (10, 20)).to_string (), "(-10,-20;-10,220;110,220;110,-20);(-10,280;-10,520;210,520;210,280)");
|
||||
EXPECT_EQ (r.processed (db::RelativeExtents (0, 0, 1.0, 1.0, 0, 0)).to_string (), "(0,0;0,200;100,200;100,0);(0,300;0,500;200,500;200,300)");
|
||||
EXPECT_EQ (r.processed (db::RelativeExtents (0.25, 0.4, 0.75, 0.6, 10, 20)).to_string (), "(15,60;15,140;85,140;85,60);(40,360;40,440;160,440;160,360)");
|
||||
EXPECT_EQ (r.processed (db::RelativeExtentsAsEdges (0, 0, 1.0, 1.0)).to_string (), "(0,0;100,200);(0,300;200,500)");
|
||||
|
|
|
|||
|
|
@ -714,3 +714,44 @@ TEST(15_issue548)
|
|||
|
||||
db::compare_layouts (_this, layout, au, db::NoNormalization);
|
||||
}
|
||||
|
||||
// Edges::extents isn't deep-enabled
|
||||
TEST(16_issue570)
|
||||
{
|
||||
std::string rs = tl::testsrc ();
|
||||
rs += "/testdata/drc/drcSimpleTests_16.drc";
|
||||
|
||||
std::string input = tl::testsrc ();
|
||||
input += "/testdata/drc/drcSimpleTests_16.gds";
|
||||
|
||||
std::string au = tl::testsrc ();
|
||||
au += "/testdata/drc/drcSimpleTests_au16.gds";
|
||||
|
||||
std::string output = this->tmp_file ("tmp.gds");
|
||||
|
||||
{
|
||||
// Set some variables
|
||||
lym::Macro config;
|
||||
config.set_text (tl::sprintf (
|
||||
"$drc_test_source = '%s'\n"
|
||||
"$drc_test_target = '%s'\n"
|
||||
, input, output)
|
||||
);
|
||||
config.set_interpreter (lym::Macro::Ruby);
|
||||
EXPECT_EQ (config.run (), 0);
|
||||
}
|
||||
|
||||
lym::Macro drc;
|
||||
drc.load_from (rs);
|
||||
EXPECT_EQ (drc.run (), 0);
|
||||
|
||||
db::Layout layout;
|
||||
|
||||
{
|
||||
tl::InputStream stream (output);
|
||||
db::Reader reader (stream);
|
||||
reader.read (layout);
|
||||
}
|
||||
|
||||
db::compare_layouts (_this, layout, au, db::NoNormalization);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,16 @@
|
|||
|
||||
source($drc_test_source)
|
||||
target($drc_test_target)
|
||||
|
||||
deep
|
||||
|
||||
input(2,0).output(2, 0)
|
||||
input(3,0).output(3, 0)
|
||||
input(4,0).output(4, 0)
|
||||
input(9,0).output(9, 0)
|
||||
|
||||
input(2,0).edges.extents(10.nm, 10.nm).output(102, 0)
|
||||
input(3,0).edges.extents(10.nm, 20.nm).output(103, 0)
|
||||
input(4,0).edges.extents(20.nm, 10.nm).output(104, 0)
|
||||
input(9,0).edges.extents(20.nm).output(109, 0)
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Loading…
Reference in New Issue