klayout/src/db/db/dbEdges.h

1246 lines
36 KiB
C++

/*
KLayout Layout Viewer
Copyright (C) 2006-2020 Matthias Koefferlein
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef HDR_dbEdges
#define HDR_dbEdges
#include "dbCommon.h"
#include "dbEdgesDelegate.h"
#include "dbRecursiveShapeIterator.h"
#include "dbCellVariants.h"
#include "dbShapeCollection.h"
#include "dbGenericShapeIterator.h"
#include <list>
namespace db {
class EdgeFilterBase;
class FlatEdges;
class EmptyEdges;
class DeepShapeStore;
/**
* @brief An edge set iterator
*
* The iterator delivers the edges of the edge set
*/
class DB_PUBLIC EdgesIterator
: public generic_shape_iterator<db::Edge>
{
public:
/**
* @brief Default constructor
*/
EdgesIterator ()
: generic_shape_iterator<db::Edge> ()
{
// .. nothing yet ..
}
/**
* @brief Constructor from a delegate
* The iterator will take ownership over the delegate
*/
EdgesIterator (EdgesIteratorDelegate *delegate)
: generic_shape_iterator<db::Edge> (delegate)
{
// .. nothing yet ..
}
/**
* @brief Copy constructor and assignment
*/
EdgesIterator (const EdgesIterator &other)
: generic_shape_iterator<db::Edge> (static_cast<const generic_shape_iterator<db::Edge> &> (other))
{
// .. nothing yet ..
}
/**
* @brief Assignment
*/
EdgesIterator &operator= (const EdgesIterator &other)
{
generic_shape_iterator<db::Edge>::operator= (other);
return *this;
}
/**
* @brief Increment
*/
EdgesIterator &operator++ ()
{
generic_shape_iterator<db::Edge>::operator++ ();
return *this;
}
};
typedef addressable_shape_delivery_gen<EdgesIterator> AddressableEdgeDelivery;
class Edges;
/**
* @brief An edge set
*
* An edge set is basically a collection of edges. They do not necessarily need to form closed contours.
* Edges can be manipulated in various ways. Edge sets closely cooperate with the Region class which is a
* set of polygons.
*
* Edge sets have some methods in common with regions. Edge sets can also be merged, which means that
* edges which are continuations of other edges are joined.
*
* Edge sets can contain degenerated edges. Such edges are some which have identical start and end points.
* Such edges are basically points which have some applications, i.e. as markers for certain locations.
*/
class DB_PUBLIC Edges
: public db::ShapeCollection
{
public:
typedef db::Coord coord_type;
typedef db::coord_traits<db::Coord> coord_traits;
typedef db::Edge edge_type;
typedef db::Vector vector_type;
typedef db::Point point_type;
typedef db::Box box_type;
typedef coord_traits::distance_type length_type;
typedef coord_traits::distance_type distance_type;
typedef EdgesIterator const_iterator;
/**
* @brief Default constructor
*
* Creates an empty edge set.
*/
Edges ();
/**
* @brief Destructor
*/
~Edges ();
/**
* @brief Constructor from a delegate
*
* The region will take ownership of the delegate.
*/
Edges (EdgesDelegate *delegate);
/**
* @brief Copy constructor
*/
Edges (const Edges &other);
/**
* @brief Assignment
*/
Edges &operator= (const Edges &other);
/**
* @brief Constructor from a box
*
* Creates an edge set representing the contour of the box
*/
explicit Edges (const db::Box &s)
: mp_delegate (0)
{
insert (s);
}
/**
* @brief Constructor from a simple polygon
*
* Creates an edge set representing the contour of the polygon
*/
explicit Edges (const db::SimplePolygon &s)
: mp_delegate (0)
{
insert (s);
}
/**
* @brief Constructor from a polygon
*
* Creates an edge set representing the contour of the polygon
*/
explicit Edges (const db::Polygon &s)
: mp_delegate (0)
{
insert (s);
}
/**
* @brief Constructor from a path
*
* Creates an edge set representing the contour of the path
*/
explicit Edges (const db::Path &s)
: mp_delegate (0)
{
insert (s);
}
/**
* @brief Constructor from an edge
*
* Creates an edge set representing the single edge
*/
explicit Edges (const db::Edge &s)
: mp_delegate (0)
{
insert (s);
}
/**
* @brief Sequence constructor
*
* Creates an edge set from a sequence of objects. The objects can be boxes,
* polygons, paths, edges or shapes. This version accepts iterators of the begin ... end
* style.
*/
template <class Iter>
explicit Edges (const Iter &b, const Iter &e)
: mp_delegate (0)
{
reserve (e - b);
for (Iter i = b; i != e; ++i) {
insert (*i);
}
}
/**
* @brief Constructor from a RecursiveShapeIterator
*
* Creates an edge set from a recursive shape iterator. This allows feeding an edge set
* from a hierarchy of cells.
*/
explicit Edges (const RecursiveShapeIterator &si, bool as_edges = true);
/**
* @brief Constructor from a RecursiveShapeIterator with a transformation
*
* Creates an edge set from a recursive shape iterator. This allows feeding an edge set
* from a hierarchy of cells. The transformation is useful to scale to a specific
* DBU for example.
*/
explicit Edges (const RecursiveShapeIterator &si, const db::ICplxTrans &trans, bool as_edges = true, bool merged_semantics = true);
/**
* @brief Constructor from a RecursiveShapeIterator providing a deep representation
*
* This version will create a hierarchical edge collection. The DeepShapeStore needs to be provided
* during the lifetime of the collection and acts as a heap for optimized data.
*/
explicit Edges (const RecursiveShapeIterator &si, DeepShapeStore &dss, bool as_edges = true);
/**
* @brief Constructor from a RecursiveShapeIterator providing a deep representation with transformation
*/
explicit Edges (const RecursiveShapeIterator &si, DeepShapeStore &dss, const db::ICplxTrans &trans, bool as_edges = true, bool merged_semantics = true);
/**
* @brief Implementation of the ShapeCollection interface
*/
ShapeCollectionDelegateBase *get_delegate () const
{
return mp_delegate;
}
/**
* @brief Gets the underlying delegate object
*/
EdgesDelegate *delegate () const
{
return mp_delegate;
}
/**
* @brief Sets the base verbosity
*
* Setting this value will make timing measurements appear at least at
* the given verbosity level and more detailed timing at the given level
* plus 10. The default level is 30.
*/
void set_base_verbosity (int vb)
{
mp_delegate->set_base_verbosity (vb);
}
/**
* @brief Gets the base verbosity
*/
unsigned int base_verbosity () const
{
return mp_delegate->base_verbosity ();
}
/**
* @brief Enable progress reporting
*
* @param progress_text The description text of the progress object
*/
void enable_progress (const std::string &desc = std::string ())
{
mp_delegate->enable_progress (desc);
}
/**
* @brief Disable progress reporting
*/
void disable_progress ()
{
mp_delegate->disable_progress ();
}
/**
* @brief Iterator of the edge set
*
* The iterator delivers the edges of the edge set.
* It follows the at_end semantics.
*/
const_iterator begin () const
{
return EdgesIterator (mp_delegate->begin ());
}
/**
* @brief Returns the merged edges if merge semantics applies
*
* If merge semantics is not enabled, this iterator delivers the individual edges.
*/
const_iterator begin_merged () const
{
return EdgesIterator (mp_delegate->begin_merged ());
}
/**
* @brief Delivers a RecursiveShapeIterator pointing to the edges plus the necessary transformation
*/
std::pair<db::RecursiveShapeIterator, db::ICplxTrans> begin_iter () const
{
return mp_delegate->begin_iter ();
}
/**
* @brief Delivers a RecursiveShapeIterator pointing to the merged edges plus the necessary transformation
*/
std::pair<db::RecursiveShapeIterator, db::ICplxTrans> begin_merged_iter () const
{
return mp_delegate->begin_merged_iter ();
}
/**
* @brief Inserts the given shape (working object) into the edge set
*/
template <class Sh>
void insert (const Sh &shape);
/**
* @brief Insert a shape reference into the edge set
*/
void insert (const db::Shape &shape);
/**
* @brief Insert a transformed shape into the edge set
*/
template <class T>
void insert (const db::Shape &shape, const T &trans);
/**
* @brief Returns true if the edge set is empty
*/
bool empty () const
{
return mp_delegate->empty ();
}
/**
* @brief Returns the number of (flat) edges in the edge set
*/
size_t count () const
{
return mp_delegate->count ();
}
/**
* @brief Returns the number of (hierarchical) edges in the edge set
*/
size_t hier_count () const
{
return mp_delegate->hier_count ();
}
/**
* @brief Returns a string representing the edge set
*
* nmax specifies how many edges are included (set to std::numeric_limits<size_t>::max() for "all".
*/
std::string to_string (size_t nmax = 10) const
{
return mp_delegate->to_string (nmax);
}
/**
* @brief Clears the edge set
*/
void clear ();
/**
* @brief Reserve memory for the given number of edges
*/
void reserve (size_t n);
/**
* @brief Sets the merged-semantics flag
*
* If merged semantics is enabled (the default), colinear edges will be considered
* as single edges.
*/
void set_merged_semantics (bool f)
{
mp_delegate->set_merged_semantics (f);
}
/**
* @brief Gets the merged-semantics flag
*/
bool merged_semantics () const
{
return mp_delegate->merged_semantics ();
}
/**
* @brief Enables or disables strict handling
*
* Strict handling means to leave away some optimizations. Specifically the
* output of boolean operations will be merged even if one input is empty.
* Without strict handling, the operation will be optimized and output
* won't be merged.
*
* Strict handling is disabled by default.
*/
void set_strict_handling (bool f)
{
mp_delegate->set_strict_handling (f);
}
/**
* @brief Gets a valid indicating whether strict handling is enabled
*/
bool strict_handling () const
{
return mp_delegate->strict_handling ();
}
/**
* @brief Returns true if the edge set is merged
*/
bool is_merged () const
{
return mp_delegate->is_merged ();
}
/**
* @brief Returns the total length of the edges
* Merged semantics applies. In merged semantics, the length is the correct total length of the edges.
* Without merged semantics, overlapping parts are counted twice.
*
* If a box is given, the computation is restricted to that box.
* Edges coincident with the box edges are counted only if the form outer edges at the box edge.
*/
length_type length (const db::Box &box = db::Box ()) const
{
return mp_delegate->length (box);
}
/**
* @brief Returns the bounding box of the edge set
*/
Box bbox () const
{
return mp_delegate->bbox ();
}
/**
* @brief Filters the edges
*
* This method will keep all edges for which the filter returns true.
* Merged semantics applies. In merged semantics, the filter will run over
* all merged edges.
*/
Edges &filter (const EdgeFilterBase &filter)
{
set_delegate (mp_delegate->filter_in_place (filter));
return *this;
}
/**
* @brief Returns the filtered edges
*
* This method will return a new region with only those edges which
* conform to the filter criterion.
*/
Edges filtered (const EdgeFilterBase &filter) const
{
return Edges (mp_delegate->filtered (filter));
}
/**
* @brief Processes the (merged) edges
*
* This method will keep all edges which the processor returns.
* The processing filter can apply modifications too. These modifications will be
* kept in the output edge collection.
*
* Merged semantics applies. In merged semantics, the filter will run over
* all merged edges.
*/
Edges &process (const EdgeProcessorBase &filter)
{
set_delegate (mp_delegate->process_in_place (filter));
return *this;
}
/**
* @brief Returns the processed edges
*
* This method will keep all edges which the processor returns.
* The processing filter can apply modifications too. These modifications will be
* kept in the output edge collection.
*
* Merged semantics applies. In merged semantics, the filter will run over
* all merged edges.
*
* This method will return a new edge collection with the modified and filtered edges.
*/
Edges processed (const EdgeProcessorBase &filter) const
{
return Edges (mp_delegate->processed (filter));
}
/**
* @brief Processes the edges into polygons
*
* This method will run the processor over all edges and return a region
* with the outputs of the processor.
*
* Merged semantics applies. In merged semantics, the filter will run over
* all merged edges.
*/
void processed (Region &output, const EdgeToPolygonProcessorBase &filter) const;
/**
* @brief Processes the edges into edge pairs
*
* This method will run the processor over all edges and return an edge pair collection
* with the outputs of the processor.
*
* Merged semantics applies. In merged semantics, the filter will run over
* all merged edges.
*/
EdgePairs processed (const EdgeToEdgePairProcessorBase &filter) const
{
return EdgePairs (mp_delegate->processed_to_edge_pairs (filter));
}
/**
* @brief Applies a width check and returns EdgePairs which correspond to violation markers
*
* The width check will create a edge pairs if the width of the area between the
* edges is less than the specified threshold d. Without "whole_edges", the parts of
* the edges are returned which violate the condition. If "whole_edges" is true, the
* result will contain the complete edges participating in the result.
*
* "Width" refers to the space between the "inside" sides of the edges.
*
* The metrics parameter specifies which metrics to use. "Euclidian", "Square" and "Projected"
* metrics are available.
*
* ignore_angle allows specification of a maximum angle the edges can have to not participate
* in the check. By choosing 90 degree, edges having an angle of 90 degree and larger are not checked,
* but acute corners are for example.
*
* With min_projection and max_projection it is possible to specify how edges must be related
* to each other. If the length of the projection of either edge on the other is >= min_projection
* or < max_projection, the edges are considered for the check.
*
* The order of the edges in the resulting edge pairs is undefined.
*
* Merged semantics applies.
*/
EdgePairs width_check (db::Coord d, bool whole_edges = false, metrics_type metrics = db::Euclidian, double ignore_angle = 90, distance_type min_projection = 0, distance_type max_projection = std::numeric_limits<distance_type>::max ()) const
{
return EdgePairs (mp_delegate->width_check (d, whole_edges, metrics, ignore_angle, min_projection, max_projection));
}
/**
* @brief Applies a space check and returns EdgePairs which correspond to violation markers
*
* "Space" refers to the space between the "outside" sides of the edges.
*
* For the parameters see \width_check. The space check reports edges for which the space is
* less than the specified threshold d.
*
* Merged semantics applies.
*/
EdgePairs space_check (db::Coord d, bool whole_edges = false, metrics_type metrics = db::Euclidian, double ignore_angle = 90, distance_type min_projection = 0, distance_type max_projection = std::numeric_limits<distance_type>::max ()) const
{
return EdgePairs (mp_delegate->space_check (d, whole_edges, metrics, ignore_angle, min_projection, max_projection));
}
/**
* @brief Applies an enclosing check and returns EdgePairs which correspond to violation markers
*
* The check will return true for edges from this edge set and the other edge set, where the other edge
* is located on the "inside" side of the edge from this edge set, the orientation is parallel
* and the distance is less than the specified threshold d.
*
* The first edges of the edge pairs will be the ones from "this", the second edges will be those of "other".
*
* For the other parameters see \width_check.
*
* Merged semantics applies.
*/
EdgePairs enclosing_check (const Edges &other, db::Coord d, bool whole_edges = false, metrics_type metrics = db::Euclidian, double ignore_angle = 90, distance_type min_projection = 0, distance_type max_projection = std::numeric_limits<distance_type>::max ()) const
{
return EdgePairs (mp_delegate->enclosing_check (other, d, whole_edges, metrics, ignore_angle, min_projection, max_projection));
}
/**
* @brief Applies an overlap check and returns EdgePairs which correspond to violation markers
*
* The check will return true for edges from this edge set and the other edge set, where the other edge
* is located on the "inside" side of the edge from this edge set, the orientation is anti-parallel
* and the distance is less than the specified threshold d.
*
* The first edges of the edge pairs will be the ones from "this", the second edges will be those of "other".
*
* For the other parameters see \width_check.
*
* Merged semantics applies.
*/
EdgePairs overlap_check (const Edges &other, db::Coord d, bool whole_edges = false, metrics_type metrics = db::Euclidian, double ignore_angle = 90, distance_type min_projection = 0, distance_type max_projection = std::numeric_limits<distance_type>::max ()) const
{
return EdgePairs (mp_delegate->overlap_check (other, d, whole_edges, metrics, ignore_angle, min_projection, max_projection));
}
/**
* @brief Applies an separation check and returns EdgePairs which correspond to violation markers
*
* The check will return true for edges from this edge set and the other edge set, where the other edge
* is located on the "outside" side of the edge from this edge set, the orientation is anti-parallel
* and the distance is less than the specified threshold d.
*
* The first edges of the edge pairs will be the ones from "this", the second edges will be those of "other".
*
* For the other parameters see \width_check.
*
* Merged semantics applies.
*/
EdgePairs separation_check (const Edges &other, db::Coord d, bool whole_edges = false, metrics_type metrics = db::Euclidian, double ignore_angle = 90, distance_type min_projection = 0, distance_type max_projection = std::numeric_limits<distance_type>::max ()) const
{
return EdgePairs (mp_delegate->separation_check (other, d, whole_edges, metrics, ignore_angle, min_projection, max_projection));
}
/**
* @brief Applies a inside check and returns EdgePairs which correspond to violation markers
*
* The check will return true for edges from this edge set and the other edge set, where the other edge
* is located on the "outide" side of the edge from this edge set, the orientation is parallel
* and the distance is less than the specified threshold d.
*
* The first edges of the edge pairs will be the ones from "this", the second edges will be those of "other".
*
* For the other parameters see \width_check.
*
* Merged semantics applies.
*/
EdgePairs inside_check (const Edges &other, db::Coord d, bool whole_edges = false, metrics_type metrics = db::Euclidian, double ignore_angle = 90, distance_type min_projection = 0, distance_type max_projection = std::numeric_limits<distance_type>::max ()) const
{
return EdgePairs (mp_delegate->inside_check (other, d, whole_edges, metrics, ignore_angle, min_projection, max_projection));
}
/**
* @brief Transforms the edge set
*/
template <class T>
Edges &transform (const T &trans);
/**
* @brief Returns the transformed edge set
*/
template <class T>
Edges transformed (const T &trans) const
{
Edges d (*this);
d.transform (trans);
return d;
}
/**
* @brief Swaps with the other edge set
*/
void swap (db::Edges &other)
{
std::swap (other.mp_delegate, mp_delegate);
}
/**
* @brief Merges the edge set
*
* This method merges the edges of the edge set if they are not merged already.
* It returns a reference to this edge set.
* An out-of-place merge version is "merged".
*/
Edges &merge ()
{
set_delegate (mp_delegate->merged_in_place ());
return *this;
}
/**
* @brief Returns the merged edge set
*
* This is the out-of-place merge. It returns a new edge set but does not modify
* the edge set it is called on. An in-place version is "merge".
*/
Edges merged () const
{
return Edges (mp_delegate->merged ());
}
/**
* @brief Boolean AND operator
*/
Edges operator& (const Edges &other) const
{
return Edges (mp_delegate->and_with (other));
}
/**
* @brief In-place boolean AND operator
*
* This method does not necessarily merge the edge set. To ensure the edge set
* is merged, call merge afterwards.
*/
Edges &operator&= (const Edges &other)
{
set_delegate (mp_delegate->and_with (other));
return *this;
}
/**
* @brief Boolean AND operator with a region
*/
Edges operator& (const Region &other) const
{
return Edges (mp_delegate->and_with (other));
}
/**
* @brief In-place boolean AND operator with a region
*
* This method will keep all edges inside the given region.
*/
Edges &operator&= (const Region &other)
{
set_delegate (mp_delegate->and_with (other));
return *this;
}
/**
* @brief Boolean NOT operator
*/
Edges operator- (const Edges &other) const
{
return Edges (mp_delegate->not_with (other));
}
/**
* @brief In-place boolean NOT operator
*
* This method does not necessarily merge the edge set. To ensure the edge set
* is merged, call merge afterwards.
*/
Edges &operator-= (const Edges &other)
{
set_delegate (mp_delegate->not_with (other));
return *this;
}
/**
* @brief Boolean NOT operator with a region
*/
Edges operator- (const Region &other) const
{
return Edges (mp_delegate->not_with (other));
}
/**
* @brief In-place boolean NOT operator with a region
*
* This method will remove all edges inside the given region.
*/
Edges &operator-= (const Region &other)
{
set_delegate (mp_delegate->not_with (other));
return *this;
}
/**
* @brief Boolean XOR operator
*/
Edges operator^ (const Edges &other) const
{
return Edges (mp_delegate->xor_with (other));
}
/**
* @brief In-place boolean XOR operator
*
* This method does not necessarily merge the edge set. To ensure the edge set
* is merged, call merge afterwards.
*/
Edges &operator^= (const Edges &other)
{
set_delegate (mp_delegate->xor_with (other));
return *this;
}
/**
* @brief Boolean OR operator
*
* This method merges the edges of both edge sets.
*/
Edges operator| (const Edges &other) const
{
return Edges (mp_delegate->or_with (other));
}
/**
* @brief In-place boolean OR operator
*/
Edges &operator|= (const Edges &other)
{
set_delegate (mp_delegate->or_with (other));
return *this;
}
/**
* @brief Joining of edge set
*
* This method joins the edge sets but does not merge them afterwards.
*/
Edges operator+ (const Edges &other) const
{
return Edges (mp_delegate->add (other));
}
/**
* @brief In-place edge set joining
*/
Edges &operator+= (const Edges &other)
{
set_delegate (mp_delegate->add_in_place (other));
return *this;
}
/**
* @brief Intersections with other edges
* Intersections are similar to "AND", but will also report
* non-parallel intersections between crossing edges.
*/
Edges intersections (const Edges &other) const
{
return Edges (mp_delegate->intersections (other));
}
/**
* @brief returns the extended edges
*
* Edges are extended by creating a rectangle on each edge. The rectangle is constructed on the
* edge by applying the extensions given by ext_o, ext_b, ext_e, ext_i at the outside, the
* beginning, the end and the inside.
* If the edge is laid flat pointing from left to right, the outside is at the top, the inside
* is at the bottom.
*
* For degenerated edges with length 0, the orientation is assumed to the horizontal. The extended
* method creates a rectangle with specified dimensions: ext_b to the left, ext_o to the top, ext_i to the bottom
* and ext_e to the right.
*
* If the joined parameter is set to true, adjacent edges are joined before the extension is applied.
* A the join points, the extension is created similar to what the sizing function does.
*
* Note: the output is given as an out parameter since because of the include hierarchy we can't use
* Region as a return value directly.
*
* Merged semantics applies.
*/
void extended (Region &output, coord_type ext_b, coord_type ext_e, coord_type ext_o, coord_type ext_i, bool join = false) const;
/**
* @brief Returns edges (point-like) representing the start part of the edges
*
* The length of the part can be chosen by length or a fraction of the original length.
* If length and fraction are 0, a point at the beginning of the edge will be created.
* If length is non-zero and fraction is 0, a segment in the direction of the edge
* with the given length is created, even if the length is larger than the original
* edge.
*
* If fraction is given and length is 0, the segment will have a length which is the specified
* fraction of the original edge.
* If both values are given, the resulting edge will have a length which is the maximum of
* both the fixed length and the length derived from the fraction.
*
* Length and fraction can be negative in which case the resulting segment will point
* in the opposite direction of the original edge.
*
* Merged semantics applies.
*/
Edges start_segments (length_type length, double fraction) const;
/**
* @brief Returns edges (point-like) representing the end part of the edges
*
* This method behaves similar to \start_segments but creates segments at the end of
* the edges.
*
* Merged semantics applies.
*/
Edges end_segments (length_type length, double fraction) const;
/**
* @brief Returns edges (point-like) representing the center of the edges
*
* This method behaves similar to \start_segments but creates segments at the centers of
* the edges.
*
* Merged semantics applies.
*/
Edges centers (length_type length, double fraction) const;
/**
* @brief Select the edges inside the given region
*
* This method will select the edges inside the given region.
* Edges on the border of the region won't be selected.
* As a side effect, the edges are made non-intersecting by introducing cut points where
* edges intersect.
*/
Edges &select_inside_part (const Region &other)
{
set_delegate (mp_delegate->inside_part (other));
return *this;
}
/**
* @brief Returns the edges inside the given region
*
* This is an out-of-place version of "select_inside_part".
*/
Edges inside_part (const Region &other) const
{
return Edges (mp_delegate->inside_part (other));
}
/**
* @brief Select the edge parts outside of the given region
*
* This method will select the edge parts outside of the given region.
* Edges on the border of the region won't be selected.
* As a side effect, the edges are made non-intersecting by introducing cut points where
* edges intersect.
*/
Edges &select_outside_part (const Region &other)
{
set_delegate (mp_delegate->outside_part (other));
return *this;
}
/**
* @brief Returns the edge parts outside of the given region
*
* This is an out-of-place version of "select_outside_part".
*/
Edges outside_part (const Region &other) const
{
return Edges (mp_delegate->outside_part (other));
}
/**
* @brief Selects all polygons of the other region set which overlap or touch edges from this edge set
*
* Merged semantics applies for the other region. Merged polygons will be selected from the other region
* if merged semantics is enabled.
*/
void pull_interacting (Region &output, const Region &other) const;
/**
* @brief Selects all edges of the other edge set which overlap or touch edges from this edge set
*
* Merged semantics applies. If merged semantics is chosen, the connected edge parts will be
* selected as a whole from other.
*/
Edges pull_interacting (const Edges &other) const
{
return Edges (mp_delegate->pull_interacting (other));
}
/**
* @brief Selects all edges of this edge set which overlap or touch with polygons from the region
*
* Merged semantics applies. If merged semantics is chosen, the connected edge parts will be
* selected as a whole.
*/
Edges &select_interacting (const Region &other)
{
set_delegate (mp_delegate->selected_interacting (other));
return *this;
}
/**
* @brief Returns all edges of this edge set which overlap or touch with polygons from the region
*
* This method is an out-of-place version of select_interacting.
*/
Edges selected_interacting (const Region &other) const
{
return Edges (mp_delegate->selected_interacting (other));
}
/**
* @brief Selects all edges of this edge set which do not overlap or touch with polygons from the region
*
* Merged semantics applies. If merged semantics is chosen, the connected edge parts will be
* selected as a whole.
*/
Edges &select_not_interacting (const Region &other)
{
set_delegate (mp_delegate->selected_not_interacting (other));
return *this;
}
/**
* @brief Returns all edges of this edge set which do not overlap or touch with polygons from the region
*
* This method is an out-of-place version of select_not_interacting.
*/
Edges selected_not_interacting (const Region &other) const
{
return Edges (mp_delegate->selected_not_interacting (other));
}
/**
* @brief Selects all edges of this edge set which overlap or touch with edges from the other edge set
*
* Merged semantics applies. If merged semantics is chosen, the connected edge parts will be
* selected as a whole.
*/
Edges &select_interacting (const Edges &other)
{
set_delegate (mp_delegate->selected_interacting (other));
return *this;
}
/**
* @brief Returns all edges of this edge set which overlap or touch with edges from the other edge set
*
* This method is an out-of-place version of select_interacting.
*/
Edges selected_interacting (const Edges &other) const
{
return Edges (mp_delegate->selected_interacting (other));
}
/**
* @brief Selects all edges of this edge set which do not overlap or touch with edges from the other edge set
*
* Merged semantics applies. If merged semantics is chosen, the connected edge parts will be
* selected as a whole.
*/
Edges &select_not_interacting (const Edges &other)
{
set_delegate (mp_delegate->selected_not_interacting (other));
return *this;
}
/**
* @brief Returns all edges of this edge set which do not overlap or touch with edges from the other edge set
*
* This method is an out-of-place version of select_not_interacting.
*/
Edges selected_not_interacting (const Edges &other) const
{
return Edges (mp_delegate->selected_not_interacting (other));
}
/**
* @brief Returns all edges which are in the other edge set
*
* This method will return all edges which are part of another edge set.
* The match is done exactly.
* The "invert" flag can be used to invert the sense, i.e. with
* "invert" set to true, this method will return all edges not
* in the other edge set.
*
* Merged semantics applies.
*/
Edges in (const Edges &other, bool invert = false) const
{
return Edges (mp_delegate->in (other, invert));
}
/**
* @brief Returns the nth edge
*
* This operation is available only for flat regions - i.e. such for which "has_valid_edges" is true.
*/
const db::Edge *nth (size_t n) const
{
return mp_delegate->nth (n);
}
/**
* @brief Forces flattening of the edge collection
*
* This method will turn any edge collection into a flat one.
*/
void flatten ()
{
flat_edges ();
}
/**
* @brief Returns true, if the edge set has valid edges stored within itself
*
* If the region has valid edges, it is permissable to use the edge's addresses
* from the iterator. Furthermore, the random access operator nth() is available.
*/
bool has_valid_edges () const
{
return mp_delegate->has_valid_edges ();
}
/**
* @brief Returns an addressable delivery for edges
*
* This object allows accessing the edges by address, even if they
* are not delivered from a container. The magic is a heap object
* inside the delivery object. Hence, the deliver object must persist
* as long as the addresses are required.
*/
AddressableEdgeDelivery addressable_edges () const
{
return AddressableEdgeDelivery (begin (), has_valid_edges ());
}
/**
* @brief Returns true, if the edge set has valid merged edges stored within itself
*
* If the region has valid merged edges, it is permissable to use the edge's addresses
* from the merged edge iterator. Furthermore, the random access operator nth() is available.
*/
bool has_valid_merged_edges () const
{
return mp_delegate->has_valid_merged_edges ();
}
/**
* @brief Returns an addressable delivery for merged polygons
*/
AddressableEdgeDelivery addressable_merged_edges () const
{
return AddressableEdgeDelivery (begin_merged (), has_valid_merged_edges ());
}
/**
* @brief Gets the internal iterator
*
* This method is intended for users who know what they are doing
*/
const db::RecursiveShapeIterator &iter () const;
/**
* @brief Equality
*/
bool operator== (const db::Edges &other) const
{
return mp_delegate->equals (other);
}
/**
* @brief Inequality
*/
bool operator!= (const db::Edges &other) const
{
return ! mp_delegate->equals (other);
}
/**
* @brief Less operator
*/
bool operator< (const db::Edges &other) const
{
return mp_delegate->less (other);
}
/**
* @brief Inserts the edge collection into the given layout, cell and layer
* If the edge collection is a hierarchical region, the hierarchy is copied into the
* layout's hierarchy.
*/
void insert_into (Layout *layout, db::cell_index_type into_cell, unsigned int into_layer) const
{
return mp_delegate->insert_into (layout, into_cell, into_layer);
}
private:
friend class EdgePairs;
friend class Texts;
EdgesDelegate *mp_delegate;
void set_delegate (EdgesDelegate *delegate, bool keep_attributes = true);
FlatEdges *flat_edges ();
};
} // namespace db
namespace tl
{
/**
* @brief The type traits for the region type
*/
template <>
struct type_traits <db::Edges> : public type_traits<void>
{
typedef true_tag supports_extractor;
typedef true_tag supports_to_string;
typedef true_tag has_less_operator;
typedef true_tag has_equal_operator;
};
}
#endif