WIP: bug fixes, one more test

This commit is contained in:
Matthias Koefferlein 2025-04-18 23:29:29 +02:00
parent 71620445ee
commit 8a122c8a7d
13 changed files with 479 additions and 65 deletions

View File

@ -57,6 +57,9 @@ $python $inst/stubgen.py tl >$pyi_srcdir/tlcore.pyi
echo "Generating stubs for db .."
$python $inst/stubgen.py db tl,lay,rdb >$pyi_srcdir/dbcore.pyi
echo "Generating stubs for pex .."
$python $inst/stubgen.py pex tl,db >$pyi_srcdir/pexcore.pyi
echo "Generating stubs for rdb .."
$python $inst/stubgen.py rdb tl,db >$pyi_srcdir/rdbcore.pyi

View File

@ -146,7 +146,7 @@ ConvexDecomposition::collect_concave_vertexes (std::vector<ConcaveCorner> &conca
// and outgoing edge.
Edge *start_segment = segment;
Vertex *vto = segment->right () ? segment->v2 () : segment->v1 ();
Vertex *vto = (segment->right () && ! segment->right ()->is_outside ()) ? segment->v2 () : segment->v1 ();
do {
@ -338,7 +338,9 @@ ConvexDecomposition::hertel_mehlhorn_decomposition (Triangulation &tris, const C
}
for (auto i = angles_and_edges.begin (); i != angles_and_edges.end (); ++i) {
essential_edges.insert (i->second);
if (i->second) {
essential_edges.insert (i->second);
}
}
}
@ -347,7 +349,9 @@ ConvexDecomposition::hertel_mehlhorn_decomposition (Triangulation &tris, const C
std::unordered_set<const Polygon *> left_triangles;
for (auto it = mp_graph->begin (); it != mp_graph->end (); ++it) {
left_triangles.insert (it.operator-> ());
if (! it->is_outside ()) {
left_triangles.insert (it.operator-> ());
}
}
std::list<std::unordered_set<Edge *> > polygons;
@ -385,7 +389,7 @@ ConvexDecomposition::hertel_mehlhorn_decomposition (Triangulation &tris, const C
ivs.insert (e->v2 ());
}
if (! qq || essential_edges.find (e) != essential_edges.end ()) {
if (! qq || qq->is_outside () || essential_edges.find (e) != essential_edges.end ()) {
edges.insert (const_cast<Edge *> (e)); // TODO: ugly const_cast
} else if (left_triangles.find (qq) != left_triangles.end ()) {
next_queue.push_back (qq);

View File

@ -47,6 +47,9 @@ struct DB_PUBLIC ConvexDecompositionParameters
{
tri_param.max_area = 0.0;
tri_param.min_b = 0.0;
// Needed for the algorithm - don't change this
tri_param.remove_outside_triangles = false;
}
/**

View File

@ -1522,7 +1522,9 @@ Triangulation::refine (const TriangulationParameters &parameters)
if (parameters.min_b < db::epsilon && parameters.max_area < db::epsilon && parameters.max_area_border < db::epsilon) {
// no refinement requested - we're done.
remove_outside_triangles ();
if (parameters.remove_outside_triangles) {
remove_outside_triangles ();
}
return;
}
@ -1690,7 +1692,9 @@ Triangulation::refine (const TriangulationParameters &parameters)
}
remove_outside_triangles ();
if (parameters.remove_outside_triangles) {
remove_outside_triangles ();
}
}
} // namespace plc

View File

@ -46,7 +46,8 @@ struct DB_PUBLIC TriangulationParameters
max_area_border (0.0),
max_iterations (std::numeric_limits<size_t>::max ()),
base_verbosity (30),
mark_triangles (false)
mark_triangles (false),
remove_outside_triangles (true)
{ }
/**
@ -93,6 +94,11 @@ struct DB_PUBLIC TriangulationParameters
* Bit 2: non-Delaunay (in the strict sense)
*/
bool mark_triangles;
/**
* @brief If false, the outside triangles are not removed after triangulation
*/
bool remove_outside_triangles;
};
/**

View File

@ -153,3 +153,37 @@ TEST(internal_vertex)
EXPECT_EQ (++p == plc.end (), true);
}
TEST(problematic_polygon)
{
db::Point contour[] = {
db::Point (14590, 990),
db::Point (6100, 990),
db::Point (7360, 4450),
db::Point (2280, 4450),
db::Point (2280, 6120),
db::Point (7360, 6120),
db::Point (8760, 7490),
db::Point (13590, 17100),
db::Point (10280, 6120),
db::Point (26790, 13060),
db::Point (41270, 970)
};
db::Polygon poly;
poly.assign_hull (contour + 0, contour + sizeof (contour) / sizeof (contour[0]));
double dbu = 0.001;
db::plc::ConvexDecompositionParameters param;
param.with_segments = true;
param.split_edges = false;
db::plc::Graph plc;
TestableConvexDecomposition decomp (&plc);
decomp.decompose (poly, param, dbu);
std::unique_ptr<db::Layout> ly (plc.to_layout ());
db::compare_layouts (_this, *ly, tl::testdata () + "/algo/hm_decomposition_au5.gds");
}

View File

@ -28,13 +28,13 @@ namespace gsi
{
// @@@
static pex::RExtractor *new_sqc_rextractor ()
static pex::RExtractor *new_sqc_rextractor (double dbu)
{
return new pex::RExtractor ();
return new pex::SquareCountingRExtractor (dbu);
}
Class<pex::RExtractor> decl_RExtractor ("pex", "RExtractor",
gsi::constructor ("square_counting", &new_sqc_rextractor,
gsi::constructor ("square_counting", &new_sqc_rextractor, gsi::arg ("dbu"),
"@brief Creates a square counting R extractor\n"
),
"@brief A base class for the R extractor\n"

View File

@ -26,11 +26,146 @@
namespace pex
{
RNetwork::RNetwork ()
{
// .. nothing yet ..
}
RNetwork::~RNetwork ()
{
clear ();
}
void
RNetwork::clear ()
{
m_elements.clear (); // must come before m_nodes
m_nodes.clear ();
m_elements_by_nodes.clear ();
m_nodes_by_type.clear ();
}
std::map<std::pair<RNode *, RNode *>, RElement *> m_elements_by_nodes;
std::map<std::pair<RNode::node_type, unsigned int>, RNode *> m_nodes;
RNode *
RNetwork::create_node (RNode::node_type type, unsigned int port_index)
{
if (type != RNode::INTERNAL) {
auto i = m_nodes_by_type.find (std::make_pair (type, port_index));
if (i != m_nodes_by_type.end ()) {
return i->second;
} else {
RNode *new_node = new RNode (type, db::DBox (), port_index);
m_nodes.push_back (new_node);
m_nodes_by_type.insert (std::make_pair (std::make_pair (type, port_index), new_node));
return new_node;
}
} else {
RNode *new_node = new RNode (type, db::DBox (), port_index);
m_nodes.push_back (new_node);
return new_node;
}
}
RElement *
RNetwork::create_element (double conductivity, RNode *a, RNode *b)
{
auto i = m_elements_by_nodes.find (std::make_pair (a, b));
if (i != m_elements_by_nodes.end ()) {
i->second->conductivity += conductivity;
return i->second;
} else {
RElement *element = new RElement (conductivity, a, b);
a->elements.push_back (element);
element->m_ia = --a->elements.end ();
b->elements.push_back (element);
element->m_ia = --b->elements.end ();
m_elements_by_nodes.insert (std::make_pair (std::make_pair (a, b), element));
return element;
}
}
void
RNetwork::remove_node (RNode *node)
{
tl_assert (node->type == RNode::INTERNAL);
while (! node->elements.empty ()) {
remove_element (const_cast<RElement *> (node->elements.front ()));
}
delete node;
}
void
RNetwork::remove_element (RElement *element)
{
RNode *a = const_cast<RNode *> (element->a);
RNode *b = const_cast<RNode *> (element->b);
delete element;
if (a && a->type == RNode::INTERNAL && a->elements.empty ()) {
delete a;
}
if (b && b->type == RNode::INTERNAL && b->elements.empty ()) {
delete b;
}
}
RExtractor::RExtractor ()
{
// .. nothing yet ..
}
RExtractor::~RExtractor ()
{
// .. nothing yet ..
}
SquareCountingRExtractor::SquareCountingRExtractor (double dbu)
{
m_dbu = dbu;
m_decomp_param.split_edges = true;
m_decomp_param.with_segments = false;
}
void
SquareCountingRExtractor::extract (const db::Polygon &polygon, const std::vector<db::Point> &vertex_ports, const std::vector<db::Polygon> &polygon_ports, RNetwork &rnetwork)
{
db::CplxTrans trans = db::CplxTrans (m_dbu) * db::ICplxTrans (db::Trans (db::Point () - polygon.box ().center ()));
auto inv_trans = trans.inverted ();
db::plc::Graph plc;
db::plc::ConvexDecomposition decomp (&plc);
decomp.decompose (polygon, vertex_ports, m_decomp_param, trans);
std::vector<std::pair<db::Polygon, db::plc::Polygon *> > decomp_polygons;
for (auto p = plc.begin (); p != plc.end (); ++p) {
// @@@decomp_polygons.push_back (db::Polygon ());
// @@@decomp_polygons.back ().first = inv_trans * p->polygon ();
}
// @@@ use box_scanner to find interactions between polygon_ports and decomp_polygons
}
}

View File

@ -24,11 +24,112 @@
#define HDR_pexRExtractor
#include "pexCommon.h"
#include "dbPolygon.h"
#include "dbPLC.h"
#include "dbPLCConvexDecomposition.h" // @@@
#include "dbPLCTriangulation.h" // @@@
#include "tlList.h"
#include <string>
#include <list>
namespace pex
{
class RElement;
class RNode;
struct PEX_PUBLIC RNode
: public tl::list_node<RNode>
{
public:
enum node_type {
INTERNAL,
VERTEX_PORT,
POLYGON_PORT
};
node_type type;
db::DBox location;
unsigned int port_index;
mutable std::list<const RElement *> elements;
protected:
friend class RNetwork;
friend class tl::list_impl<RNode, false>;
RNode (node_type _type, const db::DBox &_location, unsigned int _port_index)
: type (_type), location (_location), port_index (_port_index)
{ }
~RNode () { }
private:
RNode (const RNode &other);
RNode &operator= (const RNode &other);
};
struct PEX_PUBLIC RElement
: public tl::list_node<RElement>
{
double conductivity;
const RNode *a, *b;
double resistance () const
{
return 1.0 / conductivity;
}
protected:
friend class RNetwork;
friend class tl::list_impl<RElement, false>;
RElement (double _conductivity, const RNode *_a, const RNode *_b)
: conductivity (_conductivity), a (_a), b (_b)
{ }
~RElement ()
{
if (a) {
a->elements.erase (m_ia);
}
if (b) {
b->elements.erase (m_ib);
}
a = b = 0;
}
std::list<const RElement *>::iterator m_ia, m_ib;
private:
RElement (const RElement &other);
RElement &operator= (const RElement &other);
};
class PEX_PUBLIC RNetwork
{
public:
RNetwork ();
~RNetwork ();
RNode *create_node (RNode::node_type type, unsigned int port_index);
RElement *create_element (double conductivity, RNode *a, RNode *b);
void remove_element (RElement *element);
void remove_node (RNode *node);
void clear ();
private:
tl::list<RNode, false> m_nodes;
tl::list<RElement, false> m_elements;
std::map<std::pair<RNode *, RNode *>, RElement *> m_elements_by_nodes;
std::map<std::pair<RNode::node_type, unsigned int>, RNode *> m_nodes_by_type;
RNetwork (const RNetwork &);
RNetwork &operator= (const RNetwork &);
};
/**
* @brief A base class for an resistance extractor
*
@ -38,9 +139,42 @@ namespace pex
* Ports are points or polygons that define the connection
* points to the network.
*/
struct PEX_PUBLIC RExtractor
class PEX_PUBLIC RExtractor
{
public:
RExtractor ();
virtual ~RExtractor ();
virtual void extract (const db::Polygon &polygon, const std::vector<db::Point> &vertex_ports, const std::vector<db::Polygon> &polygon_ports, RNetwork &rnetwork) = 0;
};
// @@@
class PEX_PUBLIC SquareCountingRExtractor
: public RExtractor
{
public:
SquareCountingRExtractor (double dbu);
db::plc::ConvexDecompositionParameters &decomposition_parameters ()
{
return m_decomp_param;
}
void set_dbu (double dbu)
{
m_dbu = dbu;
}
double dbu () const
{
return m_dbu;
}
virtual void extract (const db::Polygon &polygon, const std::vector<db::Point> &vertex_ports, const std::vector<db::Polygon> &polygon_ports, RNetwork &rnetwork);
private:
db::plc::ConvexDecompositionParameters m_decomp_param;
double m_dbu;
};
}

View File

@ -13813,7 +13813,7 @@ class DPolygon:
The minimum angle of the resulting triangles relates to the 'b' parameter as: @t min_angle = arcsin(B/2) @/t.
Picking a value of 0.0 for max area and min b will make the implementation skip the refinement step. In that case, the results are identical to the standard constrained Delaunay triangulation.
Picking a value of 0.0 for max_area and min_b will make the implementation skip the refinement step. In that case, the results are identical to the standard constrained Delaunay triangulation.
This method has been introduced in version 0.30.
"""
@ -13912,6 +13912,24 @@ class DPolygon:
This method has been introduced in version 0.25.
"""
...
def hm_decomposition(self, with_segments: Optional[bool] = ..., split_edges: Optional[bool] = ..., max_area: Optional[float] = ..., min_b: Optional[float] = ...) -> List[DPolygon]:
r"""
@brief Performs a Hertel-Mehlhorn convex decomposition.
@return An array holding the polygons of the decomposition.
The Hertel-Mehlhorn decomposition starts with a Delaunay triangulation of the polygons and recombines the triangles into convex polygons.
The decomposition is controlled by two parameters: 'with_segments' and 'split_edges'.
If 'with_segments' is true (the default), new segments are introduced perpendicular to the edges forming a concave corner. If false, only diagonals (edges connecting original vertexes) are used.
If 'split_edges' is true, the algorithm is allowed to create collinear edges in the output. In this case, the resulting polygons may contain edges that are split into collinear partial edges. Such edges usually recombine into longer edges when processing the polygon further. When such a recombination happens, the edges no longer correspond to original edges or diagonals. When 'split_edges' is false (the default), the resulting polygons will not contain collinear edges, but the decomposition will be constrained to fewer cut lines.
'max_area' and 'min_b' are the corresponding parameters used for the triangulation (see \delaunay).
This method has been introduced in version 0.30.1.
"""
...
def holes(self) -> int:
r"""
@brief Returns the number of holes
@ -14926,7 +14944,7 @@ class DSimplePolygon:
The minimum angle of the resulting triangles relates to the 'b' parameter as: @t min_angle = arcsin(B/2) @/t.
Picking a value of 0.0 for max area and min b will make the implementation skip the refinement step. In that case, the results are identical to the standard constrained Delaunay triangulation.
Picking a value of 0.0 for max_area and min_b will make the implementation skip the refinement step. In that case, the results are identical to the standard constrained Delaunay triangulation.
This method has been introduced in version 0.30.
"""
@ -15003,6 +15021,24 @@ class DSimplePolygon:
This method has been introduced in version 0.25.
"""
...
def hm_decomposition(self, with_segments: Optional[bool] = ..., split_edges: Optional[bool] = ..., max_area: Optional[float] = ..., min_b: Optional[float] = ...) -> List[DSimplePolygon]:
r"""
@brief Performs a Hertel-Mehlhorn convex decomposition.
@return An array holding the polygons of the decomposition.
The Hertel-Mehlhorn decomposition starts with a Delaunay triangulation of the polygons and recombines the triangles into convex polygons.
The decomposition is controlled by two parameters: 'with_segments' and 'split_edges'.
If 'with_segments' is true (the default), new segments are introduced perpendicular to the edges forming a concave corner. If false, only diagonals (edges connecting original vertexes) are used.
If 'split_edges' is true, the algorithm is allowed to create collinear edges in the output. In this case, the resulting polygons may contain edges that are split into collinear partial edges. Such edges usually recombine into longer edges when processing the polygon further. When such a recombination happens, the edges no longer correspond to original edges or diagonals. When 'split_edges' is false (the default), the resulting polygons will not contain collinear edges, but the decomposition will be constrained to fewer cut lines.
'max_area' and 'min_b' are the corresponding parameters used for the triangulation (see \delaunay).
This method has been introduced in version 0.30.1.
"""
...
def inside(self, p: DPoint) -> bool:
r"""
@brief Gets a value indicating whether the given point is inside the polygon
@ -34920,11 +34956,11 @@ class Instance:
Starting with version 0.25 the displacement is of vector type.
Setter:
@brief Sets the displacement vector for the 'b' axis in micrometer units
@brief Sets the displacement vector for the 'b' axis
Like \b= with an integer displacement, this method will set the displacement vector but it accepts a vector in micrometer units that is of \DVector type. The vector will be translated to database units internally.
If the instance was not an array instance before it is made one.
This method has been introduced in version 0.25.
This method has been introduced in version 0.23. Starting with version 0.25 the displacement is of vector type.
"""
cell: Cell
r"""
@ -34956,10 +34992,10 @@ class Instance:
Getter:
@brief Gets the basic \CellInstArray object associated with this instance reference.
Setter:
@brief Changes the \CellInstArray object to the given one.
This method replaces the instance by the given CellInstArray object.
@brief Returns the basic cell instance array object by giving a micrometer unit object.
This method replaces the instance by the given CellInstArray object and it internally transformed into database units.
This method has been introduced in version 0.22
This method has been introduced in version 0.25
"""
cplx_trans: ICplxTrans
r"""
@ -34967,10 +35003,9 @@ class Instance:
@brief Gets the complex transformation of the instance or the first instance in the array
This method is always valid compared to \trans, since simple transformations can be expressed as complex transformations as well.
Setter:
@brief Sets the complex transformation of the instance or the first instance in the array (in micrometer units)
This method sets the transformation the same way as \cplx_trans=, but the displacement of this transformation is given in micrometer units. It is internally translated into database units.
@brief Sets the complex transformation of the instance or the first instance in the array
This method has been introduced in version 0.25.
This method has been introduced in version 0.23.
"""
da: DVector
r"""
@ -46700,17 +46735,17 @@ class NetTerminalRef:
@overload
def device(self) -> Device:
r"""
@brief Gets the device reference (non-const version).
@brief Gets the device reference.
Gets the device object that this connection is made to.
This constness variant has been introduced in version 0.26.8
"""
...
@overload
def device(self) -> Device:
r"""
@brief Gets the device reference.
@brief Gets the device reference (non-const version).
Gets the device object that this connection is made to.
This constness variant has been introduced in version 0.26.8
"""
...
def device_class(self) -> DeviceClass:
@ -47722,17 +47757,26 @@ class Netlist:
@overload
def circuit_by_name(self, name: str) -> Circuit:
r"""
@brief Gets the circuit object for a given name.
@brief Gets the circuit object for a given name (const version).
If the name is not a valid circuit name, nil is returned.
This constness variant has been introduced in version 0.26.8.
"""
...
@overload
def circuit_by_name(self, name: str) -> Circuit:
r"""
@brief Gets the circuit object for a given name (const version).
@brief Gets the circuit object for a given name.
If the name is not a valid circuit name, nil is returned.
"""
...
@overload
def circuits_by_name(self, name_pattern: str) -> List[Circuit]:
r"""
@brief Gets the circuit objects for a given name filter.
The name filter is a glob pattern. This method will return all \Circuit objects matching the glob pattern.
This constness variant has been introduced in version 0.26.8.
This method has been introduced in version 0.26.4.
"""
...
@overload
@ -47745,15 +47789,6 @@ class Netlist:
This constness variant has been introduced in version 0.26.8.
"""
...
@overload
def circuits_by_name(self, name_pattern: str) -> List[Circuit]:
r"""
@brief Gets the circuit objects for a given name filter.
The name filter is a glob pattern. This method will return all \Circuit objects matching the glob pattern.
This method has been introduced in version 0.26.4.
"""
...
def combine_devices(self) -> None:
r"""
@brief Combines devices where possible
@ -47996,7 +48031,7 @@ class Netlist:
@overload
def top_circuit(self) -> Circuit:
r"""
@brief Gets the top circuit.
@brief Gets the top circuit (const version).
This method will return nil, if there is no top circuit. It will raise an error, if there is more than a single top circuit.
This convenience method has been added in version 0.29.5.
@ -48005,7 +48040,7 @@ class Netlist:
@overload
def top_circuit(self) -> Circuit:
r"""
@brief Gets the top circuit (const version).
@brief Gets the top circuit.
This method will return nil, if there is no top circuit. It will raise an error, if there is more than a single top circuit.
This convenience method has been added in version 0.29.5.
@ -53581,11 +53616,13 @@ class Polygon:
The minimum angle of the resulting triangles relates to the 'b' parameter as: @t min_angle = arcsin(B/2) @/t.
The area value is given in terms of DBU units. Picking a value of 0.0 for area and min b will make the implementation skip the refinement step. In that case, the results are identical to the standard constrained Delaunay triangulation.
Picking a value of 0.0 for max_area and min_b will make the implementation skip the refinement step. In that case, the results are identical to the standard constrained Delaunay triangulation.
The area value is given in terms of DBU units.
The 'dbu' parameter a numerical scaling parameter. It should be choosen in a way that the polygon dimensions are "in the order of 1" (very roughly) after multiplication with the dbu parameter. A value of 0.001 is suitable for polygons with typical dimensions in the order to 1000 DBU. Usually the default value is good enough.
This method has been introduced in version 0.30.
This method has been introduced in version 0.30. Since version 0.30.1, the resulting region is in 'no merged semantics' mode, to avoid re-merging of the triangles during following operations.
"""
...
@overload
@ -53595,7 +53632,7 @@ class Polygon:
This variant of the triangulation function accepts an array of additional vertexes for the triangulation.
This method has been introduced in version 0.30.
This method has been introduced in version 0.30. Since version 0.30.1, the resulting region is in 'no merged semantics' mode, to avoid re-merging of the triangles during following operations.
"""
...
def destroy(self) -> None:
@ -53682,6 +53719,28 @@ class Polygon:
This method has been introduced in version 0.25.
"""
...
def hm_decomposition(self, with_segments: Optional[bool] = ..., split_edges: Optional[bool] = ..., max_area: Optional[float] = ..., min_b: Optional[float] = ..., dbu: Optional[float] = ...) -> Region:
r"""
@brief Performs a Hertel-Mehlhorn convex decomposition.
@return A \Region holding the polygons of the decomposition.
The resulting region is in 'no merged semantics' mode, to avoid re-merging of the polygons during following operations.
The Hertel-Mehlhorn decomposition starts with a Delaunay triangulation of the polygons and recombines the triangles into convex polygons.
The decomposition is controlled by two parameters: 'with_segments' and 'split_edges'.
If 'with_segments' is true (the default), new segments are introduced perpendicular to the edges forming a concave corner. If false, only diagonals (edges connecting original vertexes) are used.
If 'split_edges' is true, the algorithm is allowed to create collinear edges in the output. In this case, the resulting polygons may contain edges that are split into collinear partial edges. Such edges usually recombine into longer edges when processing the polygon further. When such a recombination happens, the edges no longer correspond to original edges or diagonals. When 'split_edges' is false (the default), the resulting polygons will not contain collinear edges, but the decomposition will be constrained to fewer cut lines.
'max_area' and 'min_b' are the corresponding parameters used for the triangulation (see \delaunay).
The 'dbu' parameter a numerical scaling parameter. It should be choosen in a way that the polygon dimensions are "in the order of 1" (very roughly) after multiplication with the dbu parameter. A value of 0.001 is suitable for polygons with typical dimensions in the order to 1000 DBU. Usually the default value is good enough.
This method has been introduced in version 0.30.1.
"""
...
def holes(self) -> int:
r"""
@brief Returns the number of holes
@ -62995,11 +63054,12 @@ class Shape:
This method has been introduced in version 0.23.
Setter:
@brief Sets the lower left point of the box
@brief Sets the lower left corner of the box with the point being given in micrometer units
Applies to boxes only. Changes the lower left point of the box and throws an exception if the shape is not a box.
Translation from micrometer units to database units is done internally.
This method has been introduced in version 0.23.
This method has been introduced in version 0.25.
"""
box_p2: Point
r"""
@ -63377,10 +63437,11 @@ class Shape:
Starting with version 0.23, this method returns nil, if the shape does not represent a geometrical primitive that can be converted to a simple polygon.
Setter:
@brief Replaces the shape by the given simple polygon (in micrometer units)
This method replaces the shape by the given text, like \simple_polygon= with a \SimplePolygon argument does. This version translates the polygon from micrometer units to database units internally.
@brief Replaces the shape by the given simple polygon object
This method replaces the shape by the given simple polygon object. This method can only be called for editable layouts. It does not change the user properties of the shape.
Calling this method will invalidate any iterators. It should not be called inside a loop iterating over shapes.
This method has been introduced in version 0.25.
This method has been introduced in version 0.22.
"""
text: Any
r"""
@ -66718,11 +66779,13 @@ class SimplePolygon:
The minimum angle of the resulting triangles relates to the 'b' parameter as: @t min_angle = arcsin(B/2) @/t.
The area value is given in terms of DBU units. Picking a value of 0.0 for area and min b will make the implementation skip the refinement step. In that case, the results are identical to the standard constrained Delaunay triangulation.
Picking a value of 0.0 for max_area and min_b will make the implementation skip the refinement step. In that case, the results are identical to the standard constrained Delaunay triangulation.
The area value is given in terms of DBU units.
The 'dbu' parameter a numerical scaling parameter. It should be choosen in a way that the polygon dimensions are "in the order of 1" (very roughly) after multiplication with the dbu parameter. A value of 0.001 is suitable for polygons with typical dimensions in the order to 1000 DBU. Usually the default value is good enough.
This method has been introduced in version 0.30.
This method has been introduced in version 0.30. Since version 0.30.1, the resulting region is in 'no merged semantics' mode, to avoid re-merging of the triangles during following operations.
"""
...
@overload
@ -66732,7 +66795,7 @@ class SimplePolygon:
This variant of the triangulation function accepts an array of additional vertexes for the triangulation.
This method has been introduced in version 0.30.
This method has been introduced in version 0.30. Since version 0.30.1, the resulting region is in 'no merged semantics' mode, to avoid re-merging of the triangles during following operations.
"""
...
def destroy(self) -> None:
@ -66797,6 +66860,27 @@ class SimplePolygon:
This method has been introduced in version 0.25.
"""
...
def hm_decomposition(self, with_segments: Optional[bool] = ..., split_edges: Optional[bool] = ..., max_area: Optional[float] = ..., min_b: Optional[float] = ..., dbu: Optional[float] = ...) -> Region:
r"""
@brief Performs a Hertel-Mehlhorn convex decomposition.
@return A \Region holding the polygons of the decomposition.
The resulting region is in 'no merged semantics' mode, to avoid re-merging of the polygons during following operations.
The Hertel-Mehlhorn decomposition starts with a Delaunay triangulation of the polygons and recombines the triangles into convex polygons.
The decomposition is controlled by two parameters: 'with_segments' and 'split_edges'.
If 'with_segments' is true (the default), new segments are introduced perpendicular to the edges forming a concave corner. If false, only diagonals (edges connecting original vertexes) are used.
If 'split_edges' is true, the algorithm is allowed to create collinear edges in the output. In this case, the resulting polygons may contain edges that are split into collinear partial edges. Such edges usually recombine into longer edges when processing the polygon further. When such a recombination happens, the edges no longer correspond to original edges or diagonals. When 'split_edges' is false (the default), the resulting polygons will not contain collinear edges, but the decomposition will be constrained to fewer cut lines.
'max_area' and 'min_b' are the corresponding parameters used for the triangulation (see \delaunay).
The 'dbu' parameter a numerical scaling parameter. It should be choosen in a way that the polygon dimensions are "in the order of 1" (very roughly) after multiplication with the dbu parameter. A value of 0.001 is suitable for polygons with typical dimensions in the order to 1000 DBU. Usually the default value is good enough.
This method has been introduced in version 0.30.1.
"""
...
def inside(self, p: Point) -> bool:
r"""
@brief Gets a value indicating whether the given point is inside the polygon
@ -67552,17 +67636,23 @@ class SubCircuit(NetlistObject):
@overload
def circuit(self) -> Circuit:
r"""
@brief Gets the circuit the subcircuit lives in.
@brief Gets the circuit the subcircuit lives in (non-const version).
This is NOT the circuit which is referenced. For getting the circuit that the subcircuit references, use \circuit_ref.
This constness variant has been introduced in version 0.26.8
"""
...
@overload
def circuit(self) -> Circuit:
r"""
@brief Gets the circuit the subcircuit lives in (non-const version).
@brief Gets the circuit the subcircuit lives in.
This is NOT the circuit which is referenced. For getting the circuit that the subcircuit references, use \circuit_ref.
This constness variant has been introduced in version 0.26.8
"""
...
@overload
def circuit_ref(self) -> Circuit:
r"""
@brief Gets the circuit referenced by the subcircuit.
"""
...
@overload
@ -67575,12 +67665,6 @@ class SubCircuit(NetlistObject):
"""
...
@overload
def circuit_ref(self) -> Circuit:
r"""
@brief Gets the circuit referenced by the subcircuit.
"""
...
@overload
def connect_pin(self, pin: Pin, net: Net) -> None:
r"""
@brief Connects the given pin to the specified net.
@ -68247,8 +68331,7 @@ class Text:
Setter:
@brief Sets the horizontal alignment
This property specifies how the text is aligned relative to the anchor point.
This property has been introduced in version 0.22 and extended to enums in 0.28.
This is the version accepting integer values. It's provided for backward compatibility.
"""
size: int
r"""
@ -68284,7 +68367,8 @@ class Text:
Setter:
@brief Sets the vertical alignment
This is the version accepting integer values. It's provided for backward compatibility.
This property specifies how the text is aligned relative to the anchor point.
This property has been introduced in version 0.22 and extended to enums in 0.28.
"""
x: int
r"""

View File

@ -0,0 +1,5 @@
from typing import Any, ClassVar, Dict, Sequence, List, Iterator, Optional
from typing import overload
from __future__ import annotations
import klayout.tl as tl
import klayout.db as db

View File

@ -2908,7 +2908,9 @@ class Timer:
r"""
@brief Gets the current memory usage of the process in Bytes
This method has been introduced in version 0.27.
The returned value is the resident memory size on Linux and MacOS and the working set size on Windows.
This method has been introduced in version 0.27. The value has been changed to be resident size (instead of virtual size) on Linux in version 0.30.
"""
...
@classmethod

BIN
testdata/algo/hm_decomposition_au5.gds vendored Normal file

Binary file not shown.