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 \
|
dbEdgePairs.cc \
|
||||||
dbEdgeProcessor.cc \
|
dbEdgeProcessor.cc \
|
||||||
dbEdges.cc \
|
dbEdges.cc \
|
||||||
|
dbEdgesLocalOperations.cc \
|
||||||
dbFillTool.cc \
|
dbFillTool.cc \
|
||||||
dbFuzzyCellMapping.cc \
|
dbFuzzyCellMapping.cc \
|
||||||
dbGenericShapeIterator.cc \
|
dbGenericShapeIterator.cc \
|
||||||
|
|
@ -243,6 +244,7 @@ HEADERS = \
|
||||||
dbEdgePairs.h \
|
dbEdgePairs.h \
|
||||||
dbEdgeProcessor.h \
|
dbEdgeProcessor.h \
|
||||||
dbEdges.h \
|
dbEdges.h \
|
||||||
|
dbEdgesLocalOperations.h \
|
||||||
dbEdgesToContours.h \
|
dbEdgesToContours.h \
|
||||||
dbFillTool.h \
|
dbFillTool.h \
|
||||||
dbFuzzyCellMapping.h \
|
dbFuzzyCellMapping.h \
|
||||||
|
|
|
||||||
|
|
@ -35,6 +35,7 @@
|
||||||
#include "dbLocalOperation.h"
|
#include "dbLocalOperation.h"
|
||||||
#include "dbLocalOperationUtils.h"
|
#include "dbLocalOperationUtils.h"
|
||||||
#include "dbRegionLocalOperations.h" // for db::ContainedEdgesLocalOperation
|
#include "dbRegionLocalOperations.h" // for db::ContainedEdgesLocalOperation
|
||||||
|
#include "dbEdgesLocalOperations.h"
|
||||||
#include "dbHierProcessor.h"
|
#include "dbHierProcessor.h"
|
||||||
#include "dbEmptyEdges.h"
|
#include "dbEmptyEdges.h"
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1282,125 +1282,6 @@ DeepRegion::snapped (db::Coord gx, db::Coord gy)
|
||||||
return res.release ();
|
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 *
|
EdgesDelegate *
|
||||||
DeepRegion::edges (const EdgeFilterBase *filter) const
|
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 "dbBoxConvert.h"
|
||||||
#include "dbPolygonGenerators.h"
|
#include "dbPolygonGenerators.h"
|
||||||
#include "dbPolygonTools.h"
|
#include "dbPolygonTools.h"
|
||||||
#include "dbLocalOperationUtils.h"
|
|
||||||
#include "dbEdgeBoolean.h"
|
#include "dbEdgeBoolean.h"
|
||||||
#include "dbLayoutUtils.h"
|
#include "dbLayoutUtils.h"
|
||||||
#include "tlLog.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::PolygonRef>;
|
||||||
template class DB_PUBLIC local_operation<db::TextRef, db::PolygonRef, db::TextRef>;
|
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;
|
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
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -29,6 +29,7 @@
|
||||||
|
|
||||||
#include "dbLayout.h"
|
#include "dbLayout.h"
|
||||||
#include "dbPolygonGenerators.h"
|
#include "dbPolygonGenerators.h"
|
||||||
|
#include "dbLocalOperation.h"
|
||||||
#include "dbHash.h"
|
#include "dbHash.h"
|
||||||
#include "tlThreads.h"
|
#include "tlThreads.h"
|
||||||
|
|
||||||
|
|
@ -303,6 +304,45 @@ private:
|
||||||
db::properties_id_type m_prop_id;
|
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
|
#endif
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load Diff
|
|
@ -27,6 +27,7 @@
|
||||||
#include "dbCommon.h"
|
#include "dbCommon.h"
|
||||||
#include "dbEdgePairRelations.h"
|
#include "dbEdgePairRelations.h"
|
||||||
#include "dbLocalOperation.h"
|
#include "dbLocalOperation.h"
|
||||||
|
#include "dbLocalOperationUtils.h"
|
||||||
#include "dbEdgeProcessor.h"
|
#include "dbEdgeProcessor.h"
|
||||||
#include "dbRegionCheckUtils.h"
|
#include "dbRegionCheckUtils.h"
|
||||||
#include "dbPropertyConstraint.h"
|
#include "dbPropertyConstraint.h"
|
||||||
|
|
@ -125,7 +126,8 @@ struct DB_PUBLIC RegionCheckOptions
|
||||||
bool _shielded = true,
|
bool _shielded = true,
|
||||||
OppositeFilter _opposite_filter = NoOppositeFilter,
|
OppositeFilter _opposite_filter = NoOppositeFilter,
|
||||||
RectFilter _rect_filter = NoRectFilter,
|
RectFilter _rect_filter = NoRectFilter,
|
||||||
bool _negative = false)
|
bool _negative = false,
|
||||||
|
PropertyConstraint _prop_constraint = IgnoreProperties)
|
||||||
: whole_edges (_whole_edges),
|
: whole_edges (_whole_edges),
|
||||||
metrics (_metrics),
|
metrics (_metrics),
|
||||||
ignore_angle (_ignore_angle),
|
ignore_angle (_ignore_angle),
|
||||||
|
|
@ -134,7 +136,8 @@ struct DB_PUBLIC RegionCheckOptions
|
||||||
shielded (_shielded),
|
shielded (_shielded),
|
||||||
opposite_filter (_opposite_filter),
|
opposite_filter (_opposite_filter),
|
||||||
rect_filter (_rect_filter),
|
rect_filter (_rect_filter),
|
||||||
negative (_negative)
|
negative (_negative),
|
||||||
|
prop_constraint (_prop_constraint)
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -199,6 +202,11 @@ struct DB_PUBLIC RegionCheckOptions
|
||||||
*/
|
*/
|
||||||
bool negative;
|
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
|
* @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>
|
template <class TS, class TI>
|
||||||
class check_local_operation
|
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:
|
public:
|
||||||
check_local_operation (const EdgeRelationFilter &check, bool different_polygons, bool is_merged, bool has_other, bool other_is_merged, const db::RegionCheckOptions &options);
|
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 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;
|
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:
|
private:
|
||||||
EdgeRelationFilter m_check;
|
mutable db::PropertyMapper m_pms, m_pmi;
|
||||||
bool m_different_polygons;
|
|
||||||
bool m_is_merged;
|
|
||||||
bool m_has_other;
|
|
||||||
bool m_other_is_merged;
|
|
||||||
db::RegionCheckOptions m_options;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef check_local_operation<db::PolygonRef, db::PolygonRef> CheckLocalOperation;
|
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
|
// the implementation is type-agnostic and can be used for edges too
|
||||||
typedef contained_local_operation<db::Edge, db::Edge, db::Edge> ContainedEdgesLocalOperation;
|
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
|
} // namespace db
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -30,6 +30,7 @@
|
||||||
#include "dbEdgeProcessor.h"
|
#include "dbEdgeProcessor.h"
|
||||||
#include "dbPolygonGenerators.h"
|
#include "dbPolygonGenerators.h"
|
||||||
#include "dbLocalOperationUtils.h"
|
#include "dbLocalOperationUtils.h"
|
||||||
|
#include "dbRegionLocalOperations.h"
|
||||||
#include "dbPolygon.h"
|
#include "dbPolygon.h"
|
||||||
|
|
||||||
static std::string testdata (const std::string &fn)
|
static std::string testdata (const std::string &fn)
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue