mirror of https://github.com/KLayout/klayout.git
WIP: refactoring, started implementing DRC checks with property support
This commit is contained in:
parent
bd79467b4b
commit
1b7b077cea
|
|
@ -29,6 +29,7 @@ SOURCES = \
|
|||
dbEdgePairs.cc \
|
||||
dbEdgeProcessor.cc \
|
||||
dbEdges.cc \
|
||||
dbEdgesLocalOperations.cc \
|
||||
dbFillTool.cc \
|
||||
dbFuzzyCellMapping.cc \
|
||||
dbGenericShapeIterator.cc \
|
||||
|
|
@ -243,6 +244,7 @@ HEADERS = \
|
|||
dbEdgePairs.h \
|
||||
dbEdgeProcessor.h \
|
||||
dbEdges.h \
|
||||
dbEdgesLocalOperations.h \
|
||||
dbEdgesToContours.h \
|
||||
dbFillTool.h \
|
||||
dbFuzzyCellMapping.h \
|
||||
|
|
|
|||
|
|
@ -35,6 +35,7 @@
|
|||
#include "dbLocalOperation.h"
|
||||
#include "dbLocalOperationUtils.h"
|
||||
#include "dbRegionLocalOperations.h" // for db::ContainedEdgesLocalOperation
|
||||
#include "dbEdgesLocalOperations.h"
|
||||
#include "dbHierProcessor.h"
|
||||
#include "dbEmptyEdges.h"
|
||||
|
||||
|
|
|
|||
|
|
@ -1282,125 +1282,6 @@ DeepRegion::snapped (db::Coord gx, db::Coord gy)
|
|||
return res.release ();
|
||||
}
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
template <class TS, class TI>
|
||||
static
|
||||
std::map<db::properties_id_type, std::pair<std::vector<const TS *>, std::vector<const TI *> > >
|
||||
separate_by_same_properties (const shape_interactions<db::object_with_properties<TS>, db::object_with_properties<TI> > &interactions, db::PropertyMapper &pms, db::PropertyMapper &pmi)
|
||||
{
|
||||
std::map<db::properties_id_type, std::pair<std::vector<const TS *>, std::vector<const TI *> > > by_prop_id;
|
||||
|
||||
for (auto i = interactions.begin (); i != interactions.end (); ++i) {
|
||||
|
||||
const db::object_with_properties<TS> &subject = interactions.subject_shape (i->first);
|
||||
|
||||
std::pair<std::vector<const TS *>, std::vector<const TI *> > &s2p = by_prop_id [pms (subject.properties_id ())];
|
||||
s2p.first.push_back (&subject);
|
||||
|
||||
for (auto ii = i->second.begin (); ii != i->second.end (); ++ii) {
|
||||
|
||||
const std::pair<unsigned int, db::object_with_properties<TI> > &intruder = interactions.intruder_shape (*ii);
|
||||
|
||||
if (subject.properties_id () == pmi (intruder.second.properties_id ())) {
|
||||
s2p.second.push_back (&intruder.second);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return by_prop_id;
|
||||
}
|
||||
|
||||
class PolygonToEdgeLocalOperation
|
||||
: public local_operation<db::PolygonRefWithProperties, db::PolygonRefWithProperties, db::EdgeWithProperties>
|
||||
{
|
||||
public:
|
||||
PolygonToEdgeLocalOperation (db::PropertiesRepository *target_pr, const db::PropertiesRepository *source_pr)
|
||||
: local_operation<db::PolygonRefWithProperties, db::PolygonRefWithProperties, db::EdgeWithProperties> (), m_pm (target_pr, source_pr)
|
||||
{
|
||||
// .. nothing yet ..
|
||||
}
|
||||
|
||||
virtual db::Coord dist () const { return 1; }
|
||||
virtual bool requests_single_subjects () const { return true; }
|
||||
virtual std::string description () const { return std::string ("polygon to edges"); }
|
||||
|
||||
virtual void do_compute_local (db::Layout * /*layout*/, const shape_interactions<db::PolygonRefWithProperties, db::PolygonRefWithProperties> &interactions, std::vector<std::unordered_set<db::EdgeWithProperties> > &results, size_t /*max_vertex_count*/, double /*area_ratio*/) const
|
||||
{
|
||||
db::EdgeProcessor ep;
|
||||
ep.set_base_verbosity (50);
|
||||
|
||||
auto by_prop_id = separate_by_same_properties (interactions, m_pm, m_pm);
|
||||
for (auto shapes_by_prop_id = by_prop_id.begin (); shapes_by_prop_id != by_prop_id.end (); ++shapes_by_prop_id) {
|
||||
|
||||
db::properties_id_type prop_id = shapes_by_prop_id->first;
|
||||
|
||||
for (auto s = shapes_by_prop_id->second.first.begin (); s != shapes_by_prop_id->second.first.end (); ++s) {
|
||||
ep.insert (**s);
|
||||
}
|
||||
|
||||
db::property_injector<db::Edge, std::unordered_set<db::EdgeWithProperties> > results_with_properties (&results.front (), prop_id);
|
||||
|
||||
if (shapes_by_prop_id->second.second.empty ()) {
|
||||
|
||||
db::edge_to_edge_set_generator<db::property_injector<db::Edge, std::unordered_set<db::EdgeWithProperties> > > eg (results_with_properties, prop_id);
|
||||
db::MergeOp op (0);
|
||||
ep.process (eg, op);
|
||||
|
||||
} else {
|
||||
|
||||
// With intruders: to compute our local contribution we take the edges without and with intruders
|
||||
// and deliver what is in both sets
|
||||
|
||||
db::MergeOp op (0);
|
||||
|
||||
std::vector<Edge> edges1;
|
||||
db::EdgeContainer ec1 (edges1);
|
||||
ep.process (ec1, op);
|
||||
|
||||
ep.clear ();
|
||||
|
||||
for (auto s = interactions.begin_subjects (); s != interactions.end_subjects (); ++s) {
|
||||
ep.insert (s->second);
|
||||
}
|
||||
for (auto i = interactions.begin_intruders (); i != interactions.end_intruders (); ++i) {
|
||||
ep.insert (i->second.second);
|
||||
}
|
||||
|
||||
std::vector<Edge> edges2;
|
||||
db::EdgeContainer ec2 (edges2);
|
||||
ep.process (ec2, op);
|
||||
|
||||
// Runs the boolean AND between the result with and without intruders
|
||||
|
||||
db::box_scanner<db::Edge, size_t> scanner;
|
||||
scanner.reserve (edges1.size () + edges2.size ());
|
||||
|
||||
for (std::vector<Edge>::const_iterator i = edges1.begin (); i != edges1.end (); ++i) {
|
||||
scanner.insert (i.operator-> (), 0);
|
||||
}
|
||||
for (std::vector<Edge>::const_iterator i = edges2.begin (); i != edges2.end (); ++i) {
|
||||
scanner.insert (i.operator-> (), 1);
|
||||
}
|
||||
|
||||
EdgeBooleanClusterCollector<db::property_injector<Edge, std::unordered_set<db::EdgeWithProperties> > > cluster_collector (&results_with_properties, EdgeAnd);
|
||||
scanner.process (cluster_collector, 1, db::box_convert<db::Edge> ());
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private:
|
||||
mutable db::PropertyMapper m_pm;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
EdgesDelegate *
|
||||
DeepRegion::edges (const EdgeFilterBase *filter) const
|
||||
{
|
||||
|
|
|
|||
|
|
@ -0,0 +1,203 @@
|
|||
|
||||
/*
|
||||
|
||||
KLayout Layout Viewer
|
||||
Copyright (C) 2006-2023 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 "dbEdgesLocalOperations.h"
|
||||
#include "dbHierProcessor.h"
|
||||
#include "dbLocalOperationUtils.h"
|
||||
|
||||
namespace db
|
||||
{
|
||||
|
||||
// ---------------------------------------------------------------------------------------------
|
||||
// EdgeBoolAndOrNotLocalOperation implementation
|
||||
|
||||
EdgeBoolAndOrNotLocalOperation::EdgeBoolAndOrNotLocalOperation (EdgeBoolOp op)
|
||||
: m_op (op)
|
||||
{
|
||||
// .. nothing yet ..
|
||||
}
|
||||
|
||||
OnEmptyIntruderHint
|
||||
EdgeBoolAndOrNotLocalOperation::on_empty_intruder_hint () const
|
||||
{
|
||||
return (m_op == EdgeAnd || m_op == EdgeIntersections) ? Drop : Copy;
|
||||
}
|
||||
|
||||
std::string
|
||||
EdgeBoolAndOrNotLocalOperation::description () const
|
||||
{
|
||||
if (m_op == EdgeIntersections) {
|
||||
return tl::to_string (tr ("Edge INTERSECTION operation"));
|
||||
} else if (m_op == EdgeAnd) {
|
||||
return tl::to_string (tr ("Edge AND operation"));
|
||||
} else if (m_op == EdgeNot) {
|
||||
return tl::to_string (tr ("Edge NOT operation"));
|
||||
} else {
|
||||
return std::string ();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
EdgeBoolAndOrNotLocalOperation::do_compute_local (db::Layout * /*layout*/, const shape_interactions<db::Edge, db::Edge> &interactions, std::vector<std::unordered_set<db::Edge> > &results, size_t /*max_vertex_count*/, double /*area_ratio*/) const
|
||||
{
|
||||
tl_assert (results.size () == size_t (m_op == EdgeAndNot ? 2 : 1));
|
||||
|
||||
std::unordered_set<db::Edge> &result = results.front ();
|
||||
|
||||
std::unordered_set<db::Edge> *result2 = 0;
|
||||
if (results.size () > 1) {
|
||||
result2 = &results[1];
|
||||
}
|
||||
|
||||
EdgeBooleanClusterCollector<std::unordered_set<db::Edge> > cluster_collector (&result, m_op, result2);
|
||||
|
||||
db::box_scanner<db::Edge, size_t> scanner;
|
||||
|
||||
std::set<db::Edge> others;
|
||||
for (shape_interactions<db::Edge, db::Edge>::iterator i = interactions.begin (); i != interactions.end (); ++i) {
|
||||
for (shape_interactions<db::Edge, db::Edge>::iterator2 j = i->second.begin (); j != i->second.end (); ++j) {
|
||||
others.insert (interactions.intruder_shape (*j).second);
|
||||
}
|
||||
}
|
||||
|
||||
bool any_subject = false;
|
||||
bool is_and = (m_op == EdgeAnd || m_op == EdgeAndNot || m_op == EdgeIntersections);
|
||||
|
||||
for (shape_interactions<db::Edge, db::Edge>::iterator i = interactions.begin (); i != interactions.end (); ++i) {
|
||||
|
||||
const db::Edge &subject = interactions.subject_shape (i->first);
|
||||
if (others.find (subject) != others.end ()) {
|
||||
if (is_and) {
|
||||
result.insert (subject);
|
||||
}
|
||||
} else if (i->second.empty ()) {
|
||||
// shortcut (not: keep, and: drop)
|
||||
if (! is_and) {
|
||||
result.insert (subject);
|
||||
}
|
||||
} else {
|
||||
scanner.insert (&subject, 0);
|
||||
any_subject = true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (! others.empty () || any_subject) {
|
||||
|
||||
for (std::set<db::Edge>::const_iterator o = others.begin (); o != others.end (); ++o) {
|
||||
scanner.insert (o.operator-> (), 1);
|
||||
}
|
||||
|
||||
scanner.process (cluster_collector, 1, db::box_convert<db::Edge> ());
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------------------
|
||||
// EdgeToPolygonLocalOperation implementation
|
||||
|
||||
EdgeToPolygonLocalOperation::EdgeToPolygonLocalOperation (EdgePolygonOp::mode_t op, bool include_borders)
|
||||
: m_op (op), m_include_borders (include_borders)
|
||||
{
|
||||
// .. nothing yet ..
|
||||
}
|
||||
|
||||
OnEmptyIntruderHint
|
||||
EdgeToPolygonLocalOperation::on_empty_intruder_hint () const
|
||||
{
|
||||
return m_op == EdgePolygonOp::Inside ? Drop : (m_op == EdgePolygonOp::Outside ? Copy : CopyToSecond);
|
||||
}
|
||||
|
||||
std::string
|
||||
EdgeToPolygonLocalOperation::description () const
|
||||
{
|
||||
if (m_op == EdgePolygonOp::Inside) {
|
||||
return tl::to_string (tr ("Edge to polygon AND/INSIDE"));
|
||||
} else if (m_op == EdgePolygonOp::Outside) {
|
||||
return tl::to_string (tr ("Edge to polygon NOT/OUTSIDE"));
|
||||
} else {
|
||||
return tl::to_string (tr ("Edge to polygon ANDNOT/INOUTSIDE"));
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
EdgeToPolygonLocalOperation::do_compute_local (db::Layout * /*layout*/, const shape_interactions<db::Edge, db::PolygonRef> &interactions, std::vector<std::unordered_set<db::Edge> > &results, size_t /*max_vertex_count*/, double /*area_ratio*/) const
|
||||
{
|
||||
tl_assert (results.size () == size_t (m_op == EdgePolygonOp::Both ? 2 : 1));
|
||||
|
||||
std::unordered_set<db::Edge> &result = results.front ();
|
||||
|
||||
std::unordered_set<db::Edge> *result2 = 0;
|
||||
if (results.size () > 1) {
|
||||
result2 = &results[1];
|
||||
}
|
||||
|
||||
db::EdgeProcessor ep;
|
||||
|
||||
std::set<db::PolygonRef> others;
|
||||
for (shape_interactions<db::Edge, db::PolygonRef>::iterator i = interactions.begin (); i != interactions.end (); ++i) {
|
||||
for (shape_interactions<db::Edge, db::PolygonRef>::iterator2 j = i->second.begin (); j != i->second.end (); ++j) {
|
||||
others.insert (interactions.intruder_shape (*j).second);
|
||||
}
|
||||
}
|
||||
|
||||
bool any_subject = false;
|
||||
|
||||
for (shape_interactions<db::Edge, db::PolygonRef>::iterator i = interactions.begin (); i != interactions.end (); ++i) {
|
||||
|
||||
const db::Edge &subject = interactions.subject_shape (i->first);
|
||||
if (i->second.empty ()) {
|
||||
// shortcut (outside: keep, otherwise: drop)
|
||||
if (m_op == db::EdgePolygonOp::Outside) {
|
||||
result.insert (subject);
|
||||
} else if (m_op == db::EdgePolygonOp::Both) {
|
||||
result2->insert (subject);
|
||||
}
|
||||
} else {
|
||||
ep.insert (subject, 1);
|
||||
any_subject = true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (! others.empty () || any_subject) {
|
||||
|
||||
for (std::set<db::PolygonRef>::const_iterator o = others.begin (); o != others.end (); ++o) {
|
||||
for (db::PolygonRef::polygon_edge_iterator e = o->begin_edge (); ! e.at_end (); ++e) {
|
||||
ep.insert (*e, 0);
|
||||
}
|
||||
}
|
||||
|
||||
std::unique_ptr<db::EdgeToEdgeSetGenerator> cc_second;
|
||||
if (result2) {
|
||||
cc_second.reset (new db::EdgeToEdgeSetGenerator (*result2, 2 /*second tag*/));
|
||||
}
|
||||
|
||||
db::EdgeToEdgeSetGenerator cc (result, 1 /*first tag*/, cc_second.get ());
|
||||
db::EdgePolygonOp op (m_op, m_include_borders);
|
||||
ep.process (cc, op);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,84 @@
|
|||
|
||||
/*
|
||||
|
||||
KLayout Layout Viewer
|
||||
Copyright (C) 2006-2023 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_dbEdgesLocalOperation
|
||||
#define HDR_dbEdgesLocalOperation
|
||||
|
||||
#include "dbCommon.h"
|
||||
|
||||
#include "dbLayout.h"
|
||||
#include "dbEdgeBoolean.h"
|
||||
#include "dbEdgeProcessor.h"
|
||||
#include "dbLocalOperation.h"
|
||||
|
||||
namespace db
|
||||
{
|
||||
|
||||
/**
|
||||
* @brief Implements a boolean AND or NOT operation between edges
|
||||
*/
|
||||
class DB_PUBLIC EdgeBoolAndOrNotLocalOperation
|
||||
: public local_operation<db::Edge, db::Edge, db::Edge>
|
||||
{
|
||||
public:
|
||||
EdgeBoolAndOrNotLocalOperation (db::EdgeBoolOp op);
|
||||
|
||||
virtual void do_compute_local (db::Layout *layout, const shape_interactions<db::Edge, db::Edge> &interactions, std::vector<std::unordered_set<db::Edge> > &result, size_t max_vertex_count, double area_ratio) const;
|
||||
virtual OnEmptyIntruderHint on_empty_intruder_hint () const;
|
||||
virtual std::string description () const;
|
||||
|
||||
// edge interaction distance is 1 to force overlap between edges and edge/boxes
|
||||
virtual db::Coord dist () const { return 1; }
|
||||
|
||||
private:
|
||||
db::EdgeBoolOp m_op;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Implements a boolean AND or NOT operation between edges and polygons (polygons as intruders)
|
||||
*
|
||||
* "AND" is implemented by "outside == false", "NOT" by "outside == true" with "include_borders == true".
|
||||
* With "include_borders == false" the operations are "INSIDE" and "OUTSIDE".
|
||||
*/
|
||||
class DB_PUBLIC EdgeToPolygonLocalOperation
|
||||
: public local_operation<db::Edge, db::PolygonRef, db::Edge>
|
||||
{
|
||||
public:
|
||||
EdgeToPolygonLocalOperation (EdgePolygonOp::mode_t op, bool include_borders);
|
||||
|
||||
virtual void do_compute_local (db::Layout *layout, const shape_interactions<db::Edge, db::PolygonRef> &interactions, std::vector<std::unordered_set<db::Edge> > &result, size_t max_vertex_count, double area_ratio) const;
|
||||
virtual OnEmptyIntruderHint on_empty_intruder_hint () const;
|
||||
virtual std::string description () const;
|
||||
|
||||
// edge interaction distance is 1 to force overlap between edges and edge/boxes
|
||||
virtual db::Coord dist () const { return m_include_borders ? 1 : 0; }
|
||||
|
||||
private:
|
||||
db::EdgePolygonOp::mode_t m_op;
|
||||
bool m_include_borders;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
@ -27,7 +27,6 @@
|
|||
#include "dbBoxConvert.h"
|
||||
#include "dbPolygonGenerators.h"
|
||||
#include "dbPolygonTools.h"
|
||||
#include "dbLocalOperationUtils.h"
|
||||
#include "dbEdgeBoolean.h"
|
||||
#include "dbLayoutUtils.h"
|
||||
#include "tlLog.h"
|
||||
|
|
@ -115,656 +114,5 @@ template class DB_PUBLIC local_operation<db::Edge, db::Edge, db::EdgePair>;
|
|||
template class DB_PUBLIC local_operation<db::TextRef, db::PolygonRef, db::PolygonRef>;
|
||||
template class DB_PUBLIC local_operation<db::TextRef, db::PolygonRef, db::TextRef>;
|
||||
|
||||
// ---------------------------------------------------------------------------------------------
|
||||
// BoolAndOrNotLocalOperation implementation
|
||||
|
||||
template <class TS, class TI, class TR>
|
||||
bool_and_or_not_local_operation<TS, TI, TR>::bool_and_or_not_local_operation (bool is_and)
|
||||
: m_is_and (is_and)
|
||||
{
|
||||
// .. nothing yet ..
|
||||
}
|
||||
|
||||
template <class TS, class TI, class TR>
|
||||
OnEmptyIntruderHint
|
||||
bool_and_or_not_local_operation<TS, TI, TR>::on_empty_intruder_hint () const
|
||||
{
|
||||
return m_is_and ? Drop : Copy;
|
||||
}
|
||||
|
||||
template <class TS, class TI, class TR>
|
||||
std::string
|
||||
bool_and_or_not_local_operation<TS, TI, TR>::description () const
|
||||
{
|
||||
return m_is_and ? tl::to_string (tr ("AND operation")) : tl::to_string (tr ("NOT operation"));
|
||||
}
|
||||
|
||||
template <class TS, class TI, class TR>
|
||||
void
|
||||
bool_and_or_not_local_operation<TS, TI, TR>::do_compute_local (db::Layout *layout, const shape_interactions<TS, TI> &interactions, std::vector<std::unordered_set<TR> > &results, size_t max_vertex_count, double area_ratio) const
|
||||
{
|
||||
tl_assert (results.size () == 1);
|
||||
std::unordered_set<TR> &result = results.front ();
|
||||
|
||||
db::EdgeProcessor ep;
|
||||
|
||||
size_t p1 = 0, p2 = 1;
|
||||
|
||||
std::set<TI> others;
|
||||
for (auto i = interactions.begin (); i != interactions.end (); ++i) {
|
||||
for (auto j = i->second.begin (); j != i->second.end (); ++j) {
|
||||
others.insert (interactions.intruder_shape (*j).second);
|
||||
}
|
||||
}
|
||||
|
||||
for (auto i = interactions.begin (); i != interactions.end (); ++i) {
|
||||
|
||||
const TR &subject = interactions.subject_shape (i->first);
|
||||
if (others.find (subject) != others.end ()) {
|
||||
if (m_is_and) {
|
||||
result.insert (subject);
|
||||
}
|
||||
} else if (i->second.empty ()) {
|
||||
// shortcut (not: keep, and: drop)
|
||||
if (! m_is_and) {
|
||||
result.insert (subject);
|
||||
}
|
||||
} else {
|
||||
for (auto e = subject.begin_edge (); ! e.at_end(); ++e) {
|
||||
ep.insert (*e, p1);
|
||||
}
|
||||
p1 += 2;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (! others.empty () && p1 > 0) {
|
||||
|
||||
for (auto o = others.begin (); o != others.end (); ++o) {
|
||||
for (auto e = o->begin_edge (); ! e.at_end(); ++e) {
|
||||
ep.insert (*e, p2);
|
||||
}
|
||||
p2 += 2;
|
||||
}
|
||||
|
||||
db::BooleanOp op (m_is_and ? db::BooleanOp::And : db::BooleanOp::ANotB);
|
||||
db::polygon_ref_generator<TR> pr (layout, result);
|
||||
db::PolygonSplitter splitter (pr, area_ratio, max_vertex_count);
|
||||
db::PolygonGenerator pg (splitter, true, true);
|
||||
ep.set_base_verbosity (50);
|
||||
ep.process (pg, op);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
template class DB_PUBLIC bool_and_or_not_local_operation<db::PolygonRef, db::PolygonRef, db::PolygonRef>;
|
||||
template class DB_PUBLIC bool_and_or_not_local_operation<db::Polygon, db::Polygon, db::Polygon>;
|
||||
|
||||
// ---------------------------------------------------------------------------------------------
|
||||
// BoolAndOrNotLocalOperationWithProperties implementation
|
||||
|
||||
template <class TS, class TI, class TR>
|
||||
bool_and_or_not_local_operation_with_properties<TS, TI, TR>::bool_and_or_not_local_operation_with_properties (bool is_and, db::PropertiesRepository *target_pr, const db::PropertiesRepository *subject_pr, const db::PropertiesRepository *intruder_pr, db::PropertyConstraint property_constraint)
|
||||
: m_is_and (is_and), m_property_constraint (property_constraint), m_pms (target_pr, subject_pr), m_pmi (target_pr, intruder_pr)
|
||||
{
|
||||
// .. nothing yet ..
|
||||
}
|
||||
|
||||
template <class TS, class TI, class TR>
|
||||
OnEmptyIntruderHint
|
||||
bool_and_or_not_local_operation_with_properties<TS, TI, TR>::on_empty_intruder_hint () const
|
||||
{
|
||||
return m_is_and ? Drop : Copy;
|
||||
}
|
||||
|
||||
template <class TS, class TI, class TR>
|
||||
std::string
|
||||
bool_and_or_not_local_operation_with_properties<TS, TI, TR>::description () const
|
||||
{
|
||||
return m_is_and ? tl::to_string (tr ("AND operation")) : tl::to_string (tr ("NOT operation"));
|
||||
}
|
||||
|
||||
template <class TS, class TI, class TR>
|
||||
void
|
||||
bool_and_or_not_local_operation_with_properties<TS, TI, TR>::do_compute_local (db::Layout *layout, const shape_interactions<db::object_with_properties<TS>, db::object_with_properties<TI> > &interactions, std::vector<std::unordered_set<db::object_with_properties<TR> > > &results, size_t max_vertex_count, double area_ratio) const
|
||||
{
|
||||
tl_assert (results.size () == 1);
|
||||
std::unordered_set<db::object_with_properties<TR> > &result = results.front ();
|
||||
|
||||
db::EdgeProcessor ep;
|
||||
|
||||
std::map<db::properties_id_type, std::pair<tl::slist<TS>, std::set<TI> > > by_prop_id;
|
||||
|
||||
for (auto i = interactions.begin (); i != interactions.end (); ++i) {
|
||||
|
||||
const db::object_with_properties<TS> &subject = interactions.subject_shape (i->first);
|
||||
|
||||
if (i->second.empty ()) {
|
||||
|
||||
if (! m_is_and) {
|
||||
result.insert (db::object_with_properties<TR> (subject, m_pms (subject.properties_id ())));
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
db::properties_id_type prop_id_s = m_pms (subject.properties_id ());
|
||||
|
||||
auto &shapes_by_prop = by_prop_id [prop_id_s];
|
||||
shapes_by_prop.first.push_front (subject);
|
||||
|
||||
for (auto j = i->second.begin (); j != i->second.end (); ++j) {
|
||||
const db::object_with_properties<TI> &intruder = interactions.intruder_shape (*j).second;
|
||||
db::properties_id_type prop_id_i = (m_property_constraint != db::NoPropertyConstraint ? m_pmi (intruder.properties_id ()) : prop_id_s);
|
||||
if ((prop_id_i != prop_id_s) == (m_property_constraint == db::DifferentPropertiesConstraint)) {
|
||||
shapes_by_prop.second.insert (intruder);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
for (auto p2s = by_prop_id.begin (); p2s != by_prop_id.end (); ++p2s) {
|
||||
|
||||
ep.clear ();
|
||||
size_t p1 = 0, p2 = 1;
|
||||
|
||||
const std::set<TI> &others = p2s->second.second;
|
||||
db::properties_id_type prop_id = p2s->first;
|
||||
|
||||
for (auto s = p2s->second.first.begin (); s != p2s->second.first.end (); ++s) {
|
||||
|
||||
const TS &subject = *s;
|
||||
if (others.find (subject) != others.end ()) {
|
||||
if (m_is_and) {
|
||||
result.insert (db::object_with_properties<TR> (subject, prop_id));
|
||||
}
|
||||
} else if (others.empty ()) {
|
||||
// shortcut (not: keep, and: drop)
|
||||
if (! m_is_and) {
|
||||
result.insert (db::object_with_properties<TR> (subject, prop_id));
|
||||
}
|
||||
} else {
|
||||
for (auto e = subject.begin_edge (); ! e.at_end(); ++e) {
|
||||
ep.insert (*e, p1);
|
||||
}
|
||||
p1 += 2;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (! others.empty () && p1 > 0) {
|
||||
|
||||
for (auto o = others.begin (); o != others.end (); ++o) {
|
||||
for (auto e = o->begin_edge (); ! e.at_end(); ++e) {
|
||||
ep.insert (*e, p2);
|
||||
}
|
||||
p2 += 2;
|
||||
}
|
||||
|
||||
db::BooleanOp op (m_is_and ? db::BooleanOp::And : db::BooleanOp::ANotB);
|
||||
db::polygon_ref_generator_with_properties<db::object_with_properties<TR> > pr (layout, result, prop_id);
|
||||
db::PolygonSplitter splitter (pr, area_ratio, max_vertex_count);
|
||||
db::PolygonGenerator pg (splitter, true, true);
|
||||
ep.set_base_verbosity (50);
|
||||
ep.process (pg, op);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
template class DB_PUBLIC bool_and_or_not_local_operation_with_properties<db::PolygonRef, db::PolygonRef, db::PolygonRef>;
|
||||
template class DB_PUBLIC bool_and_or_not_local_operation_with_properties<db::Polygon, db::Polygon, db::Polygon>;
|
||||
|
||||
// ---------------------------------------------------------------------------------------------
|
||||
// TwoBoolAndNotLocalOperation implementation
|
||||
|
||||
template <class TS, class TI, class TR>
|
||||
two_bool_and_not_local_operation<TS, TI, TR>::two_bool_and_not_local_operation ()
|
||||
: db::local_operation<TS, TI, TR> ()
|
||||
{
|
||||
// .. nothing yet ..
|
||||
}
|
||||
|
||||
template <class TS, class TI, class TR>
|
||||
void
|
||||
two_bool_and_not_local_operation<TS, TI, TR>::do_compute_local (db::Layout *layout, const shape_interactions<TS, TI> &interactions, std::vector<std::unordered_set<TR> > &results, size_t max_vertex_count, double area_ratio) const
|
||||
{
|
||||
tl_assert (results.size () == 2);
|
||||
|
||||
db::EdgeProcessor ep;
|
||||
|
||||
std::unordered_set<TR> &result0 = results [0];
|
||||
std::unordered_set<TR> &result1 = results [1];
|
||||
|
||||
size_t p1 = 0, p2 = 1;
|
||||
|
||||
std::set<TI> others;
|
||||
for (auto i = interactions.begin (); i != interactions.end (); ++i) {
|
||||
for (auto j = i->second.begin (); j != i->second.end (); ++j) {
|
||||
others.insert (interactions.intruder_shape (*j).second);
|
||||
}
|
||||
}
|
||||
|
||||
for (auto i = interactions.begin (); i != interactions.end (); ++i) {
|
||||
|
||||
const TS &subject = interactions.subject_shape (i->first);
|
||||
if (others.find (subject) != others.end ()) {
|
||||
result0.insert (subject);
|
||||
} else if (i->second.empty ()) {
|
||||
// shortcut (not: keep, and: drop)
|
||||
result1.insert (subject);
|
||||
} else {
|
||||
for (auto e = subject.begin_edge (); ! e.at_end(); ++e) {
|
||||
ep.insert (*e, p1);
|
||||
}
|
||||
p1 += 2;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (! others.empty () && p1 > 0) {
|
||||
|
||||
for (auto o = others.begin (); o != others.end (); ++o) {
|
||||
for (auto e = o->begin_edge (); ! e.at_end(); ++e) {
|
||||
ep.insert (*e, p2);
|
||||
}
|
||||
p2 += 2;
|
||||
}
|
||||
|
||||
db::BooleanOp op0 (db::BooleanOp::And);
|
||||
db::polygon_ref_generator<TR> pr0 (layout, result0);
|
||||
db::PolygonSplitter splitter0 (pr0, area_ratio, max_vertex_count);
|
||||
db::PolygonGenerator pg0 (splitter0, true, true);
|
||||
|
||||
db::BooleanOp op1 (db::BooleanOp::ANotB);
|
||||
db::polygon_ref_generator<TR> pr1 (layout, result1);
|
||||
db::PolygonSplitter splitter1 (pr1, area_ratio, max_vertex_count);
|
||||
db::PolygonGenerator pg1 (splitter1, true, true);
|
||||
|
||||
ep.set_base_verbosity (50);
|
||||
|
||||
std::vector<std::pair<db::EdgeSink *, db::EdgeEvaluatorBase *> > procs;
|
||||
procs.push_back (std::make_pair (&pg0, &op0));
|
||||
procs.push_back (std::make_pair (&pg1, &op1));
|
||||
ep.process (procs);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
template <class TS, class TI, class TR>
|
||||
std::string two_bool_and_not_local_operation<TS, TI, TR>::description () const
|
||||
{
|
||||
return tl::to_string (tr ("ANDNOT operation"));
|
||||
}
|
||||
|
||||
template class DB_PUBLIC two_bool_and_not_local_operation<db::PolygonRef, db::PolygonRef, db::PolygonRef>;
|
||||
template class DB_PUBLIC two_bool_and_not_local_operation<db::Polygon, db::Polygon, db::Polygon>;
|
||||
|
||||
// ---------------------------------------------------------------------------------------------
|
||||
// TwoBoolAndNotLocalOperationWithProperties implementation
|
||||
|
||||
template <class TS, class TI, class TR>
|
||||
two_bool_and_not_local_operation_with_properties<TS, TI, TR>::two_bool_and_not_local_operation_with_properties (db::PropertiesRepository *target1_pr, db::PropertiesRepository *target2_pr, const db::PropertiesRepository *subject_pr, const db::PropertiesRepository *intruder_pr, db::PropertyConstraint property_constraint)
|
||||
: db::local_operation<db::object_with_properties<TS>, db::object_with_properties<TI>, db::object_with_properties<TR> > (),
|
||||
m_property_constraint (property_constraint), m_pms (target1_pr, subject_pr), m_pmi (target1_pr, intruder_pr), m_pm12 (target2_pr, target1_pr)
|
||||
{
|
||||
// .. nothing yet ..
|
||||
}
|
||||
|
||||
template <class TS, class TI, class TR>
|
||||
void
|
||||
two_bool_and_not_local_operation_with_properties<TS, TI, TR>::do_compute_local (db::Layout *layout, const shape_interactions<db::object_with_properties<TS>, db::object_with_properties<TI> > &interactions, std::vector<std::unordered_set<db::object_with_properties<TR> > > &results, size_t max_vertex_count, double area_ratio) const
|
||||
{
|
||||
tl_assert (results.size () == 2);
|
||||
std::unordered_set<db::object_with_properties<TR> > &result0 = results [0];
|
||||
std::unordered_set<db::object_with_properties<TR> > &result1 = results [1];
|
||||
|
||||
db::EdgeProcessor ep;
|
||||
|
||||
std::map<db::properties_id_type, std::pair<tl::slist<TS>, std::set<TI> > > by_prop_id;
|
||||
|
||||
for (auto i = interactions.begin (); i != interactions.end (); ++i) {
|
||||
|
||||
const db::object_with_properties<TS> &subject = interactions.subject_shape (i->first);
|
||||
|
||||
if (i->second.empty ()) {
|
||||
|
||||
result1.insert (db::object_with_properties<TR> (subject, m_pms (subject.properties_id ())));
|
||||
|
||||
} else {
|
||||
|
||||
db::properties_id_type prop_id_s = m_pms (subject.properties_id ());
|
||||
|
||||
auto &shapes_by_prop = by_prop_id [prop_id_s];
|
||||
shapes_by_prop.first.push_front (subject);
|
||||
|
||||
for (auto j = i->second.begin (); j != i->second.end (); ++j) {
|
||||
const db::object_with_properties<TI> &intruder = interactions.intruder_shape (*j).second;
|
||||
db::properties_id_type prop_id_i = (m_property_constraint != db::NoPropertyConstraint ? m_pmi (intruder.properties_id ()) : prop_id_s);
|
||||
if ((prop_id_i != prop_id_s) == (m_property_constraint == db::DifferentPropertiesConstraint)) {
|
||||
shapes_by_prop.second.insert (intruder);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
for (auto p2s = by_prop_id.begin (); p2s != by_prop_id.end (); ++p2s) {
|
||||
|
||||
ep.clear ();
|
||||
size_t p1 = 0, p2 = 1;
|
||||
|
||||
const std::set<TR> &others = p2s->second.second;
|
||||
db::properties_id_type prop_id = p2s->first;
|
||||
|
||||
for (auto s = p2s->second.first.begin (); s != p2s->second.first.end (); ++s) {
|
||||
|
||||
const TR &subject = *s;
|
||||
if (others.find (subject) != others.end ()) {
|
||||
result0.insert (db::object_with_properties<TR> (subject, prop_id));
|
||||
} else if (others.empty ()) {
|
||||
// shortcut (not: keep, and: drop)
|
||||
result1.insert (db::object_with_properties<TR> (subject, m_pm12 (prop_id)));
|
||||
} else {
|
||||
for (auto e = subject.begin_edge (); ! e.at_end(); ++e) {
|
||||
ep.insert (*e, p1);
|
||||
}
|
||||
p1 += 2;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (! others.empty () && p1 > 0) {
|
||||
|
||||
for (auto o = others.begin (); o != others.end (); ++o) {
|
||||
for (auto e = o->begin_edge (); ! e.at_end(); ++e) {
|
||||
ep.insert (*e, p2);
|
||||
}
|
||||
p2 += 2;
|
||||
}
|
||||
|
||||
std::unordered_set<TR> result0_wo_props;
|
||||
std::unordered_set<TR> result1_wo_props;
|
||||
|
||||
db::BooleanOp op0 (db::BooleanOp::And);
|
||||
db::polygon_ref_generator<TR> pr0 (layout, result0_wo_props);
|
||||
db::PolygonSplitter splitter0 (pr0, area_ratio, max_vertex_count);
|
||||
db::PolygonGenerator pg0 (splitter0, true, true);
|
||||
|
||||
db::BooleanOp op1 (db::BooleanOp::ANotB);
|
||||
db::polygon_ref_generator<TR> pr1 (layout, result1_wo_props);
|
||||
db::PolygonSplitter splitter1 (pr1, area_ratio, max_vertex_count);
|
||||
db::PolygonGenerator pg1 (splitter1, true, true);
|
||||
|
||||
ep.set_base_verbosity (50);
|
||||
|
||||
std::vector<std::pair<db::EdgeSink *, db::EdgeEvaluatorBase *> > procs;
|
||||
procs.push_back (std::make_pair (&pg0, &op0));
|
||||
procs.push_back (std::make_pair (&pg1, &op1));
|
||||
ep.process (procs);
|
||||
|
||||
for (auto r = result0_wo_props.begin (); r != result0_wo_props.end (); ++r) {
|
||||
result0.insert (db::object_with_properties<TR> (*r, prop_id));
|
||||
}
|
||||
for (auto r = result1_wo_props.begin (); r != result1_wo_props.end (); ++r) {
|
||||
result1.insert (db::object_with_properties<TR> (*r, m_pm12 (prop_id)));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
template <class TS, class TI, class TR>
|
||||
std::string two_bool_and_not_local_operation_with_properties<TS, TI, TR>::description () const
|
||||
{
|
||||
return tl::to_string (tr ("ANDNOT operation"));
|
||||
}
|
||||
|
||||
template class DB_PUBLIC two_bool_and_not_local_operation_with_properties<db::PolygonRef, db::PolygonRef, db::PolygonRef>;
|
||||
template class DB_PUBLIC two_bool_and_not_local_operation_with_properties<db::Polygon, db::Polygon, db::Polygon>;
|
||||
|
||||
// ---------------------------------------------------------------------------------------------
|
||||
|
||||
SelfOverlapMergeLocalOperation::SelfOverlapMergeLocalOperation (unsigned int wrap_count)
|
||||
: m_wrap_count (wrap_count)
|
||||
{
|
||||
// .. nothing yet ..
|
||||
}
|
||||
|
||||
void
|
||||
SelfOverlapMergeLocalOperation::do_compute_local (db::Layout *layout, const shape_interactions<db::PolygonRef, db::PolygonRef> &interactions, std::vector<std::unordered_set<db::PolygonRef> > &results, size_t /*max_vertex_count*/, double /*area_ratio*/) const
|
||||
{
|
||||
tl_assert (results.size () == 1);
|
||||
std::unordered_set<db::PolygonRef> &result = results.front ();
|
||||
|
||||
if (m_wrap_count == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
db::EdgeProcessor ep;
|
||||
|
||||
size_t p1 = 0, p2 = 1;
|
||||
std::set<unsigned int> seen;
|
||||
|
||||
for (shape_interactions<db::PolygonRef, db::PolygonRef>::iterator i = interactions.begin (); i != interactions.end (); ++i) {
|
||||
|
||||
if (seen.find (i->first) == seen.end ()) {
|
||||
seen.insert (i->first);
|
||||
const db::PolygonRef &subject = interactions.subject_shape (i->first);
|
||||
for (db::PolygonRef::polygon_edge_iterator e = subject.begin_edge (); ! e.at_end(); ++e) {
|
||||
ep.insert (*e, p1);
|
||||
}
|
||||
p1 += 2;
|
||||
}
|
||||
|
||||
for (db::shape_interactions<db::PolygonRef, db::PolygonRef>::iterator2 o = i->second.begin (); o != i->second.end (); ++o) {
|
||||
// don't take the same (really the same, not an identical one) shape twice - the interaction
|
||||
// set does not take care to list just one copy of the same item on the intruder side.
|
||||
if (seen.find (*o) == seen.end ()) {
|
||||
seen.insert (*o);
|
||||
const db::PolygonRef &intruder = interactions.intruder_shape (*o).second;
|
||||
for (db::PolygonRef::polygon_edge_iterator e = intruder.begin_edge (); ! e.at_end(); ++e) {
|
||||
ep.insert (*e, p2);
|
||||
}
|
||||
p2 += 2;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
db::MergeOp op (m_wrap_count - 1);
|
||||
db::PolygonRefGenerator pr (layout, result);
|
||||
db::PolygonGenerator pg (pr, true, true);
|
||||
ep.set_base_verbosity (50);
|
||||
ep.process (pg, op);
|
||||
}
|
||||
|
||||
OnEmptyIntruderHint SelfOverlapMergeLocalOperation::on_empty_intruder_hint () const
|
||||
{
|
||||
return m_wrap_count > 1 ? Drop : Copy;
|
||||
}
|
||||
|
||||
std::string SelfOverlapMergeLocalOperation::description () const
|
||||
{
|
||||
return tl::sprintf (tl::to_string (tr ("Self-overlap (wrap count %d)")), int (m_wrap_count));
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------------------
|
||||
// EdgeBoolAndOrNotLocalOperation implementation
|
||||
|
||||
EdgeBoolAndOrNotLocalOperation::EdgeBoolAndOrNotLocalOperation (EdgeBoolOp op)
|
||||
: m_op (op)
|
||||
{
|
||||
// .. nothing yet ..
|
||||
}
|
||||
|
||||
OnEmptyIntruderHint
|
||||
EdgeBoolAndOrNotLocalOperation::on_empty_intruder_hint () const
|
||||
{
|
||||
return (m_op == EdgeAnd || m_op == EdgeIntersections) ? Drop : Copy;
|
||||
}
|
||||
|
||||
std::string
|
||||
EdgeBoolAndOrNotLocalOperation::description () const
|
||||
{
|
||||
if (m_op == EdgeIntersections) {
|
||||
return tl::to_string (tr ("Edge INTERSECTION operation"));
|
||||
} else if (m_op == EdgeAnd) {
|
||||
return tl::to_string (tr ("Edge AND operation"));
|
||||
} else if (m_op == EdgeNot) {
|
||||
return tl::to_string (tr ("Edge NOT operation"));
|
||||
} else {
|
||||
return std::string ();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
EdgeBoolAndOrNotLocalOperation::do_compute_local (db::Layout * /*layout*/, const shape_interactions<db::Edge, db::Edge> &interactions, std::vector<std::unordered_set<db::Edge> > &results, size_t /*max_vertex_count*/, double /*area_ratio*/) const
|
||||
{
|
||||
tl_assert (results.size () == size_t (m_op == EdgeAndNot ? 2 : 1));
|
||||
|
||||
std::unordered_set<db::Edge> &result = results.front ();
|
||||
|
||||
std::unordered_set<db::Edge> *result2 = 0;
|
||||
if (results.size () > 1) {
|
||||
result2 = &results[1];
|
||||
}
|
||||
|
||||
EdgeBooleanClusterCollector<std::unordered_set<db::Edge> > cluster_collector (&result, m_op, result2);
|
||||
|
||||
db::box_scanner<db::Edge, size_t> scanner;
|
||||
|
||||
std::set<db::Edge> others;
|
||||
for (shape_interactions<db::Edge, db::Edge>::iterator i = interactions.begin (); i != interactions.end (); ++i) {
|
||||
for (shape_interactions<db::Edge, db::Edge>::iterator2 j = i->second.begin (); j != i->second.end (); ++j) {
|
||||
others.insert (interactions.intruder_shape (*j).second);
|
||||
}
|
||||
}
|
||||
|
||||
bool any_subject = false;
|
||||
bool is_and = (m_op == EdgeAnd || m_op == EdgeAndNot || m_op == EdgeIntersections);
|
||||
|
||||
for (shape_interactions<db::Edge, db::Edge>::iterator i = interactions.begin (); i != interactions.end (); ++i) {
|
||||
|
||||
const db::Edge &subject = interactions.subject_shape (i->first);
|
||||
if (others.find (subject) != others.end ()) {
|
||||
if (is_and) {
|
||||
result.insert (subject);
|
||||
}
|
||||
} else if (i->second.empty ()) {
|
||||
// shortcut (not: keep, and: drop)
|
||||
if (! is_and) {
|
||||
result.insert (subject);
|
||||
}
|
||||
} else {
|
||||
scanner.insert (&subject, 0);
|
||||
any_subject = true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (! others.empty () || any_subject) {
|
||||
|
||||
for (std::set<db::Edge>::const_iterator o = others.begin (); o != others.end (); ++o) {
|
||||
scanner.insert (o.operator-> (), 1);
|
||||
}
|
||||
|
||||
scanner.process (cluster_collector, 1, db::box_convert<db::Edge> ());
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------------------
|
||||
// EdgeToPolygonLocalOperation implementation
|
||||
|
||||
EdgeToPolygonLocalOperation::EdgeToPolygonLocalOperation (EdgePolygonOp::mode_t op, bool include_borders)
|
||||
: m_op (op), m_include_borders (include_borders)
|
||||
{
|
||||
// .. nothing yet ..
|
||||
}
|
||||
|
||||
OnEmptyIntruderHint
|
||||
EdgeToPolygonLocalOperation::on_empty_intruder_hint () const
|
||||
{
|
||||
return m_op == EdgePolygonOp::Inside ? Drop : (m_op == EdgePolygonOp::Outside ? Copy : CopyToSecond);
|
||||
}
|
||||
|
||||
std::string
|
||||
EdgeToPolygonLocalOperation::description () const
|
||||
{
|
||||
if (m_op == EdgePolygonOp::Inside) {
|
||||
return tl::to_string (tr ("Edge to polygon AND/INSIDE"));
|
||||
} else if (m_op == EdgePolygonOp::Outside) {
|
||||
return tl::to_string (tr ("Edge to polygon NOT/OUTSIDE"));
|
||||
} else {
|
||||
return tl::to_string (tr ("Edge to polygon ANDNOT/INOUTSIDE"));
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
EdgeToPolygonLocalOperation::do_compute_local (db::Layout * /*layout*/, const shape_interactions<db::Edge, db::PolygonRef> &interactions, std::vector<std::unordered_set<db::Edge> > &results, size_t /*max_vertex_count*/, double /*area_ratio*/) const
|
||||
{
|
||||
tl_assert (results.size () == size_t (m_op == EdgePolygonOp::Both ? 2 : 1));
|
||||
|
||||
std::unordered_set<db::Edge> &result = results.front ();
|
||||
|
||||
std::unordered_set<db::Edge> *result2 = 0;
|
||||
if (results.size () > 1) {
|
||||
result2 = &results[1];
|
||||
}
|
||||
|
||||
db::EdgeProcessor ep;
|
||||
|
||||
std::set<db::PolygonRef> others;
|
||||
for (shape_interactions<db::Edge, db::PolygonRef>::iterator i = interactions.begin (); i != interactions.end (); ++i) {
|
||||
for (shape_interactions<db::Edge, db::PolygonRef>::iterator2 j = i->second.begin (); j != i->second.end (); ++j) {
|
||||
others.insert (interactions.intruder_shape (*j).second);
|
||||
}
|
||||
}
|
||||
|
||||
bool any_subject = false;
|
||||
|
||||
for (shape_interactions<db::Edge, db::PolygonRef>::iterator i = interactions.begin (); i != interactions.end (); ++i) {
|
||||
|
||||
const db::Edge &subject = interactions.subject_shape (i->first);
|
||||
if (i->second.empty ()) {
|
||||
// shortcut (outside: keep, otherwise: drop)
|
||||
if (m_op == db::EdgePolygonOp::Outside) {
|
||||
result.insert (subject);
|
||||
} else if (m_op == db::EdgePolygonOp::Both) {
|
||||
result2->insert (subject);
|
||||
}
|
||||
} else {
|
||||
ep.insert (subject, 1);
|
||||
any_subject = true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (! others.empty () || any_subject) {
|
||||
|
||||
for (std::set<db::PolygonRef>::const_iterator o = others.begin (); o != others.end (); ++o) {
|
||||
for (db::PolygonRef::polygon_edge_iterator e = o->begin_edge (); ! e.at_end (); ++e) {
|
||||
ep.insert (*e, 0);
|
||||
}
|
||||
}
|
||||
|
||||
std::unique_ptr<db::EdgeToEdgeSetGenerator> cc_second;
|
||||
if (result2) {
|
||||
cc_second.reset (new db::EdgeToEdgeSetGenerator (*result2, 2 /*second tag*/));
|
||||
}
|
||||
|
||||
db::EdgeToEdgeSetGenerator cc (result, 1 /*first tag*/, cc_second.get ());
|
||||
db::EdgePolygonOp op (m_op, m_include_borders);
|
||||
ep.process (cc, op);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -131,156 +131,6 @@ protected:
|
|||
virtual void do_compute_local (db::Layout *layout, const shape_interactions<TS, TI> &interactions, std::vector<std::unordered_set<TR> > &result, size_t max_vertex_count, double area_ratio) const = 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Implements a boolean AND or NOT operation
|
||||
*/
|
||||
|
||||
template <class TS, class TI, class TR>
|
||||
class DB_PUBLIC bool_and_or_not_local_operation
|
||||
: public local_operation<TS, TI, TR>
|
||||
{
|
||||
public:
|
||||
bool_and_or_not_local_operation (bool is_and);
|
||||
|
||||
virtual void do_compute_local (db::Layout *layout, const shape_interactions<TS, TI> &interactions, std::vector<std::unordered_set<TR> > &result, size_t max_vertex_count, double area_ratio) const;
|
||||
virtual OnEmptyIntruderHint on_empty_intruder_hint () const;
|
||||
virtual std::string description () const;
|
||||
|
||||
private:
|
||||
bool m_is_and;
|
||||
};
|
||||
|
||||
typedef bool_and_or_not_local_operation<db::PolygonRef, db::PolygonRef, db::PolygonRef> BoolAndOrNotLocalOperation;
|
||||
|
||||
/**
|
||||
* @brief Implements a boolean AND or NOT operation with property handling
|
||||
*/
|
||||
template <class TS, class TI, class TR>
|
||||
class DB_PUBLIC bool_and_or_not_local_operation_with_properties
|
||||
: public local_operation<db::object_with_properties<TS>, db::object_with_properties<TI>, db::object_with_properties<TR> >
|
||||
{
|
||||
public:
|
||||
bool_and_or_not_local_operation_with_properties (bool is_and, db::PropertiesRepository *target_pr, const db::PropertiesRepository *subject_pr, const db::PropertiesRepository *intruder_pr, db::PropertyConstraint property_constraint);
|
||||
|
||||
virtual void do_compute_local (db::Layout * /*layout*/, const shape_interactions<db::object_with_properties<TS>, db::object_with_properties<TI> > &interactions, std::vector<std::unordered_set<db::object_with_properties<TR> > > &result, size_t max_vertex_count, double area_ratio) const;
|
||||
virtual OnEmptyIntruderHint on_empty_intruder_hint () const;
|
||||
virtual std::string description () const;
|
||||
|
||||
private:
|
||||
bool m_is_and;
|
||||
db::PropertyConstraint m_property_constraint;
|
||||
mutable db::PropertyMapper m_pms;
|
||||
mutable db::PropertyMapper m_pmi;
|
||||
};
|
||||
|
||||
typedef bool_and_or_not_local_operation_with_properties<db::PolygonRef, db::PolygonRef, db::PolygonRef> BoolAndOrNotLocalOperationWithProperties;
|
||||
|
||||
/**
|
||||
* @brief Implements a boolean AND plus NOT operation
|
||||
*
|
||||
* This processor delivers two outputs: the first one having the AND result, the second
|
||||
* one having the NOT result.
|
||||
*/
|
||||
|
||||
template <class TS, class TI, class TR>
|
||||
class DB_PUBLIC two_bool_and_not_local_operation
|
||||
: public local_operation<TS, TI, TR>
|
||||
{
|
||||
public:
|
||||
two_bool_and_not_local_operation ();
|
||||
|
||||
virtual void do_compute_local (db::Layout *layout, const shape_interactions<TS, TI> &interactions, std::vector<std::unordered_set<TR> > &result, size_t max_vertex_count, double area_ratio) const;
|
||||
virtual std::string description () const;
|
||||
};
|
||||
|
||||
typedef two_bool_and_not_local_operation<db::PolygonRef, db::PolygonRef, db::PolygonRef> TwoBoolAndNotLocalOperation;
|
||||
|
||||
/**
|
||||
* @brief Implements a boolean AND plus NOT operation
|
||||
*
|
||||
* This processor delivers two outputs: the first one having the AND result, the second
|
||||
* one having the NOT result.
|
||||
*/
|
||||
template <class TS, class TI, class TR>
|
||||
class DB_PUBLIC two_bool_and_not_local_operation_with_properties
|
||||
: public local_operation<db::object_with_properties<TS>, db::object_with_properties<TI>, db::object_with_properties<TR> >
|
||||
{
|
||||
public:
|
||||
two_bool_and_not_local_operation_with_properties (db::PropertiesRepository *target1_pr, db::PropertiesRepository *target2_pr, const db::PropertiesRepository *subject_pr, const db::PropertiesRepository *intruder_pr, db::PropertyConstraint property_constraint);
|
||||
|
||||
virtual void do_compute_local (db::Layout *layout, const shape_interactions<db::object_with_properties<TS>, db::object_with_properties<TI> > &interactions, std::vector<std::unordered_set<db::object_with_properties<TR> > > &result, size_t max_vertex_count, double area_ratio) const;
|
||||
virtual std::string description () const;
|
||||
|
||||
private:
|
||||
db::PropertyConstraint m_property_constraint;
|
||||
mutable db::PropertyMapper m_pms, m_pmi, m_pm12;
|
||||
};
|
||||
|
||||
typedef two_bool_and_not_local_operation_with_properties<db::PolygonRef, db::PolygonRef, db::PolygonRef> TwoBoolAndNotLocalOperationWithProperties;
|
||||
|
||||
/**
|
||||
* @brief Implements a merge operation with an overlap count
|
||||
* With a given wrap_count, the result will only contains shapes where
|
||||
* the original shapes overlap at least "wrap_count" times.
|
||||
*/
|
||||
class DB_PUBLIC SelfOverlapMergeLocalOperation
|
||||
: public local_operation<db::PolygonRef, db::PolygonRef, db::PolygonRef>
|
||||
{
|
||||
public:
|
||||
SelfOverlapMergeLocalOperation (unsigned int wrap_count);
|
||||
|
||||
virtual void do_compute_local (db::Layout *layout, const shape_interactions<db::PolygonRef, db::PolygonRef> &interactions, std::vector<std::unordered_set<db::PolygonRef> > &result, size_t max_vertex_count, double area_ratio) const;
|
||||
virtual OnEmptyIntruderHint on_empty_intruder_hint () const;
|
||||
virtual std::string description () const;
|
||||
|
||||
private:
|
||||
unsigned int m_wrap_count;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Implements a boolean AND or NOT operation between edges
|
||||
*/
|
||||
class DB_PUBLIC EdgeBoolAndOrNotLocalOperation
|
||||
: public local_operation<db::Edge, db::Edge, db::Edge>
|
||||
{
|
||||
public:
|
||||
EdgeBoolAndOrNotLocalOperation (db::EdgeBoolOp op);
|
||||
|
||||
virtual void do_compute_local (db::Layout *layout, const shape_interactions<db::Edge, db::Edge> &interactions, std::vector<std::unordered_set<db::Edge> > &result, size_t max_vertex_count, double area_ratio) const;
|
||||
virtual OnEmptyIntruderHint on_empty_intruder_hint () const;
|
||||
virtual std::string description () const;
|
||||
|
||||
// edge interaction distance is 1 to force overlap between edges and edge/boxes
|
||||
virtual db::Coord dist () const { return 1; }
|
||||
|
||||
private:
|
||||
db::EdgeBoolOp m_op;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Implements a boolean AND or NOT operation between edges and polygons (polygons as intruders)
|
||||
*
|
||||
* "AND" is implemented by "outside == false", "NOT" by "outside == true" with "include_borders == true".
|
||||
* With "include_borders == false" the operations are "INSIDE" and "OUTSIDE".
|
||||
*/
|
||||
class DB_PUBLIC EdgeToPolygonLocalOperation
|
||||
: public local_operation<db::Edge, db::PolygonRef, db::Edge>
|
||||
{
|
||||
public:
|
||||
EdgeToPolygonLocalOperation (EdgePolygonOp::mode_t op, bool include_borders);
|
||||
|
||||
virtual void do_compute_local (db::Layout *layout, const shape_interactions<db::Edge, db::PolygonRef> &interactions, std::vector<std::unordered_set<db::Edge> > &result, size_t max_vertex_count, double area_ratio) const;
|
||||
virtual OnEmptyIntruderHint on_empty_intruder_hint () const;
|
||||
virtual std::string description () const;
|
||||
|
||||
// edge interaction distance is 1 to force overlap between edges and edge/boxes
|
||||
virtual db::Coord dist () const { return m_include_borders ? 1 : 0; }
|
||||
|
||||
private:
|
||||
db::EdgePolygonOp::mode_t m_op;
|
||||
bool m_include_borders;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@
|
|||
|
||||
#include "dbLayout.h"
|
||||
#include "dbPolygonGenerators.h"
|
||||
#include "dbLocalOperation.h"
|
||||
#include "dbHash.h"
|
||||
#include "tlThreads.h"
|
||||
|
||||
|
|
@ -303,6 +304,45 @@ private:
|
|||
db::properties_id_type m_prop_id;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Separates the interacting shapes by property relation
|
||||
*
|
||||
* Returns a map of property ID, subject shapes and intruder shapes belonging to the subject shapes.
|
||||
* Depending on the property constraint the intruders will either be ones with and properties (NoPropertyConstraint),
|
||||
* the same properties than the subject (SamePropertiesConstraint) or different properties (DifferentPropertiesConstraint).
|
||||
*/
|
||||
template <class TS, class TI>
|
||||
DB_PUBLIC
|
||||
std::map<db::properties_id_type, std::pair<std::vector<const TS *>, std::set<const TI *> > >
|
||||
separate_interactions_by_properties (const shape_interactions<db::object_with_properties<TS>, db::object_with_properties<TI> > &interactions, db::PropertyConstraint property_constraint, db::PropertyMapper &pms, db::PropertyMapper &pmi)
|
||||
{
|
||||
std::map<db::properties_id_type, std::pair<std::vector<const TS *>, std::set<const TI *> > > by_prop_id;
|
||||
|
||||
for (auto i = interactions.begin (); i != interactions.end (); ++i) {
|
||||
|
||||
const db::object_with_properties<TS> &subject = interactions.subject_shape (i->first);
|
||||
|
||||
db::properties_id_type prop_id = pms (subject.properties_id ());
|
||||
|
||||
std::pair<std::vector<const TS *>, std::set<const TI *> > &s2p = by_prop_id [prop_id];
|
||||
s2p.first.push_back (&subject);
|
||||
|
||||
for (auto ii = i->second.begin (); ii != i->second.end (); ++ii) {
|
||||
|
||||
const std::pair<unsigned int, db::object_with_properties<TI> > &intruder = interactions.intruder_shape (*ii);
|
||||
db::properties_id_type intruder_prop_id = (property_constraint == db::NoPropertyConstraint ? prop_id : pmi (intruder.second.properties_id ()));
|
||||
|
||||
if ((property_constraint == db::DifferentPropertiesConstraint) == (prop_id != intruder_prop_id)) {
|
||||
s2p.second.insert (&intruder.second);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return by_prop_id;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
|
|
@ -27,6 +27,7 @@
|
|||
#include "dbCommon.h"
|
||||
#include "dbEdgePairRelations.h"
|
||||
#include "dbLocalOperation.h"
|
||||
#include "dbLocalOperationUtils.h"
|
||||
#include "dbEdgeProcessor.h"
|
||||
#include "dbRegionCheckUtils.h"
|
||||
#include "dbPropertyConstraint.h"
|
||||
|
|
@ -125,7 +126,8 @@ struct DB_PUBLIC RegionCheckOptions
|
|||
bool _shielded = true,
|
||||
OppositeFilter _opposite_filter = NoOppositeFilter,
|
||||
RectFilter _rect_filter = NoRectFilter,
|
||||
bool _negative = false)
|
||||
bool _negative = false,
|
||||
PropertyConstraint _prop_constraint = IgnoreProperties)
|
||||
: whole_edges (_whole_edges),
|
||||
metrics (_metrics),
|
||||
ignore_angle (_ignore_angle),
|
||||
|
|
@ -134,7 +136,8 @@ struct DB_PUBLIC RegionCheckOptions
|
|||
shielded (_shielded),
|
||||
opposite_filter (_opposite_filter),
|
||||
rect_filter (_rect_filter),
|
||||
negative (_negative)
|
||||
negative (_negative),
|
||||
prop_constraint (_prop_constraint)
|
||||
{ }
|
||||
|
||||
/**
|
||||
|
|
@ -199,6 +202,11 @@ struct DB_PUBLIC RegionCheckOptions
|
|||
*/
|
||||
bool negative;
|
||||
|
||||
/**
|
||||
* @brief Specifies a property constraint - e.g. checking only shapes with the same properties
|
||||
*/
|
||||
PropertyConstraint prop_constraint;
|
||||
|
||||
/**
|
||||
* @brief Gets a value indicating whether merged primary input is required
|
||||
*/
|
||||
|
|
@ -213,9 +221,28 @@ struct DB_PUBLIC RegionCheckOptions
|
|||
}
|
||||
};
|
||||
|
||||
template <class TS, class TI>
|
||||
class check_local_operation_base
|
||||
{
|
||||
public:
|
||||
check_local_operation_base (const EdgeRelationFilter &check, bool different_polygons, bool is_merged, bool has_other, bool other_is_merged, const db::RegionCheckOptions &options);
|
||||
|
||||
protected:
|
||||
EdgeRelationFilter m_check;
|
||||
bool m_different_polygons;
|
||||
bool m_is_merged;
|
||||
bool m_has_other;
|
||||
bool m_other_is_merged;
|
||||
db::RegionCheckOptions m_options;
|
||||
|
||||
void compute_results (db::Layout *layout, const std::vector<const TS *> &subjects, const std::set<const TI *> &intruders, std::unordered_set<db::EdgePair> &result, std::unordered_set<db::EdgePair> &intra_polygon_result) const;
|
||||
void apply_opposite_filter (const std::vector<const TS *> &subjects, std::unordered_set<db::EdgePair> &result, std::unordered_set<db::EdgePair> &intra_polygon_result) const;
|
||||
void apply_rectangle_filter (const std::vector<const TS *> &subjects, std::unordered_set<db::EdgePair> &result) const;
|
||||
};
|
||||
|
||||
template <class TS, class TI>
|
||||
class check_local_operation
|
||||
: public local_operation<TS, TI, db::EdgePair>
|
||||
: public local_operation<TS, TI, db::EdgePair>, public check_local_operation_base<TS, TI>
|
||||
{
|
||||
public:
|
||||
check_local_operation (const EdgeRelationFilter &check, bool different_polygons, bool is_merged, bool has_other, bool other_is_merged, const db::RegionCheckOptions &options);
|
||||
|
|
@ -226,14 +253,24 @@ public:
|
|||
virtual std::string description () const;
|
||||
|
||||
virtual void do_compute_local (db::Layout * /*layout*/, const shape_interactions<TS, TI> &interactions, std::vector<std::unordered_set<db::EdgePair> > &results, size_t /*max_vertex_count*/, double /*area_ratio*/) const;
|
||||
};
|
||||
|
||||
template <class TS, class TI>
|
||||
class check_local_operation_with_properties
|
||||
: public local_operation<db::object_with_properties<TS>, db::object_with_properties<TI>, db::EdgePair>, public check_local_operation_base<TS, TI>
|
||||
{
|
||||
public:
|
||||
check_local_operation_with_properties (const EdgeRelationFilter &check, bool different_polygons, bool is_merged, bool has_other, bool other_is_merged, const db::RegionCheckOptions &options, db::PropertiesRepository *target_pr, const db::PropertiesRepository *subject_pr, const db::PropertiesRepository *intruder_pr);
|
||||
|
||||
virtual db::Coord dist () const;
|
||||
virtual OnEmptyIntruderHint on_empty_intruder_hint () const;
|
||||
virtual bool requests_single_subjects () const { return true; }
|
||||
virtual std::string description () const;
|
||||
|
||||
virtual void do_compute_local (db::Layout * /*layout*/, const shape_interactions<db::object_with_properties<TS>, db::object_with_properties<TI> > &interactions, std::vector<std::unordered_set<db::EdgePair> > &results, size_t /*max_vertex_count*/, double /*area_ratio*/) const;
|
||||
|
||||
private:
|
||||
EdgeRelationFilter m_check;
|
||||
bool m_different_polygons;
|
||||
bool m_is_merged;
|
||||
bool m_has_other;
|
||||
bool m_other_is_merged;
|
||||
db::RegionCheckOptions m_options;
|
||||
mutable db::PropertyMapper m_pms, m_pmi;
|
||||
};
|
||||
|
||||
typedef check_local_operation<db::PolygonRef, db::PolygonRef> CheckLocalOperation;
|
||||
|
|
@ -372,6 +409,131 @@ typedef contained_local_operation<db::PolygonRef, db::PolygonRef, db::PolygonRef
|
|||
// the implementation is type-agnostic and can be used for edges too
|
||||
typedef contained_local_operation<db::Edge, db::Edge, db::Edge> ContainedEdgesLocalOperation;
|
||||
|
||||
/**
|
||||
* @brief Implements a boolean AND or NOT operation
|
||||
*/
|
||||
|
||||
template <class TS, class TI, class TR>
|
||||
class DB_PUBLIC bool_and_or_not_local_operation
|
||||
: public local_operation<TS, TI, TR>
|
||||
{
|
||||
public:
|
||||
bool_and_or_not_local_operation (bool is_and);
|
||||
|
||||
virtual void do_compute_local (db::Layout *layout, const shape_interactions<TS, TI> &interactions, std::vector<std::unordered_set<TR> > &result, size_t max_vertex_count, double area_ratio) const;
|
||||
virtual OnEmptyIntruderHint on_empty_intruder_hint () const;
|
||||
virtual std::string description () const;
|
||||
|
||||
private:
|
||||
bool m_is_and;
|
||||
};
|
||||
|
||||
typedef bool_and_or_not_local_operation<db::PolygonRef, db::PolygonRef, db::PolygonRef> BoolAndOrNotLocalOperation;
|
||||
|
||||
/**
|
||||
* @brief Implements a boolean AND or NOT operation with property handling
|
||||
*/
|
||||
template <class TS, class TI, class TR>
|
||||
class DB_PUBLIC bool_and_or_not_local_operation_with_properties
|
||||
: public local_operation<db::object_with_properties<TS>, db::object_with_properties<TI>, db::object_with_properties<TR> >
|
||||
{
|
||||
public:
|
||||
bool_and_or_not_local_operation_with_properties (bool is_and, db::PropertiesRepository *target_pr, const db::PropertiesRepository *subject_pr, const db::PropertiesRepository *intruder_pr, db::PropertyConstraint property_constraint);
|
||||
|
||||
virtual void do_compute_local (db::Layout * /*layout*/, const shape_interactions<db::object_with_properties<TS>, db::object_with_properties<TI> > &interactions, std::vector<std::unordered_set<db::object_with_properties<TR> > > &result, size_t max_vertex_count, double area_ratio) const;
|
||||
virtual OnEmptyIntruderHint on_empty_intruder_hint () const;
|
||||
virtual std::string description () const;
|
||||
|
||||
private:
|
||||
bool m_is_and;
|
||||
db::PropertyConstraint m_property_constraint;
|
||||
mutable db::PropertyMapper m_pms;
|
||||
mutable db::PropertyMapper m_pmi;
|
||||
};
|
||||
|
||||
typedef bool_and_or_not_local_operation_with_properties<db::PolygonRef, db::PolygonRef, db::PolygonRef> BoolAndOrNotLocalOperationWithProperties;
|
||||
|
||||
/**
|
||||
* @brief Implements a boolean AND plus NOT operation
|
||||
*
|
||||
* This processor delivers two outputs: the first one having the AND result, the second
|
||||
* one having the NOT result.
|
||||
*/
|
||||
|
||||
template <class TS, class TI, class TR>
|
||||
class DB_PUBLIC two_bool_and_not_local_operation
|
||||
: public local_operation<TS, TI, TR>
|
||||
{
|
||||
public:
|
||||
two_bool_and_not_local_operation ();
|
||||
|
||||
virtual void do_compute_local (db::Layout *layout, const shape_interactions<TS, TI> &interactions, std::vector<std::unordered_set<TR> > &result, size_t max_vertex_count, double area_ratio) const;
|
||||
virtual std::string description () const;
|
||||
};
|
||||
|
||||
typedef two_bool_and_not_local_operation<db::PolygonRef, db::PolygonRef, db::PolygonRef> TwoBoolAndNotLocalOperation;
|
||||
|
||||
/**
|
||||
* @brief Implements a boolean AND plus NOT operation
|
||||
*
|
||||
* This processor delivers two outputs: the first one having the AND result, the second
|
||||
* one having the NOT result.
|
||||
*/
|
||||
template <class TS, class TI, class TR>
|
||||
class DB_PUBLIC two_bool_and_not_local_operation_with_properties
|
||||
: public local_operation<db::object_with_properties<TS>, db::object_with_properties<TI>, db::object_with_properties<TR> >
|
||||
{
|
||||
public:
|
||||
two_bool_and_not_local_operation_with_properties (db::PropertiesRepository *target1_pr, db::PropertiesRepository *target2_pr, const db::PropertiesRepository *subject_pr, const db::PropertiesRepository *intruder_pr, db::PropertyConstraint property_constraint);
|
||||
|
||||
virtual void do_compute_local (db::Layout *layout, const shape_interactions<db::object_with_properties<TS>, db::object_with_properties<TI> > &interactions, std::vector<std::unordered_set<db::object_with_properties<TR> > > &result, size_t max_vertex_count, double area_ratio) const;
|
||||
virtual std::string description () const;
|
||||
|
||||
private:
|
||||
db::PropertyConstraint m_property_constraint;
|
||||
mutable db::PropertyMapper m_pms, m_pmi, m_pm12;
|
||||
};
|
||||
|
||||
typedef two_bool_and_not_local_operation_with_properties<db::PolygonRef, db::PolygonRef, db::PolygonRef> TwoBoolAndNotLocalOperationWithProperties;
|
||||
|
||||
/**
|
||||
* @brief Implements a merge operation with an overlap count
|
||||
* With a given wrap_count, the result will only contains shapes where
|
||||
* the original shapes overlap at least "wrap_count" times.
|
||||
*/
|
||||
class DB_PUBLIC SelfOverlapMergeLocalOperation
|
||||
: public local_operation<db::PolygonRef, db::PolygonRef, db::PolygonRef>
|
||||
{
|
||||
public:
|
||||
SelfOverlapMergeLocalOperation (unsigned int wrap_count);
|
||||
|
||||
virtual void do_compute_local (db::Layout *layout, const shape_interactions<db::PolygonRef, db::PolygonRef> &interactions, std::vector<std::unordered_set<db::PolygonRef> > &result, size_t max_vertex_count, double area_ratio) const;
|
||||
virtual OnEmptyIntruderHint on_empty_intruder_hint () const;
|
||||
virtual std::string description () const;
|
||||
|
||||
private:
|
||||
unsigned int m_wrap_count;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Converts polygons to edges
|
||||
*/
|
||||
class DB_PUBLIC PolygonToEdgeLocalOperation
|
||||
: public local_operation<db::PolygonRefWithProperties, db::PolygonRefWithProperties, db::EdgeWithProperties>
|
||||
{
|
||||
public:
|
||||
PolygonToEdgeLocalOperation (db::PropertiesRepository *target_pr, const db::PropertiesRepository *source_pr);
|
||||
|
||||
virtual db::Coord dist () const { return 1; }
|
||||
virtual bool requests_single_subjects () const { return true; }
|
||||
virtual std::string description () const;
|
||||
|
||||
virtual void do_compute_local (db::Layout * /*layout*/, const shape_interactions<db::PolygonRefWithProperties, db::PolygonRefWithProperties> &interactions, std::vector<std::unordered_set<db::EdgeWithProperties> > &results, size_t /*max_vertex_count*/, double /*area_ratio*/) const;
|
||||
|
||||
private:
|
||||
mutable db::PropertyMapper m_pm;
|
||||
};
|
||||
|
||||
} // namespace db
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@
|
|||
#include "dbEdgeProcessor.h"
|
||||
#include "dbPolygonGenerators.h"
|
||||
#include "dbLocalOperationUtils.h"
|
||||
#include "dbRegionLocalOperations.h"
|
||||
#include "dbPolygon.h"
|
||||
|
||||
static std::string testdata (const std::string &fn)
|
||||
|
|
|
|||
Loading…
Reference in New Issue